blob: 2c2564d2ec90321d3f8a91c7052ede4ede0108bf [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
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100314 if (return_type == Primitive::kPrimDouble || return_type == Primitive::kPrimFloat) {
315 return false;
316 }
317
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100318 DCHECK_EQ(argument_index, number_of_arguments);
319 current_block_->AddInstruction(invoke);
320 return true;
321}
322
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000323bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000324 if (current_block_ == nullptr) {
325 return true; // Dead code
326 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000327
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000328 switch (instruction.Opcode()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000329 case Instruction::CONST_4: {
330 int32_t register_index = instruction.VRegA();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100331 HIntConstant* constant = GetIntConstant(instruction.VRegB_11n());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000332 UpdateLocal(register_index, constant);
333 break;
334 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000335
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100336 case Instruction::CONST_16: {
337 int32_t register_index = instruction.VRegA();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100338 HIntConstant* constant = GetIntConstant(instruction.VRegB_21s());
339 UpdateLocal(register_index, constant);
340 break;
341 }
342
343 case Instruction::CONST_WIDE_16: {
344 int32_t register_index = instruction.VRegA();
345 HLongConstant* constant = GetLongConstant(instruction.VRegB_21s());
346 UpdateLocal(register_index, constant);
347 break;
348 }
349
350 case Instruction::CONST_WIDE_32: {
351 int32_t register_index = instruction.VRegA();
352 HLongConstant* constant = GetLongConstant(instruction.VRegB_31i());
353 UpdateLocal(register_index, constant);
354 break;
355 }
356
357 case Instruction::CONST_WIDE: {
358 int32_t register_index = instruction.VRegA();
359 HLongConstant* constant = GetLongConstant(instruction.VRegB_51l());
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100360 UpdateLocal(register_index, constant);
361 break;
362 }
363
364 case Instruction::MOVE: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100365 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100366 UpdateLocal(instruction.VRegA(), value);
367 break;
368 }
369
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000370 case Instruction::RETURN_VOID: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100371 BuildReturn(instruction, Primitive::kPrimVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000372 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000373 }
374
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000375 case Instruction::IF_EQ: {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100376 If_22t<HEqual>(instruction, dex_offset, false);
377 break;
378 }
379
380 case Instruction::IF_NE: {
381 If_22t<HEqual>(instruction, dex_offset, true);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000382 break;
383 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000384
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000385 case Instruction::GOTO:
386 case Instruction::GOTO_16:
387 case Instruction::GOTO_32: {
388 HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset);
389 DCHECK(target != nullptr);
390 current_block_->AddInstruction(new (arena_) HGoto());
391 current_block_->AddSuccessor(target);
392 current_block_ = nullptr;
393 break;
394 }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000395
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100396 case Instruction::RETURN: {
397 BuildReturn(instruction, Primitive::kPrimInt);
398 break;
399 }
400
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100401 case Instruction::RETURN_OBJECT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100402 BuildReturn(instruction, Primitive::kPrimNot);
403 break;
404 }
405
406 case Instruction::RETURN_WIDE: {
407 BuildReturn(instruction, Primitive::kPrimLong);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000408 break;
409 }
410
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100411 case Instruction::INVOKE_STATIC:
412 case Instruction::INVOKE_DIRECT: {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000413 uint32_t method_idx = instruction.VRegB_35c();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100414 uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100415 uint32_t args[5];
Ian Rogers29a26482014-05-02 15:27:29 -0700416 instruction.GetVarArgs(args);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100417 if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) {
418 return false;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100419 }
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100420 break;
421 }
422
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100423 case Instruction::INVOKE_STATIC_RANGE:
424 case Instruction::INVOKE_DIRECT_RANGE: {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100425 uint32_t method_idx = instruction.VRegB_3rc();
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100426 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
427 uint32_t register_index = instruction.VRegC();
428 if (!BuildInvoke(instruction, dex_offset, method_idx,
429 number_of_vreg_arguments, true, nullptr, register_index)) {
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100430 return false;
431 }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000432 break;
433 }
434
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000435 case Instruction::ADD_INT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100436 Binop_32x<HAdd>(instruction, Primitive::kPrimInt);
437 break;
438 }
439
440 case Instruction::ADD_LONG: {
441 Binop_32x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100442 break;
443 }
444
445 case Instruction::SUB_INT: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100446 Binop_32x<HSub>(instruction, Primitive::kPrimInt);
447 break;
448 }
449
450 case Instruction::SUB_LONG: {
451 Binop_32x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000452 break;
453 }
454
455 case Instruction::ADD_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100456 Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
457 break;
458 }
459
460 case Instruction::ADD_LONG_2ADDR: {
461 Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100462 break;
463 }
464
465 case Instruction::SUB_INT_2ADDR: {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100466 Binop_12x<HSub>(instruction, Primitive::kPrimInt);
467 break;
468 }
469
470 case Instruction::SUB_LONG_2ADDR: {
471 Binop_12x<HSub>(instruction, Primitive::kPrimLong);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000472 break;
473 }
474
475 case Instruction::ADD_INT_LIT16: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100476 Binop_22s<HAdd>(instruction, false);
477 break;
478 }
479
480 case Instruction::RSUB_INT: {
481 Binop_22s<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000482 break;
483 }
484
485 case Instruction::ADD_INT_LIT8: {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100486 Binop_22b<HAdd>(instruction, false);
487 break;
488 }
489
490 case Instruction::RSUB_INT_LIT8: {
491 Binop_22b<HSub>(instruction, true);
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000492 break;
493 }
494
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100495 case Instruction::NEW_INSTANCE: {
496 current_block_->AddInstruction(
497 new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c()));
498 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
499 break;
500 }
501
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100502 case Instruction::MOVE_RESULT_WIDE: {
503 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
504 break;
505 }
506
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000507 case Instruction::NOP:
508 break;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000509
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000510 default:
511 return false;
512 }
513 return true;
514}
515
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100516HIntConstant* HGraphBuilder::GetIntConstant0() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000517 if (constant0_ != nullptr) {
518 return constant0_;
519 }
520 constant0_ = new(arena_) HIntConstant(0);
521 entry_block_->AddInstruction(constant0_);
522 return constant0_;
523}
524
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100525HIntConstant* HGraphBuilder::GetIntConstant1() {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000526 if (constant1_ != nullptr) {
527 return constant1_;
528 }
529 constant1_ = new(arena_) HIntConstant(1);
530 entry_block_->AddInstruction(constant1_);
531 return constant1_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000532}
533
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100534HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000535 switch (constant) {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100536 case 0: return GetIntConstant0();
537 case 1: return GetIntConstant1();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000538 default: {
539 HIntConstant* instruction = new (arena_) HIntConstant(constant);
540 entry_block_->AddInstruction(instruction);
541 return instruction;
542 }
543 }
544}
545
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100546HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) {
547 HLongConstant* instruction = new (arena_) HLongConstant(constant);
548 entry_block_->AddInstruction(instruction);
549 return instruction;
550}
551
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000552HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
553 return locals_.Get(register_index);
554}
555
556void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
557 HLocal* local = GetLocalAt(register_index);
558 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
559}
560
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100561HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000562 HLocal* local = GetLocalAt(register_index);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100563 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000564 return current_block_->GetLastInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000565}
566
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000567} // namespace art