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