xref: /llvm-project/bolt/lib/Core/MCPlusBuilder.cpp (revision b6f07d3ae8ddd749b33591f34b9519ed7b021970)
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"
15a34c753fSRafael Auler #include "llvm/MC/MCInst.h"
16a34c753fSRafael Auler #include "llvm/MC/MCInstrAnalysis.h"
17a34c753fSRafael Auler #include "llvm/MC/MCInstrDesc.h"
18a34c753fSRafael Auler #include "llvm/MC/MCInstrInfo.h"
1957f7c7d9Sserge-sans-paille #include "llvm/MC/MCRegisterInfo.h"
20a34c753fSRafael Auler #include "llvm/Support/Debug.h"
21a34c753fSRafael Auler #include <cstdint>
22a34c753fSRafael Auler #include <queue>
23a34c753fSRafael Auler 
24a34c753fSRafael Auler #define DEBUG_TYPE "mcplus"
25a34c753fSRafael Auler 
26a34c753fSRafael Auler using namespace llvm;
27a34c753fSRafael Auler using namespace bolt;
28a34c753fSRafael Auler using namespace MCPlus;
29a34c753fSRafael Auler 
30a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B,
31a34c753fSRafael Auler                            CompFuncTy Comp) const {
32a34c753fSRafael Auler   if (A.getOpcode() != B.getOpcode())
33a34c753fSRafael Auler     return false;
34a34c753fSRafael Auler 
35a34c753fSRafael Auler   unsigned NumOperands = MCPlus::getNumPrimeOperands(A);
36a34c753fSRafael Auler   if (NumOperands != MCPlus::getNumPrimeOperands(B))
37a34c753fSRafael Auler     return false;
38a34c753fSRafael Auler 
393652483cSRafael Auler   for (unsigned Index = 0; Index < NumOperands; ++Index)
40a34c753fSRafael Auler     if (!equals(A.getOperand(Index), B.getOperand(Index), Comp))
41a34c753fSRafael Auler       return false;
42a34c753fSRafael Auler 
43a34c753fSRafael Auler   return true;
44a34c753fSRafael Auler }
45a34c753fSRafael Auler 
46a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCOperand &A, const MCOperand &B,
47a34c753fSRafael Auler                            CompFuncTy Comp) const {
48a34c753fSRafael Auler   if (A.isReg()) {
49a34c753fSRafael Auler     if (!B.isReg())
50a34c753fSRafael Auler       return false;
51a34c753fSRafael Auler     return A.getReg() == B.getReg();
52a34c753fSRafael Auler   } else if (A.isImm()) {
53a34c753fSRafael Auler     if (!B.isImm())
54a34c753fSRafael Auler       return false;
55a34c753fSRafael Auler     return A.getImm() == B.getImm();
56a34c753fSRafael Auler   } else if (A.isSFPImm()) {
57a34c753fSRafael Auler     if (!B.isSFPImm())
58a34c753fSRafael Auler       return false;
59a34c753fSRafael Auler     return A.getSFPImm() == B.getSFPImm();
60a34c753fSRafael Auler   } else if (A.isDFPImm()) {
61a34c753fSRafael Auler     if (!B.isDFPImm())
62a34c753fSRafael Auler       return false;
63a34c753fSRafael Auler     return A.getDFPImm() == B.getDFPImm();
64a34c753fSRafael Auler   } else if (A.isExpr()) {
65a34c753fSRafael Auler     if (!B.isExpr())
66a34c753fSRafael Auler       return false;
67a34c753fSRafael Auler     return equals(*A.getExpr(), *B.getExpr(), Comp);
68a34c753fSRafael Auler   } else {
69a34c753fSRafael Auler     llvm_unreachable("unexpected operand kind");
70a34c753fSRafael Auler     return false;
71a34c753fSRafael Auler   }
72a34c753fSRafael Auler }
73a34c753fSRafael Auler 
74a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCExpr &A, const MCExpr &B,
75a34c753fSRafael Auler                            CompFuncTy Comp) const {
76a34c753fSRafael Auler   if (A.getKind() != B.getKind())
77a34c753fSRafael Auler     return false;
78a34c753fSRafael Auler 
79a34c753fSRafael Auler   switch (A.getKind()) {
80a34c753fSRafael Auler   case MCExpr::Constant: {
81a34c753fSRafael Auler     const auto &ConstA = cast<MCConstantExpr>(A);
82a34c753fSRafael Auler     const auto &ConstB = cast<MCConstantExpr>(B);
83a34c753fSRafael Auler     return ConstA.getValue() == ConstB.getValue();
84a34c753fSRafael Auler   }
85a34c753fSRafael Auler 
86a34c753fSRafael Auler   case MCExpr::SymbolRef: {
87a34c753fSRafael Auler     const MCSymbolRefExpr &SymbolA = cast<MCSymbolRefExpr>(A);
88a34c753fSRafael Auler     const MCSymbolRefExpr &SymbolB = cast<MCSymbolRefExpr>(B);
89a34c753fSRafael Auler     return SymbolA.getKind() == SymbolB.getKind() &&
90a34c753fSRafael Auler            Comp(&SymbolA.getSymbol(), &SymbolB.getSymbol());
91a34c753fSRafael Auler   }
92a34c753fSRafael Auler 
93a34c753fSRafael Auler   case MCExpr::Unary: {
94a34c753fSRafael Auler     const auto &UnaryA = cast<MCUnaryExpr>(A);
95a34c753fSRafael Auler     const auto &UnaryB = cast<MCUnaryExpr>(B);
96a34c753fSRafael Auler     return UnaryA.getOpcode() == UnaryB.getOpcode() &&
97a34c753fSRafael Auler            equals(*UnaryA.getSubExpr(), *UnaryB.getSubExpr(), Comp);
98a34c753fSRafael Auler   }
99a34c753fSRafael Auler 
100a34c753fSRafael Auler   case MCExpr::Binary: {
101a34c753fSRafael Auler     const auto &BinaryA = cast<MCBinaryExpr>(A);
102a34c753fSRafael Auler     const auto &BinaryB = cast<MCBinaryExpr>(B);
103a34c753fSRafael Auler     return BinaryA.getOpcode() == BinaryB.getOpcode() &&
104a34c753fSRafael Auler            equals(*BinaryA.getLHS(), *BinaryB.getLHS(), Comp) &&
105a34c753fSRafael Auler            equals(*BinaryA.getRHS(), *BinaryB.getRHS(), Comp);
106a34c753fSRafael Auler   }
107a34c753fSRafael Auler 
108a34c753fSRafael Auler   case MCExpr::Target: {
109a34c753fSRafael Auler     const auto &TargetExprA = cast<MCTargetExpr>(A);
110a34c753fSRafael Auler     const auto &TargetExprB = cast<MCTargetExpr>(B);
111a34c753fSRafael Auler     return equals(TargetExprA, TargetExprB, Comp);
112a34c753fSRafael Auler   }
113a34c753fSRafael Auler   }
114a34c753fSRafael Auler 
115a34c753fSRafael Auler   llvm_unreachable("Invalid expression kind!");
116a34c753fSRafael Auler }
117a34c753fSRafael Auler 
118a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B,
119a34c753fSRafael Auler                            CompFuncTy Comp) const {
120a34c753fSRafael Auler   llvm_unreachable("target-specific expressions are unsupported");
121a34c753fSRafael Auler }
122a34c753fSRafael Auler 
123a34c753fSRafael Auler void MCPlusBuilder::setTailCall(MCInst &Inst) {
124a34c753fSRafael Auler   assert(!hasAnnotation(Inst, MCAnnotation::kTailCall));
125a34c753fSRafael Auler   setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true);
126a34c753fSRafael Auler }
127a34c753fSRafael Auler 
128a34c753fSRafael Auler bool MCPlusBuilder::isTailCall(const MCInst &Inst) const {
129a34c753fSRafael Auler   if (hasAnnotation(Inst, MCAnnotation::kTailCall))
130a34c753fSRafael Auler     return true;
131a34c753fSRafael Auler   if (getConditionalTailCall(Inst))
132a34c753fSRafael Auler     return true;
133a34c753fSRafael Auler   return false;
134a34c753fSRafael Auler }
135a34c753fSRafael Auler 
1362563fd63SAmir Ayupov std::optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const {
137a34c753fSRafael Auler   if (!isCall(Inst))
138e324a80fSKazu Hirata     return std::nullopt;
1392563fd63SAmir Ayupov   std::optional<int64_t> LPSym =
140a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad);
141a34c753fSRafael Auler   if (!LPSym)
142e324a80fSKazu Hirata     return std::nullopt;
1432563fd63SAmir Ayupov   std::optional<int64_t> Action =
144a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kEHAction);
145a34c753fSRafael Auler   if (!Action)
146e324a80fSKazu Hirata     return std::nullopt;
147a34c753fSRafael Auler 
148a34c753fSRafael Auler   return std::make_pair(reinterpret_cast<const MCSymbol *>(*LPSym),
149a34c753fSRafael Auler                         static_cast<uint64_t>(*Action));
150a34c753fSRafael Auler }
151a34c753fSRafael Auler 
152a34c753fSRafael Auler void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) {
153a34c753fSRafael Auler   if (isCall(Inst)) {
154a34c753fSRafael Auler     assert(!getEHInfo(Inst));
155a34c753fSRafael Auler     setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,
156a34c753fSRafael Auler                          reinterpret_cast<int64_t>(LP.first));
157a34c753fSRafael Auler     setAnnotationOpValue(Inst, MCAnnotation::kEHAction,
158a34c753fSRafael Auler                          static_cast<int64_t>(LP.second));
159a34c753fSRafael Auler   }
160a34c753fSRafael Auler }
161a34c753fSRafael Auler 
162f263a66bSMaksim Panchenko bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) {
163f263a66bSMaksim Panchenko   if (!isInvoke(Inst))
164f263a66bSMaksim Panchenko     return false;
165f263a66bSMaksim Panchenko 
166f263a66bSMaksim Panchenko   setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,
167f263a66bSMaksim Panchenko                        reinterpret_cast<int64_t>(LP.first));
168f263a66bSMaksim Panchenko   setAnnotationOpValue(Inst, MCAnnotation::kEHAction,
169f263a66bSMaksim Panchenko                        static_cast<int64_t>(LP.second));
170f263a66bSMaksim Panchenko   return true;
171f263a66bSMaksim Panchenko }
172f263a66bSMaksim Panchenko 
173a34c753fSRafael Auler int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const {
1742563fd63SAmir Ayupov   std::optional<int64_t> Value =
175a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize);
176a34c753fSRafael Auler   if (!Value)
177a34c753fSRafael Auler     return -1LL;
178a34c753fSRafael Auler   return *Value;
179a34c753fSRafael Auler }
180a34c753fSRafael Auler 
181a34c753fSRafael Auler void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize,
182a34c753fSRafael Auler                                    AllocatorIdTy AllocId) {
183a34c753fSRafael Auler   assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value");
184a34c753fSRafael Auler   assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set");
185a34c753fSRafael Auler   assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke");
186a34c753fSRafael Auler 
187a34c753fSRafael Auler   setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize, AllocId);
188a34c753fSRafael Auler }
189a34c753fSRafael Auler 
190a34c753fSRafael Auler uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const {
1912563fd63SAmir Ayupov   std::optional<int64_t> Value =
192a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kJumpTable);
193a34c753fSRafael Auler   if (!Value)
194a34c753fSRafael Auler     return 0;
195a34c753fSRafael Auler   return *Value;
196a34c753fSRafael Auler }
197a34c753fSRafael Auler 
198a34c753fSRafael Auler uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const {
199a34c753fSRafael Auler   return getAnnotationAs<uint16_t>(Inst, "JTIndexReg");
200a34c753fSRafael Auler }
201a34c753fSRafael Auler 
202a34c753fSRafael Auler bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value,
203a34c753fSRafael Auler                                  uint16_t IndexReg, AllocatorIdTy AllocId) {
204a34c753fSRafael Auler   if (!isIndirectBranch(Inst))
205a34c753fSRafael Auler     return false;
206a34c753fSRafael Auler   setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value, AllocId);
207a34c753fSRafael Auler   getOrCreateAnnotationAs<uint16_t>(Inst, "JTIndexReg", AllocId) = IndexReg;
208a34c753fSRafael Auler   return true;
209a34c753fSRafael Auler }
210a34c753fSRafael Auler 
211a34c753fSRafael Auler bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) {
212a34c753fSRafael Auler   if (!getJumpTable(Inst))
213a34c753fSRafael Auler     return false;
214a34c753fSRafael Auler   removeAnnotation(Inst, MCAnnotation::kJumpTable);
215a34c753fSRafael Auler   removeAnnotation(Inst, "JTIndexReg");
216a34c753fSRafael Auler   return true;
217a34c753fSRafael Auler }
218a34c753fSRafael Auler 
2192563fd63SAmir Ayupov std::optional<uint64_t>
220a34c753fSRafael Auler MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const {
2212563fd63SAmir Ayupov   std::optional<int64_t> Value =
222a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall);
223a34c753fSRafael Auler   if (!Value)
224e324a80fSKazu Hirata     return std::nullopt;
225a34c753fSRafael Auler   return static_cast<uint64_t>(*Value);
226a34c753fSRafael Auler }
227a34c753fSRafael Auler 
22840c2e0faSMaksim Panchenko bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) {
229a34c753fSRafael Auler   if (!isConditionalBranch(Inst))
230a34c753fSRafael Auler     return false;
231a34c753fSRafael Auler 
232a34c753fSRafael Auler   setAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall, Dest);
233a34c753fSRafael Auler   return true;
234a34c753fSRafael Auler }
235a34c753fSRafael Auler 
236a34c753fSRafael Auler bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) {
237a34c753fSRafael Auler   if (!getConditionalTailCall(Inst))
238a34c753fSRafael Auler     return false;
239a34c753fSRafael Auler   removeAnnotation(Inst, MCAnnotation::kConditionalTailCall);
240a34c753fSRafael Auler   return true;
241a34c753fSRafael Auler }
242a34c753fSRafael Auler 
2432563fd63SAmir Ayupov std::optional<uint32_t> MCPlusBuilder::getOffset(const MCInst &Inst) const {
2442563fd63SAmir Ayupov   std::optional<int64_t> Value =
2452563fd63SAmir Ayupov       getAnnotationOpValue(Inst, MCAnnotation::kOffset);
246a9cd49d5SAmir Ayupov   if (!Value)
247e324a80fSKazu Hirata     return std::nullopt;
248a9cd49d5SAmir Ayupov   return static_cast<uint32_t>(*Value);
249a9cd49d5SAmir Ayupov }
250a9cd49d5SAmir Ayupov 
251a9cd49d5SAmir Ayupov uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst,
252a9cd49d5SAmir Ayupov                                              uint32_t Default) const {
2532563fd63SAmir Ayupov   if (std::optional<uint32_t> Offset = getOffset(Inst))
254a9cd49d5SAmir Ayupov     return *Offset;
255a9cd49d5SAmir Ayupov   return Default;
256a9cd49d5SAmir Ayupov }
257a9cd49d5SAmir Ayupov 
258a9cd49d5SAmir Ayupov bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset,
259a9cd49d5SAmir Ayupov                               AllocatorIdTy AllocatorId) {
260a9cd49d5SAmir Ayupov   setAnnotationOpValue(Inst, MCAnnotation::kOffset, Offset, AllocatorId);
261a9cd49d5SAmir Ayupov   return true;
262a9cd49d5SAmir Ayupov }
263a9cd49d5SAmir Ayupov 
264a9cd49d5SAmir Ayupov bool MCPlusBuilder::clearOffset(MCInst &Inst) {
265a9cd49d5SAmir Ayupov   if (!hasAnnotation(Inst, MCAnnotation::kOffset))
266a9cd49d5SAmir Ayupov     return false;
267a9cd49d5SAmir Ayupov   removeAnnotation(Inst, MCAnnotation::kOffset);
268a9cd49d5SAmir Ayupov   return true;
269a9cd49d5SAmir Ayupov }
270a9cd49d5SAmir Ayupov 
271a34c753fSRafael Auler bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const {
272a34c753fSRafael Auler   const MCInst *AnnotationInst = getAnnotationInst(Inst);
273a34c753fSRafael Auler   if (!AnnotationInst)
274a34c753fSRafael Auler     return false;
275a34c753fSRafael Auler 
276a34c753fSRafael Auler   return (bool)getAnnotationOpValue(Inst, Index);
277a34c753fSRafael Auler }
278a34c753fSRafael Auler 
279a34c753fSRafael Auler bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) {
280a34c753fSRafael Auler   MCInst *AnnotationInst = getAnnotationInst(Inst);
281a34c753fSRafael Auler   if (!AnnotationInst)
282a34c753fSRafael Auler     return false;
283a34c753fSRafael Auler 
284a34c753fSRafael Auler   for (int I = AnnotationInst->getNumOperands() - 1; I >= 0; --I) {
285a34c753fSRafael Auler     int64_t ImmValue = AnnotationInst->getOperand(I).getImm();
286a34c753fSRafael Auler     if (extractAnnotationIndex(ImmValue) == Index) {
287a34c753fSRafael Auler       AnnotationInst->erase(AnnotationInst->begin() + I);
288a34c753fSRafael Auler       return true;
289a34c753fSRafael Auler     }
290a34c753fSRafael Auler   }
291a34c753fSRafael Auler   return false;
292a34c753fSRafael Auler }
293a34c753fSRafael Auler 
294a34c753fSRafael Auler void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) {
295a34c753fSRafael Auler   MCInst *AnnotationInst = getAnnotationInst(Inst);
296a34c753fSRafael Auler   if (!AnnotationInst)
297a34c753fSRafael Auler     return;
298a34c753fSRafael Auler   // Preserve TailCall annotation.
299a34c753fSRafael Auler   auto IsTC = hasAnnotation(Inst, MCAnnotation::kTailCall);
300a34c753fSRafael Auler 
301fb28196aSMaksim Panchenko   removeAnnotationInst(Inst);
302fb28196aSMaksim Panchenko 
303a34c753fSRafael Auler   if (KeepTC && IsTC)
304a34c753fSRafael Auler     setTailCall(Inst);
305a34c753fSRafael Auler }
306a34c753fSRafael Auler 
30740c2e0faSMaksim Panchenko void MCPlusBuilder::printAnnotations(const MCInst &Inst,
30840c2e0faSMaksim Panchenko                                      raw_ostream &OS) const {
309a34c753fSRafael Auler   const MCInst *AnnotationInst = getAnnotationInst(Inst);
310a34c753fSRafael Auler   if (!AnnotationInst)
311a34c753fSRafael Auler     return;
312a34c753fSRafael Auler 
313a34c753fSRafael Auler   for (unsigned I = 0; I < AnnotationInst->getNumOperands(); ++I) {
314a34c753fSRafael Auler     const int64_t Imm = AnnotationInst->getOperand(I).getImm();
315a34c753fSRafael Auler     const unsigned Index = extractAnnotationIndex(Imm);
316a34c753fSRafael Auler     const int64_t Value = extractAnnotationValue(Imm);
31740c2e0faSMaksim Panchenko     const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value);
318a34c753fSRafael Auler     if (Index >= MCAnnotation::kGeneric) {
31940c2e0faSMaksim Panchenko       OS << " # " << AnnotationNames[Index - MCAnnotation::kGeneric] << ": ";
320a34c753fSRafael Auler       Annotation->print(OS);
321a34c753fSRafael Auler     }
322a34c753fSRafael Auler   }
323a34c753fSRafael Auler }
324a34c753fSRafael Auler 
325a34c753fSRafael Auler void MCPlusBuilder::getClobberedRegs(const MCInst &Inst,
326a34c753fSRafael Auler                                      BitVector &Regs) const {
327a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
328a34c753fSRafael Auler     return;
329a34c753fSRafael Auler 
330a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
331a34c753fSRafael Auler 
3327557b83aSBenjamin Kramer   for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())
3337557b83aSBenjamin Kramer     Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false);
334a34c753fSRafael Auler 
335*b6f07d3aSAmir Ayupov   for (const MCOperand &Operand : defOperands(Inst)) {
336a34c753fSRafael Auler     assert(Operand.isReg());
337a34c753fSRafael Auler     Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/false);
338a34c753fSRafael Auler   }
339a34c753fSRafael Auler }
340a34c753fSRafael Auler 
34140c2e0faSMaksim Panchenko void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const {
342a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
343a34c753fSRafael Auler     return;
344a34c753fSRafael Auler 
345a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
346a34c753fSRafael Auler 
3477557b83aSBenjamin Kramer   for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())
3487557b83aSBenjamin Kramer     Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false);
3497557b83aSBenjamin Kramer   for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())
3507557b83aSBenjamin Kramer     Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/false);
351a34c753fSRafael Auler 
352a34c753fSRafael Auler   for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
353a34c753fSRafael Auler     if (!Inst.getOperand(I).isReg())
354a34c753fSRafael Auler       continue;
355a34c753fSRafael Auler     Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/false);
356a34c753fSRafael Auler   }
357a34c753fSRafael Auler }
358a34c753fSRafael Auler 
35940c2e0faSMaksim Panchenko void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const {
360a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
361a34c753fSRafael Auler     return;
362a34c753fSRafael Auler 
363a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
364a34c753fSRafael Auler 
3657557b83aSBenjamin Kramer   for (MCPhysReg ImplicitDef : InstInfo.implicit_defs())
3667557b83aSBenjamin Kramer     Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/true);
367a34c753fSRafael Auler 
368*b6f07d3aSAmir Ayupov   for (const MCOperand &Operand : defOperands(Inst)) {
369a34c753fSRafael Auler     assert(Operand.isReg());
370a34c753fSRafael Auler     Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);
371a34c753fSRafael Auler   }
372a34c753fSRafael Auler }
373a34c753fSRafael Auler 
374a34c753fSRafael Auler void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const {
375a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
376a34c753fSRafael Auler     return;
377a34c753fSRafael Auler 
378a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
379a34c753fSRafael Auler 
3807557b83aSBenjamin Kramer   for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())
3817557b83aSBenjamin Kramer     Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true);
382a34c753fSRafael Auler 
383a34c753fSRafael Auler   for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
384a34c753fSRafael Auler     if (!Inst.getOperand(I).isReg())
385a34c753fSRafael Auler       continue;
386a34c753fSRafael Auler     Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/true);
387a34c753fSRafael Auler   }
388a34c753fSRafael Auler }
389a34c753fSRafael Auler 
390a34c753fSRafael Auler void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const {
391a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
392a34c753fSRafael Auler     return;
393a34c753fSRafael Auler 
394a34c753fSRafael Auler   if (isCall(Inst)) {
395a34c753fSRafael Auler     BitVector CallRegs = BitVector(Regs.size(), false);
396a34c753fSRafael Auler     getCalleeSavedRegs(CallRegs);
397a34c753fSRafael Auler     CallRegs.flip();
398a34c753fSRafael Auler     Regs |= CallRegs;
399a34c753fSRafael Auler     return;
400a34c753fSRafael Auler   }
401a34c753fSRafael Auler 
402a34c753fSRafael Auler   if (isReturn(Inst)) {
403a34c753fSRafael Auler     getDefaultLiveOut(Regs);
404a34c753fSRafael Auler     return;
405a34c753fSRafael Auler   }
406a34c753fSRafael Auler 
4073652483cSRafael Auler   if (isRep(Inst))
408a34c753fSRafael Auler     getRepRegs(Regs);
409a34c753fSRafael Auler 
410a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
411a34c753fSRafael Auler 
4127557b83aSBenjamin Kramer   for (MCPhysReg ImplicitUse : InstInfo.implicit_uses())
4137557b83aSBenjamin Kramer     Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true);
414a34c753fSRafael Auler 
415*b6f07d3aSAmir Ayupov   for (const MCOperand &Operand : useOperands(Inst))
416*b6f07d3aSAmir Ayupov     if (Operand.isReg())
417*b6f07d3aSAmir Ayupov       Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);
418a34c753fSRafael Auler }
419a34c753fSRafael Auler 
420a34c753fSRafael Auler bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const {
421a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());
422a34c753fSRafael Auler   return InstInfo.hasDefOfPhysReg(MI, Reg, *RegInfo);
423a34c753fSRafael Auler }
424a34c753fSRafael Auler 
425a34c753fSRafael Auler bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const {
426a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());
427a34c753fSRafael Auler   for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I)
428a34c753fSRafael Auler     if (MI.getOperand(I).isReg() &&
429a34c753fSRafael Auler         RegInfo->isSubRegisterEq(Reg, MI.getOperand(I).getReg()))
430a34c753fSRafael Auler       return true;
4317557b83aSBenjamin Kramer   for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) {
4327557b83aSBenjamin Kramer     if (ImplicitUse == Reg || RegInfo->isSubRegister(Reg, ImplicitUse))
433a34c753fSRafael Auler       return true;
4343652483cSRafael Auler   }
435a34c753fSRafael Auler   return false;
436a34c753fSRafael Auler }
437a34c753fSRafael Auler 
43840c2e0faSMaksim Panchenko const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg,
439a34c753fSRafael Auler                                            bool OnlySmaller) const {
440a34c753fSRafael Auler   if (OnlySmaller)
441e900f058SVladislav Khmelevsky     return SmallerAliasMap[Reg];
442a34c753fSRafael Auler   return AliasMap[Reg];
443a34c753fSRafael Auler }
444e900f058SVladislav Khmelevsky 
44568c7299fSAmir Ayupov void MCPlusBuilder::initAliases() {
44668c7299fSAmir Ayupov   assert(AliasMap.size() == 0 && SmallerAliasMap.size() == 0);
447a34c753fSRafael Auler   // Build alias map
448a34c753fSRafael Auler   for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {
449a34c753fSRafael Auler     BitVector BV(RegInfo->getNumRegs(), false);
450a34c753fSRafael Auler     BV.set(I);
451e900f058SVladislav Khmelevsky     AliasMap.emplace_back(BV);
452e900f058SVladislav Khmelevsky     SmallerAliasMap.emplace_back(BV);
453a34c753fSRafael Auler   }
454e900f058SVladislav Khmelevsky 
455e900f058SVladislav Khmelevsky   // Cache all aliases for each register
456e900f058SVladislav Khmelevsky   for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I != E; ++I) {
457e900f058SVladislav Khmelevsky     for (MCRegAliasIterator AI(I, RegInfo, true); AI.isValid(); ++AI)
458e900f058SVladislav Khmelevsky       AliasMap[I].set(*AI);
459e900f058SVladislav Khmelevsky   }
460e900f058SVladislav Khmelevsky 
461e900f058SVladislav Khmelevsky   // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister)
4623652483cSRafael Auler   for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I)
4633652483cSRafael Auler     for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI)
464e900f058SVladislav Khmelevsky       SmallerAliasMap[I] |= SmallerAliasMap[*SI];
465a34c753fSRafael Auler 
466a34c753fSRafael Auler   LLVM_DEBUG({
467a34c753fSRafael Auler     dbgs() << "Dumping reg alias table:\n";
468a34c753fSRafael Auler     for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {
469a34c753fSRafael Auler       dbgs() << "Reg " << I << ": ";
470e900f058SVladislav Khmelevsky       const BitVector &BV = AliasMap[I];
471a34c753fSRafael Auler       int Idx = BV.find_first();
472a34c753fSRafael Auler       while (Idx != -1) {
473a34c753fSRafael Auler         dbgs() << Idx << " ";
474a34c753fSRafael Auler         Idx = BV.find_next(Idx);
475a34c753fSRafael Auler       }
476a34c753fSRafael Auler       dbgs() << "\n";
477a34c753fSRafael Auler     }
478a34c753fSRafael Auler   });
479a34c753fSRafael Auler }
480a34c753fSRafael Auler 
481ce106107SAmir Ayupov void MCPlusBuilder::initSizeMap() {
482ce106107SAmir Ayupov   SizeMap.resize(RegInfo->getNumRegs());
483a34c753fSRafael Auler   // Build size map
484ce106107SAmir Ayupov   for (auto RC : RegInfo->regclasses())
485ce106107SAmir Ayupov     for (MCPhysReg Reg : RC)
486ce106107SAmir Ayupov       SizeMap[Reg] = RC.getSizeInBits() / 8;
487a34c753fSRafael Auler }
488a34c753fSRafael Auler 
489a34c753fSRafael Auler bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum,
490a34c753fSRafael Auler                                           const MCSymbol *Symbol,
491a34c753fSRafael Auler                                           int64_t Addend, MCContext *Ctx,
492a34c753fSRafael Auler                                           uint64_t RelType) const {
493a34c753fSRafael Auler   MCOperand Operand;
494a34c753fSRafael Auler   if (!Addend) {
495a34c753fSRafael Auler     Operand = MCOperand::createExpr(getTargetExprFor(
496a34c753fSRafael Auler         Inst, MCSymbolRefExpr::create(Symbol, *Ctx), *Ctx, RelType));
497a34c753fSRafael Auler   } else {
498a34c753fSRafael Auler     Operand = MCOperand::createExpr(getTargetExprFor(
499a34c753fSRafael Auler         Inst,
500a34c753fSRafael Auler         MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, *Ctx),
501a34c753fSRafael Auler                                 MCConstantExpr::create(Addend, *Ctx), *Ctx),
502a34c753fSRafael Auler         *Ctx, RelType));
503a34c753fSRafael Auler   }
504a34c753fSRafael Auler   Inst.getOperand(OpNum) = Operand;
505a34c753fSRafael Auler   return true;
506a34c753fSRafael Auler }
507