xref: /llvm-project/bolt/lib/Core/MCPlusBuilder.cpp (revision 3652483c8ea7ec20e8d0cb4aef0630688011cc08)
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"
19a34c753fSRafael Auler #include "llvm/Support/Debug.h"
20a34c753fSRafael Auler #include <cstdint>
21a34c753fSRafael Auler #include <queue>
22a34c753fSRafael Auler 
23a34c753fSRafael Auler #define DEBUG_TYPE "mcplus"
24a34c753fSRafael Auler 
25a34c753fSRafael Auler using namespace llvm;
26a34c753fSRafael Auler using namespace bolt;
27a34c753fSRafael Auler using namespace MCPlus;
28a34c753fSRafael Auler 
29a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B,
30a34c753fSRafael Auler                            CompFuncTy Comp) const {
31a34c753fSRafael Auler   if (A.getOpcode() != B.getOpcode())
32a34c753fSRafael Auler     return false;
33a34c753fSRafael Auler 
34a34c753fSRafael Auler   unsigned NumOperands = MCPlus::getNumPrimeOperands(A);
35a34c753fSRafael Auler   if (NumOperands != MCPlus::getNumPrimeOperands(B))
36a34c753fSRafael Auler     return false;
37a34c753fSRafael Auler 
38*3652483cSRafael Auler   for (unsigned Index = 0; Index < NumOperands; ++Index)
39a34c753fSRafael Auler     if (!equals(A.getOperand(Index), B.getOperand(Index), Comp))
40a34c753fSRafael Auler       return false;
41a34c753fSRafael Auler 
42a34c753fSRafael Auler   return true;
43a34c753fSRafael Auler }
44a34c753fSRafael Auler 
45a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCOperand &A, const MCOperand &B,
46a34c753fSRafael Auler                            CompFuncTy Comp) const {
47a34c753fSRafael Auler   if (A.isReg()) {
48a34c753fSRafael Auler     if (!B.isReg())
49a34c753fSRafael Auler       return false;
50a34c753fSRafael Auler     return A.getReg() == B.getReg();
51a34c753fSRafael Auler   } else if (A.isImm()) {
52a34c753fSRafael Auler     if (!B.isImm())
53a34c753fSRafael Auler       return false;
54a34c753fSRafael Auler     return A.getImm() == B.getImm();
55a34c753fSRafael Auler   } else if (A.isSFPImm()) {
56a34c753fSRafael Auler     if (!B.isSFPImm())
57a34c753fSRafael Auler       return false;
58a34c753fSRafael Auler     return A.getSFPImm() == B.getSFPImm();
59a34c753fSRafael Auler   } else if (A.isDFPImm()) {
60a34c753fSRafael Auler     if (!B.isDFPImm())
61a34c753fSRafael Auler       return false;
62a34c753fSRafael Auler     return A.getDFPImm() == B.getDFPImm();
63a34c753fSRafael Auler   } else if (A.isExpr()) {
64a34c753fSRafael Auler     if (!B.isExpr())
65a34c753fSRafael Auler       return false;
66a34c753fSRafael Auler     return equals(*A.getExpr(), *B.getExpr(), Comp);
67a34c753fSRafael Auler   } else {
68a34c753fSRafael Auler     llvm_unreachable("unexpected operand kind");
69a34c753fSRafael Auler     return false;
70a34c753fSRafael Auler   }
71a34c753fSRafael Auler }
72a34c753fSRafael Auler 
73a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCExpr &A, const MCExpr &B,
74a34c753fSRafael Auler                            CompFuncTy Comp) const {
75a34c753fSRafael Auler   if (A.getKind() != B.getKind())
76a34c753fSRafael Auler     return false;
77a34c753fSRafael Auler 
78a34c753fSRafael Auler   switch (A.getKind()) {
79a34c753fSRafael Auler   case MCExpr::Constant: {
80a34c753fSRafael Auler     const auto &ConstA = cast<MCConstantExpr>(A);
81a34c753fSRafael Auler     const auto &ConstB = cast<MCConstantExpr>(B);
82a34c753fSRafael Auler     return ConstA.getValue() == ConstB.getValue();
83a34c753fSRafael Auler   }
84a34c753fSRafael Auler 
85a34c753fSRafael Auler   case MCExpr::SymbolRef: {
86a34c753fSRafael Auler     const MCSymbolRefExpr &SymbolA = cast<MCSymbolRefExpr>(A);
87a34c753fSRafael Auler     const MCSymbolRefExpr &SymbolB = cast<MCSymbolRefExpr>(B);
88a34c753fSRafael Auler     return SymbolA.getKind() == SymbolB.getKind() &&
89a34c753fSRafael Auler            Comp(&SymbolA.getSymbol(), &SymbolB.getSymbol());
90a34c753fSRafael Auler   }
91a34c753fSRafael Auler 
92a34c753fSRafael Auler   case MCExpr::Unary: {
93a34c753fSRafael Auler     const auto &UnaryA = cast<MCUnaryExpr>(A);
94a34c753fSRafael Auler     const auto &UnaryB = cast<MCUnaryExpr>(B);
95a34c753fSRafael Auler     return UnaryA.getOpcode() == UnaryB.getOpcode() &&
96a34c753fSRafael Auler            equals(*UnaryA.getSubExpr(), *UnaryB.getSubExpr(), Comp);
97a34c753fSRafael Auler   }
98a34c753fSRafael Auler 
99a34c753fSRafael Auler   case MCExpr::Binary: {
100a34c753fSRafael Auler     const auto &BinaryA = cast<MCBinaryExpr>(A);
101a34c753fSRafael Auler     const auto &BinaryB = cast<MCBinaryExpr>(B);
102a34c753fSRafael Auler     return BinaryA.getOpcode() == BinaryB.getOpcode() &&
103a34c753fSRafael Auler            equals(*BinaryA.getLHS(), *BinaryB.getLHS(), Comp) &&
104a34c753fSRafael Auler            equals(*BinaryA.getRHS(), *BinaryB.getRHS(), Comp);
105a34c753fSRafael Auler   }
106a34c753fSRafael Auler 
107a34c753fSRafael Auler   case MCExpr::Target: {
108a34c753fSRafael Auler     const auto &TargetExprA = cast<MCTargetExpr>(A);
109a34c753fSRafael Auler     const auto &TargetExprB = cast<MCTargetExpr>(B);
110a34c753fSRafael Auler     return equals(TargetExprA, TargetExprB, Comp);
111a34c753fSRafael Auler   }
112a34c753fSRafael Auler   }
113a34c753fSRafael Auler 
114a34c753fSRafael Auler   llvm_unreachable("Invalid expression kind!");
115a34c753fSRafael Auler }
116a34c753fSRafael Auler 
117a34c753fSRafael Auler bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B,
118a34c753fSRafael Auler                            CompFuncTy Comp) const {
119a34c753fSRafael Auler   llvm_unreachable("target-specific expressions are unsupported");
120a34c753fSRafael Auler }
121a34c753fSRafael Auler 
122a34c753fSRafael Auler void MCPlusBuilder::setTailCall(MCInst &Inst) {
123a34c753fSRafael Auler   assert(!hasAnnotation(Inst, MCAnnotation::kTailCall));
124a34c753fSRafael Auler   setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true);
125a34c753fSRafael Auler }
126a34c753fSRafael Auler 
127a34c753fSRafael Auler bool MCPlusBuilder::isTailCall(const MCInst &Inst) const {
128a34c753fSRafael Auler   if (hasAnnotation(Inst, MCAnnotation::kTailCall))
129a34c753fSRafael Auler     return true;
130a34c753fSRafael Auler   if (getConditionalTailCall(Inst))
131a34c753fSRafael Auler     return true;
132a34c753fSRafael Auler   return false;
133a34c753fSRafael Auler }
134a34c753fSRafael Auler 
135a34c753fSRafael Auler Optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const {
136a34c753fSRafael Auler   if (!isCall(Inst))
137a34c753fSRafael Auler     return NoneType();
138a34c753fSRafael Auler   Optional<int64_t> LPSym =
139a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad);
140a34c753fSRafael Auler   if (!LPSym)
141a34c753fSRafael Auler     return NoneType();
142a34c753fSRafael Auler   Optional<int64_t> Action =
143a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kEHAction);
144a34c753fSRafael Auler   if (!Action)
145a34c753fSRafael Auler     return NoneType();
146a34c753fSRafael Auler 
147a34c753fSRafael Auler   return std::make_pair(reinterpret_cast<const MCSymbol *>(*LPSym),
148a34c753fSRafael Auler                         static_cast<uint64_t>(*Action));
149a34c753fSRafael Auler }
150a34c753fSRafael Auler 
151a34c753fSRafael Auler void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) {
152a34c753fSRafael Auler   if (isCall(Inst)) {
153a34c753fSRafael Auler     assert(!getEHInfo(Inst));
154a34c753fSRafael Auler     setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad,
155a34c753fSRafael Auler                          reinterpret_cast<int64_t>(LP.first));
156a34c753fSRafael Auler     setAnnotationOpValue(Inst, MCAnnotation::kEHAction,
157a34c753fSRafael Auler                          static_cast<int64_t>(LP.second));
158a34c753fSRafael Auler   }
159a34c753fSRafael Auler }
160a34c753fSRafael Auler 
161a34c753fSRafael Auler int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const {
162a34c753fSRafael Auler   Optional<int64_t> Value =
163a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize);
164a34c753fSRafael Auler   if (!Value)
165a34c753fSRafael Auler     return -1LL;
166a34c753fSRafael Auler   return *Value;
167a34c753fSRafael Auler }
168a34c753fSRafael Auler 
169a34c753fSRafael Auler void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize,
170a34c753fSRafael Auler                                    AllocatorIdTy AllocId) {
171a34c753fSRafael Auler   assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value");
172a34c753fSRafael Auler   assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set");
173a34c753fSRafael Auler   assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke");
174a34c753fSRafael Auler 
175a34c753fSRafael Auler   setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize, AllocId);
176a34c753fSRafael Auler }
177a34c753fSRafael Auler 
178a34c753fSRafael Auler uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const {
179a34c753fSRafael Auler   Optional<int64_t> Value =
180a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kJumpTable);
181a34c753fSRafael Auler   if (!Value)
182a34c753fSRafael Auler     return 0;
183a34c753fSRafael Auler   return *Value;
184a34c753fSRafael Auler }
185a34c753fSRafael Auler 
186a34c753fSRafael Auler uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const {
187a34c753fSRafael Auler   return getAnnotationAs<uint16_t>(Inst, "JTIndexReg");
188a34c753fSRafael Auler }
189a34c753fSRafael Auler 
190a34c753fSRafael Auler bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value,
191a34c753fSRafael Auler                                  uint16_t IndexReg, AllocatorIdTy AllocId) {
192a34c753fSRafael Auler   if (!isIndirectBranch(Inst))
193a34c753fSRafael Auler     return false;
194a34c753fSRafael Auler   setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value, AllocId);
195a34c753fSRafael Auler   getOrCreateAnnotationAs<uint16_t>(Inst, "JTIndexReg", AllocId) = IndexReg;
196a34c753fSRafael Auler   return true;
197a34c753fSRafael Auler }
198a34c753fSRafael Auler 
199a34c753fSRafael Auler bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) {
200a34c753fSRafael Auler   if (!getJumpTable(Inst))
201a34c753fSRafael Auler     return false;
202a34c753fSRafael Auler   removeAnnotation(Inst, MCAnnotation::kJumpTable);
203a34c753fSRafael Auler   removeAnnotation(Inst, "JTIndexReg");
204a34c753fSRafael Auler   return true;
205a34c753fSRafael Auler }
206a34c753fSRafael Auler 
207a34c753fSRafael Auler Optional<uint64_t>
208a34c753fSRafael Auler MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const {
209a34c753fSRafael Auler   Optional<int64_t> Value =
210a34c753fSRafael Auler       getAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall);
211a34c753fSRafael Auler   if (!Value)
212a34c753fSRafael Auler     return NoneType();
213a34c753fSRafael Auler   return static_cast<uint64_t>(*Value);
214a34c753fSRafael Auler }
215a34c753fSRafael Auler 
21640c2e0faSMaksim Panchenko bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) {
217a34c753fSRafael Auler   if (!isConditionalBranch(Inst))
218a34c753fSRafael Auler     return false;
219a34c753fSRafael Auler 
220a34c753fSRafael Auler   setAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall, Dest);
221a34c753fSRafael Auler   return true;
222a34c753fSRafael Auler }
223a34c753fSRafael Auler 
224a34c753fSRafael Auler bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) {
225a34c753fSRafael Auler   if (!getConditionalTailCall(Inst))
226a34c753fSRafael Auler     return false;
227a34c753fSRafael Auler   removeAnnotation(Inst, MCAnnotation::kConditionalTailCall);
228a34c753fSRafael Auler   return true;
229a34c753fSRafael Auler }
230a34c753fSRafael Auler 
231a34c753fSRafael Auler bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const {
232a34c753fSRafael Auler   const MCInst *AnnotationInst = getAnnotationInst(Inst);
233a34c753fSRafael Auler   if (!AnnotationInst)
234a34c753fSRafael Auler     return false;
235a34c753fSRafael Auler 
236a34c753fSRafael Auler   return (bool)getAnnotationOpValue(Inst, Index);
237a34c753fSRafael Auler }
238a34c753fSRafael Auler 
239a34c753fSRafael Auler bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) {
240a34c753fSRafael Auler   MCInst *AnnotationInst = getAnnotationInst(Inst);
241a34c753fSRafael Auler   if (!AnnotationInst)
242a34c753fSRafael Auler     return false;
243a34c753fSRafael Auler 
244a34c753fSRafael Auler   for (int I = AnnotationInst->getNumOperands() - 1; I >= 0; --I) {
245a34c753fSRafael Auler     int64_t ImmValue = AnnotationInst->getOperand(I).getImm();
246a34c753fSRafael Auler     if (extractAnnotationIndex(ImmValue) == Index) {
247a34c753fSRafael Auler       AnnotationInst->erase(AnnotationInst->begin() + I);
248a34c753fSRafael Auler       return true;
249a34c753fSRafael Auler     }
250a34c753fSRafael Auler   }
251a34c753fSRafael Auler   return false;
252a34c753fSRafael Auler }
253a34c753fSRafael Auler 
254a34c753fSRafael Auler void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) {
255a34c753fSRafael Auler   MCInst *AnnotationInst = getAnnotationInst(Inst);
256a34c753fSRafael Auler   if (!AnnotationInst)
257a34c753fSRafael Auler     return;
258a34c753fSRafael Auler   // Preserve TailCall annotation.
259a34c753fSRafael Auler   auto IsTC = hasAnnotation(Inst, MCAnnotation::kTailCall);
260a34c753fSRafael Auler 
261a34c753fSRafael Auler   Inst.erase(std::prev(Inst.end()));
262a34c753fSRafael Auler   if (KeepTC && IsTC)
263a34c753fSRafael Auler     setTailCall(Inst);
264a34c753fSRafael Auler }
265a34c753fSRafael Auler 
26640c2e0faSMaksim Panchenko void MCPlusBuilder::printAnnotations(const MCInst &Inst,
26740c2e0faSMaksim Panchenko                                      raw_ostream &OS) const {
268a34c753fSRafael Auler   const MCInst *AnnotationInst = getAnnotationInst(Inst);
269a34c753fSRafael Auler   if (!AnnotationInst)
270a34c753fSRafael Auler     return;
271a34c753fSRafael Auler 
272a34c753fSRafael Auler   for (unsigned I = 0; I < AnnotationInst->getNumOperands(); ++I) {
273a34c753fSRafael Auler     const int64_t Imm = AnnotationInst->getOperand(I).getImm();
274a34c753fSRafael Auler     const unsigned Index = extractAnnotationIndex(Imm);
275a34c753fSRafael Auler     const int64_t Value = extractAnnotationValue(Imm);
27640c2e0faSMaksim Panchenko     const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value);
277a34c753fSRafael Auler     if (Index >= MCAnnotation::kGeneric) {
27840c2e0faSMaksim Panchenko       OS << " # " << AnnotationNames[Index - MCAnnotation::kGeneric] << ": ";
279a34c753fSRafael Auler       Annotation->print(OS);
280a34c753fSRafael Auler     }
281a34c753fSRafael Auler   }
282a34c753fSRafael Auler }
283a34c753fSRafael Auler 
284a34c753fSRafael Auler bool MCPlusBuilder::evaluateBranch(const MCInst &Inst, uint64_t Addr,
285a34c753fSRafael Auler                                    uint64_t Size, uint64_t &Target) const {
286a34c753fSRafael Auler   return Analysis->evaluateBranch(Inst, Addr, Size, Target);
287a34c753fSRafael Auler }
288a34c753fSRafael Auler 
289a34c753fSRafael Auler void MCPlusBuilder::getClobberedRegs(const MCInst &Inst,
290a34c753fSRafael Auler                                      BitVector &Regs) const {
291a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
292a34c753fSRafael Auler     return;
293a34c753fSRafael Auler 
294a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
295a34c753fSRafael Auler 
296a34c753fSRafael Auler   const MCPhysReg *ImplicitDefs = InstInfo.getImplicitDefs();
297*3652483cSRafael Auler   for (unsigned I = 0, E = InstInfo.getNumImplicitDefs(); I != E; ++I)
298a34c753fSRafael Auler     Regs |= getAliases(ImplicitDefs[I], /*OnlySmaller=*/false);
299a34c753fSRafael Auler 
300a34c753fSRafael Auler   for (unsigned I = 0, E = InstInfo.getNumDefs(); I != E; ++I) {
301a34c753fSRafael Auler     const MCOperand &Operand = Inst.getOperand(I);
302a34c753fSRafael Auler     assert(Operand.isReg());
303a34c753fSRafael Auler     Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/false);
304a34c753fSRafael Auler   }
305a34c753fSRafael Auler }
306a34c753fSRafael Auler 
30740c2e0faSMaksim Panchenko void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const {
308a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
309a34c753fSRafael Auler     return;
310a34c753fSRafael Auler 
311a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
312a34c753fSRafael Auler 
313a34c753fSRafael Auler   const MCPhysReg *ImplicitDefs = InstInfo.getImplicitDefs();
314*3652483cSRafael Auler   for (unsigned I = 0, E = InstInfo.getNumImplicitDefs(); I != E; ++I)
315a34c753fSRafael Auler     Regs |= getAliases(ImplicitDefs[I], /*OnlySmaller=*/false);
316a34c753fSRafael Auler   const MCPhysReg *ImplicitUses = InstInfo.getImplicitUses();
317*3652483cSRafael Auler   for (unsigned I = 0, E = InstInfo.getNumImplicitUses(); I != E; ++I)
318a34c753fSRafael Auler     Regs |= getAliases(ImplicitUses[I], /*OnlySmaller=*/false);
319a34c753fSRafael Auler 
320a34c753fSRafael Auler   for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
321a34c753fSRafael Auler     if (!Inst.getOperand(I).isReg())
322a34c753fSRafael Auler       continue;
323a34c753fSRafael Auler     Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/false);
324a34c753fSRafael Auler   }
325a34c753fSRafael Auler }
326a34c753fSRafael Auler 
32740c2e0faSMaksim Panchenko void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const {
328a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
329a34c753fSRafael Auler     return;
330a34c753fSRafael Auler 
331a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
332a34c753fSRafael Auler 
333a34c753fSRafael Auler   const MCPhysReg *ImplicitDefs = InstInfo.getImplicitDefs();
334*3652483cSRafael Auler   for (unsigned I = 0, E = InstInfo.getNumImplicitDefs(); I != E; ++I)
335a34c753fSRafael Auler     Regs |= getAliases(ImplicitDefs[I], /*OnlySmaller=*/true);
336a34c753fSRafael Auler 
337a34c753fSRafael Auler   for (unsigned I = 0, E = InstInfo.getNumDefs(); I != E; ++I) {
338a34c753fSRafael Auler     const MCOperand &Operand = Inst.getOperand(I);
339a34c753fSRafael Auler     assert(Operand.isReg());
340a34c753fSRafael Auler     Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true);
341a34c753fSRafael Auler   }
342a34c753fSRafael Auler }
343a34c753fSRafael Auler 
344a34c753fSRafael Auler void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const {
345a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
346a34c753fSRafael Auler     return;
347a34c753fSRafael Auler 
348a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
349a34c753fSRafael Auler 
350a34c753fSRafael Auler   const MCPhysReg *ImplicitUses = InstInfo.getImplicitUses();
351*3652483cSRafael Auler   for (unsigned I = 0, E = InstInfo.getNumImplicitUses(); I != E; ++I)
352a34c753fSRafael Auler     Regs |= getAliases(ImplicitUses[I], /*OnlySmaller=*/true);
353a34c753fSRafael Auler 
354a34c753fSRafael Auler   for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) {
355a34c753fSRafael Auler     if (!Inst.getOperand(I).isReg())
356a34c753fSRafael Auler       continue;
357a34c753fSRafael Auler     Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/true);
358a34c753fSRafael Auler   }
359a34c753fSRafael Auler }
360a34c753fSRafael Auler 
361a34c753fSRafael Auler void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const {
362a34c753fSRafael Auler   if (isPrefix(Inst) || isCFI(Inst))
363a34c753fSRafael Auler     return;
364a34c753fSRafael Auler 
365a34c753fSRafael Auler   if (isCall(Inst)) {
366a34c753fSRafael Auler     BitVector CallRegs = BitVector(Regs.size(), false);
367a34c753fSRafael Auler     getCalleeSavedRegs(CallRegs);
368a34c753fSRafael Auler     CallRegs.flip();
369a34c753fSRafael Auler     Regs |= CallRegs;
370a34c753fSRafael Auler     return;
371a34c753fSRafael Auler   }
372a34c753fSRafael Auler 
373a34c753fSRafael Auler   if (isReturn(Inst)) {
374a34c753fSRafael Auler     getDefaultLiveOut(Regs);
375a34c753fSRafael Auler     return;
376a34c753fSRafael Auler   }
377a34c753fSRafael Auler 
378*3652483cSRafael Auler   if (isRep(Inst))
379a34c753fSRafael Auler     getRepRegs(Regs);
380a34c753fSRafael Auler 
381a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode());
382a34c753fSRafael Auler 
383a34c753fSRafael Auler   const MCPhysReg *ImplicitUses = InstInfo.getImplicitUses();
384*3652483cSRafael Auler   for (unsigned I = 0, E = InstInfo.getNumImplicitUses(); I != E; ++I)
385a34c753fSRafael Auler     Regs |= getAliases(ImplicitUses[I], /*OnlySmaller=*/true);
386a34c753fSRafael Auler 
387a34c753fSRafael Auler   for (unsigned I = InstInfo.getNumDefs(), E = InstInfo.getNumOperands();
388a34c753fSRafael Auler        I != E; ++I) {
389a34c753fSRafael Auler     if (!Inst.getOperand(I).isReg())
390a34c753fSRafael Auler       continue;
391a34c753fSRafael Auler     Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/true);
392a34c753fSRafael Auler   }
393a34c753fSRafael Auler }
394a34c753fSRafael Auler 
395a34c753fSRafael Auler bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const {
396a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());
397a34c753fSRafael Auler   return InstInfo.hasDefOfPhysReg(MI, Reg, *RegInfo);
398a34c753fSRafael Auler }
399a34c753fSRafael Auler 
400a34c753fSRafael Auler bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const {
401a34c753fSRafael Auler   const MCInstrDesc &InstInfo = Info->get(MI.getOpcode());
402a34c753fSRafael Auler   for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I)
403a34c753fSRafael Auler     if (MI.getOperand(I).isReg() &&
404a34c753fSRafael Auler         RegInfo->isSubRegisterEq(Reg, MI.getOperand(I).getReg()))
405a34c753fSRafael Auler       return true;
406*3652483cSRafael Auler   if (const uint16_t *ImpUses = InstInfo.ImplicitUses) {
407a34c753fSRafael Auler     for (; *ImpUses; ++ImpUses)
408a34c753fSRafael Auler       if (*ImpUses == Reg || RegInfo->isSubRegister(Reg, *ImpUses))
409a34c753fSRafael Auler         return true;
410*3652483cSRafael Auler   }
411a34c753fSRafael Auler   return false;
412a34c753fSRafael Auler }
413a34c753fSRafael Auler 
41440c2e0faSMaksim Panchenko const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg,
415a34c753fSRafael Auler                                            bool OnlySmaller) const {
416a34c753fSRafael Auler   // AliasMap caches a mapping of registers to the set of registers that
417a34c753fSRafael Auler   // alias (are sub or superregs of itself, including itself).
418a34c753fSRafael Auler   static std::vector<BitVector> AliasMap;
419a34c753fSRafael Auler   static std::vector<MCPhysReg> SuperReg;
420a34c753fSRafael Auler 
421a34c753fSRafael Auler   if (AliasMap.size() > 0) {
422a34c753fSRafael Auler     if (OnlySmaller)
423a34c753fSRafael Auler       return AliasMap[Reg];
424a34c753fSRafael Auler     return AliasMap[SuperReg[Reg]];
425a34c753fSRafael Auler   }
426a34c753fSRafael Auler   // Build alias map
427a34c753fSRafael Auler   for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {
428a34c753fSRafael Auler     BitVector BV(RegInfo->getNumRegs(), false);
429a34c753fSRafael Auler     BV.set(I);
430a34c753fSRafael Auler     AliasMap.emplace_back(std::move(BV));
431a34c753fSRafael Auler     SuperReg.emplace_back(I);
432a34c753fSRafael Auler   }
433a34c753fSRafael Auler   std::queue<MCPhysReg> Worklist;
434a34c753fSRafael Auler   // Propagate alias info upwards. Skip reg 0 (mapped to NoRegister)
435*3652483cSRafael Auler   for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I)
436a34c753fSRafael Auler     Worklist.push(I);
437a34c753fSRafael Auler   while (!Worklist.empty()) {
438a34c753fSRafael Auler     MCPhysReg I = Worklist.front();
439a34c753fSRafael Auler     Worklist.pop();
440*3652483cSRafael Auler     for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI)
441a34c753fSRafael Auler       AliasMap[I] |= AliasMap[*SI];
442*3652483cSRafael Auler     for (MCSuperRegIterator SI(I, RegInfo); SI.isValid(); ++SI)
443a34c753fSRafael Auler       Worklist.push(*SI);
444a34c753fSRafael Auler   }
445a34c753fSRafael Auler   // Propagate parent reg downwards
446*3652483cSRafael Auler   for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I)
447a34c753fSRafael Auler     Worklist.push(I);
448a34c753fSRafael Auler   while (!Worklist.empty()) {
449a34c753fSRafael Auler     MCPhysReg I = Worklist.front();
450a34c753fSRafael Auler     Worklist.pop();
451a34c753fSRafael Auler     for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI) {
452a34c753fSRafael Auler       SuperReg[*SI] = SuperReg[I];
453a34c753fSRafael Auler       Worklist.push(*SI);
454a34c753fSRafael Auler     }
455a34c753fSRafael Auler   }
456a34c753fSRafael Auler 
457a34c753fSRafael Auler   LLVM_DEBUG({
458a34c753fSRafael Auler     dbgs() << "Dumping reg alias table:\n";
459a34c753fSRafael Auler     for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) {
460a34c753fSRafael Auler       dbgs() << "Reg " << I << ": ";
461a34c753fSRafael Auler       const BitVector &BV = AliasMap[SuperReg[I]];
462a34c753fSRafael Auler       int Idx = BV.find_first();
463a34c753fSRafael Auler       while (Idx != -1) {
464a34c753fSRafael Auler         dbgs() << Idx << " ";
465a34c753fSRafael Auler         Idx = BV.find_next(Idx);
466a34c753fSRafael Auler       }
467a34c753fSRafael Auler       dbgs() << "\n";
468a34c753fSRafael Auler     }
469a34c753fSRafael Auler   });
470a34c753fSRafael Auler 
471a34c753fSRafael Auler   if (OnlySmaller)
472a34c753fSRafael Auler     return AliasMap[Reg];
473a34c753fSRafael Auler   return AliasMap[SuperReg[Reg]];
474a34c753fSRafael Auler }
475a34c753fSRafael Auler 
47640c2e0faSMaksim Panchenko uint8_t MCPlusBuilder::getRegSize(MCPhysReg Reg) const {
477a34c753fSRafael Auler   // SizeMap caches a mapping of registers to their sizes
478a34c753fSRafael Auler   static std::vector<uint8_t> SizeMap;
479a34c753fSRafael Auler 
480a34c753fSRafael Auler   if (SizeMap.size() > 0) {
481a34c753fSRafael Auler     return SizeMap[Reg];
482a34c753fSRafael Auler   }
483a34c753fSRafael Auler   SizeMap = std::vector<uint8_t>(RegInfo->getNumRegs());
484a34c753fSRafael Auler   // Build size map
485a34c753fSRafael Auler   for (auto I = RegInfo->regclass_begin(), E = RegInfo->regclass_end(); I != E;
486a34c753fSRafael Auler        ++I) {
487*3652483cSRafael Auler     for (MCPhysReg Reg : *I)
488a34c753fSRafael Auler       SizeMap[Reg] = I->getSizeInBits() / 8;
489a34c753fSRafael Auler   }
490a34c753fSRafael Auler 
491a34c753fSRafael Auler   return SizeMap[Reg];
492a34c753fSRafael Auler }
493a34c753fSRafael Auler 
494a34c753fSRafael Auler bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum,
495a34c753fSRafael Auler                                           const MCSymbol *Symbol,
496a34c753fSRafael Auler                                           int64_t Addend, MCContext *Ctx,
497a34c753fSRafael Auler                                           uint64_t RelType) const {
498a34c753fSRafael Auler   MCOperand Operand;
499a34c753fSRafael Auler   if (!Addend) {
500a34c753fSRafael Auler     Operand = MCOperand::createExpr(getTargetExprFor(
501a34c753fSRafael Auler         Inst, MCSymbolRefExpr::create(Symbol, *Ctx), *Ctx, RelType));
502a34c753fSRafael Auler   } else {
503a34c753fSRafael Auler     Operand = MCOperand::createExpr(getTargetExprFor(
504a34c753fSRafael Auler         Inst,
505a34c753fSRafael Auler         MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, *Ctx),
506a34c753fSRafael Auler                                 MCConstantExpr::create(Addend, *Ctx), *Ctx),
507a34c753fSRafael Auler         *Ctx, RelType));
508a34c753fSRafael Auler   }
509a34c753fSRafael Auler   Inst.getOperand(OpNum) = Operand;
510a34c753fSRafael Auler   return true;
511a34c753fSRafael Auler }
512