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
) const {
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
) const {
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
) const {
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
) const {
182 assert(GnuArgsSize
>= 0 && "cannot set GNU_args_size to negative value");
183 assert(getGnuArgsSize(Inst
) == -1LL && "GNU_args_size already set");
184 assert(isInvoke(Inst
) && "GNU_args_size can only be set for invoke");
186 setAnnotationOpValue(Inst
, MCAnnotation::kGnuArgsSize
, GnuArgsSize
);
189 uint64_t MCPlusBuilder::getJumpTable(const MCInst
&Inst
) const {
190 std::optional
<int64_t> Value
=
191 getAnnotationOpValue(Inst
, MCAnnotation::kJumpTable
);
197 uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst
&Inst
) const {
198 return getAnnotationAs
<uint16_t>(Inst
, "JTIndexReg");
201 bool MCPlusBuilder::setJumpTable(MCInst
&Inst
, uint64_t Value
,
202 uint16_t IndexReg
, AllocatorIdTy AllocId
) {
203 if (!isIndirectBranch(Inst
))
205 setAnnotationOpValue(Inst
, MCAnnotation::kJumpTable
, Value
);
206 getOrCreateAnnotationAs
<uint16_t>(Inst
, "JTIndexReg", AllocId
) = IndexReg
;
210 bool MCPlusBuilder::unsetJumpTable(MCInst
&Inst
) const {
211 if (!getJumpTable(Inst
))
213 removeAnnotation(Inst
, MCAnnotation::kJumpTable
);
214 removeAnnotation(Inst
, "JTIndexReg");
218 std::optional
<uint64_t>
219 MCPlusBuilder::getConditionalTailCall(const MCInst
&Inst
) const {
220 std::optional
<int64_t> Value
=
221 getAnnotationOpValue(Inst
, MCAnnotation::kConditionalTailCall
);
224 return static_cast<uint64_t>(*Value
);
227 bool MCPlusBuilder::setConditionalTailCall(MCInst
&Inst
, uint64_t Dest
) const {
228 if (!isConditionalBranch(Inst
))
231 setAnnotationOpValue(Inst
, MCAnnotation::kConditionalTailCall
, Dest
);
235 bool MCPlusBuilder::unsetConditionalTailCall(MCInst
&Inst
) const {
236 if (!getConditionalTailCall(Inst
))
238 removeAnnotation(Inst
, MCAnnotation::kConditionalTailCall
);
242 std::optional
<uint32_t> MCPlusBuilder::getOffset(const MCInst
&Inst
) const {
243 std::optional
<int64_t> Value
=
244 getAnnotationOpValue(Inst
, MCAnnotation::kOffset
);
247 return static_cast<uint32_t>(*Value
);
250 uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst
&Inst
,
251 uint32_t Default
) const {
252 if (std::optional
<uint32_t> Offset
= getOffset(Inst
))
257 bool MCPlusBuilder::setOffset(MCInst
&Inst
, uint32_t Offset
) const {
258 setAnnotationOpValue(Inst
, MCAnnotation::kOffset
, Offset
);
262 bool MCPlusBuilder::clearOffset(MCInst
&Inst
) const {
263 if (!hasAnnotation(Inst
, MCAnnotation::kOffset
))
265 removeAnnotation(Inst
, MCAnnotation::kOffset
);
269 MCSymbol
*MCPlusBuilder::getLabel(const MCInst
&Inst
) const {
270 if (std::optional
<int64_t> Label
=
271 getAnnotationOpValue(Inst
, MCAnnotation::kLabel
))
272 return reinterpret_cast<MCSymbol
*>(*Label
);
276 bool MCPlusBuilder::setLabel(MCInst
&Inst
, MCSymbol
*Label
) const {
277 setAnnotationOpValue(Inst
, MCAnnotation::kLabel
,
278 reinterpret_cast<int64_t>(Label
));
282 std::optional
<uint32_t> MCPlusBuilder::getSize(const MCInst
&Inst
) const {
283 if (std::optional
<int64_t> Value
=
284 getAnnotationOpValue(Inst
, MCAnnotation::kSize
))
285 return static_cast<uint32_t>(*Value
);
289 void MCPlusBuilder::setSize(MCInst
&Inst
, uint32_t Size
) const {
290 setAnnotationOpValue(Inst
, MCAnnotation::kSize
, Size
);
293 bool MCPlusBuilder::hasAnnotation(const MCInst
&Inst
, unsigned Index
) const {
294 return (bool)getAnnotationOpValue(Inst
, Index
);
297 bool MCPlusBuilder::removeAnnotation(MCInst
&Inst
, unsigned Index
) const {
298 std::optional
<unsigned> FirstAnnotationOp
= getFirstAnnotationOpIndex(Inst
);
299 if (!FirstAnnotationOp
)
302 for (unsigned I
= Inst
.getNumOperands() - 1; I
>= *FirstAnnotationOp
; --I
) {
303 const int64_t ImmValue
= Inst
.getOperand(I
).getImm();
304 if (extractAnnotationIndex(ImmValue
) == Index
) {
305 Inst
.erase(Inst
.begin() + I
);
312 void MCPlusBuilder::stripAnnotations(MCInst
&Inst
, bool KeepTC
) const {
313 KeepTC
&= hasAnnotation(Inst
, MCAnnotation::kTailCall
);
315 removeAnnotations(Inst
);
321 void MCPlusBuilder::printAnnotations(const MCInst
&Inst
,
322 raw_ostream
&OS
) const {
323 std::optional
<unsigned> FirstAnnotationOp
= getFirstAnnotationOpIndex(Inst
);
324 if (!FirstAnnotationOp
)
327 for (unsigned I
= *FirstAnnotationOp
; I
< Inst
.getNumOperands(); ++I
) {
328 const int64_t Imm
= Inst
.getOperand(I
).getImm();
329 const unsigned Index
= extractAnnotationIndex(Imm
);
330 const int64_t Value
= extractAnnotationValue(Imm
);
331 const auto *Annotation
= reinterpret_cast<const MCAnnotation
*>(Value
);
332 if (Index
>= MCAnnotation::kGeneric
) {
333 OS
<< " # " << AnnotationNames
[Index
- MCAnnotation::kGeneric
] << ": ";
334 Annotation
->print(OS
);
339 void MCPlusBuilder::getClobberedRegs(const MCInst
&Inst
,
340 BitVector
&Regs
) const {
341 if (isPrefix(Inst
) || isCFI(Inst
))
344 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
346 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
347 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/false);
349 for (const MCOperand
&Operand
: defOperands(Inst
)) {
350 assert(Operand
.isReg());
351 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/false);
355 void MCPlusBuilder::getTouchedRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
356 if (isPrefix(Inst
) || isCFI(Inst
))
359 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
361 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
362 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/false);
363 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
364 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/false);
366 for (unsigned I
= 0, E
= Inst
.getNumOperands(); I
!= E
; ++I
) {
367 if (!Inst
.getOperand(I
).isReg())
369 Regs
|= getAliases(Inst
.getOperand(I
).getReg(), /*OnlySmaller=*/false);
373 void MCPlusBuilder::getWrittenRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
374 if (isPrefix(Inst
) || isCFI(Inst
))
377 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
379 for (MCPhysReg ImplicitDef
: InstInfo
.implicit_defs())
380 Regs
|= getAliases(ImplicitDef
, /*OnlySmaller=*/true);
382 for (const MCOperand
&Operand
: defOperands(Inst
)) {
383 assert(Operand
.isReg());
384 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/true);
388 void MCPlusBuilder::getUsedRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
389 if (isPrefix(Inst
) || isCFI(Inst
))
392 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
394 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
395 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/true);
397 for (unsigned I
= 0, E
= Inst
.getNumOperands(); I
!= E
; ++I
) {
398 if (!Inst
.getOperand(I
).isReg())
400 Regs
|= getAliases(Inst
.getOperand(I
).getReg(), /*OnlySmaller=*/true);
404 void MCPlusBuilder::getSrcRegs(const MCInst
&Inst
, BitVector
&Regs
) const {
405 if (isPrefix(Inst
) || isCFI(Inst
))
409 BitVector CallRegs
= BitVector(Regs
.size(), false);
410 getCalleeSavedRegs(CallRegs
);
416 if (isReturn(Inst
)) {
417 getDefaultLiveOut(Regs
);
424 const MCInstrDesc
&InstInfo
= Info
->get(Inst
.getOpcode());
426 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses())
427 Regs
|= getAliases(ImplicitUse
, /*OnlySmaller=*/true);
429 for (const MCOperand
&Operand
: useOperands(Inst
))
431 Regs
|= getAliases(Operand
.getReg(), /*OnlySmaller=*/true);
434 bool MCPlusBuilder::hasDefOfPhysReg(const MCInst
&MI
, unsigned Reg
) const {
435 const MCInstrDesc
&InstInfo
= Info
->get(MI
.getOpcode());
436 return InstInfo
.hasDefOfPhysReg(MI
, Reg
, *RegInfo
);
439 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() && MI
.getOperand(I
).getReg() &&
443 RegInfo
->isSubRegisterEq(Reg
, MI
.getOperand(I
).getReg()))
445 for (MCPhysReg ImplicitUse
: InstInfo
.implicit_uses()) {
446 if (ImplicitUse
== Reg
|| RegInfo
->isSubRegister(Reg
, ImplicitUse
))
452 const BitVector
&MCPlusBuilder::getAliases(MCPhysReg Reg
,
453 bool OnlySmaller
) const {
455 return SmallerAliasMap
[Reg
];
456 return AliasMap
[Reg
];
459 void MCPlusBuilder::initAliases() {
460 assert(AliasMap
.size() == 0 && SmallerAliasMap
.size() == 0);
462 for (MCPhysReg I
= 0, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
463 BitVector
BV(RegInfo
->getNumRegs(), false);
465 AliasMap
.emplace_back(BV
);
466 SmallerAliasMap
.emplace_back(BV
);
469 // Cache all aliases for each register
470 for (MCPhysReg I
= 1, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
471 for (MCRegAliasIterator
AI(I
, RegInfo
, true); AI
.isValid(); ++AI
)
472 AliasMap
[I
].set(*AI
);
475 // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister)
476 for (MCPhysReg I
= 1, E
= RegInfo
->getNumRegs(); I
< E
; ++I
)
477 for (MCSubRegIterator
SI(I
, RegInfo
); SI
.isValid(); ++SI
)
478 SmallerAliasMap
[I
] |= SmallerAliasMap
[*SI
];
481 dbgs() << "Dumping reg alias table:\n";
482 for (MCPhysReg I
= 0, E
= RegInfo
->getNumRegs(); I
!= E
; ++I
) {
483 dbgs() << "Reg " << I
<< ": ";
484 const BitVector
&BV
= AliasMap
[I
];
485 int Idx
= BV
.find_first();
487 dbgs() << Idx
<< " ";
488 Idx
= BV
.find_next(Idx
);
495 void MCPlusBuilder::initSizeMap() {
496 SizeMap
.resize(RegInfo
->getNumRegs());
498 for (auto RC
: RegInfo
->regclasses())
499 for (MCPhysReg Reg
: RC
)
500 SizeMap
[Reg
] = RC
.getSizeInBits() / 8;
503 bool MCPlusBuilder::setOperandToSymbolRef(MCInst
&Inst
, int OpNum
,
504 const MCSymbol
*Symbol
,
505 int64_t Addend
, MCContext
*Ctx
,
506 uint64_t RelType
) const {
509 Operand
= MCOperand::createExpr(getTargetExprFor(
510 Inst
, MCSymbolRefExpr::create(Symbol
, *Ctx
), *Ctx
, RelType
));
512 Operand
= MCOperand::createExpr(getTargetExprFor(
514 MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol
, *Ctx
),
515 MCConstantExpr::create(Addend
, *Ctx
), *Ctx
),
518 Inst
.getOperand(OpNum
) = Operand
;