1 //===- bolt/Target/AArch64/AArch64MCPlusBuilder.cpp -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file provides AArch64-specific MCPlus builder. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/AArch64AddressingModes.h" 14 #include "MCTargetDesc/AArch64MCExpr.h" 15 #include "MCTargetDesc/AArch64MCTargetDesc.h" 16 #include "Utils/AArch64BaseInfo.h" 17 #include "bolt/Core/MCPlusBuilder.h" 18 #include "llvm/BinaryFormat/ELF.h" 19 #include "llvm/MC/MCInstrInfo.h" 20 #include "llvm/MC/MCRegisterInfo.h" 21 #include "llvm/Support/Debug.h" 22 #include "llvm/Support/ErrorHandling.h" 23 24 #define DEBUG_TYPE "mcplus" 25 26 using namespace llvm; 27 using namespace bolt; 28 29 namespace { 30 31 class AArch64MCPlusBuilder : public MCPlusBuilder { 32 public: 33 AArch64MCPlusBuilder(const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, 34 const MCRegisterInfo *RegInfo) 35 : MCPlusBuilder(Analysis, Info, RegInfo) {} 36 37 bool equals(const MCTargetExpr &A, const MCTargetExpr &B, 38 CompFuncTy Comp) const override { 39 const auto &AArch64ExprA = cast<AArch64MCExpr>(A); 40 const auto &AArch64ExprB = cast<AArch64MCExpr>(B); 41 if (AArch64ExprA.getKind() != AArch64ExprB.getKind()) 42 return false; 43 44 return MCPlusBuilder::equals(*AArch64ExprA.getSubExpr(), 45 *AArch64ExprB.getSubExpr(), Comp); 46 } 47 48 bool hasEVEXEncoding(const MCInst &) const override { return false; } 49 50 bool isMacroOpFusionPair(ArrayRef<MCInst> Insts) const override { 51 return false; 52 } 53 54 bool shortenInstruction(MCInst &) const override { return false; } 55 56 bool isADRP(const MCInst &Inst) const override { 57 return Inst.getOpcode() == AArch64::ADRP; 58 } 59 60 bool isADR(const MCInst &Inst) const override { 61 return Inst.getOpcode() == AArch64::ADR; 62 } 63 64 void getADRReg(const MCInst &Inst, MCPhysReg &RegName) const override { 65 assert((isADR(Inst) || isADRP(Inst)) && "Not an ADR instruction"); 66 assert(MCPlus::getNumPrimeOperands(Inst) != 0 && 67 "No operands for ADR instruction"); 68 assert(Inst.getOperand(0).isReg() && 69 "Unexpected operand in ADR instruction"); 70 RegName = Inst.getOperand(0).getReg(); 71 } 72 73 bool isTB(const MCInst &Inst) const { 74 return (Inst.getOpcode() == AArch64::TBNZW || 75 Inst.getOpcode() == AArch64::TBNZX || 76 Inst.getOpcode() == AArch64::TBZW || 77 Inst.getOpcode() == AArch64::TBZX); 78 } 79 80 bool isCB(const MCInst &Inst) const { 81 return (Inst.getOpcode() == AArch64::CBNZW || 82 Inst.getOpcode() == AArch64::CBNZX || 83 Inst.getOpcode() == AArch64::CBZW || 84 Inst.getOpcode() == AArch64::CBZX); 85 } 86 87 bool isMOVW(const MCInst &Inst) const { 88 return (Inst.getOpcode() == AArch64::MOVKWi || 89 Inst.getOpcode() == AArch64::MOVKXi || 90 Inst.getOpcode() == AArch64::MOVNWi || 91 Inst.getOpcode() == AArch64::MOVNXi || 92 Inst.getOpcode() == AArch64::MOVZXi || 93 Inst.getOpcode() == AArch64::MOVZWi); 94 } 95 96 bool isADD(const MCInst &Inst) const { 97 return (Inst.getOpcode() == AArch64::ADDSWri || 98 Inst.getOpcode() == AArch64::ADDSWrr || 99 Inst.getOpcode() == AArch64::ADDSWrs || 100 Inst.getOpcode() == AArch64::ADDSWrx || 101 Inst.getOpcode() == AArch64::ADDSXri || 102 Inst.getOpcode() == AArch64::ADDSXrr || 103 Inst.getOpcode() == AArch64::ADDSXrs || 104 Inst.getOpcode() == AArch64::ADDSXrx || 105 Inst.getOpcode() == AArch64::ADDSXrx64 || 106 Inst.getOpcode() == AArch64::ADDWri || 107 Inst.getOpcode() == AArch64::ADDWrr || 108 Inst.getOpcode() == AArch64::ADDWrs || 109 Inst.getOpcode() == AArch64::ADDWrx || 110 Inst.getOpcode() == AArch64::ADDXri || 111 Inst.getOpcode() == AArch64::ADDXrr || 112 Inst.getOpcode() == AArch64::ADDXrs || 113 Inst.getOpcode() == AArch64::ADDXrx || 114 Inst.getOpcode() == AArch64::ADDXrx64); 115 } 116 117 bool isLDRB(const MCInst &Inst) const { 118 return (Inst.getOpcode() == AArch64::LDRBBpost || 119 Inst.getOpcode() == AArch64::LDRBBpre || 120 Inst.getOpcode() == AArch64::LDRBBroW || 121 Inst.getOpcode() == AArch64::LDRBBroX || 122 Inst.getOpcode() == AArch64::LDRBBui || 123 Inst.getOpcode() == AArch64::LDRSBWpost || 124 Inst.getOpcode() == AArch64::LDRSBWpre || 125 Inst.getOpcode() == AArch64::LDRSBWroW || 126 Inst.getOpcode() == AArch64::LDRSBWroX || 127 Inst.getOpcode() == AArch64::LDRSBWui || 128 Inst.getOpcode() == AArch64::LDRSBXpost || 129 Inst.getOpcode() == AArch64::LDRSBXpre || 130 Inst.getOpcode() == AArch64::LDRSBXroW || 131 Inst.getOpcode() == AArch64::LDRSBXroX || 132 Inst.getOpcode() == AArch64::LDRSBXui); 133 } 134 135 bool isLDRH(const MCInst &Inst) const { 136 return (Inst.getOpcode() == AArch64::LDRHHpost || 137 Inst.getOpcode() == AArch64::LDRHHpre || 138 Inst.getOpcode() == AArch64::LDRHHroW || 139 Inst.getOpcode() == AArch64::LDRHHroX || 140 Inst.getOpcode() == AArch64::LDRHHui || 141 Inst.getOpcode() == AArch64::LDRSHWpost || 142 Inst.getOpcode() == AArch64::LDRSHWpre || 143 Inst.getOpcode() == AArch64::LDRSHWroW || 144 Inst.getOpcode() == AArch64::LDRSHWroX || 145 Inst.getOpcode() == AArch64::LDRSHWui || 146 Inst.getOpcode() == AArch64::LDRSHXpost || 147 Inst.getOpcode() == AArch64::LDRSHXpre || 148 Inst.getOpcode() == AArch64::LDRSHXroW || 149 Inst.getOpcode() == AArch64::LDRSHXroX || 150 Inst.getOpcode() == AArch64::LDRSHXui); 151 } 152 153 bool isLDRW(const MCInst &Inst) const { 154 return (Inst.getOpcode() == AArch64::LDRWpost || 155 Inst.getOpcode() == AArch64::LDRWpre || 156 Inst.getOpcode() == AArch64::LDRWroW || 157 Inst.getOpcode() == AArch64::LDRWroX || 158 Inst.getOpcode() == AArch64::LDRWui); 159 } 160 161 bool isLDRX(const MCInst &Inst) const { 162 return (Inst.getOpcode() == AArch64::LDRXpost || 163 Inst.getOpcode() == AArch64::LDRXpre || 164 Inst.getOpcode() == AArch64::LDRXroW || 165 Inst.getOpcode() == AArch64::LDRXroX || 166 Inst.getOpcode() == AArch64::LDRXui); 167 } 168 169 bool isLoad(const MCInst &Inst) const override { 170 return isLDRB(Inst) || isLDRH(Inst) || isLDRW(Inst) || isLDRX(Inst); 171 } 172 173 bool isLoadFromStack(const MCInst &Inst) const { 174 if (!isLoad(Inst)) 175 return false; 176 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); 177 unsigned NumDefs = InstInfo.getNumDefs(); 178 for (unsigned I = NumDefs, E = InstInfo.getNumOperands(); I < E; ++I) { 179 const MCOperand &Operand = Inst.getOperand(I); 180 if (!Operand.isReg()) 181 continue; 182 unsigned Reg = Operand.getReg(); 183 if (Reg == AArch64::SP || Reg == AArch64::WSP || Reg == AArch64::FP || 184 Reg == AArch64::W29) 185 return true; 186 } 187 return false; 188 } 189 190 bool isRegToRegMove(const MCInst &Inst, MCPhysReg &From, 191 MCPhysReg &To) const override { 192 if (Inst.getOpcode() != AArch64::ORRXrs) 193 return false; 194 if (Inst.getOperand(1).getReg() != AArch64::XZR) 195 return false; 196 if (Inst.getOperand(3).getImm() != 0) 197 return false; 198 From = Inst.getOperand(2).getReg(); 199 To = Inst.getOperand(0).getReg(); 200 return true; 201 } 202 203 bool isIndirectCall(const MCInst &Inst) const override { 204 return Inst.getOpcode() == AArch64::BLR; 205 } 206 207 bool hasPCRelOperand(const MCInst &Inst) const override { 208 // ADRP is blacklisted and is an exception. Even though it has a 209 // PC-relative operand, this operand is not a complete symbol reference 210 // and BOLT shouldn't try to process it in isolation. 211 if (isADRP(Inst)) 212 return false; 213 214 if (isADR(Inst)) 215 return true; 216 217 // Look for literal addressing mode (see C1-143 ARM DDI 0487B.a) 218 const MCInstrDesc &MCII = Info->get(Inst.getOpcode()); 219 for (unsigned I = 0, E = MCII.getNumOperands(); I != E; ++I) 220 if (MCII.OpInfo[I].OperandType == MCOI::OPERAND_PCREL) 221 return true; 222 223 return false; 224 } 225 226 bool evaluateADR(const MCInst &Inst, int64_t &Imm, 227 const MCExpr **DispExpr) const { 228 assert((isADR(Inst) || isADRP(Inst)) && "Not an ADR instruction"); 229 230 const MCOperand &Label = Inst.getOperand(1); 231 if (!Label.isImm()) { 232 assert(Label.isExpr() && "Unexpected ADR operand"); 233 assert(DispExpr && "DispExpr must be set"); 234 *DispExpr = Label.getExpr(); 235 return false; 236 } 237 238 if (Inst.getOpcode() == AArch64::ADR) { 239 Imm = Label.getImm(); 240 return true; 241 } 242 Imm = Label.getImm() << 12; 243 return true; 244 } 245 246 bool evaluateAArch64MemoryOperand(const MCInst &Inst, int64_t &DispImm, 247 const MCExpr **DispExpr = nullptr) const { 248 if (isADR(Inst) || isADRP(Inst)) 249 return evaluateADR(Inst, DispImm, DispExpr); 250 251 // Literal addressing mode 252 const MCInstrDesc &MCII = Info->get(Inst.getOpcode()); 253 for (unsigned I = 0, E = MCII.getNumOperands(); I != E; ++I) { 254 if (MCII.OpInfo[I].OperandType != MCOI::OPERAND_PCREL) 255 continue; 256 257 if (!Inst.getOperand(I).isImm()) { 258 assert(Inst.getOperand(I).isExpr() && "Unexpected PCREL operand"); 259 assert(DispExpr && "DispExpr must be set"); 260 *DispExpr = Inst.getOperand(I).getExpr(); 261 return true; 262 } 263 264 DispImm = Inst.getOperand(I).getImm() << 2; 265 return true; 266 } 267 return false; 268 } 269 270 bool evaluateMemOperandTarget(const MCInst &Inst, uint64_t &Target, 271 uint64_t Address, 272 uint64_t Size) const override { 273 int64_t DispValue; 274 const MCExpr *DispExpr = nullptr; 275 if (!evaluateAArch64MemoryOperand(Inst, DispValue, &DispExpr)) 276 return false; 277 278 // Make sure it's a well-formed addressing we can statically evaluate. 279 if (DispExpr) 280 return false; 281 282 Target = DispValue; 283 if (Inst.getOpcode() == AArch64::ADRP) 284 Target += Address & ~0xFFFULL; 285 else 286 Target += Address; 287 return true; 288 } 289 290 bool replaceMemOperandDisp(MCInst &Inst, MCOperand Operand) const override { 291 MCInst::iterator OI = Inst.begin(); 292 if (isADR(Inst) || isADRP(Inst)) { 293 assert(MCPlus::getNumPrimeOperands(Inst) >= 2 && 294 "Unexpected number of operands"); 295 ++OI; 296 } else { 297 const MCInstrDesc &MCII = Info->get(Inst.getOpcode()); 298 for (unsigned I = 0, E = MCII.getNumOperands(); I != E; ++I) { 299 if (MCII.OpInfo[I].OperandType == MCOI::OPERAND_PCREL) 300 break; 301 ++OI; 302 } 303 assert(OI != Inst.end() && "Literal operand not found"); 304 } 305 *OI = Operand; 306 return true; 307 } 308 309 const MCExpr *getTargetExprFor(MCInst &Inst, const MCExpr *Expr, 310 MCContext &Ctx, 311 uint64_t RelType) const override { 312 313 if (isADR(Inst) || RelType == ELF::R_AARCH64_ADR_PREL_LO21 || 314 RelType == ELF::R_AARCH64_TLSDESC_ADR_PREL21) { 315 return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, Ctx); 316 } else if (isADRP(Inst) || RelType == ELF::R_AARCH64_ADR_PREL_PG_HI21 || 317 RelType == ELF::R_AARCH64_ADR_PREL_PG_HI21_NC || 318 RelType == ELF::R_AARCH64_TLSDESC_ADR_PAGE21 || 319 RelType == ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 || 320 RelType == ELF::R_AARCH64_ADR_GOT_PAGE) { 321 // Never emit a GOT reloc, we handled this in 322 // RewriteInstance::readRelocations(). 323 return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, Ctx); 324 } else { 325 switch (RelType) { 326 case ELF::R_AARCH64_ADD_ABS_LO12_NC: 327 case ELF::R_AARCH64_LD64_GOT_LO12_NC: 328 case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 329 case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 330 case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 331 case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 332 case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 333 case ELF::R_AARCH64_TLSDESC_ADD_LO12: 334 case ELF::R_AARCH64_TLSDESC_LD64_LO12: 335 case ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: 336 case ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: 337 return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_LO12, Ctx); 338 case ELF::R_AARCH64_MOVW_UABS_G3: 339 return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_G3, Ctx); 340 case ELF::R_AARCH64_MOVW_UABS_G2: 341 case ELF::R_AARCH64_MOVW_UABS_G2_NC: 342 return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_G2_NC, Ctx); 343 case ELF::R_AARCH64_MOVW_UABS_G1: 344 case ELF::R_AARCH64_MOVW_UABS_G1_NC: 345 return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_G1_NC, Ctx); 346 case ELF::R_AARCH64_MOVW_UABS_G0: 347 case ELF::R_AARCH64_MOVW_UABS_G0_NC: 348 return AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_G0_NC, Ctx); 349 default: 350 break; 351 } 352 } 353 return Expr; 354 } 355 356 bool getSymbolRefOperandNum(const MCInst &Inst, unsigned &OpNum) const { 357 if (OpNum >= MCPlus::getNumPrimeOperands(Inst)) 358 return false; 359 360 // Auto-select correct operand number 361 if (OpNum == 0) { 362 if (isConditionalBranch(Inst) || isADR(Inst) || isADRP(Inst)) 363 OpNum = 1; 364 if (isTB(Inst)) 365 OpNum = 2; 366 if (isMOVW(Inst)) 367 OpNum = 1; 368 } 369 370 return true; 371 } 372 373 const MCSymbol *getTargetSymbol(const MCExpr *Expr) const override { 374 auto *AArchExpr = dyn_cast<AArch64MCExpr>(Expr); 375 if (AArchExpr && AArchExpr->getSubExpr()) 376 return getTargetSymbol(AArchExpr->getSubExpr()); 377 378 auto *BinExpr = dyn_cast<MCBinaryExpr>(Expr); 379 if (BinExpr) 380 return getTargetSymbol(BinExpr->getLHS()); 381 382 auto *SymExpr = dyn_cast<MCSymbolRefExpr>(Expr); 383 if (SymExpr && SymExpr->getKind() == MCSymbolRefExpr::VK_None) 384 return &SymExpr->getSymbol(); 385 386 return nullptr; 387 } 388 389 const MCSymbol *getTargetSymbol(const MCInst &Inst, 390 unsigned OpNum = 0) const override { 391 if (!getSymbolRefOperandNum(Inst, OpNum)) 392 return nullptr; 393 394 const MCOperand &Op = Inst.getOperand(OpNum); 395 if (!Op.isExpr()) 396 return nullptr; 397 398 return getTargetSymbol(Op.getExpr()); 399 } 400 401 int64_t getTargetAddend(const MCExpr *Expr) const override { 402 auto *AArchExpr = dyn_cast<AArch64MCExpr>(Expr); 403 if (AArchExpr && AArchExpr->getSubExpr()) 404 return getTargetAddend(AArchExpr->getSubExpr()); 405 406 auto *BinExpr = dyn_cast<MCBinaryExpr>(Expr); 407 if (BinExpr && BinExpr->getOpcode() == MCBinaryExpr::Add) 408 return getTargetAddend(BinExpr->getRHS()); 409 410 auto *ConstExpr = dyn_cast<MCConstantExpr>(Expr); 411 if (ConstExpr) 412 return ConstExpr->getValue(); 413 414 return 0; 415 } 416 417 int64_t getTargetAddend(const MCInst &Inst, 418 unsigned OpNum = 0) const override { 419 if (!getSymbolRefOperandNum(Inst, OpNum)) 420 return 0; 421 422 const MCOperand &Op = Inst.getOperand(OpNum); 423 if (!Op.isExpr()) 424 return 0; 425 426 return getTargetAddend(Op.getExpr()); 427 } 428 429 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, 430 uint64_t &Target) const override { 431 size_t OpNum = 0; 432 433 if (isConditionalBranch(Inst)) { 434 assert(MCPlus::getNumPrimeOperands(Inst) >= 2 && 435 "Invalid number of operands"); 436 OpNum = 1; 437 } 438 439 if (isTB(Inst)) { 440 assert(MCPlus::getNumPrimeOperands(Inst) >= 3 && 441 "Invalid number of operands"); 442 OpNum = 2; 443 } 444 445 if (Info->get(Inst.getOpcode()).OpInfo[OpNum].OperandType != 446 MCOI::OPERAND_PCREL) { 447 assert((isIndirectBranch(Inst) || isIndirectCall(Inst)) && 448 "FAILED evaluateBranch"); 449 return false; 450 } 451 452 int64_t Imm = Inst.getOperand(OpNum).getImm() << 2; 453 Target = Addr + Imm; 454 return true; 455 } 456 457 bool replaceBranchTarget(MCInst &Inst, const MCSymbol *TBB, 458 MCContext *Ctx) const override { 459 assert((isCall(Inst) || isBranch(Inst)) && !isIndirectBranch(Inst) && 460 "Invalid instruction"); 461 assert(MCPlus::getNumPrimeOperands(Inst) >= 1 && 462 "Invalid number of operands"); 463 MCInst::iterator OI = Inst.begin(); 464 465 if (isConditionalBranch(Inst)) { 466 assert(MCPlus::getNumPrimeOperands(Inst) >= 2 && 467 "Invalid number of operands"); 468 ++OI; 469 } 470 471 if (isTB(Inst)) { 472 assert(MCPlus::getNumPrimeOperands(Inst) >= 3 && 473 "Invalid number of operands"); 474 OI = Inst.begin() + 2; 475 } 476 477 *OI = MCOperand::createExpr( 478 MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx)); 479 return true; 480 } 481 482 /// Matches indirect branch patterns in AArch64 related to a jump table (JT), 483 /// helping us to build the complete CFG. A typical indirect branch to 484 /// a jump table entry in AArch64 looks like the following: 485 /// 486 /// adrp x1, #-7585792 # Get JT Page location 487 /// add x1, x1, #692 # Complement with JT Page offset 488 /// ldrh w0, [x1, w0, uxtw #1] # Loads JT entry 489 /// adr x1, #12 # Get PC + 12 (end of this BB) used next 490 /// add x0, x1, w0, sxth #2 # Finish building branch target 491 /// # (entries in JT are relative to the end 492 /// # of this BB) 493 /// br x0 # Indirect jump instruction 494 /// 495 bool analyzeIndirectBranchFragment( 496 const MCInst &Inst, 497 DenseMap<const MCInst *, SmallVector<MCInst *, 4>> &UDChain, 498 const MCExpr *&JumpTable, int64_t &Offset, int64_t &ScaleValue, 499 MCInst *&PCRelBase) const { 500 // Expect AArch64 BR 501 assert(Inst.getOpcode() == AArch64::BR && "Unexpected opcode"); 502 503 // Match the indirect branch pattern for aarch64 504 SmallVector<MCInst *, 4> &UsesRoot = UDChain[&Inst]; 505 if (UsesRoot.size() == 0 || UsesRoot[0] == nullptr) 506 return false; 507 508 const MCInst *DefAdd = UsesRoot[0]; 509 510 // Now we match an ADD 511 if (!isADD(*DefAdd)) { 512 // If the address is not broken up in two parts, this is not branching 513 // according to a jump table entry. Fail. 514 return false; 515 } 516 if (DefAdd->getOpcode() == AArch64::ADDXri) { 517 // This can happen when there is no offset, but a direct jump that was 518 // transformed into an indirect one (indirect tail call) : 519 // ADRP x2, Perl_re_compiler 520 // ADD x2, x2, :lo12:Perl_re_compiler 521 // BR x2 522 return false; 523 } 524 if (DefAdd->getOpcode() == AArch64::ADDXrs) { 525 // Covers the less common pattern where JT entries are relative to 526 // the JT itself (like x86). Seems less efficient since we can't 527 // assume the JT is aligned at 4B boundary and thus drop 2 bits from 528 // JT values. 529 // cde264: 530 // adrp x12, #21544960 ; 216a000 531 // add x12, x12, #1696 ; 216a6a0 (JT object in .rodata) 532 // ldrsw x8, [x12, x8, lsl #2] --> loads e.g. 0xfeb73bd8 533 // * add x8, x8, x12 --> = cde278, next block 534 // br x8 535 // cde278: 536 // 537 // Parsed as ADDXrs reg:x8 reg:x8 reg:x12 imm:0 538 return false; 539 } 540 assert(DefAdd->getOpcode() == AArch64::ADDXrx && 541 "Failed to match indirect branch!"); 542 543 // Validate ADD operands 544 int64_t OperandExtension = DefAdd->getOperand(3).getImm(); 545 unsigned ShiftVal = AArch64_AM::getArithShiftValue(OperandExtension); 546 AArch64_AM::ShiftExtendType ExtendType = 547 AArch64_AM::getArithExtendType(OperandExtension); 548 if (ShiftVal != 2) 549 llvm_unreachable("Failed to match indirect branch! (fragment 2)"); 550 551 if (ExtendType == AArch64_AM::SXTB) 552 ScaleValue = 1LL; 553 else if (ExtendType == AArch64_AM::SXTH) 554 ScaleValue = 2LL; 555 else if (ExtendType == AArch64_AM::SXTW) 556 ScaleValue = 4LL; 557 else 558 llvm_unreachable("Failed to match indirect branch! (fragment 3)"); 559 560 // Match an ADR to load base address to be used when addressing JT targets 561 SmallVector<MCInst *, 4> &UsesAdd = UDChain[DefAdd]; 562 if (UsesAdd.size() <= 1 || UsesAdd[1] == nullptr || UsesAdd[2] == nullptr) { 563 // This happens when we don't have enough context about this jump table 564 // because the jumping code sequence was split in multiple basic blocks. 565 // This was observed in the wild in HHVM code (dispatchImpl). 566 return false; 567 } 568 MCInst *DefBaseAddr = UsesAdd[1]; 569 assert(DefBaseAddr->getOpcode() == AArch64::ADR && 570 "Failed to match indirect branch pattern! (fragment 3)"); 571 572 PCRelBase = DefBaseAddr; 573 // Match LOAD to load the jump table (relative) target 574 const MCInst *DefLoad = UsesAdd[2]; 575 assert(isLoad(*DefLoad) && 576 "Failed to match indirect branch load pattern! (1)"); 577 assert((ScaleValue != 1LL || isLDRB(*DefLoad)) && 578 "Failed to match indirect branch load pattern! (2)"); 579 assert((ScaleValue != 2LL || isLDRH(*DefLoad)) && 580 "Failed to match indirect branch load pattern! (3)"); 581 582 // Match ADD that calculates the JumpTable Base Address (not the offset) 583 SmallVector<MCInst *, 4> &UsesLoad = UDChain[DefLoad]; 584 const MCInst *DefJTBaseAdd = UsesLoad[1]; 585 MCPhysReg From, To; 586 if (DefJTBaseAdd == nullptr || isLoadFromStack(*DefJTBaseAdd) || 587 isRegToRegMove(*DefJTBaseAdd, From, To)) { 588 // Sometimes base address may have been defined in another basic block 589 // (hoisted). Return with no jump table info. 590 JumpTable = nullptr; 591 return true; 592 } 593 594 assert(DefJTBaseAdd->getOpcode() == AArch64::ADDXri && 595 "Failed to match jump table base address pattern! (1)"); 596 597 if (DefJTBaseAdd->getOperand(2).isImm()) 598 Offset = DefJTBaseAdd->getOperand(2).getImm(); 599 SmallVector<MCInst *, 4> &UsesJTBaseAdd = UDChain[DefJTBaseAdd]; 600 const MCInst *DefJTBasePage = UsesJTBaseAdd[1]; 601 if (DefJTBasePage == nullptr || isLoadFromStack(*DefJTBasePage)) { 602 JumpTable = nullptr; 603 return true; 604 } 605 assert(DefJTBasePage->getOpcode() == AArch64::ADRP && 606 "Failed to match jump table base page pattern! (2)"); 607 if (DefJTBasePage->getOperand(1).isExpr()) 608 JumpTable = DefJTBasePage->getOperand(1).getExpr(); 609 return true; 610 } 611 612 DenseMap<const MCInst *, SmallVector<MCInst *, 4>> 613 computeLocalUDChain(const MCInst *CurInstr, InstructionIterator Begin, 614 InstructionIterator End) const { 615 DenseMap<int, MCInst *> RegAliasTable; 616 DenseMap<const MCInst *, SmallVector<MCInst *, 4>> Uses; 617 618 auto addInstrOperands = [&](const MCInst &Instr) { 619 // Update Uses table 620 for (unsigned OpNum = 0, OpEnd = MCPlus::getNumPrimeOperands(Instr); 621 OpNum != OpEnd; ++OpNum) { 622 if (!Instr.getOperand(OpNum).isReg()) 623 continue; 624 unsigned Reg = Instr.getOperand(OpNum).getReg(); 625 MCInst *AliasInst = RegAliasTable[Reg]; 626 Uses[&Instr].push_back(AliasInst); 627 LLVM_DEBUG({ 628 dbgs() << "Adding reg operand " << Reg << " refs "; 629 if (AliasInst != nullptr) 630 AliasInst->dump(); 631 else 632 dbgs() << "\n"; 633 }); 634 } 635 }; 636 637 LLVM_DEBUG(dbgs() << "computeLocalUDChain\n"); 638 bool TerminatorSeen = false; 639 for (auto II = Begin; II != End; ++II) { 640 MCInst &Instr = *II; 641 // Ignore nops and CFIs 642 if (isPseudo(Instr) || isNoop(Instr)) 643 continue; 644 if (TerminatorSeen) { 645 RegAliasTable.clear(); 646 Uses.clear(); 647 } 648 649 LLVM_DEBUG(dbgs() << "Now updating for:\n "); 650 LLVM_DEBUG(Instr.dump()); 651 addInstrOperands(Instr); 652 653 BitVector Regs = BitVector(RegInfo->getNumRegs(), false); 654 getWrittenRegs(Instr, Regs); 655 656 // Update register definitions after this point 657 int Idx = Regs.find_first(); 658 while (Idx != -1) { 659 RegAliasTable[Idx] = &Instr; 660 LLVM_DEBUG(dbgs() << "Setting reg " << Idx 661 << " def to current instr.\n"); 662 Idx = Regs.find_next(Idx); 663 } 664 665 TerminatorSeen = isTerminator(Instr); 666 } 667 668 // Process the last instruction, which is not currently added into the 669 // instruction stream 670 if (CurInstr) 671 addInstrOperands(*CurInstr); 672 673 return Uses; 674 } 675 676 IndirectBranchType analyzeIndirectBranch( 677 MCInst &Instruction, InstructionIterator Begin, InstructionIterator End, 678 const unsigned PtrSize, MCInst *&MemLocInstrOut, unsigned &BaseRegNumOut, 679 unsigned &IndexRegNumOut, int64_t &DispValueOut, 680 const MCExpr *&DispExprOut, MCInst *&PCRelBaseOut) const override { 681 MemLocInstrOut = nullptr; 682 BaseRegNumOut = AArch64::NoRegister; 683 IndexRegNumOut = AArch64::NoRegister; 684 DispValueOut = 0; 685 DispExprOut = nullptr; 686 687 // An instruction referencing memory used by jump instruction (directly or 688 // via register). This location could be an array of function pointers 689 // in case of indirect tail call, or a jump table. 690 MCInst *MemLocInstr = nullptr; 691 692 // Analyze the memory location. 693 int64_t ScaleValue, DispValue; 694 const MCExpr *DispExpr; 695 696 DenseMap<const MCInst *, SmallVector<llvm::MCInst *, 4>> UDChain = 697 computeLocalUDChain(&Instruction, Begin, End); 698 MCInst *PCRelBase; 699 if (!analyzeIndirectBranchFragment(Instruction, UDChain, DispExpr, 700 DispValue, ScaleValue, PCRelBase)) 701 return IndirectBranchType::UNKNOWN; 702 703 MemLocInstrOut = MemLocInstr; 704 DispValueOut = DispValue; 705 DispExprOut = DispExpr; 706 PCRelBaseOut = PCRelBase; 707 return IndirectBranchType::POSSIBLE_PIC_JUMP_TABLE; 708 } 709 710 /// Matches PLT entry pattern and returns the associated GOT entry address. 711 /// Typical PLT entry looks like the following: 712 /// 713 /// adrp x16, 230000 714 /// ldr x17, [x16, #3040] 715 /// add x16, x16, #0xbe0 716 /// br x17 717 /// 718 uint64_t analyzePLTEntry(MCInst &Instruction, InstructionIterator Begin, 719 InstructionIterator End, 720 uint64_t BeginPC) const override { 721 // Check branch instruction 722 MCInst *Branch = &Instruction; 723 assert(Branch->getOpcode() == AArch64::BR && "Unexpected opcode"); 724 725 DenseMap<const MCInst *, SmallVector<llvm::MCInst *, 4>> UDChain = 726 computeLocalUDChain(Branch, Begin, End); 727 728 // Match ldr instruction 729 SmallVector<MCInst *, 4> &BranchUses = UDChain[Branch]; 730 if (BranchUses.size() < 1 || BranchUses[0] == nullptr) 731 return 0; 732 733 // Check ldr instruction 734 const MCInst *Ldr = BranchUses[0]; 735 if (Ldr->getOpcode() != AArch64::LDRXui) 736 return 0; 737 738 // Get ldr value 739 const unsigned ScaleLdr = 8; // LDRX operates on 8 bytes segments 740 assert(Ldr->getOperand(2).isImm() && "Unexpected ldr operand"); 741 const uint64_t Offset = Ldr->getOperand(2).getImm() * ScaleLdr; 742 743 // Match adrp instruction 744 SmallVector<MCInst *, 4> &LdrUses = UDChain[Ldr]; 745 if (LdrUses.size() < 2 || LdrUses[1] == nullptr) 746 return 0; 747 748 // Check adrp instruction 749 MCInst *Adrp = LdrUses[1]; 750 if (Adrp->getOpcode() != AArch64::ADRP) 751 return 0; 752 753 // Get adrp instruction PC 754 const unsigned InstSize = 4; 755 uint64_t AdrpPC = BeginPC; 756 for (InstructionIterator It = Begin; It != End; ++It) { 757 if (&(*It) == Adrp) 758 break; 759 AdrpPC += InstSize; 760 } 761 762 // Get adrp value 763 uint64_t Base; 764 assert(Adrp->getOperand(1).isImm() && "Unexpected adrp operand"); 765 bool Ret = evaluateMemOperandTarget(*Adrp, Base, AdrpPC, InstSize); 766 assert(Ret && "Failed to evaluate adrp"); 767 768 return Base + Offset; 769 } 770 771 unsigned getInvertedBranchOpcode(unsigned Opcode) const { 772 switch (Opcode) { 773 default: 774 llvm_unreachable("Failed to invert branch opcode"); 775 return Opcode; 776 case AArch64::TBZW: return AArch64::TBNZW; 777 case AArch64::TBZX: return AArch64::TBNZX; 778 case AArch64::TBNZW: return AArch64::TBZW; 779 case AArch64::TBNZX: return AArch64::TBZX; 780 case AArch64::CBZW: return AArch64::CBNZW; 781 case AArch64::CBZX: return AArch64::CBNZX; 782 case AArch64::CBNZW: return AArch64::CBZW; 783 case AArch64::CBNZX: return AArch64::CBZX; 784 } 785 } 786 787 unsigned getCondCode(const MCInst &Inst) const override { 788 // AArch64 does not use conditional codes, so we just return the opcode 789 // of the conditional branch here. 790 return Inst.getOpcode(); 791 } 792 793 unsigned getCanonicalBranchCondCode(unsigned Opcode) const override { 794 switch (Opcode) { 795 default: 796 return Opcode; 797 case AArch64::TBNZW: return AArch64::TBZW; 798 case AArch64::TBNZX: return AArch64::TBZX; 799 case AArch64::CBNZW: return AArch64::CBZW; 800 case AArch64::CBNZX: return AArch64::CBZX; 801 } 802 } 803 804 bool reverseBranchCondition(MCInst &Inst, const MCSymbol *TBB, 805 MCContext *Ctx) const override { 806 if (isTB(Inst) || isCB(Inst)) { 807 Inst.setOpcode(getInvertedBranchOpcode(Inst.getOpcode())); 808 assert(Inst.getOpcode() != 0 && "Invalid branch instruction"); 809 } else if (Inst.getOpcode() == AArch64::Bcc) { 810 Inst.getOperand(0).setImm(AArch64CC::getInvertedCondCode( 811 static_cast<AArch64CC::CondCode>(Inst.getOperand(0).getImm()))); 812 assert(Inst.getOperand(0).getImm() != AArch64CC::AL && 813 Inst.getOperand(0).getImm() != AArch64CC::NV && 814 "Can't reverse ALWAYS cond code"); 815 } else { 816 LLVM_DEBUG(Inst.dump()); 817 llvm_unreachable("Unrecognized branch instruction"); 818 } 819 return replaceBranchTarget(Inst, TBB, Ctx); 820 } 821 822 int getPCRelEncodingSize(const MCInst &Inst) const override { 823 switch (Inst.getOpcode()) { 824 default: 825 llvm_unreachable("Failed to get pcrel encoding size"); 826 return 0; 827 case AArch64::TBZW: return 16; 828 case AArch64::TBZX: return 16; 829 case AArch64::TBNZW: return 16; 830 case AArch64::TBNZX: return 16; 831 case AArch64::CBZW: return 21; 832 case AArch64::CBZX: return 21; 833 case AArch64::CBNZW: return 21; 834 case AArch64::CBNZX: return 21; 835 case AArch64::B: return 28; 836 case AArch64::BL: return 28; 837 case AArch64::Bcc: return 21; 838 } 839 } 840 841 int getShortJmpEncodingSize() const override { return 33; } 842 843 int getUncondBranchEncodingSize() const override { return 28; } 844 845 bool createTailCall(MCInst &Inst, const MCSymbol *Target, 846 MCContext *Ctx) override { 847 Inst.setOpcode(AArch64::B); 848 Inst.addOperand(MCOperand::createExpr(getTargetExprFor( 849 Inst, MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx), 850 *Ctx, 0))); 851 setTailCall(Inst); 852 return true; 853 } 854 855 void createLongTailCall(InstructionListType &Seq, const MCSymbol *Target, 856 MCContext *Ctx) override { 857 createShortJmp(Seq, Target, Ctx, /*IsTailCall*/ true); 858 } 859 860 bool createTrap(MCInst &Inst) const override { 861 Inst.clear(); 862 Inst.setOpcode(AArch64::BRK); 863 Inst.addOperand(MCOperand::createImm(1)); 864 return true; 865 } 866 867 bool convertJmpToTailCall(MCInst &Inst) override { 868 setTailCall(Inst); 869 return true; 870 } 871 872 bool convertTailCallToJmp(MCInst &Inst) override { 873 removeAnnotation(Inst, MCPlus::MCAnnotation::kTailCall); 874 clearOffset(Inst); 875 if (getConditionalTailCall(Inst)) 876 unsetConditionalTailCall(Inst); 877 return true; 878 } 879 880 bool lowerTailCall(MCInst &Inst) override { 881 removeAnnotation(Inst, MCPlus::MCAnnotation::kTailCall); 882 if (getConditionalTailCall(Inst)) 883 unsetConditionalTailCall(Inst); 884 return true; 885 } 886 887 bool isNoop(const MCInst &Inst) const override { 888 return Inst.getOpcode() == AArch64::HINT && 889 Inst.getOperand(0).getImm() == 0; 890 } 891 892 bool createNoop(MCInst &Inst) const override { 893 Inst.setOpcode(AArch64::HINT); 894 Inst.clear(); 895 Inst.addOperand(MCOperand::createImm(0)); 896 return true; 897 } 898 899 bool isStore(const MCInst &Inst) const override { return false; } 900 901 bool analyzeBranch(InstructionIterator Begin, InstructionIterator End, 902 const MCSymbol *&TBB, const MCSymbol *&FBB, 903 MCInst *&CondBranch, 904 MCInst *&UncondBranch) const override { 905 auto I = End; 906 907 while (I != Begin) { 908 --I; 909 910 // Ignore nops and CFIs 911 if (isPseudo(*I) || isNoop(*I)) 912 continue; 913 914 // Stop when we find the first non-terminator 915 if (!isTerminator(*I) || isTailCall(*I) || !isBranch(*I)) 916 break; 917 918 // Handle unconditional branches. 919 if (isUnconditionalBranch(*I)) { 920 // If any code was seen after this unconditional branch, we've seen 921 // unreachable code. Ignore them. 922 CondBranch = nullptr; 923 UncondBranch = &*I; 924 const MCSymbol *Sym = getTargetSymbol(*I); 925 assert(Sym != nullptr && 926 "Couldn't extract BB symbol from jump operand"); 927 TBB = Sym; 928 continue; 929 } 930 931 // Handle conditional branches and ignore indirect branches 932 if (isIndirectBranch(*I)) 933 return false; 934 935 if (CondBranch == nullptr) { 936 const MCSymbol *TargetBB = getTargetSymbol(*I); 937 if (TargetBB == nullptr) { 938 // Unrecognized branch target 939 return false; 940 } 941 FBB = TBB; 942 TBB = TargetBB; 943 CondBranch = &*I; 944 continue; 945 } 946 947 llvm_unreachable("multiple conditional branches in one BB"); 948 } 949 return true; 950 } 951 952 void createLongJmp(InstructionListType &Seq, const MCSymbol *Target, 953 MCContext *Ctx, bool IsTailCall) override { 954 // ip0 (r16) is reserved to the linker (refer to 5.3.1.1 of "Procedure Call 955 // Standard for the ARM 64-bit Architecture (AArch64)". 956 // The sequence of instructions we create here is the following: 957 // movz ip0, #:abs_g3:<addr> 958 // movk ip0, #:abs_g2_nc:<addr> 959 // movk ip0, #:abs_g1_nc:<addr> 960 // movk ip0, #:abs_g0_nc:<addr> 961 // br ip0 962 MCInst Inst; 963 Inst.setOpcode(AArch64::MOVZXi); 964 Inst.addOperand(MCOperand::createReg(AArch64::X16)); 965 Inst.addOperand(MCOperand::createExpr(AArch64MCExpr::create( 966 MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx), 967 AArch64MCExpr::VK_ABS_G3, *Ctx))); 968 Inst.addOperand(MCOperand::createImm(0x30)); 969 Seq.emplace_back(Inst); 970 971 Inst.clear(); 972 Inst.setOpcode(AArch64::MOVKXi); 973 Inst.addOperand(MCOperand::createReg(AArch64::X16)); 974 Inst.addOperand(MCOperand::createReg(AArch64::X16)); 975 Inst.addOperand(MCOperand::createExpr(AArch64MCExpr::create( 976 MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx), 977 AArch64MCExpr::VK_ABS_G2_NC, *Ctx))); 978 Inst.addOperand(MCOperand::createImm(0x20)); 979 Seq.emplace_back(Inst); 980 981 Inst.clear(); 982 Inst.setOpcode(AArch64::MOVKXi); 983 Inst.addOperand(MCOperand::createReg(AArch64::X16)); 984 Inst.addOperand(MCOperand::createReg(AArch64::X16)); 985 Inst.addOperand(MCOperand::createExpr(AArch64MCExpr::create( 986 MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx), 987 AArch64MCExpr::VK_ABS_G1_NC, *Ctx))); 988 Inst.addOperand(MCOperand::createImm(0x10)); 989 Seq.emplace_back(Inst); 990 991 Inst.clear(); 992 Inst.setOpcode(AArch64::MOVKXi); 993 Inst.addOperand(MCOperand::createReg(AArch64::X16)); 994 Inst.addOperand(MCOperand::createReg(AArch64::X16)); 995 Inst.addOperand(MCOperand::createExpr(AArch64MCExpr::create( 996 MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx), 997 AArch64MCExpr::VK_ABS_G0_NC, *Ctx))); 998 Inst.addOperand(MCOperand::createImm(0)); 999 Seq.emplace_back(Inst); 1000 1001 Inst.clear(); 1002 Inst.setOpcode(AArch64::BR); 1003 Inst.addOperand(MCOperand::createReg(AArch64::X16)); 1004 if (IsTailCall) 1005 setTailCall(Inst); 1006 Seq.emplace_back(Inst); 1007 } 1008 1009 void createShortJmp(InstructionListType &Seq, const MCSymbol *Target, 1010 MCContext *Ctx, bool IsTailCall) override { 1011 // ip0 (r16) is reserved to the linker (refer to 5.3.1.1 of "Procedure Call 1012 // Standard for the ARM 64-bit Architecture (AArch64)". 1013 // The sequence of instructions we create here is the following: 1014 // adrp ip0, imm 1015 // add ip0, ip0, imm 1016 // br ip0 1017 MCPhysReg Reg = AArch64::X16; 1018 InstructionListType Insts = materializeAddress(Target, Ctx, Reg); 1019 Insts.emplace_back(); 1020 MCInst &Inst = Insts.back(); 1021 Inst.clear(); 1022 Inst.setOpcode(AArch64::BR); 1023 Inst.addOperand(MCOperand::createReg(Reg)); 1024 if (IsTailCall) 1025 setTailCall(Inst); 1026 Seq.swap(Insts); 1027 } 1028 1029 /// Matching pattern here is 1030 /// 1031 /// ADRP x16, imm 1032 /// ADD x16, x16, imm 1033 /// BR x16 1034 /// 1035 bool matchLinkerVeneer(InstructionIterator Begin, InstructionIterator End, 1036 uint64_t Address, const MCInst &CurInst, 1037 MCInst *&TargetHiBits, MCInst *&TargetLowBits, 1038 uint64_t &Target) const override { 1039 if (CurInst.getOpcode() != AArch64::BR || !CurInst.getOperand(0).isReg() || 1040 CurInst.getOperand(0).getReg() != AArch64::X16) 1041 return false; 1042 1043 auto I = End; 1044 if (I == Begin) 1045 return false; 1046 1047 --I; 1048 Address -= 4; 1049 if (I == Begin || I->getOpcode() != AArch64::ADDXri || 1050 MCPlus::getNumPrimeOperands(*I) < 3 || !I->getOperand(0).isReg() || 1051 !I->getOperand(1).isReg() || 1052 I->getOperand(0).getReg() != AArch64::X16 || 1053 I->getOperand(1).getReg() != AArch64::X16 || !I->getOperand(2).isImm()) 1054 return false; 1055 TargetLowBits = &*I; 1056 uint64_t Addr = I->getOperand(2).getImm() & 0xFFF; 1057 1058 --I; 1059 Address -= 4; 1060 if (I->getOpcode() != AArch64::ADRP || 1061 MCPlus::getNumPrimeOperands(*I) < 2 || !I->getOperand(0).isReg() || 1062 !I->getOperand(1).isImm() || I->getOperand(0).getReg() != AArch64::X16) 1063 return false; 1064 TargetHiBits = &*I; 1065 Addr |= (Address + ((int64_t)I->getOperand(1).getImm() << 12)) & 1066 0xFFFFFFFFFFFFF000ULL; 1067 Target = Addr; 1068 return true; 1069 } 1070 1071 bool replaceImmWithSymbolRef(MCInst &Inst, const MCSymbol *Symbol, 1072 int64_t Addend, MCContext *Ctx, int64_t &Value, 1073 uint64_t RelType) const override { 1074 unsigned ImmOpNo = -1U; 1075 for (unsigned Index = 0; Index < MCPlus::getNumPrimeOperands(Inst); 1076 ++Index) { 1077 if (Inst.getOperand(Index).isImm()) { 1078 ImmOpNo = Index; 1079 break; 1080 } 1081 } 1082 if (ImmOpNo == -1U) 1083 return false; 1084 1085 Value = Inst.getOperand(ImmOpNo).getImm(); 1086 1087 setOperandToSymbolRef(Inst, ImmOpNo, Symbol, Addend, Ctx, RelType); 1088 1089 return true; 1090 } 1091 1092 bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB, 1093 MCContext *Ctx) const override { 1094 Inst.setOpcode(AArch64::B); 1095 Inst.clear(); 1096 Inst.addOperand(MCOperand::createExpr(getTargetExprFor( 1097 Inst, MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx), 1098 *Ctx, 0))); 1099 return true; 1100 } 1101 1102 bool isMoveMem2Reg(const MCInst &Inst) const override { return false; } 1103 1104 bool isADD64rr(const MCInst &Inst) const override { return false; } 1105 1106 bool isLeave(const MCInst &Inst) const override { return false; } 1107 1108 bool isPop(const MCInst &Inst) const override { return false; } 1109 1110 bool isPrefix(const MCInst &Inst) const override { return false; } 1111 1112 bool deleteREPPrefix(MCInst &Inst) const override { return false; } 1113 1114 bool createReturn(MCInst &Inst) const override { 1115 Inst.setOpcode(AArch64::RET); 1116 Inst.clear(); 1117 Inst.addOperand(MCOperand::createReg(AArch64::LR)); 1118 return true; 1119 } 1120 1121 InstructionListType materializeAddress(const MCSymbol *Target, MCContext *Ctx, 1122 MCPhysReg RegName, 1123 int64_t Addend = 0) const override { 1124 // Get page-aligned address and add page offset 1125 InstructionListType Insts(2); 1126 Insts[0].setOpcode(AArch64::ADRP); 1127 Insts[0].clear(); 1128 Insts[0].addOperand(MCOperand::createReg(RegName)); 1129 Insts[0].addOperand(MCOperand::createImm(0)); 1130 setOperandToSymbolRef(Insts[0], /* OpNum */ 1, Target, Addend, Ctx, 1131 ELF::R_AARCH64_NONE); 1132 Insts[1].setOpcode(AArch64::ADDXri); 1133 Insts[1].clear(); 1134 Insts[1].addOperand(MCOperand::createReg(RegName)); 1135 Insts[1].addOperand(MCOperand::createReg(RegName)); 1136 Insts[1].addOperand(MCOperand::createImm(0)); 1137 Insts[1].addOperand(MCOperand::createImm(0)); 1138 setOperandToSymbolRef(Insts[1], /* OpNum */ 2, Target, Addend, Ctx, 1139 ELF::R_AARCH64_ADD_ABS_LO12_NC); 1140 return Insts; 1141 } 1142 }; 1143 1144 } // end anonymous namespace 1145 1146 namespace llvm { 1147 namespace bolt { 1148 1149 MCPlusBuilder *createAArch64MCPlusBuilder(const MCInstrAnalysis *Analysis, 1150 const MCInstrInfo *Info, 1151 const MCRegisterInfo *RegInfo) { 1152 return new AArch64MCPlusBuilder(Analysis, Info, RegInfo); 1153 } 1154 1155 } // namespace bolt 1156 } // namespace llvm 1157