code_generator.cc revision 787c3076635cf117eb646c5a89a9014b2072fb44
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "code_generator.h" 18 19#include "code_generator_arm.h" 20#include "code_generator_x86.h" 21#include "utils/assembler.h" 22 23namespace art { 24 25void CodeGenerator::Compile(CodeAllocator* allocator) { 26 const GrowableArray<HBasicBlock*>* blocks = GetGraph()->GetBlocks(); 27 DCHECK(blocks->Get(0) == GetGraph()->GetEntryBlock()); 28 DCHECK(GoesToNextBlock(GetGraph()->GetEntryBlock(), blocks->Get(1))); 29 CompileEntryBlock(); 30 for (size_t i = 1; i < blocks->Size(); i++) { 31 CompileBlock(blocks->Get(i)); 32 } 33 size_t code_size = GetAssembler()->CodeSize(); 34 uint8_t* buffer = allocator->Allocate(code_size); 35 MemoryRegion code(buffer, code_size); 36 GetAssembler()->FinalizeInstructions(code); 37} 38 39void CodeGenerator::CompileEntryBlock() { 40 HGraphVisitor* location_builder = GetLocationBuilder(); 41 HGraphVisitor* instruction_visitor = GetInstructionVisitor(); 42 // The entry block contains all locals for this method. By visiting the entry block, 43 // we're computing the required frame size. 44 for (HInstructionIterator it(GetGraph()->GetEntryBlock()); !it.Done(); it.Advance()) { 45 HInstruction* current = it.Current(); 46 // Instructions in the entry block should not generate code. 47 if (kIsDebugBuild) { 48 current->Accept(location_builder); 49 DCHECK(current->GetLocations() == nullptr); 50 } 51 current->Accept(instruction_visitor); 52 } 53 GenerateFrameEntry(); 54} 55 56void CodeGenerator::CompileBlock(HBasicBlock* block) { 57 Bind(GetLabelOf(block)); 58 HGraphVisitor* location_builder = GetLocationBuilder(); 59 HGraphVisitor* instruction_visitor = GetInstructionVisitor(); 60 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { 61 // For each instruction, we emulate a stack-based machine, where the inputs are popped from 62 // the runtime stack, and the result is pushed on the stack. We currently can do this because 63 // we do not perform any code motion, and the Dex format does not reference individual 64 // instructions but uses registers instead (our equivalent of HLocal). 65 HInstruction* current = it.Current(); 66 current->Accept(location_builder); 67 InitLocations(current); 68 current->Accept(instruction_visitor); 69 if (current->GetLocations() != nullptr && current->GetLocations()->Out().IsValid()) { 70 Push(current, current->GetLocations()->Out()); 71 } 72 } 73} 74 75void CodeGenerator::InitLocations(HInstruction* instruction) { 76 if (instruction->GetLocations() == nullptr) return; 77 for (int i = 0; i < instruction->InputCount(); i++) { 78 Location location = instruction->GetLocations()->InAt(i); 79 if (location.IsValid()) { 80 // Move the input to the desired location. 81 Move(instruction->InputAt(i), location); 82 } 83 } 84} 85 86bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const { 87 // We currently iterate over the block in insertion order. 88 return current->GetBlockId() + 1 == next->GetBlockId(); 89} 90 91Label* CodeGenerator::GetLabelOf(HBasicBlock* block) const { 92 return block_labels_.GetRawStorage() + block->GetBlockId(); 93} 94 95CodeGenerator* CodeGenerator::Create(ArenaAllocator* allocator, 96 HGraph* graph, 97 InstructionSet instruction_set) { 98 switch (instruction_set) { 99 case kArm: 100 case kThumb2: { 101 return new (allocator) arm::CodeGeneratorARM(graph); 102 } 103 case kMips: 104 return nullptr; 105 case kX86: { 106 return new (allocator) x86::CodeGeneratorX86(graph); 107 } 108 default: 109 return nullptr; 110 } 111} 112 113} // namespace art 114