blob: c96792c90351e1ec4c5db7cad3cc94a22d8dd4b9 [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 Geoffraye5038322014-07-04 09:41:32 +010018#include "builder.h"
19
20#include "class_linker.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000021#include "dex_file.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000022#include "dex_file-inl.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000023#include "dex_instruction.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000024#include "dex_instruction-inl.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010025#include "driver/compiler_driver-inl.h"
26#include "mirror/art_field.h"
27#include "mirror/art_field-inl.h"
28#include "mirror/class_loader.h"
29#include "mirror/dex_cache.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000030#include "nodes.h"
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +000031#include "primitive.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010032#include "scoped_thread_state_change.h"
33#include "thread.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000034
35namespace art {
36
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010037void HGraphBuilder::InitializeLocals(uint16_t count) {
38 graph_->SetNumberOfVRegs(count);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000039 locals_.SetSize(count);
40 for (int i = 0; i < count; i++) {
41 HLocal* local = new (arena_) HLocal(i);
42 entry_block_->AddInstruction(local);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000043 locals_.Put(i, local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000044 }
45}
46
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010047bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) {
48 // dex_compilation_unit_ is null only when unit testing.
49 if (dex_compilation_unit_ == nullptr) {
50 return true;
51 }
52
53 graph_->SetNumberOfInVRegs(number_of_parameters);
54 const char* shorty = dex_compilation_unit_->GetShorty();
55 int locals_index = locals_.Size() - number_of_parameters;
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010056 int parameter_index = 0;
57
58 if (!dex_compilation_unit_->IsStatic()) {
59 // Add the implicit 'this' argument, not expressed in the signature.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010060 HParameterValue* parameter =
61 new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010062 entry_block_->AddInstruction(parameter);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010063 HLocal* local = GetLocalAt(locals_index++);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010064 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010065 number_of_parameters--;
66 }
67
68 uint32_t pos = 1;
69 for (int i = 0; i < number_of_parameters; i++) {
70 switch (shorty[pos++]) {
71 case 'F':
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010072 case 'D': {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010073 return false;
74 }
75
76 default: {
77 // integer and reference parameters.
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010078 HParameterValue* parameter =
79 new (arena_) HParameterValue(parameter_index++, Primitive::GetType(shorty[pos - 1]));
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010080 entry_block_->AddInstruction(parameter);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010081 HLocal* local = GetLocalAt(locals_index++);
82 // Store the parameter value in the local that the dex code will use
83 // to reference that parameter.
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010084 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010085 if (parameter->GetType() == Primitive::kPrimLong) {
86 i++;
87 locals_index++;
88 parameter_index++;
89 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010090 break;
91 }
92 }
93 }
94 return true;
95}
96
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000097static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000098 if (code_item.tries_size_ > 0) {
99 return false;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000100 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000101 return true;
102}
103
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100104template<typename T>
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100105void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_offset) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100106 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
107 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Dave Allison20dfc792014-06-16 20:44:29 -0700108 T* comparison = new (arena_) T(first, second);
109 current_block_->AddInstruction(comparison);
110 HInstruction* ifinst = new (arena_) HIf(comparison);
111 current_block_->AddInstruction(ifinst);
112 HBasicBlock* target = FindBlockStartingAt(dex_offset + instruction.GetTargetOffset());
113 DCHECK(target != nullptr);
114 current_block_->AddSuccessor(target);
115 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
116 DCHECK(target != nullptr);
117 current_block_->AddSuccessor(target);
118 current_block_ = nullptr;
119}
120
121template<typename T>
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100122void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_offset) {
Dave Allison20dfc792014-06-16 20:44:29 -0700123 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
124 T* comparison = new (arena_) T(value, GetIntConstant(0));
125 current_block_->AddInstruction(comparison);
126 HInstruction* ifinst = new (arena_) HIf(comparison);
127 current_block_->AddInstruction(ifinst);
128 HBasicBlock* target = FindBlockStartingAt(dex_offset + instruction.GetTargetOffset());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100129 DCHECK(target != nullptr);
130 current_block_->AddSuccessor(target);
131 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
132 DCHECK(target != nullptr);
133 current_block_->AddSuccessor(target);
134 current_block_ = nullptr;
135}
136
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000137HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000138 if (!CanHandleCodeItem(code_item)) {
139 return nullptr;
140 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000141
142 const uint16_t* code_ptr = code_item.insns_;
143 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
144
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000145 // Setup the graph with the entry block and exit block.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000146 graph_ = new (arena_) HGraph(arena_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000147 entry_block_ = new (arena_) HBasicBlock(graph_);
148 graph_->AddBlock(entry_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000149 exit_block_ = new (arena_) HBasicBlock(graph_);
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000150 graph_->SetEntryBlock(entry_block_);
151 graph_->SetExitBlock(exit_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000152
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000153 InitializeLocals(code_item.registers_size_);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100154 graph_->UpdateMaximumNumberOfOutVRegs(code_item.outs_size_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000155
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000156 // To avoid splitting blocks, we compute ahead of time the instructions that
157 // start a new block, and create these blocks.
158 ComputeBranchTargets(code_ptr, code_end);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000159
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100160 if (!InitializeParameters(code_item.ins_size_)) {
161 return nullptr;
162 }
163
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000164 size_t dex_offset = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000165 while (code_ptr < code_end) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000166 // Update the current block if dex_offset starts a new block.
167 MaybeUpdateCurrentBlock(dex_offset);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000168 const Instruction& instruction = *Instruction::At(code_ptr);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000169 if (!AnalyzeDexInstruction(instruction, dex_offset)) return nullptr;
170 dex_offset += instruction.SizeInCodeUnits();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000171 code_ptr += instruction.SizeInCodeUnits();
172 }
173
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000174 // Add the exit block at the end to give it the highest id.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000175 graph_->AddBlock(exit_block_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000176 exit_block_->AddInstruction(new (arena_) HExit());
177 entry_block_->AddInstruction(new (arena_) HGoto());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000178 return graph_;
179}
180
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000181void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) {
182 HBasicBlock* block = FindBlockStartingAt(index);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000183 if (block == nullptr) {
184 return;
185 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000186
187 if (current_block_ != nullptr) {
188 // Branching instructions clear current_block, so we know
189 // the last instruction of the current block is not a branching
190 // instruction. We add an unconditional goto to the found block.
191 current_block_->AddInstruction(new (arena_) HGoto());
192 current_block_->AddSuccessor(block);
193 }
194 graph_->AddBlock(block);
195 current_block_ = block;
196}
197
198void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, const uint16_t* code_end) {
199 // TODO: Support switch instructions.
200 branch_targets_.SetSize(code_end - code_ptr);
201
202 // Create the first block for the dex instructions, single successor of the entry block.
203 HBasicBlock* block = new (arena_) HBasicBlock(graph_);
204 branch_targets_.Put(0, block);
205 entry_block_->AddSuccessor(block);
206
207 // Iterate over all instructions and find branching instructions. Create blocks for
208 // the locations these instructions branch to.
209 size_t dex_offset = 0;
210 while (code_ptr < code_end) {
211 const Instruction& instruction = *Instruction::At(code_ptr);
212 if (instruction.IsBranch()) {
213 int32_t target = instruction.GetTargetOffset() + dex_offset;
214 // Create a block for the target instruction.
215 if (FindBlockStartingAt(target) == nullptr) {
216 block = new (arena_) HBasicBlock(graph_);
217 branch_targets_.Put(target, block);
218 }
219 dex_offset += instruction.SizeInCodeUnits();
220 code_ptr += instruction.SizeInCodeUnits();
221 if ((code_ptr < code_end) && (FindBlockStartingAt(dex_offset) == nullptr)) {
222 block = new (arena_) HBasicBlock(graph_);
223 branch_targets_.Put(dex_offset, block);
224 }
225 } else {
226 code_ptr += instruction.SizeInCodeUnits();
227 dex_offset += instruction.SizeInCodeUnits();
228 }
229 }
230}
231
232HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const {
233 DCHECK_GE(index, 0);
234 return branch_targets_.Get(index);
235}
236
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100237template<typename T>
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100238void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100239 HInstruction* first = LoadLocal(instruction.VRegB(), type);
240 HInstruction* second = LoadLocal(instruction.VRegC(), type);
241 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100242 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
243}
244
245template<typename T>
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100246void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
247 HInstruction* first = LoadLocal(instruction.VRegA(), type);
248 HInstruction* second = LoadLocal(instruction.VRegB(), type);
249 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100250 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
251}
252
253template<typename T>
254void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100255 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
256 HInstruction* second = GetIntConstant(instruction.VRegC_22s());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100257 if (reverse) {
258 std::swap(first, second);
259 }
260 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
261 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
262}
263
264template<typename T>
265void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100266 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
267 HInstruction* second = GetIntConstant(instruction.VRegC_22b());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100268 if (reverse) {
269 std::swap(first, second);
270 }
271 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
272 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
273}
274
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100275void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
276 if (type == Primitive::kPrimVoid) {
277 current_block_->AddInstruction(new (arena_) HReturnVoid());
278 } else {
279 HInstruction* value = LoadLocal(instruction.VRegA(), type);
280 current_block_->AddInstruction(new (arena_) HReturn(value));
281 }
282 current_block_->AddSuccessor(exit_block_);
283 current_block_ = nullptr;
284}
285
286bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
287 uint32_t dex_offset,
288 uint32_t method_idx,
289 uint32_t number_of_vreg_arguments,
290 bool is_range,
291 uint32_t* args,
292 uint32_t register_index) {
293 const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
294 const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_id.proto_idx_);
295 const char* descriptor = dex_file_->StringDataByIdx(proto_id.shorty_idx_);
296 Primitive::Type return_type = Primitive::GetType(descriptor[0]);
297 bool is_instance_call =
298 instruction.Opcode() != Instruction::INVOKE_STATIC
299 && instruction.Opcode() != Instruction::INVOKE_STATIC_RANGE;
300 const size_t number_of_arguments = strlen(descriptor) - (is_instance_call ? 0 : 1);
301
302 // Treat invoke-direct like static calls for now.
303 HInvoke* invoke = new (arena_) HInvokeStatic(
304 arena_, number_of_arguments, return_type, dex_offset, method_idx);
305
306 size_t start_index = 0;
307 if (is_instance_call) {
308 HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100309 invoke->SetArgumentAt(0, arg);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100310 start_index = 1;
311 }
312
313 uint32_t descriptor_index = 1;
314 uint32_t argument_index = start_index;
315 for (size_t i = start_index; i < number_of_vreg_arguments; i++, argument_index++) {
316 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]);
317 switch (type) {
318 case Primitive::kPrimFloat:
319 case Primitive::kPrimDouble:
320 return false;
321
322 default: {
323 if (!is_range && type == Primitive::kPrimLong && args[i] + 1 != args[i + 1]) {
324 LOG(WARNING) << "Non sequential register pair in " << dex_compilation_unit_->GetSymbol()
325 << " at " << dex_offset;
326 // We do not implement non sequential register pair.
327 return false;
328 }
329 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100330 invoke->SetArgumentAt(argument_index, arg);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100331 if (type == Primitive::kPrimLong) {
332 i++;
333 }
334 }
335 }
336 }
337
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100338 if (return_type == Primitive::kPrimDouble || return_type == Primitive::kPrimFloat) {
339 return false;
340 }
341
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100342 DCHECK_EQ(argument_index, number_of_arguments);
343 current_block_->AddInstruction(invoke);
344 return true;
345}
346
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100347/**
348 * Helper class to add HTemporary instructions. This class is used when
349 * converting a DEX instruction to multiple HInstruction, and where those
350 * instructions do not die at the following instruction, but instead spans
351 * multiple instructions.
352 */
353class Temporaries : public ValueObject {
354 public:
355 Temporaries(HGraph* graph, size_t count) : graph_(graph), count_(count), index_(0) {
356 graph_->UpdateNumberOfTemporaries(count_);
357 }
358
359 void Add(HInstruction* instruction) {
360 // We currently only support vreg size temps.
361 DCHECK(instruction->GetType() != Primitive::kPrimLong
362 && instruction->GetType() != Primitive::kPrimDouble);
363 HInstruction* temp = new (graph_->GetArena()) HTemporary(index_++);
364 instruction->GetBlock()->AddInstruction(temp);
365 DCHECK(temp->GetPrevious() == instruction);
366 }
367
368 private:
369 HGraph* const graph_;
370
371 // The total number of temporaries that will be used.
372 const size_t count_;
373
374 // Current index in the temporary stack, updated by `Add`.
375 size_t index_;
376};
377
378bool HGraphBuilder::BuildFieldAccess(const Instruction& instruction,
379 uint32_t dex_offset,
380 bool is_put) {
381 uint32_t source_or_dest_reg = instruction.VRegA_22c();
382 uint32_t obj_reg = instruction.VRegB_22c();
383 uint16_t field_index = instruction.VRegC_22c();
384
385 ScopedObjectAccess soa(Thread::Current());
386 StackHandleScope<1> hs(soa.Self());
387 Handle<mirror::ArtField> resolved_field(hs.NewHandle(
388 compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa)));
389
390 if (resolved_field.Get() == nullptr) {
391 return false;
392 }
393 if (resolved_field->IsVolatile()) {
394 return false;
395 }
396
397 HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot);
398 current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_offset));
399 if (is_put) {
400 Temporaries temps(graph_, 1);
401 HInstruction* null_check = current_block_->GetLastInstruction();
402 // We need one temporary for the null check.
403 temps.Add(null_check);
404 HInstruction* value = LoadLocal(source_or_dest_reg, resolved_field->GetTypeAsPrimitiveType());
405 current_block_->AddInstruction(new (arena_) HInstanceFieldSet(
406 null_check,
407 value,
408 resolved_field->GetOffset()));
409 } else {
410 current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
411 current_block_->GetLastInstruction(),
412 resolved_field->GetTypeAsPrimitiveType(),
413 resolved_field->GetOffset()));
414
415 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
416 }
417 return true;
418}
419
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000420bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000421 if (current_block_ == nullptr) {
422 return true; // Dead code
423 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000424
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000425 switch (instruction.Opcode()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000426 case Instruction::CONST_4: {
427 int32_t register_index = instruction.VRegA();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100428 HIntConstant* constant = GetIntConstant(instruction.VRegB_11n());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000429 UpdateLocal(register_index, constant);
430 break;
431 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000432
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100433 case Instruction::CONST_16: {
434 int32_t register_index = instruction.VRegA();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100435 HIntConstant* constant = GetIntConstant(instruction.VRegB_21s());
436 UpdateLocal(register_index, constant);
437 break;
438 }
439
Dave Allison20dfc792014-06-16 20:44:29 -0700440 case Instruction::CONST: {
441 int32_t register_index = instruction.VRegA();
442 HIntConstant* constant = GetIntConstant(instruction.VRegB_31i());
443 UpdateLocal(register_index, constant);
444 break;
445 }
446
447 case Instruction::CONST_HIGH16: {
448 int32_t register_index = instruction.VRegA();
449 HIntConstant* constant = GetIntConstant(instruction.VRegB_21h() << 16);
450 UpdateLocal(register_index, constant);
451 break;
452 }
453
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100454 case Instruction::CONST_WIDE_16: {
455 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -0700456 // Get 16 bits of constant value, sign extended to 64 bits.
457 int64_t value = instruction.VRegB_21s();
458 value <<= 48;
459 value >>= 48;
460 HLongConstant* constant = GetLongConstant(value);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100461 UpdateLocal(register_index, constant);
462 break;
463 }
464
465 case Instruction::CONST_WIDE_32: {
466 int32_t register_index = instruction.VRegA();
Dave Allison20dfc792014-06-16 20:44:29 -0700467 // Get 32 bits of constant value, sign extended to 64 bits.
468 int64_t value = instruction.VRegB_31i();
469 value <<= 32;
470 value >>= 32;
471 HLongConstant* constant = GetLongConstant(value);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100472 UpdateLocal(register_index, constant);
473 break;
474 }
475
476 case Instruction::CONST_WIDE: {
477 int32_t register_index = instruction.VRegA();
478 HLongConstant* constant = GetLongConstant(instruction.VRegB_51l());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100479 UpdateLocal(register_index, constant);
480 break;
481 }
482
Dave Allison20dfc792014-06-16 20:44:29 -0700483 case Instruction::CONST_WIDE_HIGH16: {
484 int32_t register_index = instruction.VRegA();
485 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
486 HLongConstant* constant = GetLongConstant(value);
487 UpdateLocal(register_index, constant);
488 break;
489 }
490
491 // TODO: these instructions are also used to move floating point values, so what is
492 // the type (int or float)?
493 case Instruction::MOVE:
494 case Instruction::MOVE_FROM16:
495 case Instruction::MOVE_16: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100496 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100497 UpdateLocal(instruction.VRegA(), value);
498 break;
499 }
500
Dave Allison20dfc792014-06-16 20:44:29 -0700501 // TODO: these instructions are also used to move floating point values, so what is
502 // the type (long or double)?
503 case Instruction::MOVE_WIDE:
504 case Instruction::MOVE_WIDE_FROM16:
505 case Instruction::MOVE_WIDE_16: {
506 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong);
507 UpdateLocal(instruction.VRegA(), value);
508 break;
509 }
510
511 case Instruction::MOVE_OBJECT:
512 case Instruction::MOVE_OBJECT_16:
513 case Instruction::MOVE_OBJECT_FROM16: {
514 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot);
515 UpdateLocal(instruction.VRegA(), value);
516 break;
517 }
518
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000519 case Instruction::RETURN_VOID: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100520 BuildReturn(instruction, Primitive::kPrimVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000521 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000522 }
523
Dave Allison20dfc792014-06-16 20:44:29 -0700524#define IF_XX(comparison, cond) \
525 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_offset); break; \
526 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_offset); break
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100527
Dave Allison20dfc792014-06-16 20:44:29 -0700528 IF_XX(HEqual, EQ);
529 IF_XX(HNotEqual, NE);
530 IF_XX(HLessThan, LT);
531 IF_XX(HLessThanOrEqual, LE);
532 IF_XX(HGreaterThan, GT);
533 IF_XX(HGreaterThanOrEqual, GE);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000534
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000535 case Instruction::GOTO:
536 case Instruction::GOTO_16:
537 case Instruction::GOTO_32: {
538 HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset);
539 DCHECK(target != nullptr);
540 current_block_->AddInstruction(new (arena_) HGoto());
541 current_block_->AddSuccessor(target);
542 current_block_ = nullptr;
543 break;
544 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000545
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100546 case Instruction::RETURN: {
547 BuildReturn(instruction, Primitive::kPrimInt);
548 break;
549 }
550
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100551 case Instruction::RETURN_OBJECT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100552 BuildReturn(instruction, Primitive::kPrimNot);
553 break;
554 }
555
556 case Instruction::RETURN_WIDE: {
557 BuildReturn(instruction, Primitive::kPrimLong);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000558 break;
559 }
560
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100561 case Instruction::INVOKE_STATIC:
562 case Instruction::INVOKE_DIRECT: {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000563 uint32_t method_idx = instruction.VRegB_35c();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100564 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100565 uint32_t args[5];
Ian Rogers29a26482014-05-02 15:27:29 -0700566 instruction.GetVarArgs(args);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100567 if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) {
568 return false;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100569 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100570 break;
571 }
572
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100573 case Instruction::INVOKE_STATIC_RANGE:
574 case Instruction::INVOKE_DIRECT_RANGE: {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100575 uint32_t method_idx = instruction.VRegB_3rc();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100576 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
577 uint32_t register_index = instruction.VRegC();
578 if (!BuildInvoke(instruction, dex_offset, method_idx,
579 number_of_vreg_arguments, true, nullptr, register_index)) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100580 return false;
581 }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000582 break;
583 }
584
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000585 case Instruction::ADD_INT: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100586 Binop_23x<HAdd>(instruction, Primitive::kPrimInt);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100587 break;
588 }
589
590 case Instruction::ADD_LONG: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100591 Binop_23x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100592 break;
593 }
594
595 case Instruction::SUB_INT: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100596 Binop_23x<HSub>(instruction, Primitive::kPrimInt);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100597 break;
598 }
599
600 case Instruction::SUB_LONG: {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100601 Binop_23x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000602 break;
603 }
604
605 case Instruction::ADD_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100606 Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
607 break;
608 }
609
610 case Instruction::ADD_LONG_2ADDR: {
611 Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100612 break;
613 }
614
615 case Instruction::SUB_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100616 Binop_12x<HSub>(instruction, Primitive::kPrimInt);
617 break;
618 }
619
620 case Instruction::SUB_LONG_2ADDR: {
621 Binop_12x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000622 break;
623 }
624
625 case Instruction::ADD_INT_LIT16: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100626 Binop_22s<HAdd>(instruction, false);
627 break;
628 }
629
630 case Instruction::RSUB_INT: {
631 Binop_22s<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000632 break;
633 }
634
635 case Instruction::ADD_INT_LIT8: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100636 Binop_22b<HAdd>(instruction, false);
637 break;
638 }
639
640 case Instruction::RSUB_INT_LIT8: {
641 Binop_22b<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000642 break;
643 }
644
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100645 case Instruction::NEW_INSTANCE: {
646 current_block_->AddInstruction(
647 new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c()));
648 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
649 break;
650 }
651
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100652 case Instruction::MOVE_RESULT:
Dave Allison20dfc792014-06-16 20:44:29 -0700653 case Instruction::MOVE_RESULT_WIDE:
654 case Instruction::MOVE_RESULT_OBJECT:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100655 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
656 break;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100657
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100658 case Instruction::CMP_LONG: {
659 Binop_23x<HCompare>(instruction, Primitive::kPrimLong);
660 break;
661 }
662
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000663 case Instruction::NOP:
664 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000665
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100666 case Instruction::IGET:
667 case Instruction::IGET_WIDE:
668 case Instruction::IGET_OBJECT:
669 case Instruction::IGET_BOOLEAN:
670 case Instruction::IGET_BYTE:
671 case Instruction::IGET_CHAR:
672 case Instruction::IGET_SHORT: {
673 if (!BuildFieldAccess(instruction, dex_offset, false)) {
674 return false;
675 }
676 break;
677 }
678
679 case Instruction::IPUT:
680 case Instruction::IPUT_WIDE:
681 case Instruction::IPUT_OBJECT:
682 case Instruction::IPUT_BOOLEAN:
683 case Instruction::IPUT_BYTE:
684 case Instruction::IPUT_CHAR:
685 case Instruction::IPUT_SHORT: {
686 if (!BuildFieldAccess(instruction, dex_offset, true)) {
687 return false;
688 }
689 break;
690 }
691
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000692 default:
693 return false;
694 }
695 return true;
696}
697
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100698HIntConstant* HGraphBuilder::GetIntConstant0() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000699 if (constant0_ != nullptr) {
700 return constant0_;
701 }
702 constant0_ = new(arena_) HIntConstant(0);
703 entry_block_->AddInstruction(constant0_);
704 return constant0_;
705}
706
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100707HIntConstant* HGraphBuilder::GetIntConstant1() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000708 if (constant1_ != nullptr) {
709 return constant1_;
710 }
711 constant1_ = new(arena_) HIntConstant(1);
712 entry_block_->AddInstruction(constant1_);
713 return constant1_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000714}
715
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100716HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000717 switch (constant) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100718 case 0: return GetIntConstant0();
719 case 1: return GetIntConstant1();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000720 default: {
721 HIntConstant* instruction = new (arena_) HIntConstant(constant);
722 entry_block_->AddInstruction(instruction);
723 return instruction;
724 }
725 }
726}
727
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100728HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) {
729 HLongConstant* instruction = new (arena_) HLongConstant(constant);
730 entry_block_->AddInstruction(instruction);
731 return instruction;
732}
733
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000734HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
735 return locals_.Get(register_index);
736}
737
738void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
739 HLocal* local = GetLocalAt(register_index);
740 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
741}
742
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100743HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000744 HLocal* local = GetLocalAt(register_index);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100745 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000746 return current_block_->GetLastInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000747}
748
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000749} // namespace art