blob: c3a322caee4e8dd47c6e1c9fb2c17fe9cd6d437f [file] [log] [blame]
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001/*
2 *
3 * Copyright (C) 2014 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000018#include "dex_file.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000019#include "dex_file-inl.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000020#include "dex_instruction.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000021#include "dex_instruction-inl.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000022#include "builder.h"
23#include "nodes.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000024#include "primitive.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000025
26namespace art {
27
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010028void HGraphBuilder::InitializeLocals(uint16_t count) {
29 graph_->SetNumberOfVRegs(count);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000030 locals_.SetSize(count);
31 for (int i = 0; i < count; i++) {
32 HLocal* local = new (arena_) HLocal(i);
33 entry_block_->AddInstruction(local);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000034 locals_.Put(i, local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000035 }
36}
37
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010038bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
39 // dex_compilation_unit_ is null only when unit testing.
40 if (dex_compilation_unit_ == nullptr) {
41 return true;
42 }
43
44 graph_->SetNumberOfInVRegs(number_of_parameters);
45 const char* shorty = dex_compilation_unit_->GetShorty();
46 int locals_index = locals_.Size() - number_of_parameters;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010047 int parameter_index = 0;
48
49 if (!dex_compilation_unit_->IsStatic()) {
50 // Add the implicit 'this' argument, not expressed in the signature.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010051 HParameterValue* parameter =
52 new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010053 entry_block_->AddInstruction(parameter);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010054 HLocal* local = GetLocalAt(locals_index++);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010055 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010056 number_of_parameters--;
57 }
58
59 uint32_t pos = 1;
60 for (int i = 0; i < number_of_parameters; i++) {
61 switch (shorty[pos++]) {
62 case 'F':
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010063 case 'D': {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010064 return false;
65 }
66
67 default: {
68 // integer and reference parameters.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010069 HParameterValue* parameter =
70 new (arena_) HParameterValue(parameter_index++, Primitive::GetType(shorty[pos - 1]));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010071 entry_block_->AddInstruction(parameter);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010072 HLocal* local = GetLocalAt(locals_index++);
73 // Store the parameter value in the local that the dex code will use
74 // to reference that parameter.
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010075 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010076 if (parameter->GetType() == Primitive::kPrimLong) {
77 i++;
78 locals_index++;
79 parameter_index++;
80 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010081 break;
82 }
83 }
84 }
85 return true;
86}
87
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000088static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000089 if (code_item.tries_size_ > 0) {
90 return false;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000091 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000092 return true;
93}
94
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010095template<typename T>
Dave Allison20dfc792014-06-16 20:44:29 -070096void HGraphBuilder::If_22t(const Instruction& instruction, int32_t dex_offset) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010097 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
98 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Dave Allison20dfc792014-06-16 20:44:29 -070099 T* comparison = new (arena_) T(first, second);
100 current_block_->AddInstruction(comparison);
101 HInstruction* ifinst = new (arena_) HIf(comparison);
102 current_block_->AddInstruction(ifinst);
103 HBasicBlock* target = FindBlockStartingAt(dex_offset + instruction.GetTargetOffset());
104 DCHECK(target != nullptr);
105 current_block_->AddSuccessor(target);
106 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
107 DCHECK(target != nullptr);
108 current_block_->AddSuccessor(target);
109 current_block_ = nullptr;
110}
111
112template<typename T>
113void HGraphBuilder::If_21t(const Instruction& instruction, int32_t dex_offset) {
114 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
115 T* comparison = new (arena_) T(value, GetIntConstant(0));
116 current_block_->AddInstruction(comparison);
117 HInstruction* ifinst = new (arena_) HIf(comparison);
118 current_block_->AddInstruction(ifinst);
119 HBasicBlock* target = FindBlockStartingAt(dex_offset + instruction.GetTargetOffset());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100120 DCHECK(target != nullptr);
121 current_block_->AddSuccessor(target);
122 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
123 DCHECK(target != nullptr);
124 current_block_->AddSuccessor(target);
125 current_block_ = nullptr;
126}
127
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000128HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000129 if (!CanHandleCodeItem(code_item)) {
130 return nullptr;
131 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000132
133 const uint16_t* code_ptr = code_item.insns_;
134 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
135
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000136 // Setup the graph with the entry block and exit block.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000137 graph_ = new (arena_) HGraph(arena_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000138 entry_block_ = new (arena_) HBasicBlock(graph_);
139 graph_->AddBlock(entry_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000140 exit_block_ = new (arena_) HBasicBlock(graph_);
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000141 graph_->SetEntryBlock(entry_block_);
142 graph_->SetExitBlock(exit_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000143
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000144 InitializeLocals(code_item.registers_size_);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100145 graph_->UpdateMaximumNumberOfOutVRegs(code_item.outs_size_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000146
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000147 // To avoid splitting blocks, we compute ahead of time the instructions that
148 // start a new block, and create these blocks.
149 ComputeBranchTargets(code_ptr, code_end);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000150
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100151 if (!InitializeParameters(code_item.ins_size_)) {
152 return nullptr;
153 }
154
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000155 size_t dex_offset = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000156 while (code_ptr < code_end) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000157 // Update the current block if dex_offset starts a new block.
158 MaybeUpdateCurrentBlock(dex_offset);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000159 const Instruction& instruction = *Instruction::At(code_ptr);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000160 if (!AnalyzeDexInstruction(instruction, dex_offset)) return nullptr;
161 dex_offset += instruction.SizeInCodeUnits();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000162 code_ptr += instruction.SizeInCodeUnits();
163 }
164
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000165 // Add the exit block at the end to give it the highest id.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000166 graph_->AddBlock(exit_block_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000167 exit_block_->AddInstruction(new (arena_) HExit());
168 entry_block_->AddInstruction(new (arena_) HGoto());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000169 return graph_;
170}
171
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000172void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) {
173 HBasicBlock* block = FindBlockStartingAt(index);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000174 if (block == nullptr) {
175 return;
176 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000177
178 if (current_block_ != nullptr) {
179 // Branching instructions clear current_block, so we know
180 // the last instruction of the current block is not a branching
181 // instruction. We add an unconditional goto to the found block.
182 current_block_->AddInstruction(new (arena_) HGoto());
183 current_block_->AddSuccessor(block);
184 }
185 graph_->AddBlock(block);
186 current_block_ = block;
187}
188
189void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, const uint16_t* code_end) {
190 // TODO: Support switch instructions.
191 branch_targets_.SetSize(code_end - code_ptr);
192
193 // Create the first block for the dex instructions, single successor of the entry block.
194 HBasicBlock* block = new (arena_) HBasicBlock(graph_);
195 branch_targets_.Put(0, block);
196 entry_block_->AddSuccessor(block);
197
198 // Iterate over all instructions and find branching instructions. Create blocks for
199 // the locations these instructions branch to.
200 size_t dex_offset = 0;
201 while (code_ptr < code_end) {
202 const Instruction& instruction = *Instruction::At(code_ptr);
203 if (instruction.IsBranch()) {
204 int32_t target = instruction.GetTargetOffset() + dex_offset;
205 // Create a block for the target instruction.
206 if (FindBlockStartingAt(target) == nullptr) {
207 block = new (arena_) HBasicBlock(graph_);
208 branch_targets_.Put(target, block);
209 }
210 dex_offset += instruction.SizeInCodeUnits();
211 code_ptr += instruction.SizeInCodeUnits();
212 if ((code_ptr < code_end) && (FindBlockStartingAt(dex_offset) == nullptr)) {
213 block = new (arena_) HBasicBlock(graph_);
214 branch_targets_.Put(dex_offset, block);
215 }
216 } else {
217 code_ptr += instruction.SizeInCodeUnits();
218 dex_offset += instruction.SizeInCodeUnits();
219 }
220 }
221}
222
223HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const {
224 DCHECK_GE(index, 0);
225 return branch_targets_.Get(index);
226}
227
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100228template<typename T>
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100229void HGraphBuilder::Binop_32x(const Instruction& instruction, Primitive::Type type) {
230 HInstruction* first = LoadLocal(instruction.VRegB(), type);
231 HInstruction* second = LoadLocal(instruction.VRegC(), type);
232 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100233 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
234}
235
236template<typename T>
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100237void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
238 HInstruction* first = LoadLocal(instruction.VRegA(), type);
239 HInstruction* second = LoadLocal(instruction.VRegB(), type);
240 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100241 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
242}
243
244template<typename T>
245void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100246 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
247 HInstruction* second = GetIntConstant(instruction.VRegC_22s());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100248 if (reverse) {
249 std::swap(first, second);
250 }
251 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
252 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
253}
254
255template<typename T>
256void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100257 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
258 HInstruction* second = GetIntConstant(instruction.VRegC_22b());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100259 if (reverse) {
260 std::swap(first, second);
261 }
262 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
263 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
264}
265
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100266void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
267 if (type == Primitive::kPrimVoid) {
268 current_block_->AddInstruction(new (arena_) HReturnVoid());
269 } else {
270 HInstruction* value = LoadLocal(instruction.VRegA(), type);
271 current_block_->AddInstruction(new (arena_) HReturn(value));
272 }
273 current_block_->AddSuccessor(exit_block_);
274 current_block_ = nullptr;
275}
276
277bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
278 uint32_t dex_offset,
279 uint32_t method_idx,
280 uint32_t number_of_vreg_arguments,
281 bool is_range,
282 uint32_t* args,
283 uint32_t register_index) {
284 const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
285 const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_id.proto_idx_);
286 const char* descriptor = dex_file_->StringDataByIdx(proto_id.shorty_idx_);
287 Primitive::Type return_type = Primitive::GetType(descriptor[0]);
288 bool is_instance_call =
289 instruction.Opcode() != Instruction::INVOKE_STATIC
290 && instruction.Opcode() != Instruction::INVOKE_STATIC_RANGE;
291 const size_t number_of_arguments = strlen(descriptor) - (is_instance_call ? 0 : 1);
292
293 // Treat invoke-direct like static calls for now.
294 HInvoke* invoke = new (arena_) HInvokeStatic(
295 arena_, number_of_arguments, return_type, dex_offset, method_idx);
296
297 size_t start_index = 0;
298 if (is_instance_call) {
299 HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100300 invoke->SetArgumentAt(0, arg);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100301 start_index = 1;
302 }
303
304 uint32_t descriptor_index = 1;
305 uint32_t argument_index = start_index;
306 for (size_t i = start_index; i < number_of_vreg_arguments; i++, argument_index++) {
307 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]);
308 switch (type) {
309 case Primitive::kPrimFloat:
310 case Primitive::kPrimDouble:
311 return false;
312
313 default: {
314 if (!is_range && type == Primitive::kPrimLong && args[i] + 1 != args[i + 1]) {
315 LOG(WARNING) << "Non sequential register pair in " << dex_compilation_unit_->GetSymbol()
316 << " at " << dex_offset;
317 // We do not implement non sequential register pair.
318 return false;
319 }
320 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100321 invoke->SetArgumentAt(argument_index, arg);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100322 if (type == Primitive::kPrimLong) {
323 i++;
324 }
325 }
326 }
327 }
328
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100329 if (return_type == Primitive::kPrimDouble || return_type == Primitive::kPrimFloat) {
330 return false;
331 }
332
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100333 DCHECK_EQ(argument_index, number_of_arguments);
334 current_block_->AddInstruction(invoke);
335 return true;
336}
337
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000338bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000339 if (current_block_ == nullptr) {
340 return true; // Dead code
341 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000342
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000343 switch (instruction.Opcode()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000344 case Instruction::CONST_4: {
345 int32_t register_index = instruction.VRegA();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100346 HIntConstant* constant = GetIntConstant(instruction.VRegB_11n());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000347 UpdateLocal(register_index, constant);
348 break;
349 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000350
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100351 case Instruction::CONST_16: {
352 int32_t register_index = instruction.VRegA();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100353 HIntConstant* constant = GetIntConstant(instruction.VRegB_21s());
354 UpdateLocal(register_index, constant);
355 break;
356 }
357
Dave Allison20dfc792014-06-16 20:44:29 -0700358 case Instruction::CONST: {
359 int32_t register_index = instruction.VRegA();
360 HIntConstant* constant = GetIntConstant(instruction.VRegB_31i());
361 UpdateLocal(register_index, constant);
362 break;
363 }
364
365 case Instruction::CONST_HIGH16: {
366 int32_t register_index = instruction.VRegA();
367 HIntConstant* constant = GetIntConstant(instruction.VRegB_21h() << 16);
368 UpdateLocal(register_index, constant);
369 break;
370 }
371
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100372 case Instruction::CONST_WIDE_16: {
373 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -0700374 // Get 16 bits of constant value, sign extended to 64 bits.
375 int64_t value = instruction.VRegB_21s();
376 value <<= 48;
377 value >>= 48;
378 HLongConstant* constant = GetLongConstant(value);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100379 UpdateLocal(register_index, constant);
380 break;
381 }
382
383 case Instruction::CONST_WIDE_32: {
384 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -0700385 // Get 32 bits of constant value, sign extended to 64 bits.
386 int64_t value = instruction.VRegB_31i();
387 value <<= 32;
388 value >>= 32;
389 HLongConstant* constant = GetLongConstant(value);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100390 UpdateLocal(register_index, constant);
391 break;
392 }
393
394 case Instruction::CONST_WIDE: {
395 int32_t register_index = instruction.VRegA();
396 HLongConstant* constant = GetLongConstant(instruction.VRegB_51l());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100397 UpdateLocal(register_index, constant);
398 break;
399 }
400
Dave Allison20dfc792014-06-16 20:44:29 -0700401 case Instruction::CONST_WIDE_HIGH16: {
402 int32_t register_index = instruction.VRegA();
403 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
404 HLongConstant* constant = GetLongConstant(value);
405 UpdateLocal(register_index, constant);
406 break;
407 }
408
409 // TODO: these instructions are also used to move floating point values, so what is
410 // the type (int or float)?
411 case Instruction::MOVE:
412 case Instruction::MOVE_FROM16:
413 case Instruction::MOVE_16: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100414 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100415 UpdateLocal(instruction.VRegA(), value);
416 break;
417 }
418
Dave Allison20dfc792014-06-16 20:44:29 -0700419 // TODO: these instructions are also used to move floating point values, so what is
420 // the type (long or double)?
421 case Instruction::MOVE_WIDE:
422 case Instruction::MOVE_WIDE_FROM16:
423 case Instruction::MOVE_WIDE_16: {
424 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong);
425 UpdateLocal(instruction.VRegA(), value);
426 break;
427 }
428
429 case Instruction::MOVE_OBJECT:
430 case Instruction::MOVE_OBJECT_16:
431 case Instruction::MOVE_OBJECT_FROM16: {
432 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot);
433 UpdateLocal(instruction.VRegA(), value);
434 break;
435 }
436
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000437 case Instruction::RETURN_VOID: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100438 BuildReturn(instruction, Primitive::kPrimVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000439 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000440 }
441
Dave Allison20dfc792014-06-16 20:44:29 -0700442#define IF_XX(comparison, cond) \
443 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_offset); break; \
444 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_offset); break
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100445
Dave Allison20dfc792014-06-16 20:44:29 -0700446 IF_XX(HEqual, EQ);
447 IF_XX(HNotEqual, NE);
448 IF_XX(HLessThan, LT);
449 IF_XX(HLessThanOrEqual, LE);
450 IF_XX(HGreaterThan, GT);
451 IF_XX(HGreaterThanOrEqual, GE);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000452
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000453 case Instruction::GOTO:
454 case Instruction::GOTO_16:
455 case Instruction::GOTO_32: {
456 HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset);
457 DCHECK(target != nullptr);
458 current_block_->AddInstruction(new (arena_) HGoto());
459 current_block_->AddSuccessor(target);
460 current_block_ = nullptr;
461 break;
462 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000463
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100464 case Instruction::RETURN: {
465 BuildReturn(instruction, Primitive::kPrimInt);
466 break;
467 }
468
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100469 case Instruction::RETURN_OBJECT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100470 BuildReturn(instruction, Primitive::kPrimNot);
471 break;
472 }
473
474 case Instruction::RETURN_WIDE: {
475 BuildReturn(instruction, Primitive::kPrimLong);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000476 break;
477 }
478
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100479 case Instruction::INVOKE_STATIC:
480 case Instruction::INVOKE_DIRECT: {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000481 uint32_t method_idx = instruction.VRegB_35c();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100482 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100483 uint32_t args[5];
Ian Rogers29a26482014-05-02 15:27:29 -0700484 instruction.GetVarArgs(args);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100485 if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) {
486 return false;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100487 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100488 break;
489 }
490
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100491 case Instruction::INVOKE_STATIC_RANGE:
492 case Instruction::INVOKE_DIRECT_RANGE: {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100493 uint32_t method_idx = instruction.VRegB_3rc();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100494 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
495 uint32_t register_index = instruction.VRegC();
496 if (!BuildInvoke(instruction, dex_offset, method_idx,
497 number_of_vreg_arguments, true, nullptr, register_index)) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100498 return false;
499 }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000500 break;
501 }
502
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000503 case Instruction::ADD_INT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100504 Binop_32x<HAdd>(instruction, Primitive::kPrimInt);
505 break;
506 }
507
508 case Instruction::ADD_LONG: {
509 Binop_32x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100510 break;
511 }
512
513 case Instruction::SUB_INT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100514 Binop_32x<HSub>(instruction, Primitive::kPrimInt);
515 break;
516 }
517
518 case Instruction::SUB_LONG: {
519 Binop_32x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000520 break;
521 }
522
523 case Instruction::ADD_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100524 Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
525 break;
526 }
527
528 case Instruction::ADD_LONG_2ADDR: {
529 Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100530 break;
531 }
532
533 case Instruction::SUB_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100534 Binop_12x<HSub>(instruction, Primitive::kPrimInt);
535 break;
536 }
537
538 case Instruction::SUB_LONG_2ADDR: {
539 Binop_12x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000540 break;
541 }
542
543 case Instruction::ADD_INT_LIT16: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100544 Binop_22s<HAdd>(instruction, false);
545 break;
546 }
547
548 case Instruction::RSUB_INT: {
549 Binop_22s<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000550 break;
551 }
552
553 case Instruction::ADD_INT_LIT8: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100554 Binop_22b<HAdd>(instruction, false);
555 break;
556 }
557
558 case Instruction::RSUB_INT_LIT8: {
559 Binop_22b<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000560 break;
561 }
562
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100563 case Instruction::NEW_INSTANCE: {
564 current_block_->AddInstruction(
565 new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c()));
566 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
567 break;
568 }
569
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100570 case Instruction::MOVE_RESULT:
Dave Allison20dfc792014-06-16 20:44:29 -0700571 case Instruction::MOVE_RESULT_WIDE:
572 case Instruction::MOVE_RESULT_OBJECT:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100573 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
574 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100575
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000576 case Instruction::NOP:
577 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000578
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000579 default:
580 return false;
581 }
582 return true;
583}
584
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100585HIntConstant* HGraphBuilder::GetIntConstant0() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000586 if (constant0_ != nullptr) {
587 return constant0_;
588 }
589 constant0_ = new(arena_) HIntConstant(0);
590 entry_block_->AddInstruction(constant0_);
591 return constant0_;
592}
593
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100594HIntConstant* HGraphBuilder::GetIntConstant1() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000595 if (constant1_ != nullptr) {
596 return constant1_;
597 }
598 constant1_ = new(arena_) HIntConstant(1);
599 entry_block_->AddInstruction(constant1_);
600 return constant1_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000601}
602
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100603HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000604 switch (constant) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100605 case 0: return GetIntConstant0();
606 case 1: return GetIntConstant1();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000607 default: {
608 HIntConstant* instruction = new (arena_) HIntConstant(constant);
609 entry_block_->AddInstruction(instruction);
610 return instruction;
611 }
612 }
613}
614
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100615HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) {
616 HLongConstant* instruction = new (arena_) HLongConstant(constant);
617 entry_block_->AddInstruction(instruction);
618 return instruction;
619}
620
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000621HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
622 return locals_.Get(register_index);
623}
624
625void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
626 HLocal* local = GetLocalAt(register_index);
627 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
628}
629
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100630HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000631 HLocal* local = GetLocalAt(register_index);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100632 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000633 return current_block_->GetLastInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000634}
635
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000636} // namespace art