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