1 //===- bolt/Core/MCPlusBuilder.cpp - Interface for MCPlus -----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the MCPlusBuilder class.
11 //===----------------------------------------------------------------------===//
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"
26 #define DEBUG_TYPE "mcplus"
30 using namespace MCPlus
;
34 TerminalTrap("terminal-trap",
35 cl::desc("Assume that execution stops at trap instruction"),
36 cl::init(true), cl::Hidden
, cl::cat(BoltCategory
));
39 bool MCPlusBuilder::equals(const MCInst
&A
, const MCInst
&B
,
40 CompFuncTy Comp
) const {
41 if (A
.getOpcode() != B
.getOpcode())
44 unsigned NumOperands
= MCPlus::getNumPrimeOperands(A
);
45 if (NumOperands
!= MCPlus::getNumPrimeOperands(B
))
48 for (unsigned Index
= 0; Index
< NumOperands
; ++Index
)
49 if (!equals(A
.getOperand(Index
), B
.getOperand(Index
), Comp
))
55 bool MCPlusBuilder::equals(const MCOperand
&A
, const MCOperand
&B
,
56 CompFuncTy Comp
) const {
60 return A
.getReg() == B
.getReg();
61 } else if (A
.isImm()) {
64 return A
.getImm() == B
.getImm();
65 } else if (A
.isSFPImm()) {
68 return A
.getSFPImm() == B
.getSFPImm();
69 } else if (A
.isDFPImm()) {
72 return A
.getDFPImm() == B
.getDFPImm();
73 } else if (A
.isExpr()) {
76 return equals(*A
.getExpr(), *B
.getExpr(), Comp
);
78 llvm_unreachable("unexpected operand kind");
83 bool MCPlusBuilder::equals(const MCExpr
&A
, const MCExpr
&B
,
84 CompFuncTy Comp
) const {
85 if (A
.getKind() != B
.getKind())
88 switch (A
.getKind()) {
89 case MCExpr::Constant
: {
90 const auto &ConstA
= cast
<MCConstantExpr
>(A
);
91 const auto &ConstB
= cast
<MCConstantExpr
>(B
);
92 return ConstA
.getValue() == ConstB
.getValue();
95 case MCExpr::SymbolRef
: {
96 const MCSymbolRefExpr
&SymbolA
= cast
<MCSymbolRefExpr
>(A
);
97 const MCSymbolRefExpr
&SymbolB
= cast
<MCSymbolRefExpr
>(B
);
98 return SymbolA
.getKind() == SymbolB
.getKind() &&
99 Comp(&SymbolA
.getSymbol(), &SymbolB
.getSymbol());
102 case MCExpr::Unary
: {
103 const auto &UnaryA
= cast
<MCUnaryExpr
>(A
);
104 const auto &UnaryB
= cast
<MCUnaryExpr
>(B
);
105 return UnaryA
.getOpcode() == UnaryB
.getOpcode() &&
106 equals(*UnaryA
.getSubExpr(), *UnaryB
.getSubExpr(), Comp
);
109 case MCExpr::Binary
: {
110 const auto &BinaryA
= cast
<MCBinaryExpr
>(A
);
111 const auto &BinaryB
= cast
<MCBinaryExpr
>(B
);
112 return BinaryA
.getOpcode() == BinaryB
.getOpcode() &&
113 equals(*BinaryA
.getLHS(), *BinaryB
.getLHS(), Comp
) &&
114 equals(*BinaryA
.getRHS(), *BinaryB
.getRHS(), Comp
);
117 case MCExpr::Target
: {
118 const auto &TargetExprA
= cast
<MCTargetExpr
>(A
);
119 const auto &TargetExprB
= cast
<MCTargetExpr
>(B
);
120 return equals(TargetExprA
, TargetExprB
, Comp
);
124 llvm_unreachable("Invalid expression kind!");
127 bool MCPlusBuilder::equals(const MCTargetExpr
&A
, const MCTargetExpr
&B
,
128 CompFuncTy Comp
) const {
129 llvm_unreachable("target-specific expressions are unsupported");
132 bool MCPlusBuilder::isTerminator(const MCInst
&Inst
) const {
133 return Analysis
->isTerminator(Inst
) ||
134 (opts::TerminalTrap
&& Info
->get(Inst
.getOpcode()).isTrap());
137 void MCPlusBuilder::setTailCall(MCInst
&Inst
) const {
138 assert(!hasAnnotation(Inst
, MCAnnotation::kTailCall
));
139 setAnnotationOpValue(Inst
, MCAnnotation::kTailCall
, true);
142 bool MCPlusBuilder::isTailCall(const MCInst
&Inst
) const {
143 if (hasAnnotation(Inst
, MCAnnotation::kTailCall
))
145 if (getConditionalTailCall(Inst
))
150 std::optional
<MCLandingPad
> MCPlusBuilder::getEHInfo(const MCInst
&Inst
) const {
153 std::optional
<int64_t> LPSym
=
154 getAnnotationOpValue(Inst
, MCAnnotation::kEHLandingPad
);
157 std::optional
<int64_t> Action
=
158 getAnnotationOpValue(Inst
, MCAnnotation::kEHAction
);
162 return std::make_pair(reinterpret_cast<const MCSymbol
*>(*LPSym
),
163 static_cast<uint64_t>(*Action
));
166 void MCPlusBuilder::addEHInfo(MCInst
&Inst
, const MCLandingPad
&LP
) const {
168 assert(!getEHInfo(Inst
));
169 setAnnotationOpValue(Inst
, MCAnnotation::kEHLandingPad
,
170 reinterpret_cast<int64_t>(LP
.first
));
171 setAnnotationOpValue(Inst
, MCAnnotation::kEHAction
,
172 static_cast<int64_t>(LP
.second
));
176 bool MCPlusBuilder::updateEHInfo(MCInst
&Inst
, const MCLandingPad
&LP
) const {
180 setAnnotationOpValue(Inst
, MCAnnotation::kEHLandingPad
,
181 reinterpret_cast<int64_t>(LP
.first
));
182 setAnnotationOpValue(Inst
, MCAnnotation::kEHAction
,
183 static_cast<int64_t>(LP
.second
));
187 int64_t MCPlusBuilder::getGnuArgsSize(const MCInst
&Inst
) const {
188 std::optional
<int64_t> Value
=
189 getAnnotationOpValue(Inst
, MCAnnotation::kGnuArgsSize
);
195 void MCPlusBuilder::addGnuArgsSize(MCInst
&Inst
, int64_t GnuArgsSize
) const {
196 assert(GnuArgsSize
>= 0 && "cannot set GNU_args_size to negative value");
197 assert(getGnuArgsSize(Inst
) == -1LL && "GNU_args_size already set");
198 assert(isInvoke(Inst
) && "GNU_args_size can only be set for invoke");
200 setAnnotationOpValue(Inst
, MCAnnotation::kGnuArgsSize
, GnuArgsSize
);
203 uint64_t MCPlusBuilder::getJumpTable(const MCInst
&Inst
) const {
204 std::optional
<int64_t> Value
=
205 getAnnotationOpValue(Inst
, MCAnnotation::kJumpTable
);
211 uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst
&Inst
) const {
212 return getAnnotationAs
<uint16_t>(Inst
, "JTIndexReg");
215 bool MCPlusBuilder::setJumpTable(MCInst
&Inst
, uint64_t Value
,
216 uint16_t IndexReg
, AllocatorIdTy AllocId
) {
217 if (!isIndirectBranch(Inst
))
219 setAnnotationOpValue(Inst
, MCAnnotation::kJumpTable
, Value
);
220 getOrCreateAnnotationAs
<uint16_t>(Inst
, "JTIndexReg", AllocId
) = IndexReg
;
224 bool MCPlusBuilder::unsetJumpTable(MCInst
&Inst
) const {
225 if (!getJumpTable(Inst
))
227 removeAnnotation(Inst
, MCAnnotation::kJumpTable
);
228 removeAnnotation(Inst
, "JTIndexReg");
232 std::optional
<uint64_t>
233 MCPlusBuilder::getConditionalTailCall(const MCInst
&Inst
) const {
234 std::optional
<int64_t> Value
=
235 getAnnotationOpValue(Inst
, MCAnnotation::kConditionalTailCall
);
238 return static_cast<uint64_t>(*Value
);
241 bool MCPlusBuilder::setConditionalTailCall(MCInst
&Inst
, uint64_t Dest
) const {
242 if (!isConditionalBranch(Inst
))
245 setAnnotationOpValue(Inst
, MCAnnotation::kConditionalTailCall
, Dest
);
249 bool MCPlusBuilder::unsetConditionalTailCall(MCInst
&Inst
) const {
250 if (!getConditionalTailCall(Inst
))
252 removeAnnotation(Inst
, MCAnnotation::kConditionalTailCall
);
256 std::optional
<uint32_t> MCPlusBuilder::getOffset(const MCInst
&Inst
) const {
257 std::optional
<int64_t> Value
=
258 getAnnotationOpValue(Inst
, MCAnnotation::kOffset
);
261 return static_cast<uint32_t>(*Value
);
264 uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst
&Inst
,
265 uint32_t Default
) const {
266 if (std::optional
<uint32_t> Offset
= getOffset(Inst
))
271 bool MCPlusBuilder::setOffset(MCInst
&Inst
, uint32_t Offset
) const {
272 setAnnotationOpValue(Inst
, MCAnnotation::kOffset
, Offset
);
276 bool MCPlusBuilder::clearOffset(MCInst
&Inst
) const {
277 if (!hasAnnotation(Inst
, MCAnnotation::kOffset
))
279 removeAnnotation(Inst
, MCAnnotation::kOffset
);
283 MCSymbol
*MCPlusBuilder::getInstLabel(const MCInst
&Inst
) const {
284 if (std::optional
<int64_t> Label
=
285 getAnnotationOpValue(Inst
, MCAnnotation::kLabel
))
286 return reinterpret_cast<MCSymbol
*>(*Label
);
290 MCSymbol
*MCPlusBuilder::getOrCreateInstLabel(MCInst
&Inst
, const Twine
&Name
,
291 MCContext
*Ctx
) const {
292 MCSymbol
*Label
= getInstLabel(Inst
);
296 Label
= Ctx
->createNamedTempSymbol(Name
);
297 setAnnotationOpValue(Inst
, MCAnnotation::kLabel
,
298 reinterpret_cast<int64_t>(Label
));
302 void MCPlusBuilder::setInstLabel(MCInst
&Inst
, MCSymbol
*Label
) const {
303 assert(!getInstLabel(Inst
) && "Instruction already has assigned label.");
304 setAnnotationOpValue(Inst
, MCAnnotation::kLabel
,
305 reinterpret_cast<int64_t>(Label
));
308 std::optional
<uint32_t> MCPlusBuilder::getSize(const MCInst
&Inst
) const {
309 if (std::optional
<int64_t> Value
=
310 getAnnotationOpValue(Inst
, MCAnnotation::kSize
))
311 return static_cast<uint32_t>(*Value
);
315 void MCPlusBuilder::setSize(MCInst
&Inst
, uint32_t Size
) const {
316 setAnnotationOpValue(Inst
, MCAnnotation::kSize
, Size
);
319 bool MCPlusBuilder::isDynamicBranch(const MCInst
&Inst
) const {
320 if (!hasAnnotation(Inst
, MCAnnotation::kDynamicBranch
))
322 assert(isBranch(Inst
) && "Branch expected.");
326 std::optional
<uint32_t>
327 MCPlusBuilder::getDynamicBranchID(const MCInst
&Inst
) const {
328 if (std::optional
<int64_t> Value
=
329 getAnnotationOpValue(Inst
, MCAnnotation::kDynamicBranch
)) {
330 assert(isBranch(Inst
) && "Branch expected.");
331 return static_cast<uint32_t>(*Value
);
336 void MCPlusBuilder::setDynamicBranch(MCInst
&Inst
, uint32_t ID
) const {
337 assert(isBranch(Inst
) && "Branch expected.");
338 setAnnotationOpValue(Inst
, MCAnnotation::kDynamicBranch
, ID
);
341 bool MCPlusBuilder::hasAnnotation(const MCInst
&Inst
, unsigned Index
) const {
342 return (bool)getAnnotationOpValue(Inst
, Index
);
345 bool MCPlusBuilder::removeAnnotation(MCInst
&Inst
, unsigned Index
) const {
346 std::optional
<unsigned> FirstAnnotationOp
= getFirstAnnotationOpIndex(Inst
);
347 if (!FirstAnnotationOp
)
350 for (unsigned I
= Inst
.getNumOperands() - 1; I
>= *FirstAnnotationOp
; --I
) {
351 const int64_t ImmValue
= Inst
.getOperand(I
).getImm();
352 if (extractAnnotationIndex(ImmValue
) == Index
) {
353 Inst
.erase(Inst
.begin() + I
);
360 void MCPlusBuilder::stripAnnotations(MCInst
&Inst
, bool KeepTC
) const {
361 KeepTC
&= hasAnnotation(Inst
, MCAnnotation::kTailCall
);
363 removeAnnotations(Inst
);
369 void MCPlusBuilder::printAnnotations(const MCInst
&Inst
,
370 raw_ostream
&OS
) const {
371 std::optional
<unsigned> FirstAnnotationOp
= getFirstAnnotationOpIndex(Inst
);
372 if (!FirstAnnotationOp
)
375 for (unsigned I
= *FirstAnnotationOp
; I
< Inst
.getNumOperands(); ++I
) {
376 const int64_t Imm
= Inst
.getOperand(I
).getImm();
377 const unsigned Index
= extractAnnotationIndex(Imm
);
378 const int64_t Value
= extractAnnotationValue(Imm
);
379 const auto *Annotation
= reinterpret_cast<const MCAnnotation
*>(Value
);
380 if (Index
>= MCAnnotation::kGeneric
) {
381 OS
<< " # " << AnnotationNames
[Index
- MCAnnotation::kGeneric
] << ": ";
382 Annotation
->print(OS
);
387 void MCPlusBuilder::getClobberedRegs(const MCInst
&Inst
,
388 BitVector
&Regs
) const {
389 if (isPrefix(Inst
) || isCFI(Inst
))
392 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
394 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
395 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/false);
397 for (const MCOperand
&Operand
: defOperands(Inst
)) {
398 assert(Operand
.isReg());
399 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/false);
403 void MCPlusBuilder::getTouchedRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
404 if (isPrefix(Inst
) || isCFI(Inst
))
407 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
409 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
410 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/false);
411 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
412 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/false);
414 for (unsigned I
= 0, E
= Inst
.getNumOperands(); I
!= E
; ++I
) {
415 if (!Inst
.getOperand(I
).isReg())
417 Regs
|= getAliases(Inst
.getOperand(I
).getReg(), /*OnlySmaller=*/false);
421 void MCPlusBuilder::getWrittenRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
422 if (isPrefix(Inst
) || isCFI(Inst
))
425 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
427 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
428 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/true);
430 for (const MCOperand
&Operand
: defOperands(Inst
)) {
431 assert(Operand
.isReg());
432 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/true);
436 void MCPlusBuilder::getUsedRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
437 if (isPrefix(Inst
) || isCFI(Inst
))
440 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
442 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
443 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/true);
445 for (unsigned I
= 0, E
= Inst
.getNumOperands(); I
!= E
; ++I
) {
446 if (!Inst
.getOperand(I
).isReg())
448 Regs
|= getAliases(Inst
.getOperand(I
).getReg(), /*OnlySmaller=*/true);
452 void MCPlusBuilder::getSrcRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
453 if (isPrefix(Inst
) || isCFI(Inst
))
457 BitVector CallRegs
= BitVector(Regs
.size(), false);
458 getCalleeSavedRegs(CallRegs
);
464 if (isReturn(Inst
)) {
465 getDefaultLiveOut(Regs
);
472 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
474 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
475 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/true);
477 for (const MCOperand
&Operand
: useOperands(Inst
))
479 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/true);
482 bool MCPlusBuilder::hasDefOfPhysReg(const MCInst
&MI
, unsigned Reg
) const {
483 const MCInstrDesc
&InstInfo
= Info
->get(MI
.getOpcode());
484 return InstInfo
.hasDefOfPhysReg(MI
, Reg
, *RegInfo
);
487 bool MCPlusBuilder::hasUseOfPhysReg(const MCInst
&MI
, unsigned Reg
) const {
488 const MCInstrDesc
&InstInfo
= Info
->get(MI
.getOpcode());
489 for (int I
= InstInfo
.NumDefs
; I
< InstInfo
.NumOperands
; ++I
)
490 if (MI
.getOperand(I
).isReg() && MI
.getOperand(I
).getReg() &&
491 RegInfo
->isSubRegisterEq(Reg
, MI
.getOperand(I
).getReg()))
493 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses()) {
494 if (ImplicitUse
== Reg
|| RegInfo
->isSubRegister(Reg
, ImplicitUse
))
500 const BitVector
&MCPlusBuilder::getAliases(MCPhysReg Reg
,
501 bool OnlySmaller
) const {
503 return SmallerAliasMap
[Reg
];
504 return AliasMap
[Reg
];
507 void MCPlusBuilder::initAliases() {
508 assert(AliasMap
.size() == 0 && SmallerAliasMap
.size() == 0);
510 for (MCPhysReg I
= 0, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
511 BitVector
BV(RegInfo
->getNumRegs(), false);
513 AliasMap
.emplace_back(BV
);
514 SmallerAliasMap
.emplace_back(BV
);
517 // Cache all aliases for each register
518 for (MCPhysReg I
= 1, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
519 for (MCRegAliasIterator
AI(I
, RegInfo
, true); AI
.isValid(); ++AI
)
520 AliasMap
[I
].set(*AI
);
523 // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister)
524 for (MCPhysReg I
= 1, E
= RegInfo
->getNumRegs(); I
< E
; ++I
)
525 for (MCSubRegIterator
SI(I
, RegInfo
); SI
.isValid(); ++SI
)
526 SmallerAliasMap
[I
] |= SmallerAliasMap
[*SI
];
529 dbgs() << "Dumping reg alias table:\n";
530 for (MCPhysReg I
= 0, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
531 dbgs() << "Reg " << I
<< ": ";
532 const BitVector
&BV
= AliasMap
[I
];
533 int Idx
= BV
.find_first();
535 dbgs() << Idx
<< " ";
536 Idx
= BV
.find_next(Idx
);
543 void MCPlusBuilder::initSizeMap() {
544 SizeMap
.resize(RegInfo
->getNumRegs());
546 for (auto RC
: RegInfo
->regclasses())
547 for (MCPhysReg Reg
: RC
)
548 SizeMap
[Reg
] = RC
.getSizeInBits() / 8;
551 bool MCPlusBuilder::setOperandToSymbolRef(MCInst
&Inst
, int OpNum
,
552 const MCSymbol
*Symbol
,
553 int64_t Addend
, MCContext
*Ctx
,
554 uint64_t RelType
) const {
557 Operand
= MCOperand::createExpr(getTargetExprFor(
558 Inst
, MCSymbolRefExpr::create(Symbol
, *Ctx
), *Ctx
, RelType
));
560 Operand
= MCOperand::createExpr(getTargetExprFor(
562 MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol
, *Ctx
),
563 MCConstantExpr::create(Addend
, *Ctx
), *Ctx
),
566 Inst
.getOperand(OpNum
) = Operand
;