diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) |
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp b/contrib/llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp new file mode 100644 index 000000000000..2e720018262c --- /dev/null +++ b/contrib/llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -0,0 +1,329 @@ +//===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/TinyPtrVector.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Pass.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include <algorithm> +#include <cassert> +#include <memory> +#include <utility> +#include <vector> + +using namespace llvm; +using namespace llvm::dwarf; + +// Handle the Pass registration stuff necessary to use DataLayout's. +INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo", + "Machine Module Information", false, false) +char MachineModuleInfo::ID = 0; + +// Out of line virtual method. +MachineModuleInfoImpl::~MachineModuleInfoImpl() = default; + +namespace llvm { + +class MMIAddrLabelMapCallbackPtr final : CallbackVH { + MMIAddrLabelMap *Map = nullptr; + +public: + MMIAddrLabelMapCallbackPtr() = default; + MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V) {} + + void setPtr(BasicBlock *BB) { + ValueHandleBase::operator=(BB); + } + + void setMap(MMIAddrLabelMap *map) { Map = map; } + + void deleted() override; + void allUsesReplacedWith(Value *V2) override; +}; + +class MMIAddrLabelMap { + MCContext &Context; + struct AddrLabelSymEntry { + /// The symbols for the label. + TinyPtrVector<MCSymbol *> Symbols; + + Function *Fn; // The containing function of the BasicBlock. + unsigned Index; // The index in BBCallbacks for the BasicBlock. + }; + + DenseMap<AssertingVH<BasicBlock>, AddrLabelSymEntry> AddrLabelSymbols; + + /// Callbacks for the BasicBlock's that we have entries for. We use this so + /// we get notified if a block is deleted or RAUWd. + std::vector<MMIAddrLabelMapCallbackPtr> BBCallbacks; + + /// This is a per-function list of symbols whose corresponding BasicBlock got + /// deleted. These symbols need to be emitted at some point in the file, so + /// AsmPrinter emits them after the function body. + DenseMap<AssertingVH<Function>, std::vector<MCSymbol*>> + DeletedAddrLabelsNeedingEmission; + +public: + MMIAddrLabelMap(MCContext &context) : Context(context) {} + + ~MMIAddrLabelMap() { + assert(DeletedAddrLabelsNeedingEmission.empty() && + "Some labels for deleted blocks never got emitted"); + } + + ArrayRef<MCSymbol *> getAddrLabelSymbolToEmit(BasicBlock *BB); + + void takeDeletedSymbolsForFunction(Function *F, + std::vector<MCSymbol*> &Result); + + void UpdateForDeletedBlock(BasicBlock *BB); + void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New); +}; + +} // end namespace llvm + +ArrayRef<MCSymbol *> MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) { + assert(BB->hasAddressTaken() && + "Shouldn't get label for block without address taken"); + AddrLabelSymEntry &Entry = AddrLabelSymbols[BB]; + + // If we already had an entry for this block, just return it. + if (!Entry.Symbols.empty()) { + assert(BB->getParent() == Entry.Fn && "Parent changed"); + return Entry.Symbols; + } + + // Otherwise, this is a new entry, create a new symbol for it and add an + // entry to BBCallbacks so we can be notified if the BB is deleted or RAUWd. + BBCallbacks.emplace_back(BB); + BBCallbacks.back().setMap(this); + Entry.Index = BBCallbacks.size() - 1; + Entry.Fn = BB->getParent(); + Entry.Symbols.push_back(Context.createTempSymbol(!BB->hasAddressTaken())); + return Entry.Symbols; +} + +/// If we have any deleted symbols for F, return them. +void MMIAddrLabelMap:: +takeDeletedSymbolsForFunction(Function *F, std::vector<MCSymbol*> &Result) { + DenseMap<AssertingVH<Function>, std::vector<MCSymbol*>>::iterator I = + DeletedAddrLabelsNeedingEmission.find(F); + + // If there are no entries for the function, just return. + if (I == DeletedAddrLabelsNeedingEmission.end()) return; + + // Otherwise, take the list. + std::swap(Result, I->second); + DeletedAddrLabelsNeedingEmission.erase(I); +} + +void MMIAddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) { + // If the block got deleted, there is no need for the symbol. If the symbol + // was already emitted, we can just forget about it, otherwise we need to + // queue it up for later emission when the function is output. + AddrLabelSymEntry Entry = std::move(AddrLabelSymbols[BB]); + AddrLabelSymbols.erase(BB); + assert(!Entry.Symbols.empty() && "Didn't have a symbol, why a callback?"); + BBCallbacks[Entry.Index] = nullptr; // Clear the callback. + + assert((BB->getParent() == nullptr || BB->getParent() == Entry.Fn) && + "Block/parent mismatch"); + + for (MCSymbol *Sym : Entry.Symbols) { + if (Sym->isDefined()) + return; + + // If the block is not yet defined, we need to emit it at the end of the + // function. Add the symbol to the DeletedAddrLabelsNeedingEmission list + // for the containing Function. Since the block is being deleted, its + // parent may already be removed, we have to get the function from 'Entry'. + DeletedAddrLabelsNeedingEmission[Entry.Fn].push_back(Sym); + } +} + +void MMIAddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) { + // Get the entry for the RAUW'd block and remove it from our map. + AddrLabelSymEntry OldEntry = std::move(AddrLabelSymbols[Old]); + AddrLabelSymbols.erase(Old); + assert(!OldEntry.Symbols.empty() && "Didn't have a symbol, why a callback?"); + + AddrLabelSymEntry &NewEntry = AddrLabelSymbols[New]; + + // If New is not address taken, just move our symbol over to it. + if (NewEntry.Symbols.empty()) { + BBCallbacks[OldEntry.Index].setPtr(New); // Update the callback. + NewEntry = std::move(OldEntry); // Set New's entry. + return; + } + + BBCallbacks[OldEntry.Index] = nullptr; // Update the callback. + + // Otherwise, we need to add the old symbols to the new block's set. + NewEntry.Symbols.insert(NewEntry.Symbols.end(), OldEntry.Symbols.begin(), + OldEntry.Symbols.end()); +} + +void MMIAddrLabelMapCallbackPtr::deleted() { + Map->UpdateForDeletedBlock(cast<BasicBlock>(getValPtr())); +} + +void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) { + Map->UpdateForRAUWBlock(cast<BasicBlock>(getValPtr()), cast<BasicBlock>(V2)); +} + +MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM) + : ImmutablePass(ID), TM(*TM), + Context(TM->getMCAsmInfo(), TM->getMCRegisterInfo(), + TM->getObjFileLowering(), nullptr, false) { + initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry()); +} + +MachineModuleInfo::~MachineModuleInfo() = default; + +bool MachineModuleInfo::doInitialization(Module &M) { + ObjFileMMI = nullptr; + CurCallSite = 0; + UsesMSVCFloatingPoint = UsesMorestackAddr = false; + HasSplitStack = HasNosplitStack = false; + AddrLabelSymbols = nullptr; + TheModule = &M; + DbgInfoAvailable = !llvm::empty(M.debug_compile_units()); + return false; +} + +bool MachineModuleInfo::doFinalization(Module &M) { + Personalities.clear(); + + delete AddrLabelSymbols; + AddrLabelSymbols = nullptr; + + Context.reset(); + + delete ObjFileMMI; + ObjFileMMI = nullptr; + + return false; +} + +//===- Address of Block Management ----------------------------------------===// + +ArrayRef<MCSymbol *> +MachineModuleInfo::getAddrLabelSymbolToEmit(const BasicBlock *BB) { + // Lazily create AddrLabelSymbols. + if (!AddrLabelSymbols) + AddrLabelSymbols = new MMIAddrLabelMap(Context); + return AddrLabelSymbols->getAddrLabelSymbolToEmit(const_cast<BasicBlock*>(BB)); +} + +void MachineModuleInfo:: +takeDeletedSymbolsForFunction(const Function *F, + std::vector<MCSymbol*> &Result) { + // If no blocks have had their addresses taken, we're done. + if (!AddrLabelSymbols) return; + return AddrLabelSymbols-> + takeDeletedSymbolsForFunction(const_cast<Function*>(F), Result); +} + +/// \name Exception Handling +/// \{ + +void MachineModuleInfo::addPersonality(const Function *Personality) { + for (unsigned i = 0; i < Personalities.size(); ++i) + if (Personalities[i] == Personality) + return; + Personalities.push_back(Personality); +} + +/// \} + +MachineFunction * +MachineModuleInfo::getMachineFunction(const Function &F) const { + auto I = MachineFunctions.find(&F); + return I != MachineFunctions.end() ? I->second.get() : nullptr; +} + +MachineFunction & +MachineModuleInfo::getOrCreateMachineFunction(const Function &F) { + // Shortcut for the common case where a sequence of MachineFunctionPasses + // all query for the same Function. + if (LastRequest == &F) + return *LastResult; + + auto I = MachineFunctions.insert( + std::make_pair(&F, std::unique_ptr<MachineFunction>())); + MachineFunction *MF; + if (I.second) { + // No pre-existing machine function, create a new one. + const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F); + MF = new MachineFunction(F, TM, STI, NextFnNum++, *this); + // Update the set entry. + I.first->second.reset(MF); + } else { + MF = I.first->second.get(); + } + + LastRequest = &F; + LastResult = MF; + return *MF; +} + +void MachineModuleInfo::deleteMachineFunctionFor(Function &F) { + MachineFunctions.erase(&F); + LastRequest = nullptr; + LastResult = nullptr; +} + +namespace { + +/// This pass frees the MachineFunction object associated with a Function. +class FreeMachineFunction : public FunctionPass { +public: + static char ID; + + FreeMachineFunction() : FunctionPass(ID) {} + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired<MachineModuleInfo>(); + AU.addPreserved<MachineModuleInfo>(); + } + + bool runOnFunction(Function &F) override { + MachineModuleInfo &MMI = getAnalysis<MachineModuleInfo>(); + MMI.deleteMachineFunctionFor(F); + return true; + } + + StringRef getPassName() const override { + return "Free MachineFunction"; + } +}; + +} // end anonymous namespace + +char FreeMachineFunction::ID; + +FunctionPass *llvm::createFreeMachineFunctionPass() { + return new FreeMachineFunction(); +} |