diff --git a/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/llvm/include/llvm/CodeGen/MachineModuleInfo.h --- a/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -243,6 +243,13 @@ /// 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 /// \{ diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -791,6 +791,16 @@ // their wild and crazy things as required. emitFunctionEntryLabel(); + // If the function had address-taken blocks that got deleted, then we have + // 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); + for (unsigned i = 0, e = DeadBlockSyms.size(); i != e; ++i) { + OutStreamer->AddComment("Address taken block that was later removed"); + OutStreamer->emitLabel(DeadBlockSyms[i]); + } + if (CurrentFnBegin) { if (MAI->useAssignmentForEHBegin()) { MCSymbol *CurPos = OutContext.createTempSymbol(); diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -78,11 +78,25 @@ /// 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); }; @@ -112,6 +126,21 @@ 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 @@ -124,8 +153,16 @@ assert((BB->getParent() == nullptr || BB->getParent() == Entry.Fn) && "Block/parent mismatch"); - assert(llvm::all_of(Entry.Symbols, [](MCSymbol *Sym) { - return Sym->isDefined(); })); + 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) { @@ -220,6 +257,15 @@ 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 /// \{ diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -924,7 +924,6 @@ void TargetPassConfig::addCodeGenPrepare() { if (getOptLevel() != CodeGenOpt::None && !DisableCGP) addPass(createCodeGenPreparePass()); - addPass(createRewriteSymbolsPass()); } /// Add common passes that perform LLVM IR to IR transforms in preparation for diff --git a/llvm/test/CodeGen/AArch64/O0-pipeline.ll b/llvm/test/CodeGen/AArch64/O0-pipeline.ll --- a/llvm/test/CodeGen/AArch64/O0-pipeline.ll +++ b/llvm/test/CodeGen/AArch64/O0-pipeline.ll @@ -24,8 +24,6 @@ ; CHECK-NEXT: Scalarize Masked Memory Intrinsics ; CHECK-NEXT: Expand reduction intrinsics ; CHECK-NEXT: AArch64 Stack Tagging -; CHECK-NEXT: Rewrite Symbols -; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Exception handling preparation ; CHECK-NEXT: Safe Stack instrumentation pass ; CHECK-NEXT: Insert stack protectors diff --git a/llvm/test/CodeGen/AArch64/O3-pipeline.ll b/llvm/test/CodeGen/AArch64/O3-pipeline.ll --- a/llvm/test/CodeGen/AArch64/O3-pipeline.ll +++ b/llvm/test/CodeGen/AArch64/O3-pipeline.ll @@ -76,8 +76,6 @@ ; CHECK-NEXT: Interleaved Access Pass ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: CodeGen Prepare -; CHECK-NEXT: Rewrite Symbols -; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Exception handling preparation ; CHECK-NEXT: AArch64 Promote Constant diff --git a/llvm/test/CodeGen/ARM/O3-pipeline.ll b/llvm/test/CodeGen/ARM/O3-pipeline.ll --- a/llvm/test/CodeGen/ARM/O3-pipeline.ll +++ b/llvm/test/CodeGen/ARM/O3-pipeline.ll @@ -49,8 +49,6 @@ ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: CodeGen Prepare -; CHECK-NEXT: Rewrite Symbols -; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Exception handling preparation ; CHECK-NEXT: Merge internal globals diff --git a/llvm/test/CodeGen/Generic/addr-label.ll b/llvm/test/CodeGen/Generic/addr-label.ll --- a/llvm/test/CodeGen/Generic/addr-label.ll +++ b/llvm/test/CodeGen/Generic/addr-label.ll @@ -16,7 +16,7 @@ } -;; Issues with referring to a label that gets RAUW'd later. +; Issues with referring to a label that gets RAUW'd later. define i32 @test2a() nounwind { entry: %target = bitcast i8* blockaddress(@test2b, %test_label) to i8* diff --git a/llvm/test/CodeGen/X86/O0-pipeline.ll b/llvm/test/CodeGen/X86/O0-pipeline.ll --- a/llvm/test/CodeGen/X86/O0-pipeline.ll +++ b/llvm/test/CodeGen/X86/O0-pipeline.ll @@ -28,8 +28,6 @@ ; CHECK-NEXT: Scalarize Masked Memory Intrinsics ; CHECK-NEXT: Expand reduction intrinsics ; CHECK-NEXT: Expand indirectbr instructions -; CHECK-NEXT: Rewrite Symbols -; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Exception handling preparation ; CHECK-NEXT: Safe Stack instrumentation pass ; CHECK-NEXT: Insert stack protectors diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll --- a/llvm/test/CodeGen/X86/opt-pipeline.ll +++ b/llvm/test/CodeGen/X86/opt-pipeline.ll @@ -61,8 +61,6 @@ ; CHECK-NEXT: Expand indirectbr instructions ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: CodeGen Prepare -; CHECK-NEXT: Rewrite Symbols -; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Dominator Tree Construction ; CHECK-NEXT: Exception handling preparation ; CHECK-NEXT: Safe Stack instrumentation pass diff --git a/llvm/test/CodeGen/X86/select_meta.ll b/llvm/test/CodeGen/X86/select_meta.ll --- a/llvm/test/CodeGen/X86/select_meta.ll +++ b/llvm/test/CodeGen/X86/select_meta.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=x86_64-unknown-unknown -print-after-all < %s 2>&1 | FileCheck %s +; RUN: opt -mtriple=x86_64-unknown-unknown -codegenprepare -S < %s 2>&1 | FileCheck %s ; Function Attrs: norecurse nounwind readnone uwtable define i32 @foo(i32, i32, i32) { diff --git a/llvm/test/Other/2010-05-06-Printer.ll b/llvm/test/Other/2010-05-06-Printer.ll --- a/llvm/test/Other/2010-05-06-Printer.ll +++ b/llvm/test/Other/2010-05-06-Printer.ll @@ -10,10 +10,8 @@ ret void } -;ALL-NOT: IR Dump After {{.*}}; ModuleID = ;ALL: define void @tester() ;ALL: define void @foo() -;ALL: ModuleID = ;FOO: IR Dump After ;FOO-NEXT: define void @foo()