12f09f445SMaksim Panchenko //===- bolt/Core/MCPlusBuilder.cpp - Interface for MCPlus -----------------===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler //
92f09f445SMaksim Panchenko // This file implements the MCPlusBuilder class.
10a34c753fSRafael Auler //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
12a34c753fSRafael Auler
13a34c753fSRafael Auler #include "bolt/Core/MCPlusBuilder.h"
14a34c753fSRafael Auler #include "bolt/Core/MCPlus.h"
15*7de82ca3SMaksim Panchenko #include "bolt/Utils/CommandLineOpts.h"
167c206c78SMaksim Panchenko #include "llvm/MC/MCContext.h"
17a34c753fSRafael Auler #include "llvm/MC/MCInst.h"
18a34c753fSRafael Auler #include "llvm/MC/MCInstrAnalysis.h"
19a34c753fSRafael Auler #include "llvm/MC/MCInstrDesc.h"
20a34c753fSRafael Auler #include "llvm/MC/MCInstrInfo.h"
2157f7c7d9Sserge-sans-paille #include "llvm/MC/MCRegisterInfo.h"
22*7de82ca3SMaksim Panchenko #include "llvm/Support/CommandLine.h"
23a34c753fSRafael Auler #include "llvm/Support/Debug.h"
24a34c753fSRafael Auler #include <cstdint>
25a34c753fSRafael Auler
26a34c753fSRafael Auler #define DEBUG_TYPE "mcplus"
27a34c753fSRafael Auler
28a34c753fSRafael Auler using namespace llvm;
29a34c753fSRafael Auler using namespace bolt;
30a34c753fSRafael Auler using namespace MCPlus;
31a34c753fSRafael Auler
32*7de82ca3SMaksim Panchenko namespace opts {
33*7de82ca3SMaksim Panchenko cl::opt<bool>
34*7de82ca3SMaksim Panchenko TerminalTrap("terminal-trap",
35*7de82ca3SMaksim Panchenko cl::desc("Assume that execution stops at trap instruction"),
36*7de82ca3SMaksim Panchenko cl::init(true), cl::Hidden, cl::cat(BoltCategory));
37*7de82ca3SMaksim Panchenko }
38*7de82ca3SMaksim Panchenko
equals(const MCInst & A,const MCInst & B,CompFuncTy Comp) const39a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B,
40a34c753fSRafael Auler CompFuncTy Comp) const {
41a34c753fSRafael Auler if (A.getOpcode() != B.getOpcode())
42a34c753fSRafael Auler return false;
43a34c753fSRafael Auler
44a34c753fSRafael Auler unsigned NumOperands = MCPlus::getNumPrimeOperands(A);
45a34c753fSRafael Auler if (NumOperands != MCPlus::getNumPrimeOperands(B))
46a34c753fSRafael Auler return false;
47a34c753fSRafael Auler
483652483cSRafael Auler for (unsigned Index = 0; Index < NumOperands; ++Index)
49a34c753fSRafael Auler if (!equals(A.getOperand(Index), B.getOperand(Index), Comp))
50a34c753fSRafael Auler return false;
51a34c753fSRafael Auler
52a34c753fSRafael Auler return true;
53a34c753fSRafael Auler }
54a34c753fSRafael Auler
equals(const MCOperand & A,const MCOperand & B,CompFuncTy Comp) const55a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCOperand &A, const MCOperand &B,
56a34c753fSRafael Auler CompFuncTy Comp) const {
57a34c753fSRafael Auler if (A.isReg()) {
58a34c753fSRafael Auler if (!B.isReg())
59a34c753fSRafael Auler return false;
60a34c753fSRafael Auler return A.getReg() == B.getReg();
61a34c753fSRafael Auler } else if (A.isImm()) {
62a34c753fSRafael Auler if (!B.isImm())
63a34c753fSRafael Auler return false;
64a34c753fSRafael Auler return A.getImm() == B.getImm();
65a34c753fSRafael Auler } else if (A.isSFPImm()) {
66a34c753fSRafael Auler if (!B.isSFPImm())
67a34c753fSRafael Auler return false;
68a34c753fSRafael Auler return A.getSFPImm() == B.getSFPImm();
69a34c753fSRafael Auler } else if (A.isDFPImm()) {
70a34c753fSRafael Auler if (!B.isDFPImm())
71a34c753fSRafael Auler return false;
72a34c753fSRafael Auler return A.getDFPImm() == B.getDFPImm();
73a34c753fSRafael Auler } else if (A.isExpr()) {
74a34c753fSRafael Auler if (!B.isExpr())
75a34c753fSRafael Auler return false;
76a34c753fSRafael Auler return equals(*A.getExpr(), *B.getExpr(), Comp);
77a34c753fSRafael Auler } else {
78a34c753fSRafael Auler llvm_unreachable("unexpected operand kind");
79a34c753fSRafael Auler return false;
80a34c753fSRafael Auler }
81a34c753fSRafael Auler }
82a34c753fSRafael Auler
equals(const MCExpr & A,const MCExpr & B,CompFuncTy Comp) const83a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCExpr &A, const MCExpr &B,
84a34c753fSRafael Auler CompFuncTy Comp) const {
85a34c753fSRafael Auler if (A.getKind() != B.getKind())
86a34c753fSRafael Auler return false;
87a34c753fSRafael Auler
88a34c753fSRafael Auler switch (A.getKind()) {
89a34c753fSRafael Auler case MCExpr::Constant: {
90a34c753fSRafael Auler const auto &ConstA = cast<MCConstantExpr>(A);
91a34c753fSRafael Auler const auto &ConstB = cast<MCConstantExpr>(B);
92a34c753fSRafael Auler return ConstA.getValue() == ConstB.getValue();
93a34c753fSRafael Auler }
94a34c753fSRafael Auler
95a34c753fSRafael Auler case MCExpr::SymbolRef: {
96a34c753fSRafael Auler const MCSymbolRefExpr &SymbolA = cast<MCSymbolRefExpr>(A);
97a34c753fSRafael Auler const MCSymbolRefExpr &SymbolB = cast<MCSymbolRefExpr>(B);
98a34c753fSRafael Auler return SymbolA.getKind() == SymbolB.getKind() &&
99a34c753fSRafael Auler Comp(&SymbolA.getSymbol(), &SymbolB.getSymbol());
100a34c753fSRafael Auler }
101a34c753fSRafael Auler
102a34c753fSRafael Auler case MCExpr::Unary: {
103a34c753fSRafael Auler const auto &UnaryA = cast<MCUnaryExpr>(A);
104a34c753fSRafael Auler const auto &UnaryB = cast<MCUnaryExpr>(B);
105a34c753fSRafael Auler return UnaryA.getOpcode() == UnaryB.getOpcode() &&
106a34c753fSRafael Auler equals(*UnaryA.getSubExpr(), *UnaryB.getSubExpr(), Comp);
107a34c753fSRafael Auler }
108a34c753fSRafael Auler
109a34c753fSRafael Auler case MCExpr::Binary: {
110a34c753fSRafael Auler const auto &BinaryA = cast<MCBinaryExpr>(A);
111a34c753fSRafael Auler const auto &BinaryB = cast<MCBinaryExpr>(B);
112a34c753fSRafael Auler return BinaryA.getOpcode() == BinaryB.getOpcode() &&
113a34c753fSRafael Auler equals(*BinaryA.getLHS(), *BinaryB.getLHS(), Comp) &&
114a34c753fSRafael Auler equals(*BinaryA.getRHS(), *BinaryB.getRHS(), Comp);
115a34c753fSRafael Auler }
116a34c753fSRafael Auler
117a34c753fSRafael Auler case MCExpr::Target: {
118a34c753fSRafael Auler const auto &TargetExprA = cast<MCTargetExpr>(A);
119a34c753fSRafael Auler const auto &TargetExprB = cast<MCTargetExpr>(B);
120a34c753fSRafael Auler return equals(TargetExprA, TargetExprB, Comp);
121a34c753fSRafael Auler }
122a34c753fSRafael Auler }
123a34c753fSRafael Auler
124a34c753fSRafael Auler llvm_unreachable("Invalid expression kind!");
125a34c753fSRafael Auler }
126a34c753fSRafael Auler
equals(const MCTargetExpr & A,const MCTargetExpr & B,CompFuncTy Comp) const127a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B,
128a34c753fSRafael Auler CompFuncTy Comp) const {
129a34c753fSRafael Auler llvm_unreachable("target-specific expressions are unsupported");
130a34c753fSRafael Auler }
131a34c753fSRafael Auler
isTerminator(const MCInst & Inst) const132*7de82ca3SMaksim Panchenko bool MCPlusBuilder::isTerminator(const MCInst &Inst) const {
133*7de82ca3SMaksim Panchenko return Analysis->isTerminator(Inst) ||
134*7de82ca3SMaksim Panchenko (opts::TerminalTrap && Info->get(Inst.getOpcode()).isTrap());
135*7de82ca3SMaksim Panchenko }
136*7de82ca3SMaksim Panchenko
setTailCall(MCInst & Inst) const13774e0a26fSmaksfb void MCPlusBuilder::setTailCall(MCInst &Inst) const {
138a34c753fSRafael Auler assert(!hasAnnotation(Inst, MCAnnotation::kTailCall));
139a34c753fSRafael Auler setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true);
140a34c753fSRafael Auler }
141a34c753fSRafael Auler
isTailCall(const MCInst & Inst) const142a34c753fSRafael Auler bool MCPlusBuilder::isTailCall(const MCInst &Inst) const {
143a34c753fSRafael Auler if (hasAnnotation(Inst, MCAnnotation::kTailCall))
144a34c753fSRafael Auler return true;
145a34c753fSRafael Auler if (getConditionalTailCall(Inst))
146a34c753fSRafael Auler return true;
147a34c753fSRafael Auler return false;
148a34c753fSRafael Auler }
149a34c753fSRafael Auler
getEHInfo(const MCInst & Inst) const1502563fd63SAmir Ayupov std::optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const {
151a34c753fSRafael Auler if (!isCall(Inst))
152e324a80fSKazu Hirata return std::nullopt;
1532563fd63SAmir Ayupov std::optional<int64_t> LPSym =
154a34c753fSRafael Auler getAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad);
155a34c753fSRafael Auler if (!LPSym)
156e324a80fSKazu Hirata return std::nullopt;
1572563fd63SAmir Ayupov std::optional<int64_t> Action =
158a34c753fSRafael Auler getAnnotationOpValue(Inst, MCAnnotation::kEHAction);
159a34c753fSRafael Auler if (!Action)
160e324a80fSKazu Hirata return std::nullopt;
161a34c753fSRafael Auler
162a34c753fSRafael Auler return std::make_pair(reinterpret_cast<const MCSymbol *>(*LPSym),
163a34c753fSRafael Auler static_cast<uint64_t>(*Action));
164a34c753fSRafael Auler }
165a34c753fSRafael Auler
addEHInfo(MCInst & Inst,const MCLandingPad & LP) const16674e0a26fSmaksfb void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) const {
167a34c753fSRafael Auler if (isCall(Inst)) {
168a34c753fSRafael Auler assert(!getEHInfo(Inst));
169a34c753fSRafael Auler setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,
170a34c753fSRafael Auler reinterpret_cast<int64_t>(LP.first));
171a34c753fSRafael Auler setAnnotationOpValue(Inst, MCAnnotation::kEHAction,
172a34c753fSRafael Auler static_cast<int64_t>(LP.second));
173a34c753fSRafael Auler }
174a34c753fSRafael Auler }
175a34c753fSRafael Auler
updateEHInfo(MCInst & Inst,const MCLandingPad & LP) const17674e0a26fSmaksfb bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) const {
177f263a66bSMaksim Panchenko if (!isInvoke(Inst))
178f263a66bSMaksim Panchenko return false;
179f263a66bSMaksim Panchenko
180f263a66bSMaksim Panchenko setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,
181f263a66bSMaksim Panchenko reinterpret_cast<int64_t>(LP.first));
182f263a66bSMaksim Panchenko setAnnotationOpValue(Inst, MCAnnotation::kEHAction,
183f263a66bSMaksim Panchenko static_cast<int64_t>(LP.second));
184f263a66bSMaksim Panchenko return true;
185f263a66bSMaksim Panchenko }
186f263a66bSMaksim Panchenko
getGnuArgsSize(const MCInst & Inst) const187a34c753fSRafael Auler int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const {
1882563fd63SAmir Ayupov std::optional<int64_t> Value =
189a34c753fSRafael Auler getAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize);
190a34c753fSRafael Auler if (!Value)
191a34c753fSRafael Auler return -1LL;
192a34c753fSRafael Auler return *Value;
193a34c753fSRafael Auler }
194a34c753fSRafael Auler
addGnuArgsSize(MCInst & Inst,int64_t GnuArgsSize) const19574e0a26fSmaksfb void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize) const {
196a34c753fSRafael Auler assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value");
197a34c753fSRafael Auler assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set");
198a34c753fSRafael Auler assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke");
199a34c753fSRafael Auler
20074e0a26fSmaksfb setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize);
201a34c753fSRafael Auler }
202a34c753fSRafael Auler
getJumpTable(const MCInst & Inst) const203a34c753fSRafael Auler uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const {
2042563fd63SAmir Ayupov std::optional<int64_t> Value =
205a34c753fSRafael Auler getAnnotationOpValue(Inst, MCAnnotation::kJumpTable);
206a34c753fSRafael Auler if (!Value)
207a34c753fSRafael Auler return 0;
208a34c753fSRafael Auler return *Value;
209a34c753fSRafael Auler }
210a34c753fSRafael Auler
getJumpTableIndexReg(const MCInst & Inst) const211a34c753fSRafael Auler uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const {
212a34c753fSRafael Auler return getAnnotationAs<uint16_t>(Inst, "JTIndexReg");
213a34c753fSRafael Auler }
214a34c753fSRafael Auler
setJumpTable(MCInst & Inst,uint64_t Value,uint16_t IndexReg,AllocatorIdTy AllocId)215a34c753fSRafael Auler bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value,
216a34c753fSRafael Auler uint16_t IndexReg, AllocatorIdTy AllocId) {
217a34c753fSRafael Auler if (!isIndirectBranch(Inst))
218a34c753fSRafael Auler return false;
21974e0a26fSmaksfb setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value);
220a34c753fSRafael Auler getOrCreateAnnotationAs<uint16_t>(Inst, "JTIndexReg", AllocId) = IndexReg;
221a34c753fSRafael Auler return true;
222a34c753fSRafael Auler }
223a34c753fSRafael Auler
unsetJumpTable(MCInst & Inst) const22474e0a26fSmaksfb bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) const {
225a34c753fSRafael Auler if (!getJumpTable(Inst))
226a34c753fSRafael Auler return false;
227a34c753fSRafael Auler removeAnnotation(Inst, MCAnnotation::kJumpTable);
228a34c753fSRafael Auler removeAnnotation(Inst, "JTIndexReg");
229a34c753fSRafael Auler return true;
230a34c753fSRafael Auler }
231a34c753fSRafael Auler
2322563fd63SAmir Ayupov std::optional<uint64_t>
getConditionalTailCall(const MCInst & Inst) const233a34c753fSRafael Auler MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const {
2342563fd63SAmir Ayupov std::optional<int64_t> Value =
235a34c753fSRafael Auler getAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall);
236a34c753fSRafael Auler if (!Value)
237e324a80fSKazu Hirata return std::nullopt;
238a34c753fSRafael Auler return static_cast<uint64_t>(*Value);
239a34c753fSRafael Auler }
240a34c753fSRafael Auler
setConditionalTailCall(MCInst & Inst,uint64_t Dest) const24174e0a26fSmaksfb bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) const {
242a34c753fSRafael Auler if (!isConditionalBranch(Inst))
243a34c753fSRafael Auler return false;
244a34c753fSRafael Auler
245a34c753fSRafael Auler setAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall, Dest);
246a34c753fSRafael Auler return true;
247a34c753fSRafael Auler }
248a34c753fSRafael Auler
unsetConditionalTailCall(MCInst & Inst) const24974e0a26fSmaksfb bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) const {
250a34c753fSRafael Auler if (!getConditionalTailCall(Inst))
251a34c753fSRafael Auler return false;
252a34c753fSRafael Auler removeAnnotation(Inst, MCAnnotation::kConditionalTailCall);
253a34c753fSRafael Auler return true;
254a34c753fSRafael Auler }
255a34c753fSRafael Auler
getOffset(const MCInst & Inst) const2562563fd63SAmir Ayupov std::optional<uint32_t> MCPlusBuilder::getOffset(const MCInst &Inst) const {
2572563fd63SAmir Ayupov std::optional<int64_t> Value =
2582563fd63SAmir Ayupov getAnnotationOpValue(Inst, MCAnnotation::kOffset);
259a9cd49d5SAmir Ayupov if (!Value)
260e324a80fSKazu Hirata return std::nullopt;
261a9cd49d5SAmir Ayupov return static_cast<uint32_t>(*Value);
262a9cd49d5SAmir Ayupov }
263a9cd49d5SAmir Ayupov
getOffsetWithDefault(const MCInst & Inst,uint32_t Default) const264a9cd49d5SAmir Ayupov uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst,
265a9cd49d5SAmir Ayupov uint32_t Default) const {
2662563fd63SAmir Ayupov if (std::optional<uint32_t> Offset = getOffset(Inst))
267a9cd49d5SAmir Ayupov return *Offset;
268a9cd49d5SAmir Ayupov return Default;
269a9cd49d5SAmir Ayupov }
270a9cd49d5SAmir Ayupov
setOffset(MCInst & Inst,uint32_t Offset) const27174e0a26fSmaksfb bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset) const {
27274e0a26fSmaksfb setAnnotationOpValue(Inst, MCAnnotation::kOffset, Offset);
273a9cd49d5SAmir Ayupov return true;
274a9cd49d5SAmir Ayupov }
275a9cd49d5SAmir Ayupov
clearOffset(MCInst & Inst) const27674e0a26fSmaksfb bool MCPlusBuilder::clearOffset(MCInst &Inst) const {
277a9cd49d5SAmir Ayupov if (!hasAnnotation(Inst, MCAnnotation::kOffset))
278a9cd49d5SAmir Ayupov return false;
279a9cd49d5SAmir Ayupov removeAnnotation(Inst, MCAnnotation::kOffset);
280a9cd49d5SAmir Ayupov return true;
281a9cd49d5SAmir Ayupov }
282a9cd49d5SAmir Ayupov
getInstLabel(const MCInst & Inst) const2837c206c78SMaksim Panchenko MCSymbol *MCPlusBuilder::getInstLabel(const MCInst &Inst) const {
284b336d741SMaksim Panchenko if (std::optional<int64_t> Label =
285b336d741SMaksim Panchenko getAnnotationOpValue(Inst, MCAnnotation::kLabel))
286b336d741SMaksim Panchenko return reinterpret_cast<MCSymbol *>(*Label);
287e28c393bSmaksfb return nullptr;
288ff5e2babSJob Noorman }
289ff5e2babSJob Noorman
getOrCreateInstLabel(MCInst & Inst,const Twine & Name,MCContext * Ctx) const2907c206c78SMaksim Panchenko MCSymbol *MCPlusBuilder::getOrCreateInstLabel(MCInst &Inst, const Twine &Name,
2917c206c78SMaksim Panchenko MCContext *Ctx) const {
2927c206c78SMaksim Panchenko MCSymbol *Label = getInstLabel(Inst);
2937c206c78SMaksim Panchenko if (Label)
2947c206c78SMaksim Panchenko return Label;
2957c206c78SMaksim Panchenko
2967c206c78SMaksim Panchenko Label = Ctx->createNamedTempSymbol(Name);
297b336d741SMaksim Panchenko setAnnotationOpValue(Inst, MCAnnotation::kLabel,
298b336d741SMaksim Panchenko reinterpret_cast<int64_t>(Label));
2997c206c78SMaksim Panchenko return Label;
3007c206c78SMaksim Panchenko }
3017c206c78SMaksim Panchenko
setInstLabel(MCInst & Inst,MCSymbol * Label) const3027c206c78SMaksim Panchenko void MCPlusBuilder::setInstLabel(MCInst &Inst, MCSymbol *Label) const {
3037c206c78SMaksim Panchenko assert(!getInstLabel(Inst) && "Instruction already has assigned label.");
3047c206c78SMaksim Panchenko setAnnotationOpValue(Inst, MCAnnotation::kLabel,
3057c206c78SMaksim Panchenko reinterpret_cast<int64_t>(Label));
306ff5e2babSJob Noorman }
307ff5e2babSJob Noorman
getSize(const MCInst & Inst) const3082db9b6a9SMaksim Panchenko std::optional<uint32_t> MCPlusBuilder::getSize(const MCInst &Inst) const {
3092db9b6a9SMaksim Panchenko if (std::optional<int64_t> Value =
3102db9b6a9SMaksim Panchenko getAnnotationOpValue(Inst, MCAnnotation::kSize))
3112db9b6a9SMaksim Panchenko return static_cast<uint32_t>(*Value);
3122db9b6a9SMaksim Panchenko return std::nullopt;
3132db9b6a9SMaksim Panchenko }
3142db9b6a9SMaksim Panchenko
setSize(MCInst & Inst,uint32_t Size) const3152db9b6a9SMaksim Panchenko void MCPlusBuilder::setSize(MCInst &Inst, uint32_t Size) const {
3162db9b6a9SMaksim Panchenko setAnnotationOpValue(Inst, MCAnnotation::kSize, Size);
3172db9b6a9SMaksim Panchenko }
3182db9b6a9SMaksim Panchenko
isDynamicBranch(const MCInst & Inst) const3196b1cf004SMaksim Panchenko bool MCPlusBuilder::isDynamicBranch(const MCInst &Inst) const {
3206b1cf004SMaksim Panchenko if (!hasAnnotation(Inst, MCAnnotation::kDynamicBranch))
3216b1cf004SMaksim Panchenko return false;
3226b1cf004SMaksim Panchenko assert(isBranch(Inst) && "Branch expected.");
3236b1cf004SMaksim Panchenko return true;
3246b1cf004SMaksim Panchenko }
3256b1cf004SMaksim Panchenko
3266b1cf004SMaksim Panchenko std::optional<uint32_t>
getDynamicBranchID(const MCInst & Inst) const3276b1cf004SMaksim Panchenko MCPlusBuilder::getDynamicBranchID(const MCInst &Inst) const {
3286b1cf004SMaksim Panchenko if (std::optional<int64_t> Value =
3296b1cf004SMaksim Panchenko getAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch)) {
3306b1cf004SMaksim Panchenko assert(isBranch(Inst) && "Branch expected.");
3316b1cf004SMaksim Panchenko return static_cast<uint32_t>(*Value);
3326b1cf004SMaksim Panchenko }
3336b1cf004SMaksim Panchenko return std::nullopt;
3346b1cf004SMaksim Panchenko }
3356b1cf004SMaksim Panchenko
setDynamicBranch(MCInst & Inst,uint32_t ID) const3366b1cf004SMaksim Panchenko void MCPlusBuilder::setDynamicBranch(MCInst &Inst, uint32_t ID) const {
3376b1cf004SMaksim Panchenko assert(isBranch(Inst) && "Branch expected.");
3386b1cf004SMaksim Panchenko setAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch, ID);
3396b1cf004SMaksim Panchenko }
3406b1cf004SMaksim Panchenko
hasAnnotation(const MCInst & Inst,unsigned Index) const341a34c753fSRafael Auler bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const {
342a34c753fSRafael Auler return (bool)getAnnotationOpValue(Inst, Index);
343a34c753fSRafael Auler }
344a34c753fSRafael Auler
removeAnnotation(MCInst & Inst,unsigned Index) const34574e0a26fSmaksfb bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) const {
34674e0a26fSmaksfb std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst);
34774e0a26fSmaksfb if (!FirstAnnotationOp)
348a34c753fSRafael Auler return false;
349a34c753fSRafael Auler
35074e0a26fSmaksfb for (unsigned I = Inst.getNumOperands() - 1; I >= *FirstAnnotationOp; --I) {
35174e0a26fSmaksfb const int64_t ImmValue = Inst.getOperand(I).getImm();
352a34c753fSRafael Auler if (extractAnnotationIndex(ImmValue) == Index) {
35374e0a26fSmaksfb Inst.erase(Inst.begin() + I);
354a34c753fSRafael Auler return true;
355a34c753fSRafael Auler }
356a34c753fSRafael Auler }
357a34c753fSRafael Auler return false;
358a34c753fSRafael Auler }
359a34c753fSRafael Auler
stripAnnotations(MCInst & Inst,bool KeepTC) const36074e0a26fSmaksfb void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) const {
36174e0a26fSmaksfb KeepTC &= hasAnnotation(Inst, MCAnnotation::kTailCall);
362a34c753fSRafael Auler
36374e0a26fSmaksfb removeAnnotations(Inst);
364fb28196aSMaksim Panchenko
36574e0a26fSmaksfb if (KeepTC)
366a34c753fSRafael Auler setTailCall(Inst);
367a34c753fSRafael Auler }
368a34c753fSRafael Auler
printAnnotations(const MCInst & Inst,raw_ostream & OS) const36940c2e0faSMaksim Panchenko void MCPlusBuilder::printAnnotations(const MCInst &Inst,
37040c2e0faSMaksim Panchenko raw_ostream &OS) const {
37174e0a26fSmaksfb std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst);
37274e0a26fSmaksfb if (!FirstAnnotationOp)
373a34c753fSRafael Auler return;
374a34c753fSRafael Auler
37574e0a26fSmaksfb for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) {
37674e0a26fSmaksfb const int64_t Imm = Inst.getOperand(I).getImm();
377a34c753fSRafael Auler const unsigned Index = extractAnnotationIndex(Imm);
378a34c753fSRafael Auler const int64_t Value = extractAnnotationValue(Imm);
37940c2e0faSMaksim Panchenko const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value);
380a34c753fSRafael Auler if (Index >= MCAnnotation::kGeneric) {
38140c2e0faSMaksim Panchenko OS << " # " << AnnotationNames[Index - MCAnnotation::kGeneric] << ": ";
382a34c753fSRafael Auler Annotation->print(OS);
383a34c753fSRafael Auler }
384a34c753fSRafael Auler }
385a34c753fSRafael Auler }
386a34c753fSRafael Auler
getClobberedRegs(const MCInst & Inst,BitVector & Regs) const387a34c753fSRafael Auler void MCPlusBuilder::getClobberedRegs(const MCInst &Inst,
388a34c753fSRafael Auler BitVector &Regs) const {
389a34c753fSRafael Auler if (isPrefix(Inst) || isCFI(Inst))
390a34c753fSRafael Auler return;
391a34c753fSRafael Auler
392a34c753fSRafael Auler const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
393a34c753fSRafael Auler
3947557b83aSBenjamin Kramer for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())
3957557b83aSBenjamin Kramer Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false);
396a34c753fSRafael Auler
397b6f07d3aSAmir Ayupov for (const MCOperand &Operand : defOperands(Inst)) {
398a34c753fSRafael Auler assert(Operand.isReg());
399a34c753fSRafael Auler Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/false);
400a34c753fSRafael Auler }
401a34c753fSRafael Auler }
402a34c753fSRafael Auler
getTouchedRegs(const MCInst & Inst,BitVector & Regs) const40340c2e0faSMaksim Panchenko void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const {
404a34c753fSRafael Auler if (isPrefix(Inst) || isCFI(Inst))
405a34c753fSRafael Auler return;
406a34c753fSRafael Auler
407a34c753fSRafael Auler const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
408a34c753fSRafael Auler
4097557b83aSBenjamin Kramer for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())
4107557b83aSBenjamin Kramer Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false);
4117557b83aSBenjamin Kramer for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())
4127557b83aSBenjamin Kramer Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/false);
413a34c753fSRafael Auler
414a34c753fSRafael Auler for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
415a34c753fSRafael Auler if (!Inst.getOperand(I).isReg())
416a34c753fSRafael Auler continue;
417a34c753fSRafael Auler Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/false);
418a34c753fSRafael Auler }
419a34c753fSRafael Auler }
420a34c753fSRafael Auler
getWrittenRegs(const MCInst & Inst,BitVector & Regs) const42140c2e0faSMaksim Panchenko void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const {
422a34c753fSRafael Auler if (isPrefix(Inst) || isCFI(Inst))
423a34c753fSRafael Auler return;
424a34c753fSRafael Auler
425a34c753fSRafael Auler const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
426a34c753fSRafael Auler
4277557b83aSBenjamin Kramer for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())
4287557b83aSBenjamin Kramer Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/true);
429a34c753fSRafael Auler
430b6f07d3aSAmir Ayupov for (const MCOperand &Operand : defOperands(Inst)) {
431a34c753fSRafael Auler assert(Operand.isReg());
432a34c753fSRafael Auler Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);
433a34c753fSRafael Auler }
434a34c753fSRafael Auler }
435a34c753fSRafael Auler
getUsedRegs(const MCInst & Inst,BitVector & Regs) const436a34c753fSRafael Auler void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const {
437a34c753fSRafael Auler if (isPrefix(Inst) || isCFI(Inst))
438a34c753fSRafael Auler return;
439a34c753fSRafael Auler
440a34c753fSRafael Auler const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
441a34c753fSRafael Auler
4427557b83aSBenjamin Kramer for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())
4437557b83aSBenjamin Kramer Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true);
444a34c753fSRafael Auler
445a34c753fSRafael Auler for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
446a34c753fSRafael Auler if (!Inst.getOperand(I).isReg())
447a34c753fSRafael Auler continue;
448a34c753fSRafael Auler Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/true);
449a34c753fSRafael Auler }
450a34c753fSRafael Auler }
451a34c753fSRafael Auler
getSrcRegs(const MCInst & Inst,BitVector & Regs) const452a34c753fSRafael Auler void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const {
453a34c753fSRafael Auler if (isPrefix(Inst) || isCFI(Inst))
454a34c753fSRafael Auler return;
455a34c753fSRafael Auler
456a34c753fSRafael Auler if (isCall(Inst)) {
457a34c753fSRafael Auler BitVector CallRegs = BitVector(Regs.size(), false);
458a34c753fSRafael Auler getCalleeSavedRegs(CallRegs);
459a34c753fSRafael Auler CallRegs.flip();
460a34c753fSRafael Auler Regs |= CallRegs;
461a34c753fSRafael Auler return;
462a34c753fSRafael Auler }
463a34c753fSRafael Auler
464a34c753fSRafael Auler if (isReturn(Inst)) {
465a34c753fSRafael Auler getDefaultLiveOut(Regs);
466a34c753fSRafael Auler return;
467a34c753fSRafael Auler }
468a34c753fSRafael Auler
4693652483cSRafael Auler if (isRep(Inst))
470a34c753fSRafael Auler getRepRegs(Regs);
471a34c753fSRafael Auler
472a34c753fSRafael Auler const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
473a34c753fSRafael Auler
4747557b83aSBenjamin Kramer for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())
4757557b83aSBenjamin Kramer Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true);
476a34c753fSRafael Auler
477b6f07d3aSAmir Ayupov for (const MCOperand &Operand : useOperands(Inst))
478b6f07d3aSAmir Ayupov if (Operand.isReg())
479b6f07d3aSAmir Ayupov Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);
480a34c753fSRafael Auler }
481a34c753fSRafael Auler
hasDefOfPhysReg(const MCInst & MI,unsigned Reg) const482a34c753fSRafael Auler bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const {
483a34c753fSRafael Auler const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());
484a34c753fSRafael Auler return InstInfo.hasDefOfPhysReg(MI, Reg, *RegInfo);
485a34c753fSRafael Auler }
486a34c753fSRafael Auler
hasUseOfPhysReg(const MCInst & MI,unsigned Reg) const487a34c753fSRafael Auler bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const {
488a34c753fSRafael Auler const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());
489a34c753fSRafael Auler for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I)
490ee1d5f63SSergei Barannikov if (MI.getOperand(I).isReg() && MI.getOperand(I).getReg() &&
491a34c753fSRafael Auler RegInfo->isSubRegisterEq(Reg, MI.getOperand(I).getReg()))
492a34c753fSRafael Auler return true;
4937557b83aSBenjamin Kramer for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) {
4947557b83aSBenjamin Kramer if (ImplicitUse == Reg || RegInfo->isSubRegister(Reg, ImplicitUse))
495a34c753fSRafael Auler return true;
4963652483cSRafael Auler }
497a34c753fSRafael Auler return false;
498a34c753fSRafael Auler }
499a34c753fSRafael Auler
getAliases(MCPhysReg Reg,bool OnlySmaller) const50040c2e0faSMaksim Panchenko const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg,
501a34c753fSRafael Auler bool OnlySmaller) const {
502a34c753fSRafael Auler if (OnlySmaller)
503e900f058SVladislav Khmelevsky return SmallerAliasMap[Reg];
504a34c753fSRafael Auler return AliasMap[Reg];
505a34c753fSRafael Auler }
506e900f058SVladislav Khmelevsky
initAliases()50768c7299fSAmir Ayupov void MCPlusBuilder::initAliases() {
50868c7299fSAmir Ayupov assert(AliasMap.size() == 0 && SmallerAliasMap.size() == 0);
509a34c753fSRafael Auler // Build alias map
510a34c753fSRafael Auler for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {
511a34c753fSRafael Auler BitVector BV(RegInfo->getNumRegs(), false);
512a34c753fSRafael Auler BV.set(I);
513e900f058SVladislav Khmelevsky AliasMap.emplace_back(BV);
514e900f058SVladislav Khmelevsky SmallerAliasMap.emplace_back(BV);
515a34c753fSRafael Auler }
516e900f058SVladislav Khmelevsky
517e900f058SVladislav Khmelevsky // Cache all aliases for each register
518e900f058SVladislav Khmelevsky for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I != E; ++I) {
519e900f058SVladislav Khmelevsky for (MCRegAliasIterator AI(I, RegInfo, true); AI.isValid(); ++AI)
520e900f058SVladislav Khmelevsky AliasMap[I].set(*AI);
521e900f058SVladislav Khmelevsky }
522e900f058SVladislav Khmelevsky
523e900f058SVladislav Khmelevsky // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister)
5243652483cSRafael Auler for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I)
5253652483cSRafael Auler for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI)
526e900f058SVladislav Khmelevsky SmallerAliasMap[I] |= SmallerAliasMap[*SI];
527a34c753fSRafael Auler
528a34c753fSRafael Auler LLVM_DEBUG({
529a34c753fSRafael Auler dbgs() << "Dumping reg alias table:\n";
530a34c753fSRafael Auler for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {
531a34c753fSRafael Auler dbgs() << "Reg " << I << ": ";
532e900f058SVladislav Khmelevsky const BitVector &BV = AliasMap[I];
533a34c753fSRafael Auler int Idx = BV.find_first();
534a34c753fSRafael Auler while (Idx != -1) {
535a34c753fSRafael Auler dbgs() << Idx << " ";
536a34c753fSRafael Auler Idx = BV.find_next(Idx);
537a34c753fSRafael Auler }
538a34c753fSRafael Auler dbgs() << "\n";
539a34c753fSRafael Auler }
540a34c753fSRafael Auler });
541a34c753fSRafael Auler }
542a34c753fSRafael Auler
initSizeMap()543ce106107SAmir Ayupov void MCPlusBuilder::initSizeMap() {
544ce106107SAmir Ayupov SizeMap.resize(RegInfo->getNumRegs());
545a34c753fSRafael Auler // Build size map
546ce106107SAmir Ayupov for (auto RC : RegInfo->regclasses())
547ce106107SAmir Ayupov for (MCPhysReg Reg : RC)
548ce106107SAmir Ayupov SizeMap[Reg] = RC.getSizeInBits() / 8;
549a34c753fSRafael Auler }
550a34c753fSRafael Auler
setOperandToSymbolRef(MCInst & Inst,int OpNum,const MCSymbol * Symbol,int64_t Addend,MCContext * Ctx,uint64_t RelType) const551a34c753fSRafael Auler bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum,
552a34c753fSRafael Auler const MCSymbol *Symbol,
553a34c753fSRafael Auler int64_t Addend, MCContext *Ctx,
554a34c753fSRafael Auler uint64_t RelType) const {
555a34c753fSRafael Auler MCOperand Operand;
556a34c753fSRafael Auler if (!Addend) {
557a34c753fSRafael Auler Operand = MCOperand::createExpr(getTargetExprFor(
558a34c753fSRafael Auler Inst, MCSymbolRefExpr::create(Symbol, *Ctx), *Ctx, RelType));
559a34c753fSRafael Auler } else {
560a34c753fSRafael Auler Operand = MCOperand::createExpr(getTargetExprFor(
561a34c753fSRafael Auler Inst,
562a34c753fSRafael Auler MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, *Ctx),
563a34c753fSRafael Auler MCConstantExpr::create(Addend, *Ctx), *Ctx),
564a34c753fSRafael Auler *Ctx, RelType));
565a34c753fSRafael Auler }
566a34c753fSRafael Auler Inst.getOperand(OpNum) = Operand;
567a34c753fSRafael Auler return true;
568a34c753fSRafael Auler }
569