blob: b0aa63bb3e02b87a4df29994cc0d60cbc9a87b07 [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>
96void HGraphBuilder::If_22t(const Instruction& instruction, int32_t dex_offset, bool is_not) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +010097 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
98 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +010099 current_block_->AddInstruction(new (arena_) T(first, second));
100 if (is_not) {
101 current_block_->AddInstruction(new (arena_) HNot(current_block_->GetLastInstruction()));
102 }
103 current_block_->AddInstruction(new (arena_) HIf(current_block_->GetLastInstruction()));
104 HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset);
105 DCHECK(target != nullptr);
106 current_block_->AddSuccessor(target);
107 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits());
108 DCHECK(target != nullptr);
109 current_block_->AddSuccessor(target);
110 current_block_ = nullptr;
111}
112
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000113HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000114 if (!CanHandleCodeItem(code_item)) {
115 return nullptr;
116 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000117
118 const uint16_t* code_ptr = code_item.insns_;
119 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_;
120
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000121 // Setup the graph with the entry block and exit block.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000122 graph_ = new (arena_) HGraph(arena_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000123 entry_block_ = new (arena_) HBasicBlock(graph_);
124 graph_->AddBlock(entry_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000125 exit_block_ = new (arena_) HBasicBlock(graph_);
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000126 graph_->SetEntryBlock(entry_block_);
127 graph_->SetExitBlock(exit_block_);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000128
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000129 InitializeLocals(code_item.registers_size_);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100130 graph_->UpdateMaximumNumberOfOutVRegs(code_item.outs_size_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000131
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000132 // To avoid splitting blocks, we compute ahead of time the instructions that
133 // start a new block, and create these blocks.
134 ComputeBranchTargets(code_ptr, code_end);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000135
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100136 if (!InitializeParameters(code_item.ins_size_)) {
137 return nullptr;
138 }
139
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000140 size_t dex_offset = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000141 while (code_ptr < code_end) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000142 // Update the current block if dex_offset starts a new block.
143 MaybeUpdateCurrentBlock(dex_offset);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000144 const Instruction& instruction = *Instruction::At(code_ptr);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000145 if (!AnalyzeDexInstruction(instruction, dex_offset)) return nullptr;
146 dex_offset += instruction.SizeInCodeUnits();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000147 code_ptr += instruction.SizeInCodeUnits();
148 }
149
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000150 // Add the exit block at the end to give it the highest id.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000151 graph_->AddBlock(exit_block_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000152 exit_block_->AddInstruction(new (arena_) HExit());
153 entry_block_->AddInstruction(new (arena_) HGoto());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000154 return graph_;
155}
156
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000157void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) {
158 HBasicBlock* block = FindBlockStartingAt(index);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000159 if (block == nullptr) {
160 return;
161 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000162
163 if (current_block_ != nullptr) {
164 // Branching instructions clear current_block, so we know
165 // the last instruction of the current block is not a branching
166 // instruction. We add an unconditional goto to the found block.
167 current_block_->AddInstruction(new (arena_) HGoto());
168 current_block_->AddSuccessor(block);
169 }
170 graph_->AddBlock(block);
171 current_block_ = block;
172}
173
174void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, const uint16_t* code_end) {
175 // TODO: Support switch instructions.
176 branch_targets_.SetSize(code_end - code_ptr);
177
178 // Create the first block for the dex instructions, single successor of the entry block.
179 HBasicBlock* block = new (arena_) HBasicBlock(graph_);
180 branch_targets_.Put(0, block);
181 entry_block_->AddSuccessor(block);
182
183 // Iterate over all instructions and find branching instructions. Create blocks for
184 // the locations these instructions branch to.
185 size_t dex_offset = 0;
186 while (code_ptr < code_end) {
187 const Instruction& instruction = *Instruction::At(code_ptr);
188 if (instruction.IsBranch()) {
189 int32_t target = instruction.GetTargetOffset() + dex_offset;
190 // Create a block for the target instruction.
191 if (FindBlockStartingAt(target) == nullptr) {
192 block = new (arena_) HBasicBlock(graph_);
193 branch_targets_.Put(target, block);
194 }
195 dex_offset += instruction.SizeInCodeUnits();
196 code_ptr += instruction.SizeInCodeUnits();
197 if ((code_ptr < code_end) && (FindBlockStartingAt(dex_offset) == nullptr)) {
198 block = new (arena_) HBasicBlock(graph_);
199 branch_targets_.Put(dex_offset, block);
200 }
201 } else {
202 code_ptr += instruction.SizeInCodeUnits();
203 dex_offset += instruction.SizeInCodeUnits();
204 }
205 }
206}
207
208HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const {
209 DCHECK_GE(index, 0);
210 return branch_targets_.Get(index);
211}
212
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100213template<typename T>
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100214void HGraphBuilder::Binop_32x(const Instruction& instruction, Primitive::Type type) {
215 HInstruction* first = LoadLocal(instruction.VRegB(), type);
216 HInstruction* second = LoadLocal(instruction.VRegC(), type);
217 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100218 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
219}
220
221template<typename T>
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100222void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
223 HInstruction* first = LoadLocal(instruction.VRegA(), type);
224 HInstruction* second = LoadLocal(instruction.VRegB(), type);
225 current_block_->AddInstruction(new (arena_) T(type, first, second));
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100226 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
227}
228
229template<typename T>
230void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100231 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
232 HInstruction* second = GetIntConstant(instruction.VRegC_22s());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100233 if (reverse) {
234 std::swap(first, second);
235 }
236 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
237 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
238}
239
240template<typename T>
241void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100242 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
243 HInstruction* second = GetIntConstant(instruction.VRegC_22b());
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100244 if (reverse) {
245 std::swap(first, second);
246 }
247 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
248 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
249}
250
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100251void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
252 if (type == Primitive::kPrimVoid) {
253 current_block_->AddInstruction(new (arena_) HReturnVoid());
254 } else {
255 HInstruction* value = LoadLocal(instruction.VRegA(), type);
256 current_block_->AddInstruction(new (arena_) HReturn(value));
257 }
258 current_block_->AddSuccessor(exit_block_);
259 current_block_ = nullptr;
260}
261
262bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
263 uint32_t dex_offset,
264 uint32_t method_idx,
265 uint32_t number_of_vreg_arguments,
266 bool is_range,
267 uint32_t* args,
268 uint32_t register_index) {
269 const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
270 const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_id.proto_idx_);
271 const char* descriptor = dex_file_->StringDataByIdx(proto_id.shorty_idx_);
272 Primitive::Type return_type = Primitive::GetType(descriptor[0]);
273 bool is_instance_call =
274 instruction.Opcode() != Instruction::INVOKE_STATIC
275 && instruction.Opcode() != Instruction::INVOKE_STATIC_RANGE;
276 const size_t number_of_arguments = strlen(descriptor) - (is_instance_call ? 0 : 1);
277
278 // Treat invoke-direct like static calls for now.
279 HInvoke* invoke = new (arena_) HInvokeStatic(
280 arena_, number_of_arguments, return_type, dex_offset, method_idx);
281
282 size_t start_index = 0;
283 if (is_instance_call) {
284 HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100285 invoke->SetArgumentAt(0, arg);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100286 start_index = 1;
287 }
288
289 uint32_t descriptor_index = 1;
290 uint32_t argument_index = start_index;
291 for (size_t i = start_index; i < number_of_vreg_arguments; i++, argument_index++) {
292 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]);
293 switch (type) {
294 case Primitive::kPrimFloat:
295 case Primitive::kPrimDouble:
296 return false;
297
298 default: {
299 if (!is_range && type == Primitive::kPrimLong && args[i] + 1 != args[i + 1]) {
300 LOG(WARNING) << "Non sequential register pair in " << dex_compilation_unit_->GetSymbol()
301 << " at " << dex_offset;
302 // We do not implement non sequential register pair.
303 return false;
304 }
305 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
Nicolas Geoffraydb928fc2014-04-16 17:38:32 +0100306 invoke->SetArgumentAt(argument_index, arg);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100307 if (type == Primitive::kPrimLong) {
308 i++;
309 }
310 }
311 }
312 }
313
314 DCHECK_EQ(argument_index, number_of_arguments);
315 current_block_->AddInstruction(invoke);
316 return true;
317}
318
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000319bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000320 if (current_block_ == nullptr) {
321 return true; // Dead code
322 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000323
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000324 switch (instruction.Opcode()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000325 case Instruction::CONST_4: {
326 int32_t register_index = instruction.VRegA();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100327 HIntConstant* constant = GetIntConstant(instruction.VRegB_11n());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000328 UpdateLocal(register_index, constant);
329 break;
330 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000331
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100332 case Instruction::CONST_16: {
333 int32_t register_index = instruction.VRegA();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100334 HIntConstant* constant = GetIntConstant(instruction.VRegB_21s());
335 UpdateLocal(register_index, constant);
336 break;
337 }
338
339 case Instruction::CONST_WIDE_16: {
340 int32_t register_index = instruction.VRegA();
341 HLongConstant* constant = GetLongConstant(instruction.VRegB_21s());
342 UpdateLocal(register_index, constant);
343 break;
344 }
345
346 case Instruction::CONST_WIDE_32: {
347 int32_t register_index = instruction.VRegA();
348 HLongConstant* constant = GetLongConstant(instruction.VRegB_31i());
349 UpdateLocal(register_index, constant);
350 break;
351 }
352
353 case Instruction::CONST_WIDE: {
354 int32_t register_index = instruction.VRegA();
355 HLongConstant* constant = GetLongConstant(instruction.VRegB_51l());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100356 UpdateLocal(register_index, constant);
357 break;
358 }
359
360 case Instruction::MOVE: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100361 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100362 UpdateLocal(instruction.VRegA(), value);
363 break;
364 }
365
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000366 case Instruction::RETURN_VOID: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100367 BuildReturn(instruction, Primitive::kPrimVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000368 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000369 }
370
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000371 case Instruction::IF_EQ: {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100372 If_22t<HEqual>(instruction, dex_offset, false);
373 break;
374 }
375
376 case Instruction::IF_NE: {
377 If_22t<HEqual>(instruction, dex_offset, true);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000378 break;
379 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000380
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000381 case Instruction::GOTO:
382 case Instruction::GOTO_16:
383 case Instruction::GOTO_32: {
384 HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset);
385 DCHECK(target != nullptr);
386 current_block_->AddInstruction(new (arena_) HGoto());
387 current_block_->AddSuccessor(target);
388 current_block_ = nullptr;
389 break;
390 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000391
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100392 case Instruction::RETURN: {
393 BuildReturn(instruction, Primitive::kPrimInt);
394 break;
395 }
396
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100397 case Instruction::RETURN_OBJECT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100398 BuildReturn(instruction, Primitive::kPrimNot);
399 break;
400 }
401
402 case Instruction::RETURN_WIDE: {
403 BuildReturn(instruction, Primitive::kPrimLong);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000404 break;
405 }
406
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100407 case Instruction::INVOKE_STATIC:
408 case Instruction::INVOKE_DIRECT: {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000409 uint32_t method_idx = instruction.VRegB_35c();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100410 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100411 uint32_t args[5];
Ian Rogers29a26482014-05-02 15:27:29 -0700412 instruction.GetVarArgs(args);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100413 if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) {
414 return false;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100415 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100416 break;
417 }
418
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100419 case Instruction::INVOKE_STATIC_RANGE:
420 case Instruction::INVOKE_DIRECT_RANGE: {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100421 uint32_t method_idx = instruction.VRegB_3rc();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100422 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
423 uint32_t register_index = instruction.VRegC();
424 if (!BuildInvoke(instruction, dex_offset, method_idx,
425 number_of_vreg_arguments, true, nullptr, register_index)) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100426 return false;
427 }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000428 break;
429 }
430
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000431 case Instruction::ADD_INT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100432 Binop_32x<HAdd>(instruction, Primitive::kPrimInt);
433 break;
434 }
435
436 case Instruction::ADD_LONG: {
437 Binop_32x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100438 break;
439 }
440
441 case Instruction::SUB_INT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100442 Binop_32x<HSub>(instruction, Primitive::kPrimInt);
443 break;
444 }
445
446 case Instruction::SUB_LONG: {
447 Binop_32x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000448 break;
449 }
450
451 case Instruction::ADD_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100452 Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
453 break;
454 }
455
456 case Instruction::ADD_LONG_2ADDR: {
457 Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100458 break;
459 }
460
461 case Instruction::SUB_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100462 Binop_12x<HSub>(instruction, Primitive::kPrimInt);
463 break;
464 }
465
466 case Instruction::SUB_LONG_2ADDR: {
467 Binop_12x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000468 break;
469 }
470
471 case Instruction::ADD_INT_LIT16: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100472 Binop_22s<HAdd>(instruction, false);
473 break;
474 }
475
476 case Instruction::RSUB_INT: {
477 Binop_22s<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000478 break;
479 }
480
481 case Instruction::ADD_INT_LIT8: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100482 Binop_22b<HAdd>(instruction, false);
483 break;
484 }
485
486 case Instruction::RSUB_INT_LIT8: {
487 Binop_22b<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000488 break;
489 }
490
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100491 case Instruction::NEW_INSTANCE: {
492 current_block_->AddInstruction(
493 new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c()));
494 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
495 break;
496 }
497
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100498 case Instruction::MOVE_RESULT_WIDE: {
499 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
500 break;
501 }
502
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000503 case Instruction::NOP:
504 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000505
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000506 default:
507 return false;
508 }
509 return true;
510}
511
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100512HIntConstant* HGraphBuilder::GetIntConstant0() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000513 if (constant0_ != nullptr) {
514 return constant0_;
515 }
516 constant0_ = new(arena_) HIntConstant(0);
517 entry_block_->AddInstruction(constant0_);
518 return constant0_;
519}
520
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100521HIntConstant* HGraphBuilder::GetIntConstant1() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000522 if (constant1_ != nullptr) {
523 return constant1_;
524 }
525 constant1_ = new(arena_) HIntConstant(1);
526 entry_block_->AddInstruction(constant1_);
527 return constant1_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000528}
529
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100530HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000531 switch (constant) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100532 case 0: return GetIntConstant0();
533 case 1: return GetIntConstant1();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000534 default: {
535 HIntConstant* instruction = new (arena_) HIntConstant(constant);
536 entry_block_->AddInstruction(instruction);
537 return instruction;
538 }
539 }
540}
541
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100542HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) {
543 HLongConstant* instruction = new (arena_) HLongConstant(constant);
544 entry_block_->AddInstruction(instruction);
545 return instruction;
546}
547
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000548HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
549 return locals_.Get(register_index);
550}
551
552void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
553 HLocal* local = GetLocalAt(register_index);
554 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
555}
556
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100557HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000558 HLocal* local = GetLocalAt(register_index);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100559 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000560 return current_block_->GetLastInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000561}
562
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000563} // namespace art