code_generator_x86.cc revision bab4ed7057799a4fadc6283108ab56f389d117d4
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_x86.h" 18#include "utils/assembler.h" 19#include "utils/x86/assembler_x86.h" 20 21#define __ reinterpret_cast<X86Assembler*>(assembler())-> 22 23namespace art { 24namespace x86 { 25 26void CodeGeneratorX86::GenerateFrameEntry() { 27 __ pushl(EBP); 28 __ movl(EBP, ESP); 29 30 if (frame_size_ != 0) { 31 __ subl(ESP, Immediate(frame_size_)); 32 } 33} 34 35void CodeGeneratorX86::GenerateFrameExit() { 36 __ movl(ESP, EBP); 37 __ popl(EBP); 38} 39 40void CodeGeneratorX86::Bind(Label* label) { 41 __ Bind(label); 42} 43 44void CodeGeneratorX86::Push(HInstruction* instruction, Location location) { 45 __ pushl(location.reg<Register>()); 46} 47 48void CodeGeneratorX86::Move(HInstruction* instruction, Location location) { 49 HIntConstant* constant = instruction->AsIntConstant(); 50 if (constant != nullptr) { 51 __ movl(location.reg<Register>(), Immediate(constant->value())); 52 } else { 53 __ popl(location.reg<Register>()); 54 } 55} 56 57void LocationsBuilderX86::VisitGoto(HGoto* got) { 58 got->set_locations(nullptr); 59} 60 61void CodeGeneratorX86::VisitGoto(HGoto* got) { 62 HBasicBlock* successor = got->GetSuccessor(); 63 if (graph()->exit_block() == successor) { 64 GenerateFrameExit(); 65 } else if (!GoesToNextBlock(got->block(), successor)) { 66 __ jmp(GetLabelOf(successor)); 67 } 68} 69 70void LocationsBuilderX86::VisitExit(HExit* exit) { 71 exit->set_locations(nullptr); 72} 73 74void CodeGeneratorX86::VisitExit(HExit* exit) { 75 if (kIsDebugBuild) { 76 __ Comment("Unreachable"); 77 __ int3(); 78 } 79} 80 81void LocationsBuilderX86::VisitIf(HIf* if_instr) { 82 LocationSummary* locations = new (graph()->arena()) LocationSummary(if_instr); 83 locations->SetInAt(0, Location(EAX)); 84 if_instr->set_locations(locations); 85} 86 87void CodeGeneratorX86::VisitIf(HIf* if_instr) { 88 // TODO: Generate the input as a condition, instead of materializing in a register. 89 __ cmpl(if_instr->locations()->InAt(0).reg<Register>(), Immediate(0)); 90 __ j(kEqual, GetLabelOf(if_instr->IfFalseSuccessor())); 91 if (!GoesToNextBlock(if_instr->block(), if_instr->IfTrueSuccessor())) { 92 __ jmp(GetLabelOf(if_instr->IfTrueSuccessor())); 93 } 94} 95 96void LocationsBuilderX86::VisitLocal(HLocal* local) { 97 local->set_locations(nullptr); 98} 99 100void CodeGeneratorX86::VisitLocal(HLocal* local) { 101 DCHECK_EQ(local->block(), graph()->entry_block()); 102 frame_size_ += kWordSize; 103} 104 105void LocationsBuilderX86::VisitLoadLocal(HLoadLocal* local) { 106 LocationSummary* locations = new (graph()->arena()) LocationSummary(local); 107 locations->SetOut(Location(EAX)); 108 local->set_locations(locations); 109} 110 111static int32_t GetStackSlot(HLocal* local) { 112 // We are currently using EBP to access locals, so the offset must be negative. 113 return (local->reg_number() + 1) * -kWordSize; 114} 115 116void CodeGeneratorX86::VisitLoadLocal(HLoadLocal* load) { 117 __ movl(load->locations()->Out().reg<Register>(), 118 Address(EBP, GetStackSlot(load->GetLocal()))); 119} 120 121void LocationsBuilderX86::VisitStoreLocal(HStoreLocal* local) { 122 LocationSummary* locations = new (graph()->arena()) LocationSummary(local); 123 locations->SetInAt(1, Location(EAX)); 124 local->set_locations(locations); 125} 126 127void CodeGeneratorX86::VisitStoreLocal(HStoreLocal* store) { 128 __ movl(Address(EBP, GetStackSlot(store->GetLocal())), 129 store->locations()->InAt(1).reg<Register>()); 130} 131 132void LocationsBuilderX86::VisitEqual(HEqual* equal) { 133 LocationSummary* locations = new (graph()->arena()) LocationSummary(equal); 134 locations->SetInAt(0, Location(EAX)); 135 locations->SetInAt(1, Location(ECX)); 136 locations->SetOut(Location(EAX)); 137 equal->set_locations(locations); 138} 139 140void CodeGeneratorX86::VisitEqual(HEqual* equal) { 141 __ cmpl(equal->locations()->InAt(0).reg<Register>(), 142 equal->locations()->InAt(1).reg<Register>()); 143 __ setb(kEqual, equal->locations()->Out().reg<Register>()); 144} 145 146void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) { 147 constant->set_locations(nullptr); 148} 149 150void CodeGeneratorX86::VisitIntConstant(HIntConstant* constant) { 151 // Will be generated at use site. 152} 153 154void LocationsBuilderX86::VisitReturnVoid(HReturnVoid* ret) { 155 ret->set_locations(nullptr); 156} 157 158void CodeGeneratorX86::VisitReturnVoid(HReturnVoid* ret) { 159 GenerateFrameExit(); 160 __ ret(); 161} 162 163void LocationsBuilderX86::VisitReturn(HReturn* ret) { 164 LocationSummary* locations = new (graph()->arena()) LocationSummary(ret); 165 locations->SetInAt(0, Location(EAX)); 166 ret->set_locations(locations); 167} 168 169void CodeGeneratorX86::VisitReturn(HReturn* ret) { 170 DCHECK_EQ(ret->locations()->InAt(0).reg<Register>(), EAX); 171 GenerateFrameExit(); 172 __ ret(); 173} 174 175} // namespace x86 176} // namespace art 177