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-exception
6 //
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 "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCInstrAnalysis.h"
17 #include "llvm/MC/MCInstrDesc.h"
18 #include "llvm/MC/MCInstrInfo.h"
19 #include "llvm/MC/MCRegisterInfo.h"
20 #include "llvm/Support/Debug.h"
21 #include <cstdint>
22 #include <queue>
23
24 #define DEBUG_TYPE "mcplus"
25
26 using namespace llvm;
27 using namespace bolt;
28 using namespace MCPlus;
29
equals(const MCInst & A,const MCInst & B,CompFuncTy Comp) const30 bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B,
31 CompFuncTy Comp) const {
32 if (A.getOpcode() != B.getOpcode())
33 return false;
34
35 unsigned NumOperands = MCPlus::getNumPrimeOperands(A);
36 if (NumOperands != MCPlus::getNumPrimeOperands(B))
37 return false;
38
39 for (unsigned Index = 0; Index < NumOperands; ++Index)
40 if (!equals(A.getOperand(Index), B.getOperand(Index), Comp))
41 return false;
42
43 return true;
44 }
45
equals(const MCOperand & A,const MCOperand & B,CompFuncTy Comp) const46 bool MCPlusBuilder::equals(const MCOperand &A, const MCOperand &B,
47 CompFuncTy Comp) const {
48 if (A.isReg()) {
49 if (!B.isReg())
50 return false;
51 return A.getReg() == B.getReg();
52 } else if (A.isImm()) {
53 if (!B.isImm())
54 return false;
55 return A.getImm() == B.getImm();
56 } else if (A.isSFPImm()) {
57 if (!B.isSFPImm())
58 return false;
59 return A.getSFPImm() == B.getSFPImm();
60 } else if (A.isDFPImm()) {
61 if (!B.isDFPImm())
62 return false;
63 return A.getDFPImm() == B.getDFPImm();
64 } else if (A.isExpr()) {
65 if (!B.isExpr())
66 return false;
67 return equals(*A.getExpr(), *B.getExpr(), Comp);
68 } else {
69 llvm_unreachable("unexpected operand kind");
70 return false;
71 }
72 }
73
equals(const MCExpr & A,const MCExpr & B,CompFuncTy Comp) const74 bool MCPlusBuilder::equals(const MCExpr &A, const MCExpr &B,
75 CompFuncTy Comp) const {
76 if (A.getKind() != B.getKind())
77 return false;
78
79 switch (A.getKind()) {
80 case MCExpr::Constant: {
81 const auto &ConstA = cast<MCConstantExpr>(A);
82 const auto &ConstB = cast<MCConstantExpr>(B);
83 return ConstA.getValue() == ConstB.getValue();
84 }
85
86 case MCExpr::SymbolRef: {
87 const MCSymbolRefExpr &SymbolA = cast<MCSymbolRefExpr>(A);
88 const MCSymbolRefExpr &SymbolB = cast<MCSymbolRefExpr>(B);
89 return SymbolA.getKind() == SymbolB.getKind() &&
90 Comp(&SymbolA.getSymbol(), &SymbolB.getSymbol());
91 }
92
93 case MCExpr::Unary: {
94 const auto &UnaryA = cast<MCUnaryExpr>(A);
95 const auto &UnaryB = cast<MCUnaryExpr>(B);
96 return UnaryA.getOpcode() == UnaryB.getOpcode() &&
97 equals(*UnaryA.getSubExpr(), *UnaryB.getSubExpr(), Comp);
98 }
99
100 case MCExpr::Binary: {
101 const auto &BinaryA = cast<MCBinaryExpr>(A);
102 const auto &BinaryB = cast<MCBinaryExpr>(B);
103 return BinaryA.getOpcode() == BinaryB.getOpcode() &&
104 equals(*BinaryA.getLHS(), *BinaryB.getLHS(), Comp) &&
105 equals(*BinaryA.getRHS(), *BinaryB.getRHS(), Comp);
106 }
107
108 case MCExpr::Target: {
109 const auto &TargetExprA = cast<MCTargetExpr>(A);
110 const auto &TargetExprB = cast<MCTargetExpr>(B);
111 return equals(TargetExprA, TargetExprB, Comp);
112 }
113 }
114
115 llvm_unreachable("Invalid expression kind!");
116 }
117
equals(const MCTargetExpr & A,const MCTargetExpr & B,CompFuncTy Comp) const118 bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B,
119 CompFuncTy Comp) const {
120 llvm_unreachable("target-specific expressions are unsupported");
121 }
122
setTailCall(MCInst & Inst)123 void MCPlusBuilder::setTailCall(MCInst &Inst) {
124 assert(!hasAnnotation(Inst, MCAnnotation::kTailCall));
125 setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true);
126 }
127
isTailCall(const MCInst & Inst) const128 bool MCPlusBuilder::isTailCall(const MCInst &Inst) const {
129 if (hasAnnotation(Inst, MCAnnotation::kTailCall))
130 return true;
131 if (getConditionalTailCall(Inst))
132 return true;
133 return false;
134 }
135
getEHInfo(const MCInst & Inst) const136 Optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const {
137 if (!isCall(Inst))
138 return NoneType();
139 Optional<int64_t> LPSym =
140 getAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad);
141 if (!LPSym)
142 return NoneType();
143 Optional<int64_t> Action =
144 getAnnotationOpValue(Inst, MCAnnotation::kEHAction);
145 if (!Action)
146 return NoneType();
147
148 return std::make_pair(reinterpret_cast<const MCSymbol *>(*LPSym),
149 static_cast<uint64_t>(*Action));
150 }
151
addEHInfo(MCInst & Inst,const MCLandingPad & LP)152 void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) {
153 if (isCall(Inst)) {
154 assert(!getEHInfo(Inst));
155 setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,
156 reinterpret_cast<int64_t>(LP.first));
157 setAnnotationOpValue(Inst, MCAnnotation::kEHAction,
158 static_cast<int64_t>(LP.second));
159 }
160 }
161
updateEHInfo(MCInst & Inst,const MCLandingPad & LP)162 bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) {
163 if (!isInvoke(Inst))
164 return false;
165
166 setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,
167 reinterpret_cast<int64_t>(LP.first));
168 setAnnotationOpValue(Inst, MCAnnotation::kEHAction,
169 static_cast<int64_t>(LP.second));
170 return true;
171 }
172
getGnuArgsSize(const MCInst & Inst) const173 int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const {
174 Optional<int64_t> Value =
175 getAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize);
176 if (!Value)
177 return -1LL;
178 return *Value;
179 }
180
addGnuArgsSize(MCInst & Inst,int64_t GnuArgsSize,AllocatorIdTy AllocId)181 void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize,
182 AllocatorIdTy AllocId) {
183 assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value");
184 assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set");
185 assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke");
186
187 setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize, AllocId);
188 }
189
getJumpTable(const MCInst & Inst) const190 uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const {
191 Optional<int64_t> Value =
192 getAnnotationOpValue(Inst, MCAnnotation::kJumpTable);
193 if (!Value)
194 return 0;
195 return *Value;
196 }
197
getJumpTableIndexReg(const MCInst & Inst) const198 uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const {
199 return getAnnotationAs<uint16_t>(Inst, "JTIndexReg");
200 }
201
setJumpTable(MCInst & Inst,uint64_t Value,uint16_t IndexReg,AllocatorIdTy AllocId)202 bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value,
203 uint16_t IndexReg, AllocatorIdTy AllocId) {
204 if (!isIndirectBranch(Inst))
205 return false;
206 setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value, AllocId);
207 getOrCreateAnnotationAs<uint16_t>(Inst, "JTIndexReg", AllocId) = IndexReg;
208 return true;
209 }
210
unsetJumpTable(MCInst & Inst)211 bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) {
212 if (!getJumpTable(Inst))
213 return false;
214 removeAnnotation(Inst, MCAnnotation::kJumpTable);
215 removeAnnotation(Inst, "JTIndexReg");
216 return true;
217 }
218
219 Optional<uint64_t>
getConditionalTailCall(const MCInst & Inst) const220 MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const {
221 Optional<int64_t> Value =
222 getAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall);
223 if (!Value)
224 return NoneType();
225 return static_cast<uint64_t>(*Value);
226 }
227
setConditionalTailCall(MCInst & Inst,uint64_t Dest)228 bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) {
229 if (!isConditionalBranch(Inst))
230 return false;
231
232 setAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall, Dest);
233 return true;
234 }
235
unsetConditionalTailCall(MCInst & Inst)236 bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) {
237 if (!getConditionalTailCall(Inst))
238 return false;
239 removeAnnotation(Inst, MCAnnotation::kConditionalTailCall);
240 return true;
241 }
242
getOffset(const MCInst & Inst) const243 Optional<uint32_t> MCPlusBuilder::getOffset(const MCInst &Inst) const {
244 Optional<int64_t> Value = getAnnotationOpValue(Inst, MCAnnotation::kOffset);
245 if (!Value)
246 return NoneType();
247 return static_cast<uint32_t>(*Value);
248 }
249
getOffsetWithDefault(const MCInst & Inst,uint32_t Default) const250 uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst,
251 uint32_t Default) const {
252 if (Optional<uint32_t> Offset = getOffset(Inst))
253 return *Offset;
254 return Default;
255 }
256
setOffset(MCInst & Inst,uint32_t Offset,AllocatorIdTy AllocatorId)257 bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset,
258 AllocatorIdTy AllocatorId) {
259 setAnnotationOpValue(Inst, MCAnnotation::kOffset, Offset, AllocatorId);
260 return true;
261 }
262
clearOffset(MCInst & Inst)263 bool MCPlusBuilder::clearOffset(MCInst &Inst) {
264 if (!hasAnnotation(Inst, MCAnnotation::kOffset))
265 return false;
266 removeAnnotation(Inst, MCAnnotation::kOffset);
267 return true;
268 }
269
hasAnnotation(const MCInst & Inst,unsigned Index) const270 bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const {
271 const MCInst *AnnotationInst = getAnnotationInst(Inst);
272 if (!AnnotationInst)
273 return false;
274
275 return (bool)getAnnotationOpValue(Inst, Index);
276 }
277
removeAnnotation(MCInst & Inst,unsigned Index)278 bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) {
279 MCInst *AnnotationInst = getAnnotationInst(Inst);
280 if (!AnnotationInst)
281 return false;
282
283 for (int I = AnnotationInst->getNumOperands() - 1; I >= 0; --I) {
284 int64_t ImmValue = AnnotationInst->getOperand(I).getImm();
285 if (extractAnnotationIndex(ImmValue) == Index) {
286 AnnotationInst->erase(AnnotationInst->begin() + I);
287 return true;
288 }
289 }
290 return false;
291 }
292
stripAnnotations(MCInst & Inst,bool KeepTC)293 void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) {
294 MCInst *AnnotationInst = getAnnotationInst(Inst);
295 if (!AnnotationInst)
296 return;
297 // Preserve TailCall annotation.
298 auto IsTC = hasAnnotation(Inst, MCAnnotation::kTailCall);
299
300 Inst.erase(std::prev(Inst.end()));
301 if (KeepTC && IsTC)
302 setTailCall(Inst);
303 }
304
printAnnotations(const MCInst & Inst,raw_ostream & OS) const305 void MCPlusBuilder::printAnnotations(const MCInst &Inst,
306 raw_ostream &OS) const {
307 const MCInst *AnnotationInst = getAnnotationInst(Inst);
308 if (!AnnotationInst)
309 return;
310
311 for (unsigned I = 0; I < AnnotationInst->getNumOperands(); ++I) {
312 const int64_t Imm = AnnotationInst->getOperand(I).getImm();
313 const unsigned Index = extractAnnotationIndex(Imm);
314 const int64_t Value = extractAnnotationValue(Imm);
315 const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value);
316 if (Index >= MCAnnotation::kGeneric) {
317 OS << " # " << AnnotationNames[Index - MCAnnotation::kGeneric] << ": ";
318 Annotation->print(OS);
319 }
320 }
321 }
322
evaluateBranch(const MCInst & Inst,uint64_t Addr,uint64_t Size,uint64_t & Target) const323 bool MCPlusBuilder::evaluateBranch(const MCInst &Inst, uint64_t Addr,
324 uint64_t Size, uint64_t &Target) const {
325 return Analysis->evaluateBranch(Inst, Addr, Size, Target);
326 }
327
getClobberedRegs(const MCInst & Inst,BitVector & Regs) const328 void MCPlusBuilder::getClobberedRegs(const MCInst &Inst,
329 BitVector &Regs) const {
330 if (isPrefix(Inst) || isCFI(Inst))
331 return;
332
333 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
334
335 const MCPhysReg *ImplicitDefs = InstInfo.getImplicitDefs();
336 for (unsigned I = 0, E = InstInfo.getNumImplicitDefs(); I != E; ++I)
337 Regs |= getAliases(ImplicitDefs[I], /*OnlySmaller=*/false);
338
339 for (unsigned I = 0, E = InstInfo.getNumDefs(); I != E; ++I) {
340 const MCOperand &Operand = Inst.getOperand(I);
341 assert(Operand.isReg());
342 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/false);
343 }
344 }
345
getTouchedRegs(const MCInst & Inst,BitVector & Regs) const346 void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const {
347 if (isPrefix(Inst) || isCFI(Inst))
348 return;
349
350 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
351
352 const MCPhysReg *ImplicitDefs = InstInfo.getImplicitDefs();
353 for (unsigned I = 0, E = InstInfo.getNumImplicitDefs(); I != E; ++I)
354 Regs |= getAliases(ImplicitDefs[I], /*OnlySmaller=*/false);
355 const MCPhysReg *ImplicitUses = InstInfo.getImplicitUses();
356 for (unsigned I = 0, E = InstInfo.getNumImplicitUses(); I != E; ++I)
357 Regs |= getAliases(ImplicitUses[I], /*OnlySmaller=*/false);
358
359 for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
360 if (!Inst.getOperand(I).isReg())
361 continue;
362 Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/false);
363 }
364 }
365
getWrittenRegs(const MCInst & Inst,BitVector & Regs) const366 void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const {
367 if (isPrefix(Inst) || isCFI(Inst))
368 return;
369
370 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
371
372 const MCPhysReg *ImplicitDefs = InstInfo.getImplicitDefs();
373 for (unsigned I = 0, E = InstInfo.getNumImplicitDefs(); I != E; ++I)
374 Regs |= getAliases(ImplicitDefs[I], /*OnlySmaller=*/true);
375
376 for (unsigned I = 0, E = InstInfo.getNumDefs(); I != E; ++I) {
377 const MCOperand &Operand = Inst.getOperand(I);
378 assert(Operand.isReg());
379 Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);
380 }
381 }
382
getUsedRegs(const MCInst & Inst,BitVector & Regs) const383 void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const {
384 if (isPrefix(Inst) || isCFI(Inst))
385 return;
386
387 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
388
389 const MCPhysReg *ImplicitUses = InstInfo.getImplicitUses();
390 for (unsigned I = 0, E = InstInfo.getNumImplicitUses(); I != E; ++I)
391 Regs |= getAliases(ImplicitUses[I], /*OnlySmaller=*/true);
392
393 for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
394 if (!Inst.getOperand(I).isReg())
395 continue;
396 Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/true);
397 }
398 }
399
getSrcRegs(const MCInst & Inst,BitVector & Regs) const400 void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const {
401 if (isPrefix(Inst) || isCFI(Inst))
402 return;
403
404 if (isCall(Inst)) {
405 BitVector CallRegs = BitVector(Regs.size(), false);
406 getCalleeSavedRegs(CallRegs);
407 CallRegs.flip();
408 Regs |= CallRegs;
409 return;
410 }
411
412 if (isReturn(Inst)) {
413 getDefaultLiveOut(Regs);
414 return;
415 }
416
417 if (isRep(Inst))
418 getRepRegs(Regs);
419
420 const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
421
422 const MCPhysReg *ImplicitUses = InstInfo.getImplicitUses();
423 for (unsigned I = 0, E = InstInfo.getNumImplicitUses(); I != E; ++I)
424 Regs |= getAliases(ImplicitUses[I], /*OnlySmaller=*/true);
425
426 for (unsigned I = InstInfo.getNumDefs(), E = InstInfo.getNumOperands();
427 I != E; ++I) {
428 if (!Inst.getOperand(I).isReg())
429 continue;
430 Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/true);
431 }
432 }
433
hasDefOfPhysReg(const MCInst & MI,unsigned Reg) const434 bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const {
435 const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());
436 return InstInfo.hasDefOfPhysReg(MI, Reg, *RegInfo);
437 }
438
hasUseOfPhysReg(const MCInst & MI,unsigned Reg) const439 bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const {
440 const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());
441 for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I)
442 if (MI.getOperand(I).isReg() &&
443 RegInfo->isSubRegisterEq(Reg, MI.getOperand(I).getReg()))
444 return true;
445 if (const uint16_t *ImpUses = InstInfo.ImplicitUses) {
446 for (; *ImpUses; ++ImpUses)
447 if (*ImpUses == Reg || RegInfo->isSubRegister(Reg, *ImpUses))
448 return true;
449 }
450 return false;
451 }
452
getAliases(MCPhysReg Reg,bool OnlySmaller) const453 const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg,
454 bool OnlySmaller) const {
455 if (OnlySmaller)
456 return SmallerAliasMap[Reg];
457 return AliasMap[Reg];
458 }
459
initAliases()460 void MCPlusBuilder::initAliases() {
461 assert(AliasMap.size() == 0 && SmallerAliasMap.size() == 0);
462 // Build alias map
463 for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {
464 BitVector BV(RegInfo->getNumRegs(), false);
465 BV.set(I);
466 AliasMap.emplace_back(BV);
467 SmallerAliasMap.emplace_back(BV);
468 }
469
470 // Cache all aliases for each register
471 for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I != E; ++I) {
472 for (MCRegAliasIterator AI(I, RegInfo, true); AI.isValid(); ++AI)
473 AliasMap[I].set(*AI);
474 }
475
476 // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister)
477 std::queue<MCPhysReg> Worklist;
478 for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I)
479 Worklist.push(I);
480 while (!Worklist.empty()) {
481 MCPhysReg I = Worklist.front();
482 Worklist.pop();
483 for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI)
484 SmallerAliasMap[I] |= SmallerAliasMap[*SI];
485 for (MCSuperRegIterator SI(I, RegInfo); SI.isValid(); ++SI)
486 Worklist.push(*SI);
487 }
488
489 LLVM_DEBUG({
490 dbgs() << "Dumping reg alias table:\n";
491 for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {
492 dbgs() << "Reg " << I << ": ";
493 const BitVector &BV = AliasMap[I];
494 int Idx = BV.find_first();
495 while (Idx != -1) {
496 dbgs() << Idx << " ";
497 Idx = BV.find_next(Idx);
498 }
499 dbgs() << "\n";
500 }
501 });
502 }
503
getRegSize(MCPhysReg Reg) const504 uint8_t MCPlusBuilder::getRegSize(MCPhysReg Reg) const {
505 // SizeMap caches a mapping of registers to their sizes
506 static std::vector<uint8_t> SizeMap;
507
508 if (SizeMap.size() > 0) {
509 return SizeMap[Reg];
510 }
511 SizeMap = std::vector<uint8_t>(RegInfo->getNumRegs());
512 // Build size map
513 for (auto I = RegInfo->regclass_begin(), E = RegInfo->regclass_end(); I != E;
514 ++I) {
515 for (MCPhysReg Reg : *I)
516 SizeMap[Reg] = I->getSizeInBits() / 8;
517 }
518
519 return SizeMap[Reg];
520 }
521
setOperandToSymbolRef(MCInst & Inst,int OpNum,const MCSymbol * Symbol,int64_t Addend,MCContext * Ctx,uint64_t RelType) const522 bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum,
523 const MCSymbol *Symbol,
524 int64_t Addend, MCContext *Ctx,
525 uint64_t RelType) const {
526 MCOperand Operand;
527 if (!Addend) {
528 Operand = MCOperand::createExpr(getTargetExprFor(
529 Inst, MCSymbolRefExpr::create(Symbol, *Ctx), *Ctx, RelType));
530 } else {
531 Operand = MCOperand::createExpr(getTargetExprFor(
532 Inst,
533 MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, *Ctx),
534 MCConstantExpr::create(Addend, *Ctx), *Ctx),
535 *Ctx, RelType));
536 }
537 Inst.getOperand(OpNum) = Operand;
538 return true;
539 }
540