blob: 8daa39713548e5eea600e7bc296d2d9e83409ccb [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "dex/compiler_internals.h"
18#include "dex_file-inl.h"
19#include "gc_map.h"
20#include "mir_to_lir-inl.h"
21#include "verifier/dex_gc_map.h"
22#include "verifier/method_verifier.h"
23
24namespace art {
25
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070026bool Mir2Lir::IsInexpensiveConstant(RegLocation rl_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070027 bool res = false;
28 if (rl_src.is_const) {
29 if (rl_src.wide) {
30 if (rl_src.fp) {
31 res = InexpensiveConstantDouble(mir_graph_->ConstantValueWide(rl_src));
32 } else {
33 res = InexpensiveConstantLong(mir_graph_->ConstantValueWide(rl_src));
34 }
35 } else {
36 if (rl_src.fp) {
37 res = InexpensiveConstantFloat(mir_graph_->ConstantValue(rl_src));
38 } else {
39 res = InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src));
40 }
41 }
42 }
43 return res;
44}
45
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070046void Mir2Lir::MarkSafepointPC(LIR* inst) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070047 inst->def_mask = ENCODE_ALL;
48 LIR* safepoint_pc = NewLIR0(kPseudoSafepointPC);
49 DCHECK_EQ(safepoint_pc->def_mask, ENCODE_ALL);
50}
51
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070052bool Mir2Lir::FastInstance(uint32_t field_idx, int& field_offset, bool& is_volatile, bool is_put) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070053 return cu_->compiler_driver->ComputeInstanceFieldInfo(
54 field_idx, mir_graph_->GetCurrentDexCompilationUnit(), field_offset, is_volatile, is_put);
55}
56
57/* Convert an instruction to a NOP */
Brian Carlstromdf629502013-07-17 22:39:56 -070058void Mir2Lir::NopLIR(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070059 lir->flags.is_nop = true;
60}
61
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070062void Mir2Lir::SetMemRefType(LIR* lir, bool is_load, int mem_type) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070063 uint64_t *mask_ptr;
Brian Carlstromf69863b2013-07-17 21:53:13 -070064 uint64_t mask = ENCODE_MEM;
Brian Carlstrom7940e442013-07-12 13:46:57 -070065 DCHECK(GetTargetInstFlags(lir->opcode) & (IS_LOAD | IS_STORE));
66 if (is_load) {
67 mask_ptr = &lir->use_mask;
68 } else {
69 mask_ptr = &lir->def_mask;
70 }
71 /* Clear out the memref flags */
72 *mask_ptr &= ~mask;
73 /* ..and then add back the one we need */
74 switch (mem_type) {
75 case kLiteral:
76 DCHECK(is_load);
77 *mask_ptr |= ENCODE_LITERAL;
78 break;
79 case kDalvikReg:
80 *mask_ptr |= ENCODE_DALVIK_REG;
81 break;
82 case kHeapRef:
83 *mask_ptr |= ENCODE_HEAP_REF;
84 break;
85 case kMustNotAlias:
86 /* Currently only loads can be marked as kMustNotAlias */
87 DCHECK(!(GetTargetInstFlags(lir->opcode) & IS_STORE));
88 *mask_ptr |= ENCODE_MUST_NOT_ALIAS;
89 break;
90 default:
91 LOG(FATAL) << "Oat: invalid memref kind - " << mem_type;
92 }
93}
94
95/*
96 * Mark load/store instructions that access Dalvik registers through the stack.
97 */
98void Mir2Lir::AnnotateDalvikRegAccess(LIR* lir, int reg_id, bool is_load,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070099 bool is64bit) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700100 SetMemRefType(lir, is_load, kDalvikReg);
101
102 /*
103 * Store the Dalvik register id in alias_info. Mark the MSB if it is a 64-bit
104 * access.
105 */
106 lir->alias_info = ENCODE_ALIAS_INFO(reg_id, is64bit);
107}
108
109/*
110 * Debugging macros
111 */
112#define DUMP_RESOURCE_MASK(X)
113
114/* Pretty-print a LIR instruction */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700115void Mir2Lir::DumpLIRInsn(LIR* lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700116 int offset = lir->offset;
117 int dest = lir->operands[0];
118 const bool dump_nop = (cu_->enable_debug & (1 << kDebugShowNops));
119
120 /* Handle pseudo-ops individually, and all regular insns as a group */
121 switch (lir->opcode) {
122 case kPseudoMethodEntry:
123 LOG(INFO) << "-------- method entry "
124 << PrettyMethod(cu_->method_idx, *cu_->dex_file);
125 break;
126 case kPseudoMethodExit:
127 LOG(INFO) << "-------- Method_Exit";
128 break;
129 case kPseudoBarrier:
130 LOG(INFO) << "-------- BARRIER";
131 break;
132 case kPseudoEntryBlock:
133 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
134 break;
135 case kPseudoDalvikByteCodeBoundary:
136 if (lir->operands[0] == 0) {
137 lir->operands[0] = reinterpret_cast<uintptr_t>("No instruction string");
138 }
139 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex
140 << lir->dalvik_offset << " @ " << reinterpret_cast<char*>(lir->operands[0]);
141 break;
142 case kPseudoExitBlock:
143 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
144 break;
145 case kPseudoPseudoAlign4:
146 LOG(INFO) << reinterpret_cast<uintptr_t>(base_addr) + offset << " (0x" << std::hex
147 << offset << "): .align4";
148 break;
149 case kPseudoEHBlockLabel:
150 LOG(INFO) << "Exception_Handling:";
151 break;
152 case kPseudoTargetLabel:
153 case kPseudoNormalBlockLabel:
154 LOG(INFO) << "L" << reinterpret_cast<void*>(lir) << ":";
155 break;
156 case kPseudoThrowTarget:
157 LOG(INFO) << "LT" << reinterpret_cast<void*>(lir) << ":";
158 break;
159 case kPseudoIntrinsicRetry:
160 LOG(INFO) << "IR" << reinterpret_cast<void*>(lir) << ":";
161 break;
162 case kPseudoSuspendTarget:
163 LOG(INFO) << "LS" << reinterpret_cast<void*>(lir) << ":";
164 break;
165 case kPseudoSafepointPC:
166 LOG(INFO) << "LsafepointPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
167 break;
168 case kPseudoExportedPC:
169 LOG(INFO) << "LexportedPC_0x" << std::hex << lir->offset << "_" << lir->dalvik_offset << ":";
170 break;
171 case kPseudoCaseLabel:
172 LOG(INFO) << "LC" << reinterpret_cast<void*>(lir) << ": Case target 0x"
173 << std::hex << lir->operands[0] << "|" << std::dec <<
174 lir->operands[0];
175 break;
176 default:
177 if (lir->flags.is_nop && !dump_nop) {
178 break;
179 } else {
180 std::string op_name(BuildInsnString(GetTargetInstName(lir->opcode),
181 lir, base_addr));
182 std::string op_operands(BuildInsnString(GetTargetInstFmt(lir->opcode),
183 lir, base_addr));
184 LOG(INFO) << StringPrintf("%05x: %-9s%s%s",
185 reinterpret_cast<unsigned int>(base_addr + offset),
186 op_name.c_str(), op_operands.c_str(),
187 lir->flags.is_nop ? "(nop)" : "");
188 }
189 break;
190 }
191
192 if (lir->use_mask && (!lir->flags.is_nop || dump_nop)) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700193 DUMP_RESOURCE_MASK(DumpResourceMask((LIR*) lir, lir->use_mask, "use"));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700194 }
195 if (lir->def_mask && (!lir->flags.is_nop || dump_nop)) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700196 DUMP_RESOURCE_MASK(DumpResourceMask((LIR*) lir, lir->def_mask, "def"));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700197 }
198}
199
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700200void Mir2Lir::DumpPromotionMap() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700201 int num_regs = cu_->num_dalvik_registers + cu_->num_compiler_temps + 1;
202 for (int i = 0; i < num_regs; i++) {
203 PromotionMap v_reg_map = promotion_map_[i];
204 std::string buf;
205 if (v_reg_map.fp_location == kLocPhysReg) {
206 StringAppendF(&buf, " : s%d", v_reg_map.FpReg & FpRegMask());
207 }
208
209 std::string buf3;
210 if (i < cu_->num_dalvik_registers) {
211 StringAppendF(&buf3, "%02d", i);
212 } else if (i == mir_graph_->GetMethodSReg()) {
213 buf3 = "Method*";
214 } else {
215 StringAppendF(&buf3, "ct%d", i - cu_->num_dalvik_registers);
216 }
217
218 LOG(INFO) << StringPrintf("V[%s] -> %s%d%s", buf3.c_str(),
219 v_reg_map.core_location == kLocPhysReg ?
220 "r" : "SP+", v_reg_map.core_location == kLocPhysReg ?
221 v_reg_map.core_reg : SRegOffset(i),
222 buf.c_str());
223 }
224}
225
226/* Dump a mapping table */
227void Mir2Lir::DumpMappingTable(const char* table_name, const std::string& descriptor,
228 const std::string& name, const std::string& signature,
229 const std::vector<uint32_t>& v) {
230 if (v.size() > 0) {
231 std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
232 descriptor.c_str(), name.c_str(), signature.c_str(), v.size()));
233 std::replace(line.begin(), line.end(), ';', '_');
234 LOG(INFO) << line;
235 for (uint32_t i = 0; i < v.size(); i+=2) {
236 line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
237 LOG(INFO) << line;
238 }
239 LOG(INFO) <<" };\n\n";
240 }
241}
242
243/* Dump instructions and constant pool contents */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700244void Mir2Lir::CodegenDump() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700245 LOG(INFO) << "Dumping LIR insns for "
246 << PrettyMethod(cu_->method_idx, *cu_->dex_file);
247 LIR* lir_insn;
248 int insns_size = cu_->code_item->insns_size_in_code_units_;
249
250 LOG(INFO) << "Regs (excluding ins) : " << cu_->num_regs;
251 LOG(INFO) << "Ins : " << cu_->num_ins;
252 LOG(INFO) << "Outs : " << cu_->num_outs;
253 LOG(INFO) << "CoreSpills : " << num_core_spills_;
254 LOG(INFO) << "FPSpills : " << num_fp_spills_;
255 LOG(INFO) << "CompilerTemps : " << cu_->num_compiler_temps;
256 LOG(INFO) << "Frame size : " << frame_size_;
257 LOG(INFO) << "code size is " << total_size_ <<
258 " bytes, Dalvik size is " << insns_size * 2;
259 LOG(INFO) << "expansion factor: "
260 << static_cast<float>(total_size_) / static_cast<float>(insns_size * 2);
261 DumpPromotionMap();
262 for (lir_insn = first_lir_insn_; lir_insn != NULL; lir_insn = lir_insn->next) {
263 DumpLIRInsn(lir_insn, 0);
264 }
265 for (lir_insn = literal_list_; lir_insn != NULL; lir_insn = lir_insn->next) {
266 LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", lir_insn->offset, lir_insn->offset,
267 lir_insn->operands[0]);
268 }
269
270 const DexFile::MethodId& method_id =
271 cu_->dex_file->GetMethodId(cu_->method_idx);
272 std::string signature(cu_->dex_file->GetMethodSignature(method_id));
273 std::string name(cu_->dex_file->GetMethodName(method_id));
274 std::string descriptor(cu_->dex_file->GetMethodDeclaringClassDescriptor(method_id));
275
276 // Dump mapping tables
277 DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, pc2dex_mapping_table_);
278 DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, dex2pc_mapping_table_);
279}
280
281/*
282 * Search the existing constants in the literal pool for an exact or close match
283 * within specified delta (greater or equal to 0).
284 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700285LIR* Mir2Lir::ScanLiteralPool(LIR* data_target, int value, unsigned int delta) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700286 while (data_target) {
287 if ((static_cast<unsigned>(value - data_target->operands[0])) <= delta)
288 return data_target;
289 data_target = data_target->next;
290 }
291 return NULL;
292}
293
294/* Search the existing constants in the literal pool for an exact wide match */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700295LIR* Mir2Lir::ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700296 bool lo_match = false;
297 LIR* lo_target = NULL;
298 while (data_target) {
299 if (lo_match && (data_target->operands[0] == val_hi)) {
300 // Record high word in case we need to expand this later.
301 lo_target->operands[1] = val_hi;
302 return lo_target;
303 }
304 lo_match = false;
305 if (data_target->operands[0] == val_lo) {
306 lo_match = true;
307 lo_target = data_target;
308 }
309 data_target = data_target->next;
310 }
311 return NULL;
312}
313
314/*
315 * The following are building blocks to insert constants into the pool or
316 * instruction streams.
317 */
318
319/* Add a 32-bit constant to the constant pool */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700320LIR* Mir2Lir::AddWordData(LIR* *constant_list_p, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700321 /* Add the constant to the literal pool */
322 if (constant_list_p) {
323 LIR* new_value = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocData));
324 new_value->operands[0] = value;
325 new_value->next = *constant_list_p;
326 *constant_list_p = new_value;
327 return new_value;
328 }
329 return NULL;
330}
331
332/* Add a 64-bit constant to the constant pool or mixed with code */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700333LIR* Mir2Lir::AddWideData(LIR* *constant_list_p, int val_lo, int val_hi) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700334 AddWordData(constant_list_p, val_hi);
335 return AddWordData(constant_list_p, val_lo);
336}
337
338static void PushWord(std::vector<uint8_t>&buf, int data) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700339 buf.push_back(data & 0xff);
340 buf.push_back((data >> 8) & 0xff);
341 buf.push_back((data >> 16) & 0xff);
342 buf.push_back((data >> 24) & 0xff);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700343}
344
345static void AlignBuffer(std::vector<uint8_t>&buf, size_t offset) {
346 while (buf.size() < offset) {
347 buf.push_back(0);
348 }
349}
350
351/* Write the literal pool to the output stream */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700352void Mir2Lir::InstallLiteralPools() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700353 AlignBuffer(code_buffer_, data_offset_);
354 LIR* data_lir = literal_list_;
355 while (data_lir != NULL) {
356 PushWord(code_buffer_, data_lir->operands[0]);
357 data_lir = NEXT_LIR(data_lir);
358 }
359 // Push code and method literals, record offsets for the compiler to patch.
360 data_lir = code_literal_list_;
361 while (data_lir != NULL) {
362 uint32_t target = data_lir->operands[0];
363 cu_->compiler_driver->AddCodePatch(cu_->dex_file,
364 cu_->method_idx,
365 cu_->invoke_type,
366 target,
367 static_cast<InvokeType>(data_lir->operands[1]),
368 code_buffer_.size());
369 const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
370 // unique based on target to ensure code deduplication works
371 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
372 PushWord(code_buffer_, unique_patch_value);
373 data_lir = NEXT_LIR(data_lir);
374 }
375 data_lir = method_literal_list_;
376 while (data_lir != NULL) {
377 uint32_t target = data_lir->operands[0];
378 cu_->compiler_driver->AddMethodPatch(cu_->dex_file,
379 cu_->method_idx,
380 cu_->invoke_type,
381 target,
382 static_cast<InvokeType>(data_lir->operands[1]),
383 code_buffer_.size());
384 const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
385 // unique based on target to ensure code deduplication works
386 uint32_t unique_patch_value = reinterpret_cast<uint32_t>(&id);
387 PushWord(code_buffer_, unique_patch_value);
388 data_lir = NEXT_LIR(data_lir);
389 }
390}
391
392/* Write the switch tables to the output stream */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700393void Mir2Lir::InstallSwitchTables() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700394 GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
395 while (true) {
396 Mir2Lir::SwitchTable* tab_rec = iterator.Next();
397 if (tab_rec == NULL) break;
398 AlignBuffer(code_buffer_, tab_rec->offset);
399 /*
400 * For Arm, our reference point is the address of the bx
401 * instruction that does the launch, so we have to subtract
402 * the auto pc-advance. For other targets the reference point
403 * is a label, so we can use the offset as-is.
404 */
405 int bx_offset = INVALID_OFFSET;
406 switch (cu_->instruction_set) {
407 case kThumb2:
408 bx_offset = tab_rec->anchor->offset + 4;
409 break;
410 case kX86:
411 bx_offset = 0;
412 break;
413 case kMips:
414 bx_offset = tab_rec->anchor->offset;
415 break;
416 default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set;
417 }
418 if (cu_->verbose) {
419 LOG(INFO) << "Switch table for offset 0x" << std::hex << bx_offset;
420 }
421 if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
422 const int* keys = reinterpret_cast<const int*>(&(tab_rec->table[2]));
423 for (int elems = 0; elems < tab_rec->table[1]; elems++) {
424 int disp = tab_rec->targets[elems]->offset - bx_offset;
425 if (cu_->verbose) {
426 LOG(INFO) << " Case[" << elems << "] key: 0x"
427 << std::hex << keys[elems] << ", disp: 0x"
428 << std::hex << disp;
429 }
430 PushWord(code_buffer_, keys[elems]);
431 PushWord(code_buffer_,
432 tab_rec->targets[elems]->offset - bx_offset);
433 }
434 } else {
435 DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
436 static_cast<int>(Instruction::kPackedSwitchSignature));
437 for (int elems = 0; elems < tab_rec->table[1]; elems++) {
438 int disp = tab_rec->targets[elems]->offset - bx_offset;
439 if (cu_->verbose) {
440 LOG(INFO) << " Case[" << elems << "] disp: 0x"
441 << std::hex << disp;
442 }
443 PushWord(code_buffer_, tab_rec->targets[elems]->offset - bx_offset);
444 }
445 }
446 }
447}
448
449/* Write the fill array dta to the output stream */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700450void Mir2Lir::InstallFillArrayData() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700451 GrowableArray<FillArrayData*>::Iterator iterator(&fill_array_data_);
452 while (true) {
453 Mir2Lir::FillArrayData *tab_rec = iterator.Next();
454 if (tab_rec == NULL) break;
455 AlignBuffer(code_buffer_, tab_rec->offset);
456 for (int i = 0; i < (tab_rec->size + 1) / 2; i++) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700457 code_buffer_.push_back(tab_rec->table[i] & 0xFF);
458 code_buffer_.push_back((tab_rec->table[i] >> 8) & 0xFF);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700459 }
460 }
461}
462
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700463static int AssignLiteralOffsetCommon(LIR* lir, int offset) {
Brian Carlstrom02c8cc62013-07-18 15:54:44 -0700464 for (; lir != NULL; lir = lir->next) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700465 lir->offset = offset;
466 offset += 4;
467 }
468 return offset;
469}
470
471// Make sure we have a code address for every declared catch entry
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700472bool Mir2Lir::VerifyCatchEntries() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700473 bool success = true;
474 for (std::set<uint32_t>::const_iterator it = mir_graph_->catches_.begin();
475 it != mir_graph_->catches_.end(); ++it) {
476 uint32_t dex_pc = *it;
477 bool found = false;
478 for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
479 if (dex_pc == dex2pc_mapping_table_[i+1]) {
480 found = true;
481 break;
482 }
483 }
484 if (!found) {
485 LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc;
486 success = false;
487 }
488 }
489 // Now, try in the other direction
490 for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
491 uint32_t dex_pc = dex2pc_mapping_table_[i+1];
492 if (mir_graph_->catches_.find(dex_pc) == mir_graph_->catches_.end()) {
493 LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc;
494 success = false;
495 }
496 }
497 if (!success) {
498 LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
499 LOG(INFO) << "Entries @ decode: " << mir_graph_->catches_.size() << ", Entries in table: "
500 << dex2pc_mapping_table_.size()/2;
501 }
502 return success;
503}
504
505
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700506void Mir2Lir::CreateMappingTables() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700507 for (LIR* tgt_lir = first_lir_insn_; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) {
508 if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
509 pc2dex_mapping_table_.push_back(tgt_lir->offset);
510 pc2dex_mapping_table_.push_back(tgt_lir->dalvik_offset);
511 }
512 if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
513 dex2pc_mapping_table_.push_back(tgt_lir->offset);
514 dex2pc_mapping_table_.push_back(tgt_lir->dalvik_offset);
515 }
516 }
517 if (kIsDebugBuild) {
518 DCHECK(VerifyCatchEntries());
519 }
520 combined_mapping_table_.push_back(pc2dex_mapping_table_.size() +
521 dex2pc_mapping_table_.size());
522 combined_mapping_table_.push_back(pc2dex_mapping_table_.size());
523 combined_mapping_table_.insert(combined_mapping_table_.end(), pc2dex_mapping_table_.begin(),
524 pc2dex_mapping_table_.end());
525 combined_mapping_table_.insert(combined_mapping_table_.end(), dex2pc_mapping_table_.begin(),
526 dex2pc_mapping_table_.end());
527}
528
529class NativePcToReferenceMapBuilder {
530 public:
531 NativePcToReferenceMapBuilder(std::vector<uint8_t>* table,
532 size_t entries, uint32_t max_native_offset,
533 size_t references_width) : entries_(entries),
534 references_width_(references_width), in_use_(entries),
535 table_(table) {
536 // Compute width in bytes needed to hold max_native_offset.
537 native_offset_width_ = 0;
538 while (max_native_offset != 0) {
539 native_offset_width_++;
540 max_native_offset >>= 8;
541 }
542 // Resize table and set up header.
543 table->resize((EntryWidth() * entries) + sizeof(uint32_t));
544 CHECK_LT(native_offset_width_, 1U << 3);
545 (*table)[0] = native_offset_width_ & 7;
546 CHECK_LT(references_width_, 1U << 13);
547 (*table)[0] |= (references_width_ << 3) & 0xFF;
548 (*table)[1] = (references_width_ >> 5) & 0xFF;
549 CHECK_LT(entries, 1U << 16);
550 (*table)[2] = entries & 0xFF;
551 (*table)[3] = (entries >> 8) & 0xFF;
552 }
553
554 void AddEntry(uint32_t native_offset, const uint8_t* references) {
555 size_t table_index = TableIndex(native_offset);
556 while (in_use_[table_index]) {
557 table_index = (table_index + 1) % entries_;
558 }
559 in_use_[table_index] = true;
560 SetNativeOffset(table_index, native_offset);
561 DCHECK_EQ(native_offset, GetNativeOffset(table_index));
562 SetReferences(table_index, references);
563 }
564
565 private:
566 size_t TableIndex(uint32_t native_offset) {
567 return NativePcOffsetToReferenceMap::Hash(native_offset) % entries_;
568 }
569
570 uint32_t GetNativeOffset(size_t table_index) {
571 uint32_t native_offset = 0;
572 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
573 for (size_t i = 0; i < native_offset_width_; i++) {
574 native_offset |= (*table_)[table_offset + i] << (i * 8);
575 }
576 return native_offset;
577 }
578
579 void SetNativeOffset(size_t table_index, uint32_t native_offset) {
580 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
581 for (size_t i = 0; i < native_offset_width_; i++) {
582 (*table_)[table_offset + i] = (native_offset >> (i * 8)) & 0xFF;
583 }
584 }
585
586 void SetReferences(size_t table_index, const uint8_t* references) {
587 size_t table_offset = (table_index * EntryWidth()) + sizeof(uint32_t);
588 memcpy(&(*table_)[table_offset + native_offset_width_], references, references_width_);
589 }
590
591 size_t EntryWidth() const {
592 return native_offset_width_ + references_width_;
593 }
594
595 // Number of entries in the table.
596 const size_t entries_;
597 // Number of bytes used to encode the reference bitmap.
598 const size_t references_width_;
599 // Number of bytes used to encode a native offset.
600 size_t native_offset_width_;
601 // Entries that are in use.
602 std::vector<bool> in_use_;
603 // The table we're building.
604 std::vector<uint8_t>* const table_;
605};
606
607void Mir2Lir::CreateNativeGcMap() {
608 const std::vector<uint32_t>& mapping_table = pc2dex_mapping_table_;
609 uint32_t max_native_offset = 0;
610 for (size_t i = 0; i < mapping_table.size(); i += 2) {
611 uint32_t native_offset = mapping_table[i + 0];
612 if (native_offset > max_native_offset) {
613 max_native_offset = native_offset;
614 }
615 }
616 MethodReference method_ref(cu_->dex_file, cu_->method_idx);
617 const std::vector<uint8_t>* gc_map_raw = verifier::MethodVerifier::GetDexGcMap(method_ref);
618 verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
619 // Compute native offset to references size.
620 NativePcToReferenceMapBuilder native_gc_map_builder(&native_gc_map_,
621 mapping_table.size() / 2, max_native_offset,
622 dex_gc_map.RegWidth());
623
624 for (size_t i = 0; i < mapping_table.size(); i += 2) {
625 uint32_t native_offset = mapping_table[i + 0];
626 uint32_t dex_pc = mapping_table[i + 1];
627 const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
628 CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
629 native_gc_map_builder.AddEntry(native_offset, references);
630 }
631}
632
633/* Determine the offset of each literal field */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700634int Mir2Lir::AssignLiteralOffset(int offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700635 offset = AssignLiteralOffsetCommon(literal_list_, offset);
636 offset = AssignLiteralOffsetCommon(code_literal_list_, offset);
637 offset = AssignLiteralOffsetCommon(method_literal_list_, offset);
638 return offset;
639}
640
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700641int Mir2Lir::AssignSwitchTablesOffset(int offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700642 GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
643 while (true) {
644 Mir2Lir::SwitchTable *tab_rec = iterator.Next();
645 if (tab_rec == NULL) break;
646 tab_rec->offset = offset;
647 if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
648 offset += tab_rec->table[1] * (sizeof(int) * 2);
649 } else {
650 DCHECK_EQ(static_cast<int>(tab_rec->table[0]),
651 static_cast<int>(Instruction::kPackedSwitchSignature));
652 offset += tab_rec->table[1] * sizeof(int);
653 }
654 }
655 return offset;
656}
657
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700658int Mir2Lir::AssignFillArrayDataOffset(int offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700659 GrowableArray<FillArrayData*>::Iterator iterator(&fill_array_data_);
660 while (true) {
661 Mir2Lir::FillArrayData *tab_rec = iterator.Next();
662 if (tab_rec == NULL) break;
663 tab_rec->offset = offset;
664 offset += tab_rec->size;
665 // word align
666 offset = (offset + 3) & ~3;
667 }
668 return offset;
669}
670
671// LIR offset assignment.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700672int Mir2Lir::AssignInsnOffsets() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700673 LIR* lir;
674 int offset = 0;
675
676 for (lir = first_lir_insn_; lir != NULL; lir = NEXT_LIR(lir)) {
677 lir->offset = offset;
678 if (lir->opcode >= 0) {
679 if (!lir->flags.is_nop) {
680 offset += lir->flags.size;
681 }
682 } else if (lir->opcode == kPseudoPseudoAlign4) {
683 if (offset & 0x2) {
684 offset += 2;
685 lir->operands[0] = 1;
686 } else {
687 lir->operands[0] = 0;
688 }
689 }
690 /* Pseudo opcodes don't consume space */
691 }
692
693 return offset;
694}
695
696/*
697 * Walk the compilation unit and assign offsets to instructions
698 * and literals and compute the total size of the compiled unit.
699 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700700void Mir2Lir::AssignOffsets() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700701 int offset = AssignInsnOffsets();
702
703 /* Const values have to be word aligned */
704 offset = (offset + 3) & ~3;
705
706 /* Set up offsets for literals */
707 data_offset_ = offset;
708
709 offset = AssignLiteralOffset(offset);
710
711 offset = AssignSwitchTablesOffset(offset);
712
713 offset = AssignFillArrayDataOffset(offset);
714
715 total_size_ = offset;
716}
717
718/*
719 * Go over each instruction in the list and calculate the offset from the top
720 * before sending them off to the assembler. If out-of-range branch distance is
721 * seen rearrange the instructions a bit to correct it.
722 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700723void Mir2Lir::AssembleLIR() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700724 AssignOffsets();
725 int assembler_retries = 0;
726 /*
727 * Assemble here. Note that we generate code with optimistic assumptions
728 * and if found now to work, we'll have to redo the sequence and retry.
729 */
730
731 while (true) {
732 AssemblerStatus res = AssembleInstructions(0);
733 if (res == kSuccess) {
734 break;
735 } else {
736 assembler_retries++;
737 if (assembler_retries > MAX_ASSEMBLER_RETRIES) {
738 CodegenDump();
739 LOG(FATAL) << "Assembler error - too many retries";
740 }
741 // Redo offsets and try again
742 AssignOffsets();
743 code_buffer_.clear();
744 }
745 }
746
747 // Install literals
748 InstallLiteralPools();
749
750 // Install switch tables
751 InstallSwitchTables();
752
753 // Install fill array data
754 InstallFillArrayData();
755
756 // Create the mapping table and native offset to reference map.
757 CreateMappingTables();
758
759 CreateNativeGcMap();
760}
761
762/*
763 * Insert a kPseudoCaseLabel at the beginning of the Dalvik
764 * offset vaddr. This label will be used to fix up the case
765 * branch table during the assembly phase. Be sure to set
766 * all resource flags on this to prevent code motion across
767 * target boundaries. KeyVal is just there for debugging.
768 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700769LIR* Mir2Lir::InsertCaseLabel(int vaddr, int keyVal) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700770 SafeMap<unsigned int, LIR*>::iterator it;
771 it = boundary_map_.find(vaddr);
772 if (it == boundary_map_.end()) {
773 LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
774 }
775 LIR* new_label = static_cast<LIR*>(arena_->NewMem(sizeof(LIR), true, ArenaAllocator::kAllocLIR));
776 new_label->dalvik_offset = vaddr;
777 new_label->opcode = kPseudoCaseLabel;
778 new_label->operands[0] = keyVal;
779 InsertLIRAfter(it->second, new_label);
780 return new_label;
781}
782
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700783void Mir2Lir::MarkPackedCaseLabels(Mir2Lir::SwitchTable *tab_rec) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700784 const uint16_t* table = tab_rec->table;
785 int base_vaddr = tab_rec->vaddr;
786 const int *targets = reinterpret_cast<const int*>(&table[4]);
787 int entries = table[1];
788 int low_key = s4FromSwitchData(&table[2]);
789 for (int i = 0; i < entries; i++) {
790 tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], i + low_key);
791 }
792}
793
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700794void Mir2Lir::MarkSparseCaseLabels(Mir2Lir::SwitchTable *tab_rec) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700795 const uint16_t* table = tab_rec->table;
796 int base_vaddr = tab_rec->vaddr;
797 int entries = table[1];
798 const int* keys = reinterpret_cast<const int*>(&table[2]);
799 const int* targets = &keys[entries];
800 for (int i = 0; i < entries; i++) {
801 tab_rec->targets[i] = InsertCaseLabel(base_vaddr + targets[i], keys[i]);
802 }
803}
804
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700805void Mir2Lir::ProcessSwitchTables() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700806 GrowableArray<SwitchTable*>::Iterator iterator(&switch_tables_);
807 while (true) {
808 Mir2Lir::SwitchTable *tab_rec = iterator.Next();
809 if (tab_rec == NULL) break;
810 if (tab_rec->table[0] == Instruction::kPackedSwitchSignature) {
811 MarkPackedCaseLabels(tab_rec);
812 } else if (tab_rec->table[0] == Instruction::kSparseSwitchSignature) {
813 MarkSparseCaseLabels(tab_rec);
814 } else {
815 LOG(FATAL) << "Invalid switch table";
816 }
817 }
818}
819
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700820void Mir2Lir::DumpSparseSwitchTable(const uint16_t* table) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700821 /*
822 * Sparse switch data format:
823 * ushort ident = 0x0200 magic value
824 * ushort size number of entries in the table; > 0
825 * int keys[size] keys, sorted low-to-high; 32-bit aligned
826 * int targets[size] branch targets, relative to switch opcode
827 *
828 * Total size is (2+size*4) 16-bit code units.
829 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700830 uint16_t ident = table[0];
831 int entries = table[1];
832 const int* keys = reinterpret_cast<const int*>(&table[2]);
833 const int* targets = &keys[entries];
834 LOG(INFO) << "Sparse switch table - ident:0x" << std::hex << ident
835 << ", entries: " << std::dec << entries;
836 for (int i = 0; i < entries; i++) {
837 LOG(INFO) << " Key[" << keys[i] << "] -> 0x" << std::hex << targets[i];
838 }
839}
840
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700841void Mir2Lir::DumpPackedSwitchTable(const uint16_t* table) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700842 /*
843 * Packed switch data format:
844 * ushort ident = 0x0100 magic value
845 * ushort size number of entries in the table
846 * int first_key first (and lowest) switch case value
847 * int targets[size] branch targets, relative to switch opcode
848 *
849 * Total size is (4+size*2) 16-bit code units.
850 */
Brian Carlstrom7940e442013-07-12 13:46:57 -0700851 uint16_t ident = table[0];
852 const int* targets = reinterpret_cast<const int*>(&table[4]);
853 int entries = table[1];
854 int low_key = s4FromSwitchData(&table[2]);
855 LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident
856 << ", entries: " << std::dec << entries << ", low_key: " << low_key;
857 for (int i = 0; i < entries; i++) {
858 LOG(INFO) << " Key[" << (i + low_key) << "] -> 0x" << std::hex
859 << targets[i];
860 }
861}
862
863/*
864 * Set up special LIR to mark a Dalvik byte-code instruction start and
865 * record it in the boundary_map. NOTE: in cases such as kMirOpCheck in
866 * which we split a single Dalvik instruction, only the first MIR op
867 * associated with a Dalvik PC should be entered into the map.
868 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700869LIR* Mir2Lir::MarkBoundary(int offset, const char* inst_str) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700870 LIR* res = NewLIR1(kPseudoDalvikByteCodeBoundary, reinterpret_cast<uintptr_t>(inst_str));
871 if (boundary_map_.find(offset) == boundary_map_.end()) {
872 boundary_map_.Put(offset, res);
873 }
874 return res;
875}
876
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700877bool Mir2Lir::EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700878 bool is_taken;
879 switch (opcode) {
880 case Instruction::IF_EQ: is_taken = (src1 == src2); break;
881 case Instruction::IF_NE: is_taken = (src1 != src2); break;
882 case Instruction::IF_LT: is_taken = (src1 < src2); break;
883 case Instruction::IF_GE: is_taken = (src1 >= src2); break;
884 case Instruction::IF_GT: is_taken = (src1 > src2); break;
885 case Instruction::IF_LE: is_taken = (src1 <= src2); break;
886 case Instruction::IF_EQZ: is_taken = (src1 == 0); break;
887 case Instruction::IF_NEZ: is_taken = (src1 != 0); break;
888 case Instruction::IF_LTZ: is_taken = (src1 < 0); break;
889 case Instruction::IF_GEZ: is_taken = (src1 >= 0); break;
890 case Instruction::IF_GTZ: is_taken = (src1 > 0); break;
891 case Instruction::IF_LEZ: is_taken = (src1 <= 0); break;
892 default:
893 LOG(FATAL) << "Unexpected opcode " << opcode;
894 is_taken = false;
895 }
896 return is_taken;
897}
898
899// Convert relation of src1/src2 to src2/src1
900ConditionCode Mir2Lir::FlipComparisonOrder(ConditionCode before) {
901 ConditionCode res;
902 switch (before) {
903 case kCondEq: res = kCondEq; break;
904 case kCondNe: res = kCondNe; break;
905 case kCondLt: res = kCondGt; break;
906 case kCondGt: res = kCondLt; break;
907 case kCondLe: res = kCondGe; break;
908 case kCondGe: res = kCondLe; break;
909 default:
910 res = static_cast<ConditionCode>(0);
911 LOG(FATAL) << "Unexpected ccode " << before;
912 }
913 return res;
914}
915
916// TODO: move to mir_to_lir.cc
917Mir2Lir::Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
918 : Backend(arena),
919 literal_list_(NULL),
920 method_literal_list_(NULL),
921 code_literal_list_(NULL),
922 cu_(cu),
923 mir_graph_(mir_graph),
924 switch_tables_(arena, 4, kGrowableArraySwitchTables),
925 fill_array_data_(arena, 4, kGrowableArrayFillArrayData),
926 throw_launchpads_(arena, 2048, kGrowableArrayThrowLaunchPads),
927 suspend_launchpads_(arena, 4, kGrowableArraySuspendLaunchPads),
928 intrinsic_launchpads_(arena, 2048, kGrowableArrayMisc),
929 data_offset_(0),
930 total_size_(0),
931 block_label_list_(NULL),
932 current_dalvik_offset_(0),
933 reg_pool_(NULL),
934 live_sreg_(0),
935 num_core_spills_(0),
936 num_fp_spills_(0),
937 frame_size_(0),
938 core_spill_mask_(0),
939 fp_spill_mask_(0),
940 first_lir_insn_(NULL),
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700941 last_lir_insn_(NULL) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700942 promotion_map_ = static_cast<PromotionMap*>
943 (arena_->NewMem((cu_->num_dalvik_registers + cu_->num_compiler_temps + 1) *
944 sizeof(promotion_map_[0]), true, ArenaAllocator::kAllocRegAlloc));
945}
946
947void Mir2Lir::Materialize() {
948 CompilerInitializeRegAlloc(); // Needs to happen after SSA naming
949
950 /* Allocate Registers using simple local allocation scheme */
951 SimpleRegAlloc();
952
953 //FIXME: re-enable by retrieving from mir_graph
954 SpecialCaseHandler special_case = kNoHandler;
955
956 if (special_case != kNoHandler) {
957 /*
958 * Custom codegen for special cases. If for any reason the
959 * special codegen doesn't succeed, first_lir_insn_ will
960 * set to NULL;
961 */
962 SpecialMIR2LIR(special_case);
963 }
964
965 /* Convert MIR to LIR, etc. */
966 if (first_lir_insn_ == NULL) {
967 MethodMIR2LIR();
968 }
969
970 /* Method is not empty */
971 if (first_lir_insn_) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700972 // mark the targets of switch statement case labels
973 ProcessSwitchTables();
974
975 /* Convert LIR into machine code. */
976 AssembleLIR();
977
978 if (cu_->verbose) {
979 CodegenDump();
980 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700981 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700982}
983
984CompiledMethod* Mir2Lir::GetCompiledMethod() {
985 // Combine vmap tables - core regs, then fp regs - into vmap_table
986 std::vector<uint16_t> vmap_table;
987 // Core regs may have been inserted out of order - sort first
988 std::sort(core_vmap_table_.begin(), core_vmap_table_.end());
989 for (size_t i = 0 ; i < core_vmap_table_.size(); i++) {
990 // Copy, stripping out the phys register sort key
991 vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]);
992 }
993 // If we have a frame, push a marker to take place of lr
994 if (frame_size_ > 0) {
995 vmap_table.push_back(INVALID_VREG);
996 } else {
997 DCHECK_EQ(__builtin_popcount(core_spill_mask_), 0);
998 DCHECK_EQ(__builtin_popcount(fp_spill_mask_), 0);
999 }
1000 // Combine vmap tables - core regs, then fp regs. fp regs already sorted
1001 for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) {
1002 vmap_table.push_back(fp_vmap_table_[i]);
1003 }
1004 CompiledMethod* result =
1005 new CompiledMethod(cu_->instruction_set, code_buffer_,
1006 frame_size_, core_spill_mask_, fp_spill_mask_,
1007 combined_mapping_table_, vmap_table, native_gc_map_);
1008 return result;
1009}
1010
1011int Mir2Lir::ComputeFrameSize() {
1012 /* Figure out the frame size */
1013 static const uint32_t kAlignMask = kStackAlignment - 1;
1014 uint32_t size = (num_core_spills_ + num_fp_spills_ +
1015 1 /* filler word */ + cu_->num_regs + cu_->num_outs +
1016 cu_->num_compiler_temps + 1 /* cur_method* */)
1017 * sizeof(uint32_t);
1018 /* Align and set */
1019 return (size + kAlignMask) & ~(kAlignMask);
1020}
1021
1022/*
1023 * Append an LIR instruction to the LIR list maintained by a compilation
1024 * unit
1025 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -07001026void Mir2Lir::AppendLIR(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -07001027 if (first_lir_insn_ == NULL) {
1028 DCHECK(last_lir_insn_ == NULL);
1029 last_lir_insn_ = first_lir_insn_ = lir;
1030 lir->prev = lir->next = NULL;
1031 } else {
1032 last_lir_insn_->next = lir;
1033 lir->prev = last_lir_insn_;
1034 lir->next = NULL;
1035 last_lir_insn_ = lir;
1036 }
1037}
1038
1039/*
1040 * Insert an LIR instruction before the current instruction, which cannot be the
1041 * first instruction.
1042 *
1043 * prev_lir <-> new_lir <-> current_lir
1044 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -07001045void Mir2Lir::InsertLIRBefore(LIR* current_lir, LIR* new_lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -07001046 DCHECK(current_lir->prev != NULL);
1047 LIR *prev_lir = current_lir->prev;
1048
1049 prev_lir->next = new_lir;
1050 new_lir->prev = prev_lir;
1051 new_lir->next = current_lir;
1052 current_lir->prev = new_lir;
1053}
1054
1055/*
1056 * Insert an LIR instruction after the current instruction, which cannot be the
1057 * first instruction.
1058 *
1059 * current_lir -> new_lir -> old_next
1060 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -07001061void Mir2Lir::InsertLIRAfter(LIR* current_lir, LIR* new_lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -07001062 new_lir->prev = current_lir;
1063 new_lir->next = current_lir->next;
1064 current_lir->next = new_lir;
1065 new_lir->next->prev = new_lir;
1066}
1067
1068
1069} // namespace art