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