OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "courgette/assembly_program.h" | 5 #include "courgette/assembly_program.h" |
6 | 6 |
7 #include <memory.h> | 7 #include "base/callback.h" |
8 #include <stddef.h> | |
9 #include <stdint.h> | |
10 | |
11 #include <memory> | |
12 #include <utility> | |
13 #include <vector> | |
14 | |
15 #include "base/logging.h" | 8 #include "base/logging.h" |
16 #include "base/macros.h" | |
17 #include "courgette/courgette.h" | 9 #include "courgette/courgette.h" |
18 #include "courgette/encoded_program.h" | 10 #include "courgette/encoded_program.h" |
19 | 11 |
20 namespace courgette { | 12 namespace courgette { |
21 | 13 |
22 namespace { | 14 namespace { |
23 | 15 |
24 // Sets the current address for the emitting instructions. | 16 // Sets the current address for the emitting instructions. |
25 class OriginInstruction : public Instruction { | 17 class OriginInstruction : public Instruction { |
26 public: | 18 public: |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 private: | 179 private: |
188 AssemblyProgram* program_; | 180 AssemblyProgram* program_; |
189 | 181 |
190 DISALLOW_COPY_AND_ASSIGN(InstructionStoreReceptor); | 182 DISALLOW_COPY_AND_ASSIGN(InstructionStoreReceptor); |
191 }; | 183 }; |
192 | 184 |
193 } // namespace | 185 } // namespace |
194 | 186 |
195 /******** AssemblyProgram ********/ | 187 /******** AssemblyProgram ********/ |
196 | 188 |
197 AssemblyProgram::AssemblyProgram(ExecutableType kind) | 189 AssemblyProgram::AssemblyProgram(ExecutableType kind, uint64_t image_base) |
198 : kind_(kind), image_base_(0) { | 190 : kind_(kind), image_base_(image_base) {} |
199 } | |
200 | 191 |
201 AssemblyProgram::~AssemblyProgram() { | 192 AssemblyProgram::~AssemblyProgram() { |
202 for (size_t i = 0; i < instructions_.size(); ++i) { | 193 for (size_t i = 0; i < instructions_.size(); ++i) { |
203 Instruction* instruction = instructions_[i]; | 194 Instruction* instruction = instructions_[i]; |
204 if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_. | 195 if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_. |
205 UncheckedDelete(instruction); | 196 UncheckedDelete(instruction); |
206 } | 197 } |
207 if (byte_instruction_cache_.get()) { | 198 if (byte_instruction_cache_.get()) { |
208 for (size_t i = 0; i < 256; ++i) | 199 for (size_t i = 0; i < 256; ++i) |
209 UncheckedDelete(byte_instruction_cache_[i]); | 200 UncheckedDelete(byte_instruction_cache_[i]); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 // Ownership successfully passed to instructions_. | 325 // Ownership successfully passed to instructions_. |
335 ignore_result(instruction.release()); | 326 ignore_result(instruction.release()); |
336 return true; | 327 return true; |
337 } | 328 } |
338 | 329 |
339 CheckBool AssemblyProgram::EmitShared(Instruction* instruction) { | 330 CheckBool AssemblyProgram::EmitShared(Instruction* instruction) { |
340 DCHECK(!instruction || instruction->op() == DEFBYTE); | 331 DCHECK(!instruction || instruction->op() == DEFBYTE); |
341 return instruction && instructions_.push_back(instruction); | 332 return instruction && instructions_.push_back(instruction); |
342 } | 333 } |
343 | 334 |
344 void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) { | |
345 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { | |
346 Label* current = p->second; | |
347 current->index_ = Label::kNoIndex; | |
348 } | |
349 } | |
350 | |
351 // DefaultAssignIndexes takes a set of labels and assigns indexes in increasing | |
352 // address order. | |
353 void AssemblyProgram::DefaultAssignIndexes(RVAToLabel* labels) { | |
354 int index = 0; | |
355 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { | |
356 Label* current = p->second; | |
357 if (current->index_ != Label::kNoIndex) | |
358 NOTREACHED(); | |
359 current->index_ = index; | |
360 ++index; | |
361 } | |
362 } | |
363 | |
364 // AssignRemainingIndexes assigns indexes to any addresses (labels) that are not | |
365 // yet assigned an index. | |
366 void AssemblyProgram::AssignRemainingIndexes(RVAToLabel* labels) { | |
367 // An address table compresses best when each index is associated with an | |
368 // address that is slight larger than the previous index. | |
369 | |
370 // First see which indexes have not been used. The 'available' vector could | |
371 // grow even bigger, but the number of addresses is a better starting size | |
372 // than empty. | |
373 std::vector<bool> available(labels->size(), true); | |
374 int used = 0; | |
375 | |
376 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { | |
377 int index = p->second->index_; | |
378 if (index != Label::kNoIndex) { | |
379 while (static_cast<size_t>(index) >= available.size()) | |
380 available.push_back(true); | |
381 available.at(index) = false; | |
382 ++used; | |
383 } | |
384 } | |
385 | |
386 VLOG(1) << used << " of " << labels->size() << " labels pre-assigned"; | |
387 | |
388 // Are there any unused labels that happen to be adjacent following a used | |
389 // label? | |
390 int fill_forward_count = 0; | |
391 Label* prev = 0; | |
392 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { | |
393 Label* current = p->second; | |
394 if (current->index_ == Label::kNoIndex) { | |
395 int index = 0; | |
396 if (prev && prev->index_ != Label::kNoIndex) | |
397 index = prev->index_ + 1; | |
398 if (index < static_cast<int>(available.size()) && available.at(index)) { | |
399 current->index_ = index; | |
400 available.at(index) = false; | |
401 ++fill_forward_count; | |
402 } | |
403 } | |
404 prev = current; | |
405 } | |
406 | |
407 // Are there any unused labels that happen to be adjacent preceeding a used | |
408 // label? | |
409 int fill_backward_count = 0; | |
410 prev = 0; | |
411 for (RVAToLabel::reverse_iterator p = labels->rbegin(); | |
412 p != labels->rend(); | |
413 ++p) { | |
414 Label* current = p->second; | |
415 if (current->index_ == Label::kNoIndex) { | |
416 int prev_index; | |
417 if (prev) | |
418 prev_index = prev->index_; | |
419 else | |
420 prev_index = static_cast<uint32_t>(available.size()); | |
421 if (prev_index != 0 && | |
422 prev_index != Label::kNoIndex && | |
423 available.at(prev_index - 1)) { | |
424 current->index_ = prev_index - 1; | |
425 available.at(current->index_) = false; | |
426 ++fill_backward_count; | |
427 } | |
428 } | |
429 prev = current; | |
430 } | |
431 | |
432 // Fill in any remaining indexes | |
433 int fill_infill_count = 0; | |
434 int index = 0; | |
435 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { | |
436 Label* current = p->second; | |
437 if (current->index_ == Label::kNoIndex) { | |
438 while (!available.at(index)) { | |
439 ++index; | |
440 } | |
441 current->index_ = index; | |
442 available.at(index) = false; | |
443 ++index; | |
444 ++fill_infill_count; | |
445 } | |
446 } | |
447 | |
448 VLOG(1) << " fill forward " << fill_forward_count | |
449 << " backward " << fill_backward_count | |
450 << " infill " << fill_infill_count; | |
451 } | |
452 | |
453 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const { | 335 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const { |
454 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram()); | 336 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram()); |
455 | 337 |
456 encoded->set_image_base(image_base_); | 338 encoded->set_image_base(image_base_); |
457 | 339 |
458 if (!encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_)) | 340 if (!encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_)) |
459 return nullptr; | 341 return nullptr; |
460 | 342 |
461 for (size_t i = 0; i < instructions_.size(); ++i) { | 343 for (size_t i = 0; i < instructions_.size(); ++i) { |
462 Instruction* instruction = instructions_[i]; | 344 Instruction* instruction = instructions_[i]; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 Status Encode(const AssemblyProgram& program, | 445 Status Encode(const AssemblyProgram& program, |
564 std::unique_ptr<EncodedProgram>* output) { | 446 std::unique_ptr<EncodedProgram>* output) { |
565 // Explicitly release any memory associated with the output before encoding. | 447 // Explicitly release any memory associated with the output before encoding. |
566 output->reset(); | 448 output->reset(); |
567 | 449 |
568 *output = program.Encode(); | 450 *output = program.Encode(); |
569 return (*output) ? C_OK : C_GENERAL_ERROR; | 451 return (*output) ? C_OK : C_GENERAL_ERROR; |
570 } | 452 } |
571 | 453 |
572 } // namespace courgette | 454 } // namespace courgette |
OLD | NEW |