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 "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"
24 #define DEBUG_TYPE "mcplus"
28 using namespace MCPlus
;
30 bool MCPlusBuilder::equals(const MCInst
&A
, const MCInst
&B
,
31 CompFuncTy Comp
) const {
32 if (A
.getOpcode() != B
.getOpcode())
35 unsigned NumOperands
= MCPlus::getNumPrimeOperands(A
);
36 if (NumOperands
!= MCPlus::getNumPrimeOperands(B
))
39 for (unsigned Index
= 0; Index
< NumOperands
; ++Index
)
40 if (!equals(A
.getOperand(Index
), B
.getOperand(Index
), Comp
))
46 bool MCPlusBuilder::equals(const MCOperand
&A
, const MCOperand
&B
,
47 CompFuncTy Comp
) const {
51 return A
.getReg() == B
.getReg();
52 } else if (A
.isImm()) {
55 return A
.getImm() == B
.getImm();
56 } else if (A
.isSFPImm()) {
59 return A
.getSFPImm() == B
.getSFPImm();
60 } else if (A
.isDFPImm()) {
63 return A
.getDFPImm() == B
.getDFPImm();
64 } else if (A
.isExpr()) {
67 return equals(*A
.getExpr(), *B
.getExpr(), Comp
);
69 llvm_unreachable("unexpected operand kind");
74 bool MCPlusBuilder::equals(const MCExpr
&A
, const MCExpr
&B
,
75 CompFuncTy Comp
) const {
76 if (A
.getKind() != B
.getKind())
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();
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());
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
);
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
);
108 case MCExpr::Target
: {
109 const auto &TargetExprA
= cast
<MCTargetExpr
>(A
);
110 const auto &TargetExprB
= cast
<MCTargetExpr
>(B
);
111 return equals(TargetExprA
, TargetExprB
, Comp
);
115 llvm_unreachable("Invalid expression kind!");
118 bool MCPlusBuilder::equals(const MCTargetExpr
&A
, const MCTargetExpr
&B
,
119 CompFuncTy Comp
) const {
120 llvm_unreachable("target-specific expressions are unsupported");
123 void MCPlusBuilder::setTailCall(MCInst
&Inst
) {
124 assert(!hasAnnotation(Inst
, MCAnnotation::kTailCall
));
125 setAnnotationOpValue(Inst
, MCAnnotation::kTailCall
, true);
128 bool MCPlusBuilder::isTailCall(const MCInst
&Inst
) const {
129 if (hasAnnotation(Inst
, MCAnnotation::kTailCall
))
131 if (getConditionalTailCall(Inst
))
136 std::optional
<MCLandingPad
> MCPlusBuilder::getEHInfo(const MCInst
&Inst
) const {
139 std::optional
<int64_t> LPSym
=
140 getAnnotationOpValue(Inst
, MCAnnotation::kEHLandingPad
);
143 std::optional
<int64_t> Action
=
144 getAnnotationOpValue(Inst
, MCAnnotation::kEHAction
);
148 return std::make_pair(reinterpret_cast<const MCSymbol
*>(*LPSym
),
149 static_cast<uint64_t>(*Action
));
152 void MCPlusBuilder::addEHInfo(MCInst
&Inst
, const MCLandingPad
&LP
) {
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
));
162 bool MCPlusBuilder::updateEHInfo(MCInst
&Inst
, const MCLandingPad
&LP
) {
166 setAnnotationOpValue(Inst
, MCAnnotation::kEHLandingPad
,
167 reinterpret_cast<int64_t>(LP
.first
));
168 setAnnotationOpValue(Inst
, MCAnnotation::kEHAction
,
169 static_cast<int64_t>(LP
.second
));
173 int64_t MCPlusBuilder::getGnuArgsSize(const MCInst
&Inst
) const {
174 std::optional
<int64_t> Value
=
175 getAnnotationOpValue(Inst
, MCAnnotation::kGnuArgsSize
);
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");
187 setAnnotationOpValue(Inst
, MCAnnotation::kGnuArgsSize
, GnuArgsSize
, AllocId
);
190 uint64_t MCPlusBuilder::getJumpTable(const MCInst
&Inst
) const {
191 std::optional
<int64_t> Value
=
192 getAnnotationOpValue(Inst
, MCAnnotation::kJumpTable
);
198 uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst
&Inst
) const {
199 return getAnnotationAs
<uint16_t>(Inst
, "JTIndexReg");
202 bool MCPlusBuilder::setJumpTable(MCInst
&Inst
, uint64_t Value
,
203 uint16_t IndexReg
, AllocatorIdTy AllocId
) {
204 if (!isIndirectBranch(Inst
))
206 setAnnotationOpValue(Inst
, MCAnnotation::kJumpTable
, Value
, AllocId
);
207 getOrCreateAnnotationAs
<uint16_t>(Inst
, "JTIndexReg", AllocId
) = IndexReg
;
211 bool MCPlusBuilder::unsetJumpTable(MCInst
&Inst
) {
212 if (!getJumpTable(Inst
))
214 removeAnnotation(Inst
, MCAnnotation::kJumpTable
);
215 removeAnnotation(Inst
, "JTIndexReg");
219 std::optional
<uint64_t>
220 MCPlusBuilder::getConditionalTailCall(const MCInst
&Inst
) const {
221 std::optional
<int64_t> Value
=
222 getAnnotationOpValue(Inst
, MCAnnotation::kConditionalTailCall
);
225 return static_cast<uint64_t>(*Value
);
228 bool MCPlusBuilder::setConditionalTailCall(MCInst
&Inst
, uint64_t Dest
) {
229 if (!isConditionalBranch(Inst
))
232 setAnnotationOpValue(Inst
, MCAnnotation::kConditionalTailCall
, Dest
);
236 bool MCPlusBuilder::unsetConditionalTailCall(MCInst
&Inst
) {
237 if (!getConditionalTailCall(Inst
))
239 removeAnnotation(Inst
, MCAnnotation::kConditionalTailCall
);
243 std::optional
<uint32_t> MCPlusBuilder::getOffset(const MCInst
&Inst
) const {
244 std::optional
<int64_t> Value
=
245 getAnnotationOpValue(Inst
, MCAnnotation::kOffset
);
248 return static_cast<uint32_t>(*Value
);
251 uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst
&Inst
,
252 uint32_t Default
) const {
253 if (std::optional
<uint32_t> Offset
= getOffset(Inst
))
258 bool MCPlusBuilder::setOffset(MCInst
&Inst
, uint32_t Offset
,
259 AllocatorIdTy AllocatorId
) {
260 setAnnotationOpValue(Inst
, MCAnnotation::kOffset
, Offset
, AllocatorId
);
264 bool MCPlusBuilder::clearOffset(MCInst
&Inst
) {
265 if (!hasAnnotation(Inst
, MCAnnotation::kOffset
))
267 removeAnnotation(Inst
, MCAnnotation::kOffset
);
271 std::optional
<MCSymbol
*> MCPlusBuilder::getLabel(const MCInst
&Inst
) const {
272 if (auto Label
= tryGetAnnotationAs
<MCSymbol
*>(Inst
, MCAnnotation::kLabel
))
277 bool MCPlusBuilder::setLabel(MCInst
&Inst
, MCSymbol
*Label
,
278 AllocatorIdTy AllocatorId
) {
279 getOrCreateAnnotationAs
<MCSymbol
*>(Inst
, MCAnnotation::kLabel
, AllocatorId
) =
284 bool MCPlusBuilder::hasAnnotation(const MCInst
&Inst
, unsigned Index
) const {
285 const MCInst
*AnnotationInst
= getAnnotationInst(Inst
);
289 return (bool)getAnnotationOpValue(Inst
, Index
);
292 bool MCPlusBuilder::removeAnnotation(MCInst
&Inst
, unsigned Index
) {
293 MCInst
*AnnotationInst
= getAnnotationInst(Inst
);
297 for (int I
= AnnotationInst
->getNumOperands() - 1; I
>= 0; --I
) {
298 int64_t ImmValue
= AnnotationInst
->getOperand(I
).getImm();
299 if (extractAnnotationIndex(ImmValue
) == Index
) {
300 AnnotationInst
->erase(AnnotationInst
->begin() + I
);
307 void MCPlusBuilder::stripAnnotations(MCInst
&Inst
, bool KeepTC
) {
308 MCInst
*AnnotationInst
= getAnnotationInst(Inst
);
311 // Preserve TailCall annotation.
312 auto IsTC
= hasAnnotation(Inst
, MCAnnotation::kTailCall
);
314 removeAnnotationInst(Inst
);
320 void MCPlusBuilder::printAnnotations(const MCInst
&Inst
,
321 raw_ostream
&OS
) const {
322 const MCInst
*AnnotationInst
= getAnnotationInst(Inst
);
326 for (unsigned I
= 0; I
< AnnotationInst
->getNumOperands(); ++I
) {
327 const int64_t Imm
= AnnotationInst
->getOperand(I
).getImm();
328 const unsigned Index
= extractAnnotationIndex(Imm
);
329 const int64_t Value
= extractAnnotationValue(Imm
);
330 const auto *Annotation
= reinterpret_cast<const MCAnnotation
*>(Value
);
331 if (Index
>= MCAnnotation::kGeneric
) {
332 OS
<< " # " << AnnotationNames
[Index
- MCAnnotation::kGeneric
] << ": ";
333 Annotation
->print(OS
);
338 void MCPlusBuilder::getClobberedRegs(const MCInst
&Inst
,
339 BitVector
&Regs
) const {
340 if (isPrefix(Inst
) || isCFI(Inst
))
343 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
345 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
346 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/false);
348 for (const MCOperand
&Operand
: defOperands(Inst
)) {
349 assert(Operand
.isReg());
350 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/false);
354 void MCPlusBuilder::getTouchedRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
355 if (isPrefix(Inst
) || isCFI(Inst
))
358 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
360 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
361 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/false);
362 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
363 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/false);
365 for (unsigned I
= 0, E
= Inst
.getNumOperands(); I
!= E
; ++I
) {
366 if (!Inst
.getOperand(I
).isReg())
368 Regs
|= getAliases(Inst
.getOperand(I
).getReg(), /*OnlySmaller=*/false);
372 void MCPlusBuilder::getWrittenRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
373 if (isPrefix(Inst
) || isCFI(Inst
))
376 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
378 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
379 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/true);
381 for (const MCOperand
&Operand
: defOperands(Inst
)) {
382 assert(Operand
.isReg());
383 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/true);
387 void MCPlusBuilder::getUsedRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
388 if (isPrefix(Inst
) || isCFI(Inst
))
391 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
393 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
394 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/true);
396 for (unsigned I
= 0, E
= Inst
.getNumOperands(); I
!= E
; ++I
) {
397 if (!Inst
.getOperand(I
).isReg())
399 Regs
|= getAliases(Inst
.getOperand(I
).getReg(), /*OnlySmaller=*/true);
403 void MCPlusBuilder::getSrcRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
404 if (isPrefix(Inst
) || isCFI(Inst
))
408 BitVector CallRegs
= BitVector(Regs
.size(), false);
409 getCalleeSavedRegs(CallRegs
);
415 if (isReturn(Inst
)) {
416 getDefaultLiveOut(Regs
);
423 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
425 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
426 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/true);
428 for (const MCOperand
&Operand
: useOperands(Inst
))
430 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/true);
433 bool MCPlusBuilder::hasDefOfPhysReg(const MCInst
&MI
, unsigned Reg
) const {
434 const MCInstrDesc
&InstInfo
= Info
->get(MI
.getOpcode());
435 return InstInfo
.hasDefOfPhysReg(MI
, Reg
, *RegInfo
);
438 bool MCPlusBuilder::hasUseOfPhysReg(const MCInst
&MI
, unsigned Reg
) const {
439 const MCInstrDesc
&InstInfo
= Info
->get(MI
.getOpcode());
440 for (int I
= InstInfo
.NumDefs
; I
< InstInfo
.NumOperands
; ++I
)
441 if (MI
.getOperand(I
).isReg() && MI
.getOperand(I
).getReg() &&
442 RegInfo
->isSubRegisterEq(Reg
, MI
.getOperand(I
).getReg()))
444 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses()) {
445 if (ImplicitUse
== Reg
|| RegInfo
->isSubRegister(Reg
, ImplicitUse
))
451 const BitVector
&MCPlusBuilder::getAliases(MCPhysReg Reg
,
452 bool OnlySmaller
) const {
454 return SmallerAliasMap
[Reg
];
455 return AliasMap
[Reg
];
458 void MCPlusBuilder::initAliases() {
459 assert(AliasMap
.size() == 0 && SmallerAliasMap
.size() == 0);
461 for (MCPhysReg I
= 0, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
462 BitVector
BV(RegInfo
->getNumRegs(), false);
464 AliasMap
.emplace_back(BV
);
465 SmallerAliasMap
.emplace_back(BV
);
468 // Cache all aliases for each register
469 for (MCPhysReg I
= 1, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
470 for (MCRegAliasIterator
AI(I
, RegInfo
, true); AI
.isValid(); ++AI
)
471 AliasMap
[I
].set(*AI
);
474 // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister)
475 for (MCPhysReg I
= 1, E
= RegInfo
->getNumRegs(); I
< E
; ++I
)
476 for (MCSubRegIterator
SI(I
, RegInfo
); SI
.isValid(); ++SI
)
477 SmallerAliasMap
[I
] |= SmallerAliasMap
[*SI
];
480 dbgs() << "Dumping reg alias table:\n";
481 for (MCPhysReg I
= 0, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
482 dbgs() << "Reg " << I
<< ": ";
483 const BitVector
&BV
= AliasMap
[I
];
484 int Idx
= BV
.find_first();
486 dbgs() << Idx
<< " ";
487 Idx
= BV
.find_next(Idx
);
494 void MCPlusBuilder::initSizeMap() {
495 SizeMap
.resize(RegInfo
->getNumRegs());
497 for (auto RC
: RegInfo
->regclasses())
498 for (MCPhysReg Reg
: RC
)
499 SizeMap
[Reg
] = RC
.getSizeInBits() / 8;
502 bool MCPlusBuilder::setOperandToSymbolRef(MCInst
&Inst
, int OpNum
,
503 const MCSymbol
*Symbol
,
504 int64_t Addend
, MCContext
*Ctx
,
505 uint64_t RelType
) const {
508 Operand
= MCOperand::createExpr(getTargetExprFor(
509 Inst
, MCSymbolRefExpr::create(Symbol
, *Ctx
), *Ctx
, RelType
));
511 Operand
= MCOperand::createExpr(getTargetExprFor(
513 MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol
, *Ctx
),
514 MCConstantExpr::create(Addend
, *Ctx
), *Ctx
),
517 Inst
.getOperand(OpNum
) = Operand
;