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