| //===- bolt/Core/MCPlusBuilder.cpp - Interface for MCPlus -----------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements the MCPlusBuilder class. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "bolt/Core/MCPlusBuilder.h" | |
| #include "bolt/Core/MCPlus.h" | |
| #include "bolt/Utils/CommandLineOpts.h" | |
| #include "llvm/MC/MCContext.h" | |
| #include "llvm/MC/MCInst.h" | |
| #include "llvm/MC/MCInstrAnalysis.h" | |
| #include "llvm/MC/MCInstrDesc.h" | |
| #include "llvm/MC/MCInstrInfo.h" | |
| #include "llvm/MC/MCRegisterInfo.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/Debug.h" | |
| #include <cstdint> | |
| #define DEBUG_TYPE "mcplus" | |
| using namespace llvm; | |
| using namespace bolt; | |
| using namespace MCPlus; | |
| namespace opts { | |
| cl::opt<bool> | |
| TerminalHLT("terminal-x86-hlt", | |
| cl::desc("Assume that execution stops at x86 HLT instruction"), | |
| cl::init(true), cl::Hidden, cl::cat(BoltCategory)); | |
| cl::opt<bool> | |
| TerminalTrap("terminal-trap", | |
| cl::desc("Assume that execution stops at trap instruction"), | |
| cl::init(true), cl::Hidden, cl::cat(BoltCategory)); | |
| } | |
| bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B, | |
| CompFuncTy Comp) const { | |
| if (A.getOpcode() != B.getOpcode()) | |
| return false; | |
| unsigned NumOperands = MCPlus::getNumPrimeOperands(A); | |
| if (NumOperands != MCPlus::getNumPrimeOperands(B)) | |
| return false; | |
| for (unsigned Index = 0; Index < NumOperands; ++Index) | |
| if (!equals(A.getOperand(Index), B.getOperand(Index), Comp)) | |
| return false; | |
| return true; | |
| } | |
| bool MCPlusBuilder::equals(const MCOperand &A, const MCOperand &B, | |
| CompFuncTy Comp) const { | |
| if (A.isReg()) { | |
| if (!B.isReg()) | |
| return false; | |
| return A.getReg() == B.getReg(); | |
| } else if (A.isImm()) { | |
| if (!B.isImm()) | |
| return false; | |
| return A.getImm() == B.getImm(); | |
| } else if (A.isSFPImm()) { | |
| if (!B.isSFPImm()) | |
| return false; | |
| return A.getSFPImm() == B.getSFPImm(); | |
| } else if (A.isDFPImm()) { | |
| if (!B.isDFPImm()) | |
| return false; | |
| return A.getDFPImm() == B.getDFPImm(); | |
| } else if (A.isExpr()) { | |
| if (!B.isExpr()) | |
| return false; | |
| return equals(*A.getExpr(), *B.getExpr(), Comp); | |
| } else { | |
| llvm_unreachable("unexpected operand kind"); | |
| return false; | |
| } | |
| } | |
| bool MCPlusBuilder::equals(const MCExpr &A, const MCExpr &B, | |
| CompFuncTy Comp) const { | |
| if (A.getKind() != B.getKind()) | |
| return false; | |
| switch (A.getKind()) { | |
| case MCExpr::Constant: { | |
| const auto &ConstA = cast<MCConstantExpr>(A); | |
| const auto &ConstB = cast<MCConstantExpr>(B); | |
| return ConstA.getValue() == ConstB.getValue(); | |
| } | |
| case MCExpr::SymbolRef: { | |
| const MCSymbolRefExpr &SymbolA = cast<MCSymbolRefExpr>(A); | |
| const MCSymbolRefExpr &SymbolB = cast<MCSymbolRefExpr>(B); | |
| return SymbolA.getKind() == SymbolB.getKind() && | |
| Comp(&SymbolA.getSymbol(), &SymbolB.getSymbol()); | |
| } | |
| case MCExpr::Unary: { | |
| const auto &UnaryA = cast<MCUnaryExpr>(A); | |
| const auto &UnaryB = cast<MCUnaryExpr>(B); | |
| return UnaryA.getOpcode() == UnaryB.getOpcode() && | |
| equals(*UnaryA.getSubExpr(), *UnaryB.getSubExpr(), Comp); | |
| } | |
| case MCExpr::Binary: { | |
| const auto &BinaryA = cast<MCBinaryExpr>(A); | |
| const auto &BinaryB = cast<MCBinaryExpr>(B); | |
| return BinaryA.getOpcode() == BinaryB.getOpcode() && | |
| equals(*BinaryA.getLHS(), *BinaryB.getLHS(), Comp) && | |
| equals(*BinaryA.getRHS(), *BinaryB.getRHS(), Comp); | |
| } | |
| case MCExpr::Specifier: { | |
| const auto &TargetExprA = cast<MCSpecifierExpr>(A); | |
| const auto &TargetExprB = cast<MCSpecifierExpr>(B); | |
| return equals(TargetExprA, TargetExprB, Comp); | |
| } | |
| case MCExpr::Target: | |
| llvm_unreachable("Not implemented"); | |
| } | |
| llvm_unreachable("Invalid expression kind!"); | |
| } | |
| bool MCPlusBuilder::equals(const MCSpecifierExpr &A, const MCSpecifierExpr &B, | |
| CompFuncTy Comp) const { | |
| llvm_unreachable("target-specific expressions are unsupported"); | |
| } | |
| bool MCPlusBuilder::isTerminator(const MCInst &Inst) const { | |
| if (isX86HLT(Inst)) | |
| return opts::TerminalHLT; | |
| if (Info->get(Inst.getOpcode()).isTrap()) | |
| return opts::TerminalTrap; | |
| return Analysis->isTerminator(Inst); | |
| } | |
| void MCPlusBuilder::setTailCall(MCInst &Inst) const { | |
| assert(!hasAnnotation(Inst, MCAnnotation::kTailCall)); | |
| setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true); | |
| } | |
| bool MCPlusBuilder::isTailCall(const MCInst &Inst) const { | |
| if (hasAnnotation(Inst, MCAnnotation::kTailCall)) | |
| return true; | |
| if (getConditionalTailCall(Inst)) | |
| return true; | |
| return false; | |
| } | |
| void MCPlusBuilder::setNegateRAState(MCInst &Inst) const { | |
| assert(!hasAnnotation(Inst, MCAnnotation::kNegateState)); | |
| setAnnotationOpValue(Inst, MCAnnotation::kNegateState, true); | |
| } | |
| bool MCPlusBuilder::hasNegateRAState(const MCInst &Inst) const { | |
| return hasAnnotation(Inst, MCAnnotation::kNegateState); | |
| } | |
| void MCPlusBuilder::setRememberState(MCInst &Inst) const { | |
| assert(!hasAnnotation(Inst, MCAnnotation::kRememberState)); | |
| setAnnotationOpValue(Inst, MCAnnotation::kRememberState, true); | |
| } | |
| bool MCPlusBuilder::hasRememberState(const MCInst &Inst) const { | |
| return hasAnnotation(Inst, MCAnnotation::kRememberState); | |
| } | |
| void MCPlusBuilder::setRestoreState(MCInst &Inst) const { | |
| assert(!hasAnnotation(Inst, MCAnnotation::kRestoreState)); | |
| setAnnotationOpValue(Inst, MCAnnotation::kRestoreState, true); | |
| } | |
| bool MCPlusBuilder::hasRestoreState(const MCInst &Inst) const { | |
| return hasAnnotation(Inst, MCAnnotation::kRestoreState); | |
| } | |
| void MCPlusBuilder::setRAState(MCInst &Inst, bool State) const { | |
| assert(!hasAnnotation(Inst, MCAnnotation::kRASigned)); | |
| assert(!hasAnnotation(Inst, MCAnnotation::kRAUnsigned)); | |
| if (State) | |
| setAnnotationOpValue(Inst, MCAnnotation::kRASigned, true); | |
| else | |
| setAnnotationOpValue(Inst, MCAnnotation::kRAUnsigned, true); | |
| } | |
| std::optional<bool> MCPlusBuilder::getRAState(const MCInst &Inst) const { | |
| if (hasAnnotation(Inst, MCAnnotation::kRASigned)) | |
| return true; | |
| if (hasAnnotation(Inst, MCAnnotation::kRAUnsigned)) | |
| return false; | |
| return std::nullopt; | |
| } | |
| std::optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const { | |
| if (!isCall(Inst)) | |
| return std::nullopt; | |
| std::optional<int64_t> LPSym = | |
| getAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad); | |
| if (!LPSym) | |
| return std::nullopt; | |
| std::optional<int64_t> Action = | |
| getAnnotationOpValue(Inst, MCAnnotation::kEHAction); | |
| if (!Action) | |
| return std::nullopt; | |
| return std::make_pair(reinterpret_cast<const MCSymbol *>(*LPSym), | |
| static_cast<uint64_t>(*Action)); | |
| } | |
| void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) const { | |
| if (isCall(Inst)) { | |
| assert(!getEHInfo(Inst)); | |
| setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad, | |
| reinterpret_cast<int64_t>(LP.first)); | |
| setAnnotationOpValue(Inst, MCAnnotation::kEHAction, | |
| static_cast<int64_t>(LP.second)); | |
| } | |
| } | |
| bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) const { | |
| if (!isInvoke(Inst)) | |
| return false; | |
| setAnnotationOpValue(Inst, MCAnnotation::kEHLandingPad, | |
| reinterpret_cast<int64_t>(LP.first)); | |
| setAnnotationOpValue(Inst, MCAnnotation::kEHAction, | |
| static_cast<int64_t>(LP.second)); | |
| return true; | |
| } | |
| int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const { | |
| std::optional<int64_t> Value = | |
| getAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize); | |
| if (!Value) | |
| return -1LL; | |
| return *Value; | |
| } | |
| void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize) const { | |
| assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value"); | |
| assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set"); | |
| assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke"); | |
| setAnnotationOpValue(Inst, MCAnnotation::kGnuArgsSize, GnuArgsSize); | |
| } | |
| uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const { | |
| std::optional<int64_t> Value = | |
| getAnnotationOpValue(Inst, MCAnnotation::kJumpTable); | |
| if (!Value) | |
| return 0; | |
| return *Value; | |
| } | |
| uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const { | |
| return getAnnotationAs<uint16_t>(Inst, "JTIndexReg"); | |
| } | |
| bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value, | |
| uint16_t IndexReg, AllocatorIdTy AllocId) { | |
| if (!isIndirectBranch(Inst)) | |
| return false; | |
| setAnnotationOpValue(Inst, MCAnnotation::kJumpTable, Value); | |
| getOrCreateAnnotationAs<uint16_t>(Inst, "JTIndexReg", AllocId) = IndexReg; | |
| return true; | |
| } | |
| bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) const { | |
| if (!getJumpTable(Inst)) | |
| return false; | |
| removeAnnotation(Inst, MCAnnotation::kJumpTable); | |
| removeAnnotation(Inst, "JTIndexReg"); | |
| return true; | |
| } | |
| std::optional<uint64_t> | |
| MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const { | |
| std::optional<int64_t> Value = | |
| getAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall); | |
| if (!Value) | |
| return std::nullopt; | |
| return static_cast<uint64_t>(*Value); | |
| } | |
| bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) const { | |
| if (!isConditionalBranch(Inst)) | |
| return false; | |
| setAnnotationOpValue(Inst, MCAnnotation::kConditionalTailCall, Dest); | |
| return true; | |
| } | |
| bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) const { | |
| if (!getConditionalTailCall(Inst)) | |
| return false; | |
| removeAnnotation(Inst, MCAnnotation::kConditionalTailCall); | |
| return true; | |
| } | |
| std::optional<uint32_t> MCPlusBuilder::getOffset(const MCInst &Inst) const { | |
| std::optional<int64_t> Value = | |
| getAnnotationOpValue(Inst, MCAnnotation::kOffset); | |
| if (!Value) | |
| return std::nullopt; | |
| return static_cast<uint32_t>(*Value); | |
| } | |
| uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst, | |
| uint32_t Default) const { | |
| if (std::optional<uint32_t> Offset = getOffset(Inst)) | |
| return *Offset; | |
| return Default; | |
| } | |
| bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset) const { | |
| setAnnotationOpValue(Inst, MCAnnotation::kOffset, Offset); | |
| return true; | |
| } | |
| bool MCPlusBuilder::clearOffset(MCInst &Inst) const { | |
| if (!hasAnnotation(Inst, MCAnnotation::kOffset)) | |
| return false; | |
| removeAnnotation(Inst, MCAnnotation::kOffset); | |
| return true; | |
| } | |
| MCSymbol *MCPlusBuilder::getInstLabel(const MCInst &Inst) const { | |
| if (std::optional<int64_t> Label = | |
| getAnnotationOpValue(Inst, MCAnnotation::kLabel)) | |
| return reinterpret_cast<MCSymbol *>(*Label); | |
| return nullptr; | |
| } | |
| MCSymbol *MCPlusBuilder::getOrCreateInstLabel(MCInst &Inst, const Twine &Name, | |
| MCContext *Ctx) const { | |
| MCSymbol *Label = getInstLabel(Inst); | |
| if (Label) | |
| return Label; | |
| Label = Ctx->createNamedTempSymbol(Name); | |
| setAnnotationOpValue(Inst, MCAnnotation::kLabel, | |
| reinterpret_cast<int64_t>(Label)); | |
| return Label; | |
| } | |
| void MCPlusBuilder::setInstLabel(MCInst &Inst, MCSymbol *Label) const { | |
| assert(!getInstLabel(Inst) && "Instruction already has assigned label."); | |
| setAnnotationOpValue(Inst, MCAnnotation::kLabel, | |
| reinterpret_cast<int64_t>(Label)); | |
| } | |
| std::optional<uint32_t> MCPlusBuilder::getSize(const MCInst &Inst) const { | |
| if (std::optional<int64_t> Value = | |
| getAnnotationOpValue(Inst, MCAnnotation::kSize)) | |
| return static_cast<uint32_t>(*Value); | |
| return std::nullopt; | |
| } | |
| void MCPlusBuilder::setSize(MCInst &Inst, uint32_t Size) const { | |
| setAnnotationOpValue(Inst, MCAnnotation::kSize, Size); | |
| } | |
| bool MCPlusBuilder::isDynamicBranch(const MCInst &Inst) const { | |
| if (!hasAnnotation(Inst, MCAnnotation::kDynamicBranch)) | |
| return false; | |
| assert(isBranch(Inst) && "Branch expected."); | |
| return true; | |
| } | |
| std::optional<uint32_t> | |
| MCPlusBuilder::getDynamicBranchID(const MCInst &Inst) const { | |
| if (std::optional<int64_t> Value = | |
| getAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch)) { | |
| assert(isBranch(Inst) && "Branch expected."); | |
| return static_cast<uint32_t>(*Value); | |
| } | |
| return std::nullopt; | |
| } | |
| void MCPlusBuilder::setDynamicBranch(MCInst &Inst, uint32_t ID) const { | |
| assert(isBranch(Inst) && "Branch expected."); | |
| setAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch, ID); | |
| } | |
| bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const { | |
| return (bool)getAnnotationOpValue(Inst, Index); | |
| } | |
| bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) const { | |
| std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst); | |
| if (!FirstAnnotationOp) | |
| return false; | |
| for (unsigned I = Inst.getNumOperands() - 1; I >= *FirstAnnotationOp; --I) { | |
| const int64_t ImmValue = Inst.getOperand(I).getImm(); | |
| if (extractAnnotationIndex(ImmValue) == Index) { | |
| Inst.erase(Inst.begin() + I); | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) const { | |
| KeepTC &= hasAnnotation(Inst, MCAnnotation::kTailCall); | |
| removeAnnotations(Inst); | |
| if (KeepTC) | |
| setTailCall(Inst); | |
| } | |
| void MCPlusBuilder::printAnnotations(const MCInst &Inst, raw_ostream &OS, | |
| bool PrintMemData) const { | |
| std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst); | |
| if (!FirstAnnotationOp) | |
| return; | |
| for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) { | |
| const int64_t Imm = Inst.getOperand(I).getImm(); | |
| const unsigned Index = extractAnnotationIndex(Imm); | |
| const int64_t Value = extractAnnotationValue(Imm); | |
| const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value); | |
| if (Index >= MCAnnotation::kGeneric) { | |
| std::string AnnotationName = | |
| AnnotationNames[Index - MCAnnotation::kGeneric]; | |
| if (!PrintMemData && AnnotationName == "MemoryAccessProfile") | |
| continue; | |
| OS << " # " << AnnotationName << ": "; | |
| Annotation->print(OS); | |
| } | |
| } | |
| } | |
| void MCPlusBuilder::getClobberedRegs(const MCInst &Inst, | |
| BitVector &Regs) const { | |
| if (isPrefix(Inst) || isCFI(Inst)) | |
| return; | |
| const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); | |
| for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) | |
| Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false); | |
| for (const MCOperand &Operand : defOperands(Inst)) { | |
| assert(Operand.isReg()); | |
| Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/false); | |
| } | |
| } | |
| void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const { | |
| if (isPrefix(Inst) || isCFI(Inst)) | |
| return; | |
| const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); | |
| for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) | |
| Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/false); | |
| for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) | |
| Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/false); | |
| for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) { | |
| if (!Inst.getOperand(I).isReg()) | |
| continue; | |
| Regs |= getAliases(Inst.getOperand(I).getReg(), /*OnlySmaller=*/false); | |
| } | |
| } | |
| void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const { | |
| if (isPrefix(Inst) || isCFI(Inst)) | |
| return; | |
| const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); | |
| for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) | |
| Regs |= getAliases(ImplicitDef, /*OnlySmaller=*/true); | |
| for (const MCOperand &Operand : defOperands(Inst)) { | |
| assert(Operand.isReg()); | |
| Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true); | |
| } | |
| } | |
| void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const { | |
| if (isPrefix(Inst) || isCFI(Inst)) | |
| return; | |
| const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); | |
| for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) | |
| Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true); | |
| for (const MCOperand &Operand : useOperands(Inst)) { | |
| if (!Operand.isReg()) | |
| continue; | |
| Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true); | |
| } | |
| } | |
| void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const { | |
| if (isPrefix(Inst) || isCFI(Inst)) | |
| return; | |
| if (isCall(Inst)) { | |
| BitVector CallRegs = BitVector(Regs.size(), false); | |
| getCalleeSavedRegs(CallRegs); | |
| CallRegs.flip(); | |
| Regs |= CallRegs; | |
| return; | |
| } | |
| if (isReturn(Inst)) { | |
| getDefaultLiveOut(Regs); | |
| return; | |
| } | |
| if (isRep(Inst)) | |
| getRepRegs(Regs); | |
| const MCInstrDesc &InstInfo = Info->get(Inst.getOpcode()); | |
| for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) | |
| Regs |= getAliases(ImplicitUse, /*OnlySmaller=*/true); | |
| for (const MCOperand &Operand : useOperands(Inst)) | |
| if (Operand.isReg()) | |
| Regs |= getAliases(Operand.getReg(), /*OnlySmaller=*/true); | |
| } | |
| bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const { | |
| const MCInstrDesc &InstInfo = Info->get(MI.getOpcode()); | |
| return InstInfo.hasDefOfPhysReg(MI, Reg, *RegInfo); | |
| } | |
| bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const { | |
| const MCInstrDesc &InstInfo = Info->get(MI.getOpcode()); | |
| for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I) | |
| if (MI.getOperand(I).isReg() && MI.getOperand(I).getReg() && | |
| RegInfo->isSubRegisterEq(Reg, MI.getOperand(I).getReg())) | |
| return true; | |
| for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) { | |
| if (ImplicitUse == Reg || RegInfo->isSubRegister(Reg, ImplicitUse)) | |
| return true; | |
| } | |
| return false; | |
| } | |
| const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg, | |
| bool OnlySmaller) const { | |
| if (OnlySmaller) | |
| return SmallerAliasMap[Reg]; | |
| return AliasMap[Reg]; | |
| } | |
| void MCPlusBuilder::initAliases() { | |
| assert(AliasMap.size() == 0 && SmallerAliasMap.size() == 0); | |
| // Build alias map | |
| for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) { | |
| BitVector BV(RegInfo->getNumRegs(), false); | |
| BV.set(I); | |
| AliasMap.emplace_back(BV); | |
| SmallerAliasMap.emplace_back(BV); | |
| } | |
| // Cache all aliases for each register | |
| for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I != E; ++I) { | |
| for (MCRegAliasIterator AI(I, RegInfo, true); AI.isValid(); ++AI) | |
| AliasMap[I].set(*AI); | |
| } | |
| // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister) | |
| for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I) | |
| for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI) | |
| SmallerAliasMap[I] |= SmallerAliasMap[*SI]; | |
| LLVM_DEBUG({ | |
| dbgs() << "Dumping reg alias table:\n"; | |
| for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) { | |
| dbgs() << "Reg " << I << ": "; | |
| const BitVector &BV = AliasMap[I]; | |
| int Idx = BV.find_first(); | |
| while (Idx != -1) { | |
| dbgs() << Idx << " "; | |
| Idx = BV.find_next(Idx); | |
| } | |
| dbgs() << "\n"; | |
| } | |
| }); | |
| } | |
| void MCPlusBuilder::initSizeMap() { | |
| SizeMap.resize(RegInfo->getNumRegs()); | |
| // Build size map | |
| for (const auto &RC : RegInfo->regclasses()) | |
| for (MCPhysReg Reg : RC) | |
| SizeMap[Reg] = RC.getSizeInBits() / 8; | |
| } | |
| bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum, | |
| const MCSymbol *Symbol, | |
| int64_t Addend, MCContext *Ctx, | |
| uint32_t RelType) const { | |
| MCOperand Operand; | |
| if (!Addend) { | |
| Operand = MCOperand::createExpr(getTargetExprFor( | |
| Inst, MCSymbolRefExpr::create(Symbol, *Ctx), *Ctx, RelType)); | |
| } else { | |
| Operand = MCOperand::createExpr(getTargetExprFor( | |
| Inst, | |
| MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, *Ctx), | |
| MCConstantExpr::create(Addend, *Ctx), *Ctx), | |
| *Ctx, RelType)); | |
| } | |
| Inst.getOperand(OpNum) = Operand; | |
| return true; | |
| } |