Index: llvm/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/include/llvm/CodeGen/AsmPrinter.h +++ llvm/include/llvm/CodeGen/AsmPrinter.h @@ -63,6 +63,7 @@ class MCSymbol; class MCTargetOptions; class MDNode; +class MMIAddrLabelMap; class Module; class PseudoProbeHandler; class raw_ostream; @@ -174,6 +175,10 @@ // function. This is used to calculate the size of the BB section. MCSymbol *CurrentSectionBeginSym = nullptr; + /// This map keeps track of which symbol is being used for the specified basic + /// block's address of label. + MMIAddrLabelMap *AddrLabelSymbols = nullptr; + // The garbage collection metadata printer table. void *GCMetadataPrinters = nullptr; // Really a DenseMap. @@ -262,6 +267,25 @@ // given basic block. MCSymbol *getMBBExceptionSym(const MachineBasicBlock &MBB); + /// Return the symbol to be used for the specified basic block when its + /// address is taken. This cannot be its normal LBB label because the block + /// may be accessed outside its containing function. + MCSymbol *getAddrLabelSymbol(const BasicBlock *BB) { + return getAddrLabelSymbolToEmit(BB).front(); + } + + /// Return the symbol to be used for the specified basic block when its + /// address is taken. If other blocks were RAUW'd to this one, we may have + /// to emit them as well, return the whole set. + ArrayRef getAddrLabelSymbolToEmit(const BasicBlock *BB); + + /// If the specified function has had any references to address-taken blocks + /// generated, but the block got deleted, return the symbol now so we can + /// emit it. This prevents emitting a reference to a symbol that has no + /// definition. + void takeDeletedSymbolsForFunction(const Function *F, + std::vector &Result); + /// Return information about object file lowering. const TargetLoweringObjectFile &getObjFileLowering() const; Index: llvm/include/llvm/CodeGen/MachineModuleInfo.h =================================================================== --- llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -45,7 +45,6 @@ class BasicBlock; class Function; class LLVMTargetMachine; -class MMIAddrLabelMap; class MachineFunction; class Module; class MCSymbol; @@ -106,10 +105,6 @@ /// \} - /// This map keeps track of which symbol is being used for the specified - /// basic block's address of label. - MMIAddrLabelMap *AddrLabelSymbols; - // TODO: Ideally, what we'd like is to have a switch that allows emitting // synchronous (precise at call-sites only) CFA into .eh_frame. However, // even under this switch, we'd like .debug_frame to be precise when using @@ -181,25 +176,6 @@ /// Returns true if valid debug info is present. bool hasDebugInfo() const { return DbgInfoAvailable; } - /// Return the symbol to be used for the specified basic block when its - /// address is taken. This cannot be its normal LBB label because the block - /// may be accessed outside its containing function. - MCSymbol *getAddrLabelSymbol(const BasicBlock *BB) { - return getAddrLabelSymbolToEmit(BB).front(); - } - - /// Return the symbol to be used for the specified basic block when its - /// address is taken. If other blocks were RAUW'd to this one, we may have - /// to emit them as well, return the whole set. - ArrayRef getAddrLabelSymbolToEmit(const BasicBlock *BB); - - /// If the specified function has had any references to address-taken blocks - /// generated, but the block got deleted, return the symbol now so we can - /// emit it. This prevents emitting a reference to a symbol that has no - /// definition. - void takeDeletedSymbolsForFunction(const Function *F, - std::vector &Result); - /// \name Exception Handling /// \{ Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -153,6 +153,178 @@ return *(gcp_map_type*)P; } +namespace { + +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; +}; +} // namespace + +namespace llvm { +class MMIAddrLabelMap { + MCContext &Context; + struct AddrLabelSymEntry { + /// The symbols for the label. + TinyPtrVector Symbols; + + Function *Fn; // The containing function of the BasicBlock. + unsigned Index; // The index in BBCallbacks for the BasicBlock. + }; + + DenseMap, 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 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, std::vector> + DeletedAddrLabelsNeedingEmission; + +public: + MMIAddrLabelMap(MCContext &context) : Context(context) {} + + ~MMIAddrLabelMap() { + assert(DeletedAddrLabelsNeedingEmission.empty() && + "Some labels for deleted blocks never got emitted"); + } + + ArrayRef getAddrLabelSymbolToEmit(BasicBlock *BB); + + void takeDeletedSymbolsForFunction(Function *F, + std::vector &Result); + + void UpdateForDeletedBlock(BasicBlock *BB); + void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New); +}; +} // namespace llvm + +ArrayRef 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(); + MCSymbol *Sym = BB->hasAddressTaken() ? Context.createNamedTempSymbol() + : Context.createTempSymbol(); + Entry.Symbols.push_back(Sym); + return Entry.Symbols; +} + +/// If we have any deleted symbols for F, return them. +void MMIAddrLabelMap::takeDeletedSymbolsForFunction( + Function *F, std::vector &Result) { + DenseMap, std::vector>::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); +} + +//===- Address of Block Management ----------------------------------------===// + +ArrayRef +AsmPrinter::getAddrLabelSymbolToEmit(const BasicBlock *BB) { + // Lazily create AddrLabelSymbols. + if (!AddrLabelSymbols) + AddrLabelSymbols = new MMIAddrLabelMap(OutContext); + return AddrLabelSymbols->getAddrLabelSymbolToEmit( + const_cast(BB)); +} + +void AsmPrinter::takeDeletedSymbolsForFunction( + const Function *F, std::vector &Result) { + // If no blocks have had their addresses taken, we're done. + if (!AddrLabelSymbols) + return; + return AddrLabelSymbols->takeDeletedSymbolsForFunction( + const_cast(F), Result); +} + +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. + llvm::append_range(NewEntry.Symbols, OldEntry.Symbols); +} + +void MMIAddrLabelMapCallbackPtr::deleted() { + Map->UpdateForDeletedBlock(cast(getValPtr())); +} + +void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) { + Map->UpdateForRAUWBlock(cast(getValPtr()), cast(V2)); +} + /// getGVAlignment - Return the alignment to use for the specified global /// value. This rounds up to the preferred alignment if possible and legal. Align AsmPrinter::getGVAlignment(const GlobalObject *GV, const DataLayout &DL, @@ -260,6 +432,8 @@ HasSplitStack = false; HasNoSplitStack = false; + AddrLabelSymbols = nullptr; + // Initialize TargetLoweringObjectFile. const_cast(getObjFileLowering()) .Initialize(OutContext, TM); @@ -802,7 +976,7 @@ // references to the dangling symbols. Emit them at the start of the function // so that we don't get references to undefined symbols. std::vector DeadBlockSyms; - MMI->takeDeletedSymbolsForFunction(&F, DeadBlockSyms); + takeDeletedSymbolsForFunction(&F, DeadBlockSyms); for (MCSymbol *DeadBlockSym : DeadBlockSyms) { OutStreamer->AddComment("Address taken block that was later removed"); OutStreamer->emitLabel(DeadBlockSym); @@ -1956,6 +2130,8 @@ emitEndOfAsmFile(M); MMI = nullptr; + delete AddrLabelSymbols; + AddrLabelSymbols = nullptr; OutStreamer->Finish(); OutStreamer->reset(); @@ -3147,11 +3323,12 @@ } MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const { - return MMI->getAddrLabelSymbol(BA->getBasicBlock()); + return const_cast(this)->getAddrLabelSymbol( + BA->getBasicBlock()); } MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const { - return MMI->getAddrLabelSymbol(BB); + return const_cast(this)->getAddrLabelSymbol(BB); } /// GetCPISymbol - Return the symbol for the specified constant pool entry. @@ -3310,7 +3487,7 @@ // MBBs can have their address taken as part of CodeGen without having // their corresponding BB's address taken in IR if (BB && BB->hasAddressTaken()) - for (MCSymbol *Sym : MMI->getAddrLabelSymbolToEmit(BB)) + for (MCSymbol *Sym : getAddrLabelSymbolToEmit(BB)) OutStreamer->emitLabel(Sym); } Index: llvm/lib/CodeGen/MachineModuleInfo.cpp =================================================================== --- llvm/lib/CodeGen/MachineModuleInfo.cpp +++ llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -46,168 +46,19 @@ 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 Symbols; - - Function *Fn; // The containing function of the BasicBlock. - unsigned Index; // The index in BBCallbacks for the BasicBlock. - }; - - DenseMap, 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 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, std::vector> - DeletedAddrLabelsNeedingEmission; - -public: - MMIAddrLabelMap(MCContext &context) : Context(context) {} - - ~MMIAddrLabelMap() { - assert(DeletedAddrLabelsNeedingEmission.empty() && - "Some labels for deleted blocks never got emitted"); - } - - ArrayRef getAddrLabelSymbolToEmit(BasicBlock *BB); - - void takeDeletedSymbolsForFunction(Function *F, - std::vector &Result); - - void UpdateForDeletedBlock(BasicBlock *BB); - void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New); -}; } // end namespace llvm -ArrayRef 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(); - MCSymbol *Sym = BB->hasAddressTaken() ? Context.createNamedTempSymbol() - : Context.createTempSymbol(); - Entry.Symbols.push_back(Sym); - return Entry.Symbols; -} - -/// If we have any deleted symbols for F, return them. -void MMIAddrLabelMap:: -takeDeletedSymbolsForFunction(Function *F, std::vector &Result) { - DenseMap, std::vector>::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. - llvm::append_range(NewEntry.Symbols, OldEntry.Symbols); -} - -void MMIAddrLabelMapCallbackPtr::deleted() { - Map->UpdateForDeletedBlock(cast(getValPtr())); -} - -void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) { - Map->UpdateForRAUWBlock(cast(getValPtr()), cast(V2)); -} - void MachineModuleInfo::initialize() { ObjFileMMI = nullptr; CurCallSite = 0; NextFnNum = 0; - AddrLabelSymbols = nullptr; DbgInfoAvailable = false; } void MachineModuleInfo::finalize() { Personalities.clear(); - delete AddrLabelSymbols; - AddrLabelSymbols = nullptr; - Context.reset(); // We don't clear the ExternalContext. @@ -224,7 +75,6 @@ Context.setObjectFileInfo(MMI.TM.getObjFileLowering()); ObjFileMMI = MMI.ObjFileMMI; CurCallSite = MMI.CurCallSite; - AddrLabelSymbols = MMI.AddrLabelSymbols; ExternalContext = MMI.ExternalContext; TheModule = MMI.TheModule; } @@ -249,25 +99,6 @@ MachineModuleInfo::~MachineModuleInfo() { finalize(); } -//===- Address of Block Management ----------------------------------------===// - -ArrayRef -MachineModuleInfo::getAddrLabelSymbolToEmit(const BasicBlock *BB) { - // Lazily create AddrLabelSymbols. - if (!AddrLabelSymbols) - AddrLabelSymbols = new MMIAddrLabelMap(getContext()); - return AddrLabelSymbols->getAddrLabelSymbolToEmit(const_cast(BB)); -} - -void MachineModuleInfo:: -takeDeletedSymbolsForFunction(const Function *F, - std::vector &Result) { - // If no blocks have had their addresses taken, we're done. - if (!AddrLabelSymbols) return; - return AddrLabelSymbols-> - takeDeletedSymbolsForFunction(const_cast(F), Result); -} - /// \name Exception Handling /// \{