1 /* 2 * Copyright (C) 2017 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 "slicer/common.h" 18 #include "slicer/code_ir.h" 19 #include "slicer/dex_bytecode.h" 20 #include "slicer/dex_format.h" 21 #include "slicer/dex_ir.h" 22 #include "slicer/dex_leb128.h" 23 #include "slicer/bytecode_encoder.h" 24 #include "slicer/debuginfo_encoder.h" 25 #include "slicer/tryblocks_encoder.h" 26 27 #include <assert.h> 28 #include <string.h> 29 #include <algorithm> 30 #include <cstdlib> 31 #include <type_traits> 32 #include <vector> 33 34 namespace lir { 35 36 void CodeIr::Assemble() { 37 auto ir_code = ir_method->code; 38 SLICER_CHECK(ir_code != nullptr); 39 40 // new .dex bytecode 41 // 42 // NOTE: this must be done before the debug information and 43 // try/catch blocks since here is where we update the final offsets 44 // 45 BytecodeEncoder bytecode_encoder(instructions); 46 bytecode_encoder.Encode(ir_code, dex_ir); 47 48 // debug information 49 if (ir_code->debug_info != nullptr) { 50 DebugInfoEncoder dbginfo_encoder(instructions); 51 dbginfo_encoder.Encode(ir_method, dex_ir); 52 } 53 54 // try/catch blocks 55 TryBlocksEncoder try_blocks_encoder(instructions); 56 try_blocks_encoder.Encode(ir_code, dex_ir); 57 } 58 59 void CodeIr::DissasembleTryBlocks(const ir::Code* ir_code) { 60 int nextTryBlockId = 1; 61 for (const auto& tryBlock : ir_code->try_blocks) { 62 auto try_block_begin = Alloc<TryBlockBegin>(); 63 try_block_begin->id = nextTryBlockId++; 64 try_block_begin->offset = tryBlock.start_addr; 65 66 auto try_block_end = Alloc<TryBlockEnd>(); 67 try_block_end->try_begin = try_block_begin; 68 try_block_end->offset = tryBlock.start_addr + tryBlock.insn_count; 69 70 // parse the catch handlers 71 const dex::u1* ptr = 72 ir_code->catch_handlers.ptr<dex::u1>() + tryBlock.handler_off; 73 int catchCount = dex::ReadSLeb128(&ptr); 74 75 for (int catchIndex = 0; catchIndex < std::abs(catchCount); ++catchIndex) { 76 CatchHandler handler = {}; 77 78 // type 79 dex::u4 type_index = dex::ReadULeb128(&ptr); 80 handler.ir_type = dex_ir->types_map[type_index]; 81 SLICER_CHECK(handler.ir_type != nullptr); 82 83 // address 84 dex::u4 address = dex::ReadULeb128(&ptr); 85 handler.label = GetLabel(address); 86 87 try_block_end->handlers.push_back(handler); 88 } 89 90 // catch_all handler? 91 // 92 // NOTE: this is used to generate code for the "finally" blocks 93 // (see Java Virtual Machine Specification - 3.13 "Compiling finally") 94 // 95 if (catchCount < 1) { 96 dex::u4 address = dex::ReadULeb128(&ptr); 97 try_block_end->catch_all = GetLabel(address); 98 } 99 100 // we should have at least one handler 101 SLICER_CHECK(!try_block_end->handlers.empty() || 102 try_block_end->catch_all != nullptr); 103 104 try_begins_.push_back(try_block_begin); 105 try_ends_.push_back(try_block_end); 106 } 107 } 108 109 void CodeIr::DissasembleDebugInfo(const ir::DebugInfo* ir_debug_info) { 110 if (ir_debug_info == nullptr) { 111 return; 112 } 113 114 // debug info state machine registers 115 dex::u4 address = 0; 116 int line = ir_debug_info->line_start; 117 ir::String* source_file = ir_method->decl->parent->class_def->source_file; 118 119 // header 120 if (!ir_debug_info->param_names.empty()) { 121 auto dbg_header = Alloc<DbgInfoHeader>(); 122 dbg_header->param_names = ir_debug_info->param_names; 123 dbg_header->offset = 0; 124 dbg_annotations_.push_back(dbg_header); 125 } 126 127 // initial source file 128 { 129 auto annotation = Alloc<DbgInfoAnnotation>(dex::DBG_SET_FILE); 130 annotation->offset = 0; 131 annotation->operands.push_back(Alloc<String>( 132 source_file, source_file ? source_file->orig_index : dex::kNoIndex)); 133 dbg_annotations_.push_back(annotation); 134 } 135 136 // initial line number - redundant? 137 { 138 auto annotation = Alloc<DbgInfoAnnotation>(dex::DBG_ADVANCE_LINE); 139 annotation->offset = 0; 140 annotation->operands.push_back(Alloc<LineNumber>(line)); 141 dbg_annotations_.push_back(annotation); 142 } 143 144 // debug info annotations 145 const dex::u1* ptr = ir_debug_info->data.ptr<dex::u1>(); 146 dex::u1 opcode = 0; 147 while ((opcode = *ptr++) != dex::DBG_END_SEQUENCE) { 148 DbgInfoAnnotation* annotation = nullptr; 149 150 switch (opcode) { 151 case dex::DBG_ADVANCE_PC: 152 // addr_diff 153 address += dex::ReadULeb128(&ptr); 154 break; 155 156 case dex::DBG_ADVANCE_LINE: 157 // line_diff 158 line += dex::ReadSLeb128(&ptr); 159 SLICER_WEAK_CHECK(line > 0); 160 break; 161 162 case dex::DBG_START_LOCAL: { 163 annotation = Alloc<DbgInfoAnnotation>(opcode); 164 165 // register_num 166 annotation->operands.push_back(Alloc<VReg>(dex::ReadULeb128(&ptr))); 167 168 // name 169 dex::u4 name_index = dex::ReadULeb128(&ptr) - 1; 170 annotation->operands.push_back(GetString(name_index)); 171 172 // type 173 dex::u4 type_index = dex::ReadULeb128(&ptr) - 1; 174 annotation->operands.push_back(GetType(type_index)); 175 } break; 176 177 case dex::DBG_START_LOCAL_EXTENDED: { 178 annotation = Alloc<DbgInfoAnnotation>(opcode); 179 180 // register_num 181 annotation->operands.push_back(Alloc<VReg>(dex::ReadULeb128(&ptr))); 182 183 // name 184 dex::u4 name_index = dex::ReadULeb128(&ptr) - 1; 185 annotation->operands.push_back(GetString(name_index)); 186 187 // type 188 dex::u4 type_index = dex::ReadULeb128(&ptr) - 1; 189 annotation->operands.push_back(GetType(type_index)); 190 191 // signature 192 dex::u4 sig_index = dex::ReadULeb128(&ptr) - 1; 193 annotation->operands.push_back(GetString(sig_index)); 194 } break; 195 196 case dex::DBG_END_LOCAL: 197 case dex::DBG_RESTART_LOCAL: 198 annotation = Alloc<DbgInfoAnnotation>(opcode); 199 // register_num 200 annotation->operands.push_back(Alloc<VReg>(dex::ReadULeb128(&ptr))); 201 break; 202 203 case dex::DBG_SET_PROLOGUE_END: 204 annotation = Alloc<DbgInfoAnnotation>(opcode); 205 break; 206 207 case dex::DBG_SET_EPILOGUE_BEGIN: 208 annotation = Alloc<DbgInfoAnnotation>(opcode); 209 break; 210 211 case dex::DBG_SET_FILE: { 212 annotation = Alloc<DbgInfoAnnotation>(opcode); 213 214 // source file name 215 dex::u4 name_index = dex::ReadULeb128(&ptr) - 1; 216 source_file = (name_index == dex::kNoIndex) 217 ? nullptr 218 : dex_ir->strings_map[name_index]; 219 annotation->operands.push_back(Alloc<String>(source_file, name_index)); 220 } break; 221 222 default: { 223 int adjusted_opcode = opcode - dex::DBG_FIRST_SPECIAL; 224 line += dex::DBG_LINE_BASE + (adjusted_opcode % dex::DBG_LINE_RANGE); 225 address += (adjusted_opcode / dex::DBG_LINE_RANGE); 226 SLICER_WEAK_CHECK(line > 0); 227 annotation = Alloc<DbgInfoAnnotation>(dex::DBG_ADVANCE_LINE); 228 annotation->operands.push_back(Alloc<LineNumber>(line)); 229 } break; 230 } 231 232 if (annotation != nullptr) { 233 annotation->offset = address; 234 dbg_annotations_.push_back(annotation); 235 } 236 } 237 } 238 239 void CodeIr::DissasembleBytecode(const ir::Code* ir_code) { 240 const dex::u2* begin = ir_code->instructions.begin(); 241 const dex::u2* end = ir_code->instructions.end(); 242 const dex::u2* ptr = begin; 243 244 while (ptr < end) { 245 auto isize = dex::GetWidthFromBytecode(ptr); 246 SLICER_CHECK(isize > 0); 247 248 dex::u4 offset = ptr - begin; 249 250 Instruction* instr = nullptr; 251 switch (*ptr) { 252 case dex::kPackedSwitchSignature: 253 instr = DecodePackedSwitch(ptr, offset); 254 break; 255 256 case dex::kSparseSwitchSignature: 257 instr = DecodeSparseSwitch(ptr, offset); 258 break; 259 260 case dex::kArrayDataSignature: 261 instr = DecodeArrayData(ptr, offset); 262 break; 263 264 default: 265 instr = DecodeBytecode(ptr, offset); 266 break; 267 } 268 269 instr->offset = offset; 270 instructions.push_back(instr); 271 ptr += isize; 272 } 273 SLICER_CHECK(ptr == end); 274 } 275 276 void CodeIr::FixupSwitches() { 277 const dex::u2* begin = ir_method->code->instructions.begin(); 278 279 // packed switches 280 for (auto& fixup : packed_switches_) { 281 FixupPackedSwitch(fixup.second.instr, fixup.second.base_offset, 282 begin + fixup.first); 283 } 284 285 // sparse switches 286 for (auto& fixup : sparse_switches_) { 287 FixupSparseSwitch(fixup.second.instr, fixup.second.base_offset, 288 begin + fixup.first); 289 } 290 } 291 292 // merge a set of extra instructions into the instruction list 293 template <class I_LIST, class E_LIST> 294 static void MergeInstructions(I_LIST& instructions, const E_LIST& extra) { 295 296 // the extra instructins must be sorted by offset 297 SLICER_CHECK(std::is_sorted(extra.begin(), extra.end(), 298 [](const Instruction* a, const Instruction* b) { 299 return a->offset < b->offset; 300 })); 301 302 auto instrIt = instructions.begin(); 303 auto extraIt = extra.begin(); 304 305 while (extraIt != extra.end()) { 306 if (instrIt == instructions.end() || 307 (*extraIt)->offset == (*instrIt)->offset) { 308 instructions.insert(instrIt, *extraIt); 309 ++extraIt; 310 } else { 311 ++instrIt; 312 } 313 } 314 } 315 316 void CodeIr::Dissasemble() { 317 nodes_.clear(); 318 labels_.clear(); 319 320 try_begins_.clear(); 321 try_ends_.clear(); 322 dbg_annotations_.clear(); 323 packed_switches_.clear(); 324 sparse_switches_.clear(); 325 326 auto ir_code = ir_method->code; 327 if (ir_code == nullptr) { 328 return; 329 } 330 331 // decode the .dex bytecodes 332 DissasembleBytecode(ir_code); 333 334 // try/catch blocks 335 DissasembleTryBlocks(ir_code); 336 337 // debug information 338 DissasembleDebugInfo(ir_code->debug_info); 339 340 // fixup switches 341 FixupSwitches(); 342 343 // assign label ids 344 std::vector<Label*> tmp_labels; 345 int nextLabelId = 1; 346 for (auto& label : labels_) { 347 label.second->id = nextLabelId++; 348 tmp_labels.push_back(label.second); 349 } 350 351 // merge the labels into the instructions stream 352 MergeInstructions(instructions, dbg_annotations_); 353 MergeInstructions(instructions, try_begins_); 354 MergeInstructions(instructions, tmp_labels); 355 MergeInstructions(instructions, try_ends_); 356 } 357 358 PackedSwitchPayload* CodeIr::DecodePackedSwitch(const dex::u2* /*ptr*/, 359 dex::u4 offset) { 360 // actual decoding is delayed to FixupPackedSwitch() 361 // (since the label offsets are relative to the referring 362 // instruction, not the switch data) 363 SLICER_CHECK(offset % 2 == 0); 364 auto& instr = packed_switches_[offset].instr; 365 SLICER_CHECK(instr == nullptr); 366 instr = Alloc<PackedSwitchPayload>(); 367 return instr; 368 } 369 370 void CodeIr::FixupPackedSwitch(PackedSwitchPayload* instr, dex::u4 base_offset, 371 const dex::u2* ptr) { 372 SLICER_CHECK(instr->targets.empty()); 373 374 auto dex_packed_switch = reinterpret_cast<const dex::PackedSwitchPayload*>(ptr); 375 SLICER_CHECK(dex_packed_switch->ident == dex::kPackedSwitchSignature); 376 377 instr->first_key = dex_packed_switch->first_key; 378 for (dex::u2 i = 0; i < dex_packed_switch->size; ++i) { 379 instr->targets.push_back( 380 GetLabel(base_offset + dex_packed_switch->targets[i])); 381 } 382 } 383 384 SparseSwitchPayload* CodeIr::DecodeSparseSwitch(const dex::u2* /*ptr*/, 385 dex::u4 offset) { 386 // actual decoding is delayed to FixupSparseSwitch() 387 // (since the label offsets are relative to the referring 388 // instruction, not the switch data) 389 SLICER_CHECK(offset % 2 == 0); 390 auto& instr = sparse_switches_[offset].instr; 391 SLICER_CHECK(instr == nullptr); 392 instr = Alloc<SparseSwitchPayload>(); 393 return instr; 394 } 395 396 void CodeIr::FixupSparseSwitch(SparseSwitchPayload* instr, dex::u4 base_offset, 397 const dex::u2* ptr) { 398 SLICER_CHECK(instr->switch_cases.empty()); 399 400 auto dex_sparse_switch = reinterpret_cast<const dex::SparseSwitchPayload*>(ptr); 401 SLICER_CHECK(dex_sparse_switch->ident == dex::kSparseSwitchSignature); 402 403 auto& data = dex_sparse_switch->data; 404 auto& size = dex_sparse_switch->size; 405 406 for (dex::u2 i = 0; i < size; ++i) { 407 SparseSwitchPayload::SwitchCase switch_case = {}; 408 switch_case.key = data[i]; 409 switch_case.target = GetLabel(base_offset + data[i + size]); 410 instr->switch_cases.push_back(switch_case); 411 } 412 } 413 414 ArrayData* CodeIr::DecodeArrayData(const dex::u2* ptr, dex::u4 offset) { 415 auto dex_array_data = reinterpret_cast<const dex::ArrayData*>(ptr); 416 SLICER_CHECK(dex_array_data->ident == dex::kArrayDataSignature); 417 SLICER_CHECK(offset % 2 == 0); 418 419 auto instr = Alloc<ArrayData>(); 420 instr->data = slicer::MemView(ptr, dex::GetWidthFromBytecode(ptr) * 2); 421 return instr; 422 } 423 424 Operand* CodeIr::GetRegA(const dex::Instruction& dex_instr) { 425 auto verify_flags = dex::GetVerifyFlagsFromOpcode(dex_instr.opcode); 426 if ((verify_flags & dex::kVerifyRegAWide) != 0) { 427 return Alloc<VRegPair>(dex_instr.vA); 428 } else { 429 return Alloc<VReg>(dex_instr.vA); 430 } 431 } 432 433 Operand* CodeIr::GetRegB(const dex::Instruction& dex_instr) { 434 auto verify_flags = dex::GetVerifyFlagsFromOpcode(dex_instr.opcode); 435 if ((verify_flags & dex::kVerifyRegBWide) != 0) { 436 return Alloc<VRegPair>(dex_instr.vB); 437 } else { 438 return Alloc<VReg>(dex_instr.vB); 439 } 440 } 441 442 Operand* CodeIr::GetRegC(const dex::Instruction& dex_instr) { 443 auto verify_flags = dex::GetVerifyFlagsFromOpcode(dex_instr.opcode); 444 if ((verify_flags & dex::kVerifyRegCWide) != 0) { 445 return Alloc<VRegPair>(dex_instr.vC); 446 } else { 447 return Alloc<VReg>(dex_instr.vC); 448 } 449 } 450 451 Bytecode* CodeIr::DecodeBytecode(const dex::u2* ptr, dex::u4 offset) { 452 auto dex_instr = dex::DecodeInstruction(ptr); 453 454 auto instr = Alloc<Bytecode>(); 455 instr->opcode = dex_instr.opcode; 456 457 auto index_type = dex::GetIndexTypeFromOpcode(dex_instr.opcode); 458 459 switch (dex::GetFormatFromOpcode(dex_instr.opcode)) { 460 case dex::k10x: // op 461 break; 462 463 case dex::k12x: // op vA, vB 464 case dex::k22x: // op vAA, vBBBB 465 case dex::k32x: // op vAAAA, vBBBB 466 instr->operands.push_back(GetRegA(dex_instr)); 467 instr->operands.push_back(GetRegB(dex_instr)); 468 break; 469 470 case dex::k11n: // op vA, #+B 471 case dex::k21s: // op vAA, #+BBBB 472 case dex::k31i: // op vAA, #+BBBBBBBB 473 instr->operands.push_back(GetRegA(dex_instr)); 474 instr->operands.push_back(Alloc<Const32>(dex_instr.vB)); 475 break; 476 477 case dex::k11x: // op vAA 478 instr->operands.push_back(GetRegA(dex_instr)); 479 break; 480 481 case dex::k10t: // op +AA 482 case dex::k20t: // op +AAAA 483 case dex::k30t: // op +AAAAAAAA 484 { 485 auto label = GetLabel(offset + dex::s4(dex_instr.vA)); 486 instr->operands.push_back(Alloc<CodeLocation>(label)); 487 } break; 488 489 case dex::k21t: // op vAA, +BBBB 490 case dex::k31t: // op vAA, +BBBBBBBB 491 { 492 dex::u4 targetOffset = offset + dex::s4(dex_instr.vB); 493 instr->operands.push_back(GetRegA(dex_instr)); 494 auto label = GetLabel(targetOffset); 495 instr->operands.push_back(Alloc<CodeLocation>(label)); 496 497 if (dex_instr.opcode == dex::OP_PACKED_SWITCH) { 498 label->aligned = true; 499 dex::u4& base_offset = packed_switches_[targetOffset].base_offset; 500 SLICER_CHECK(base_offset == kInvalidOffset); 501 base_offset = offset; 502 } else if (dex_instr.opcode == dex::OP_SPARSE_SWITCH) { 503 label->aligned = true; 504 dex::u4& base_offset = sparse_switches_[targetOffset].base_offset; 505 SLICER_CHECK(base_offset == kInvalidOffset); 506 base_offset = offset; 507 } else if (dex_instr.opcode == dex::OP_FILL_ARRAY_DATA) { 508 label->aligned = true; 509 } 510 } break; 511 512 case dex::k23x: // op vAA, vBB, vCC 513 instr->operands.push_back(GetRegA(dex_instr)); 514 instr->operands.push_back(GetRegB(dex_instr)); 515 instr->operands.push_back(GetRegC(dex_instr)); 516 break; 517 518 case dex::k22t: // op vA, vB, +CCCC 519 { 520 instr->operands.push_back(GetRegA(dex_instr)); 521 instr->operands.push_back(GetRegB(dex_instr)); 522 auto label = GetLabel(offset + dex::s4(dex_instr.vC)); 523 instr->operands.push_back(Alloc<CodeLocation>(label)); 524 } break; 525 526 case dex::k22b: // op vAA, vBB, #+CC 527 case dex::k22s: // op vA, vB, #+CCCC 528 instr->operands.push_back(GetRegA(dex_instr)); 529 instr->operands.push_back(GetRegB(dex_instr)); 530 instr->operands.push_back(Alloc<Const32>(dex_instr.vC)); 531 break; 532 533 case dex::k22c: // op vA, vB, thing@CCCC 534 instr->operands.push_back(GetRegA(dex_instr)); 535 instr->operands.push_back(GetRegB(dex_instr)); 536 instr->operands.push_back(GetIndexedOperand(index_type, dex_instr.vC)); 537 break; 538 539 case dex::k21c: // op vAA, thing@BBBB 540 case dex::k31c: // op vAA, string@BBBBBBBB 541 instr->operands.push_back(GetRegA(dex_instr)); 542 instr->operands.push_back(GetIndexedOperand(index_type, dex_instr.vB)); 543 break; 544 545 case dex::k35c: // op {vC,vD,vE,vF,vG}, thing@BBBB 546 { 547 SLICER_CHECK(dex_instr.vA <= 5); 548 auto vreg_list = Alloc<VRegList>(); 549 for (dex::u4 i = 0; i < dex_instr.vA; ++i) { 550 vreg_list->registers.push_back(dex_instr.arg[i]); 551 } 552 instr->operands.push_back(vreg_list); 553 instr->operands.push_back(GetIndexedOperand(index_type, dex_instr.vB)); 554 } break; 555 556 case dex::k3rc: // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB 557 { 558 auto vreg_range = Alloc<VRegRange>(dex_instr.vC, dex_instr.vA); 559 instr->operands.push_back(vreg_range); 560 instr->operands.push_back(GetIndexedOperand(index_type, dex_instr.vB)); 561 } break; 562 563 case dex::k21h: // op vAA, #+BBBB0000[00000000] 564 switch (dex_instr.opcode) { 565 case dex::OP_CONST_HIGH16: 566 instr->operands.push_back(GetRegA(dex_instr)); 567 instr->operands.push_back(Alloc<Const32>(dex_instr.vB << 16)); 568 break; 569 570 case dex::OP_CONST_WIDE_HIGH16: 571 instr->operands.push_back(GetRegA(dex_instr)); 572 instr->operands.push_back(Alloc<Const64>(dex::u8(dex_instr.vB) << 48)); 573 break; 574 575 default: 576 SLICER_FATAL("Unexpected opcode 0x%02x", dex_instr.opcode); 577 } 578 break; 579 580 case dex::k51l: // op vAA, #+BBBBBBBBBBBBBBBB 581 instr->operands.push_back(GetRegA(dex_instr)); 582 instr->operands.push_back(Alloc<Const64>(dex_instr.vB_wide)); 583 break; 584 585 default: 586 SLICER_FATAL("Unexpected bytecode format (opcode 0x%02x)", dex_instr.opcode); 587 } 588 589 return instr; 590 } 591 592 // Get a indexed object (string, field, ...) 593 // (index must be valid != kNoIndex) 594 IndexedOperand* CodeIr::GetIndexedOperand(dex::InstructionIndexType index_type, 595 dex::u4 index) { 596 SLICER_CHECK(index != dex::kNoIndex); 597 switch (index_type) { 598 case dex::kIndexStringRef: 599 return Alloc<String>(dex_ir->strings_map[index], index); 600 601 case dex::kIndexTypeRef: 602 return Alloc<Type>(dex_ir->types_map[index], index); 603 604 case dex::kIndexFieldRef: 605 return Alloc<Field>(dex_ir->fields_map[index], index); 606 607 case dex::kIndexMethodRef: 608 return Alloc<Method>(dex_ir->methods_map[index], index); 609 610 default: 611 SLICER_FATAL("Unexpected index type 0x%02x", index_type); 612 } 613 } 614 615 // Get a type based on its index (potentially kNoIndex) 616 Type* CodeIr::GetType(dex::u4 index) { 617 auto ir_type = (index == dex::kNoIndex) ? nullptr : dex_ir->types_map[index]; 618 return Alloc<Type>(ir_type, index); 619 } 620 621 // Get a string based on its index (potentially kNoIndex) 622 String* CodeIr::GetString(dex::u4 index) { 623 auto ir_string = (index == dex::kNoIndex) ? nullptr : dex_ir->strings_map[index]; 624 return Alloc<String>(ir_string, index); 625 } 626 627 // Get en existing, or new label for a particular offset 628 Label* CodeIr::GetLabel(dex::u4 offset) { 629 auto& p = labels_[offset]; 630 if (p == nullptr) { 631 p = Alloc<Label>(offset); 632 } 633 ++p->refCount; 634 return p; 635 } 636 637 } // namespace lir 638