629 lines · cpp
1//===- bolt/Core/MCPlusBuilder.cpp - Interface for MCPlus -----------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the MCPlusBuilder class.10//11//===----------------------------------------------------------------------===//12 13#include "bolt/Core/MCPlusBuilder.h"14#include "bolt/Core/MCPlus.h"15#include "bolt/Utils/CommandLineOpts.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCInst.h"18#include "llvm/MC/MCInstrAnalysis.h"19#include "llvm/MC/MCInstrDesc.h"20#include "llvm/MC/MCInstrInfo.h"21#include "llvm/MC/MCRegisterInfo.h"22#include "llvm/Support/CommandLine.h"23#include "llvm/Support/Debug.h"24#include <cstdint>25 26#define DEBUG_TYPE "mcplus"27 28using namespace llvm;29using namespace bolt;30using namespace MCPlus;31 32namespace opts {33cl::opt<bool>34 TerminalHLT("terminal-x86-hlt",35 cl::desc("Assume that execution stops at x86 HLT instruction"),36 cl::init(true), cl::Hidden, cl::cat(BoltCategory));37 38cl::opt<bool>39 TerminalTrap("terminal-trap",40 cl::desc("Assume that execution stops at trap instruction"),41 cl::init(true), cl::Hidden, cl::cat(BoltCategory));42}43 44bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B,45 CompFuncTy Comp) const {46 if (A.getOpcode() != B.getOpcode())47 return false;48 49 unsigned NumOperands = MCPlus::getNumPrimeOperands(A);50 if (NumOperands != MCPlus::getNumPrimeOperands(B))51 return false;52 53 for (unsigned Index = 0; Index < NumOperands; ++Index)54 if (!equals(A.getOperand(Index), B.getOperand(Index), Comp))55 return false;56 57 return true;58}59 60bool MCPlusBuilder::equals(const MCOperand &A, const MCOperand &B,61 CompFuncTy Comp) const {62 if (A.isReg()) {63 if (!B.isReg())64 return false;65 return A.getReg() == B.getReg();66 } else if (A.isImm()) {67 if (!B.isImm())68 return false;69 return A.getImm() == B.getImm();70 } else if (A.isSFPImm()) {71 if (!B.isSFPImm())72 return false;73 return A.getSFPImm() == B.getSFPImm();74 } else if (A.isDFPImm()) {75 if (!B.isDFPImm())76 return false;77 return A.getDFPImm() == B.getDFPImm();78 } else if (A.isExpr()) {79 if (!B.isExpr())80 return false;81 return equals(*A.getExpr(), *B.getExpr(), Comp);82 } else {83 llvm_unreachable("unexpected operand kind");84 return false;85 }86}87 88bool MCPlusBuilder::equals(const MCExpr &A, const MCExpr &B,89 CompFuncTy Comp) const {90 if (A.getKind() != B.getKind())91 return false;92 93 switch (A.getKind()) {94 case MCExpr::Constant: {95 const auto &ConstA = cast<MCConstantExpr>(A);96 const auto &ConstB = cast<MCConstantExpr>(B);97 return ConstA.getValue() == ConstB.getValue();98 }99 100 case MCExpr::SymbolRef: {101 const MCSymbolRefExpr &SymbolA = cast<MCSymbolRefExpr>(A);102 const MCSymbolRefExpr &SymbolB = cast<MCSymbolRefExpr>(B);103 return SymbolA.getKind() == SymbolB.getKind() &&104 Comp(&SymbolA.getSymbol(), &SymbolB.getSymbol());105 }106 107 case MCExpr::Unary: {108 const auto &UnaryA = cast<MCUnaryExpr>(A);109 const auto &UnaryB = cast<MCUnaryExpr>(B);110 return UnaryA.getOpcode() == UnaryB.getOpcode() &&111 equals(*UnaryA.getSubExpr(), *UnaryB.getSubExpr(), Comp);112 }113 114 case MCExpr::Binary: {115 const auto &BinaryA = cast<MCBinaryExpr>(A);116 const auto &BinaryB = cast<MCBinaryExpr>(B);117 return BinaryA.getOpcode() == BinaryB.getOpcode() &&118 equals(*BinaryA.getLHS(), *BinaryB.getLHS(), Comp) &&119 equals(*BinaryA.getRHS(), *BinaryB.getRHS(), Comp);120 }121 122 case MCExpr::Specifier: {123 const auto &TargetExprA = cast<MCSpecifierExpr>(A);124 const auto &TargetExprB = cast<MCSpecifierExpr>(B);125 return equals(TargetExprA, TargetExprB, Comp);126 }127 case MCExpr::Target:128 llvm_unreachable("Not implemented");129 }130 131 llvm_unreachable("Invalid expression kind!");132}133 134bool MCPlusBuilder::equals(const MCSpecifierExpr &A, const MCSpecifierExpr &B,135 CompFuncTy Comp) const {136 llvm_unreachable("target-specific expressions are unsupported");137}138 139bool MCPlusBuilder::isTerminator(const MCInst &Inst) const {140 if (isX86HLT(Inst))141 return opts::TerminalHLT;142 143 if (Info->get(Inst.getOpcode()).isTrap())144 return opts::TerminalTrap;145 146 return Analysis->isTerminator(Inst);147}148 149void MCPlusBuilder::setTailCall(MCInst &Inst) const {150 assert(!hasAnnotation(Inst, MCAnnotation::kTailCall));151 setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true);152}153 154bool MCPlusBuilder::isTailCall(const MCInst &Inst) const {155 if (hasAnnotation(Inst, MCAnnotation::kTailCall))156 return true;157 if (getConditionalTailCall(Inst))158 return true;159 return false;160}161 162void MCPlusBuilder::setNegateRAState(MCInst &Inst) const {163 assert(!hasAnnotation(Inst, MCAnnotation::kNegateState));164 setAnnotationOpValue(Inst, MCAnnotation::kNegateState, true);165}166 167bool MCPlusBuilder::hasNegateRAState(const MCInst &Inst) const {168 return hasAnnotation(Inst, MCAnnotation::kNegateState);169}170 171void MCPlusBuilder::setRememberState(MCInst &Inst) const {172 assert(!hasAnnotation(Inst, MCAnnotation::kRememberState));173 setAnnotationOpValue(Inst, MCAnnotation::kRememberState, true);174}175 176bool MCPlusBuilder::hasRememberState(const MCInst &Inst) const {177 return hasAnnotation(Inst, MCAnnotation::kRememberState);178}179 180void MCPlusBuilder::setRestoreState(MCInst &Inst) const {181 assert(!hasAnnotation(Inst, MCAnnotation::kRestoreState));182 setAnnotationOpValue(Inst, MCAnnotation::kRestoreState, true);183}184 185bool MCPlusBuilder::hasRestoreState(const MCInst &Inst) const {186 return hasAnnotation(Inst, MCAnnotation::kRestoreState);187}188 189void MCPlusBuilder::setRAState(MCInst &Inst, bool State) const {190 assert(!hasAnnotation(Inst, MCAnnotation::kRASigned));191 assert(!hasAnnotation(Inst, MCAnnotation::kRAUnsigned));192 if (State)193 setAnnotationOpValue(Inst, MCAnnotation::kRASigned, true);194 else195 setAnnotationOpValue(Inst, MCAnnotation::kRAUnsigned, true);196}197 198std::optional<bool> MCPlusBuilder::getRAState(const MCInst &Inst) const {199 if (hasAnnotation(Inst, MCAnnotation::kRASigned))200 return true;201 if (hasAnnotation(Inst, MCAnnotation::kRAUnsigned))202 return false;203 return std::nullopt;204}205 206std::optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const {207 if (!isCall(Inst))208 return std::nullopt;209 std::optional<int64_t> LPSym =210 getAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad);211 if (!LPSym)212 return std::nullopt;213 std::optional<int64_t> Action =214 getAnnotationOpValue(Inst, MCAnnotation::kEHAction);215 if (!Action)216 return std::nullopt;217 218 return std::make_pair(reinterpret_cast<const MCSymbol *>(*LPSym),219 static_cast<uint64_t>(*Action));220}221 222void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) const {223 if (isCall(Inst)) {224 assert(!getEHInfo(Inst));225 setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,226 reinterpret_cast<int64_t>(LP.first));227 setAnnotationOpValue(Inst, MCAnnotation::kEHAction,228 static_cast<int64_t>(LP.second));229 }230}231 232bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) const {233 if (!isInvoke(Inst))234 return false;235 236 setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,237 reinterpret_cast<int64_t>(LP.first));238 setAnnotationOpValue(Inst, MCAnnotation::kEHAction,239 static_cast<int64_t>(LP.second));240 return true;241}242 243int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const {244 std::optional<int64_t> Value =245 getAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize);246 if (!Value)247 return -1LL;248 return *Value;249}250 251void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize) const {252 assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value");253 assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set");254 assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke");255 256 setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize);257}258 259uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const {260 std::optional<int64_t> Value =261 getAnnotationOpValue(Inst, MCAnnotation::kJumpTable);262 if (!Value)263 return 0;264 return *Value;265}266 267uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const {268 return getAnnotationAs<uint16_t>(Inst, "JTIndexReg");269}270 271bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value,272 uint16_t IndexReg, AllocatorIdTy AllocId) {273 if (!isIndirectBranch(Inst))274 return false;275 setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value);276 getOrCreateAnnotationAs<uint16_t>(Inst, "JTIndexReg", AllocId) = IndexReg;277 return true;278}279 280bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) const {281 if (!getJumpTable(Inst))282 return false;283 removeAnnotation(Inst, MCAnnotation::kJumpTable);284 removeAnnotation(Inst, "JTIndexReg");285 return true;286}287 288std::optional<uint64_t>289MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const {290 std::optional<int64_t> Value =291 getAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall);292 if (!Value)293 return std::nullopt;294 return static_cast<uint64_t>(*Value);295}296 297bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) const {298 if (!isConditionalBranch(Inst))299 return false;300 301 setAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall, Dest);302 return true;303}304 305bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) const {306 if (!getConditionalTailCall(Inst))307 return false;308 removeAnnotation(Inst, MCAnnotation::kConditionalTailCall);309 return true;310}311 312std::optional<uint32_t> MCPlusBuilder::getOffset(const MCInst &Inst) const {313 std::optional<int64_t> Value =314 getAnnotationOpValue(Inst, MCAnnotation::kOffset);315 if (!Value)316 return std::nullopt;317 return static_cast<uint32_t>(*Value);318}319 320uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst,321 uint32_t Default) const {322 if (std::optional<uint32_t> Offset = getOffset(Inst))323 return *Offset;324 return Default;325}326 327bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset) const {328 setAnnotationOpValue(Inst, MCAnnotation::kOffset, Offset);329 return true;330}331 332bool MCPlusBuilder::clearOffset(MCInst &Inst) const {333 if (!hasAnnotation(Inst, MCAnnotation::kOffset))334 return false;335 removeAnnotation(Inst, MCAnnotation::kOffset);336 return true;337}338 339MCSymbol *MCPlusBuilder::getInstLabel(const MCInst &Inst) const {340 if (std::optional<int64_t> Label =341 getAnnotationOpValue(Inst, MCAnnotation::kLabel))342 return reinterpret_cast<MCSymbol *>(*Label);343 return nullptr;344}345 346MCSymbol *MCPlusBuilder::getOrCreateInstLabel(MCInst &Inst, const Twine &Name,347 MCContext *Ctx) const {348 MCSymbol *Label = getInstLabel(Inst);349 if (Label)350 return Label;351 352 Label = Ctx->createNamedTempSymbol(Name);353 setAnnotationOpValue(Inst, MCAnnotation::kLabel,354 reinterpret_cast<int64_t>(Label));355 return Label;356}357 358void MCPlusBuilder::setInstLabel(MCInst &Inst, MCSymbol *Label) const {359 assert(!getInstLabel(Inst) && "Instruction already has assigned label.");360 setAnnotationOpValue(Inst, MCAnnotation::kLabel,361 reinterpret_cast<int64_t>(Label));362}363 364std::optional<uint32_t> MCPlusBuilder::getSize(const MCInst &Inst) const {365 if (std::optional<int64_t> Value =366 getAnnotationOpValue(Inst, MCAnnotation::kSize))367 return static_cast<uint32_t>(*Value);368 return std::nullopt;369}370 371void MCPlusBuilder::setSize(MCInst &Inst, uint32_t Size) const {372 setAnnotationOpValue(Inst, MCAnnotation::kSize, Size);373}374 375bool MCPlusBuilder::isDynamicBranch(const MCInst &Inst) const {376 if (!hasAnnotation(Inst, MCAnnotation::kDynamicBranch))377 return false;378 assert(isBranch(Inst) && "Branch expected.");379 return true;380}381 382std::optional<uint32_t>383MCPlusBuilder::getDynamicBranchID(const MCInst &Inst) const {384 if (std::optional<int64_t> Value =385 getAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch)) {386 assert(isBranch(Inst) && "Branch expected.");387 return static_cast<uint32_t>(*Value);388 }389 return std::nullopt;390}391 392void MCPlusBuilder::setDynamicBranch(MCInst &Inst, uint32_t ID) const {393 assert(isBranch(Inst) && "Branch expected.");394 setAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch, ID);395}396 397bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const {398 return (bool)getAnnotationOpValue(Inst, Index);399}400 401bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) const {402 std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst);403 if (!FirstAnnotationOp)404 return false;405 406 for (unsigned I = Inst.getNumOperands() - 1; I >= *FirstAnnotationOp; --I) {407 const int64_t ImmValue = Inst.getOperand(I).getImm();408 if (extractAnnotationIndex(ImmValue) == Index) {409 Inst.erase(Inst.begin() + I);410 return true;411 }412 }413 return false;414}415 416void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) const {417 KeepTC &= hasAnnotation(Inst, MCAnnotation::kTailCall);418 419 removeAnnotations(Inst);420 421 if (KeepTC)422 setTailCall(Inst);423}424 425void MCPlusBuilder::printAnnotations(const MCInst &Inst, raw_ostream &OS,426 bool PrintMemData) const {427 std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst);428 if (!FirstAnnotationOp)429 return;430 431 for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) {432 const int64_t Imm = Inst.getOperand(I).getImm();433 const unsigned Index = extractAnnotationIndex(Imm);434 const int64_t Value = extractAnnotationValue(Imm);435 const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value);436 if (Index >= MCAnnotation::kGeneric) {437 std::string AnnotationName =438 AnnotationNames[Index - MCAnnotation::kGeneric];439 if (!PrintMemData && AnnotationName == "MemoryAccessProfile")440 continue;441 OS << " # " << AnnotationName << ": ";442 Annotation->print(OS);443 }444 }445}446 447void MCPlusBuilder::getClobberedRegs(const MCInst &Inst,448 BitVector &Regs) const {449 if (isPrefix(Inst) || isCFI(Inst))450 return;451 452 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());453 454 for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())455 Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false);456 457 for (const MCOperand &Operand : defOperands(Inst)) {458 assert(Operand.isReg());459 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/false);460 }461}462 463void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const {464 if (isPrefix(Inst) || isCFI(Inst))465 return;466 467 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());468 469 for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())470 Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false);471 for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())472 Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/false);473 474 for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {475 if (!Inst.getOperand(I).isReg())476 continue;477 Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/false);478 }479}480 481void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const {482 if (isPrefix(Inst) || isCFI(Inst))483 return;484 485 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());486 487 for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())488 Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/true);489 490 for (const MCOperand &Operand : defOperands(Inst)) {491 assert(Operand.isReg());492 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);493 }494}495 496void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const {497 if (isPrefix(Inst) || isCFI(Inst))498 return;499 500 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());501 502 for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())503 Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true);504 505 for (const MCOperand &Operand : useOperands(Inst)) {506 if (!Operand.isReg())507 continue;508 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);509 }510}511 512void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const {513 if (isPrefix(Inst) || isCFI(Inst))514 return;515 516 if (isCall(Inst)) {517 BitVector CallRegs = BitVector(Regs.size(), false);518 getCalleeSavedRegs(CallRegs);519 CallRegs.flip();520 Regs |= CallRegs;521 return;522 }523 524 if (isReturn(Inst)) {525 getDefaultLiveOut(Regs);526 return;527 }528 529 if (isRep(Inst))530 getRepRegs(Regs);531 532 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());533 534 for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())535 Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true);536 537 for (const MCOperand &Operand : useOperands(Inst))538 if (Operand.isReg())539 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);540}541 542bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const {543 const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());544 return InstInfo.hasDefOfPhysReg(MI, Reg, *RegInfo);545}546 547bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const {548 const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());549 for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I)550 if (MI.getOperand(I).isReg() && MI.getOperand(I).getReg() &&551 RegInfo->isSubRegisterEq(Reg, MI.getOperand(I).getReg()))552 return true;553 for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) {554 if (ImplicitUse == Reg || RegInfo->isSubRegister(Reg, ImplicitUse))555 return true;556 }557 return false;558}559 560const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg,561 bool OnlySmaller) const {562 if (OnlySmaller)563 return SmallerAliasMap[Reg];564 return AliasMap[Reg];565}566 567void MCPlusBuilder::initAliases() {568 assert(AliasMap.size() == 0 && SmallerAliasMap.size() == 0);569 // Build alias map570 for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {571 BitVector BV(RegInfo->getNumRegs(), false);572 BV.set(I);573 AliasMap.emplace_back(BV);574 SmallerAliasMap.emplace_back(BV);575 }576 577 // Cache all aliases for each register578 for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I != E; ++I) {579 for (MCRegAliasIterator AI(I, RegInfo, true); AI.isValid(); ++AI)580 AliasMap[I].set(*AI);581 }582 583 // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister)584 for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I)585 for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI)586 SmallerAliasMap[I] |= SmallerAliasMap[*SI];587 588 LLVM_DEBUG({589 dbgs() << "Dumping reg alias table:\n";590 for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {591 dbgs() << "Reg " << I << ": ";592 const BitVector &BV = AliasMap[I];593 int Idx = BV.find_first();594 while (Idx != -1) {595 dbgs() << Idx << " ";596 Idx = BV.find_next(Idx);597 }598 dbgs() << "\n";599 }600 });601}602 603void MCPlusBuilder::initSizeMap() {604 SizeMap.resize(RegInfo->getNumRegs());605 // Build size map606 for (auto RC : RegInfo->regclasses())607 for (MCPhysReg Reg : RC)608 SizeMap[Reg] = RC.getSizeInBits() / 8;609}610 611bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum,612 const MCSymbol *Symbol,613 int64_t Addend, MCContext *Ctx,614 uint32_t RelType) const {615 MCOperand Operand;616 if (!Addend) {617 Operand = MCOperand::createExpr(getTargetExprFor(618 Inst, MCSymbolRefExpr::create(Symbol, *Ctx), *Ctx, RelType));619 } else {620 Operand = MCOperand::createExpr(getTargetExprFor(621 Inst,622 MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, *Ctx),623 MCConstantExpr::create(Addend, *Ctx), *Ctx),624 *Ctx, RelType));625 }626 Inst.getOperand(OpNum) = Operand;627 return true;628}629