summaryrefslogtreecommitdiff
path: root/lib/CodeGen/MachineModuleInfo.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-03-16 00:29:39 +0000
committerChris Lattner <sabre@nondot.org>2010-03-16 00:29:39 +0000
commit999aee24c7b7511575146b9950bb85830fab0378 (patch)
tree56d7c9f3f6bf51422f9c4f96c0803f39db59102a /lib/CodeGen/MachineModuleInfo.cpp
parent4e815f8a8cae6c846cdca52420046cab902865de (diff)
downloadllvm-999aee24c7b7511575146b9950bb85830fab0378.tar.gz
llvm-999aee24c7b7511575146b9950bb85830fab0378.tar.bz2
llvm-999aee24c7b7511575146b9950bb85830fab0378.tar.xz
Fix the third (and last known) case of code update problems due
to LLVM IR changes with addr label weirdness. In the testcase, we generate references to the two bb's when codegen'ing the first function: _test1: ## @test1 leaq Ltmp0(%rip), %rax .. leaq Ltmp1(%rip), %rax Then continue to codegen the second function where the blocks get merged. We're now smart enough to emit both labels, producing this code: _test_fun: ## @test_fun ## BB#0: ## %entry Ltmp1: ## Block address taken Ltmp0: ## BB#1: ## %ret movl $-1, %eax ret Rejoice. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98595 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/MachineModuleInfo.cpp')
-rw-r--r--lib/CodeGen/MachineModuleInfo.cpp133
1 files changed, 112 insertions, 21 deletions
diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp
index b18e34c0d8..af48e9ebb5 100644
--- a/lib/CodeGen/MachineModuleInfo.cpp
+++ b/lib/CodeGen/MachineModuleInfo.cpp
@@ -23,6 +23,7 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@@ -52,7 +53,10 @@ public:
class MMIAddrLabelMap {
MCContext &Context;
struct AddrLabelSymEntry {
- MCSymbol *Sym; // The symbol for the label.
+ /// Symbols - The symbols for the label. This is a pointer union that is
+ /// either one symbol (the common case) or a list of symbols.
+ PointerUnion<MCSymbol *, std::vector<MCSymbol*>*> Symbols;
+
Function *Fn; // The containing function of the BasicBlock.
unsigned Index; // The index in BBCallbacks for the BasicBlock.
};
@@ -75,9 +79,17 @@ public:
~MMIAddrLabelMap() {
assert(DeletedAddrLabelsNeedingEmission.empty() &&
"Some labels for deleted blocks never got emitted");
+
+ // Deallocate any of the 'list of symbols' case.
+ for (DenseMap<AssertingVH<BasicBlock>, AddrLabelSymEntry>::iterator
+ I = AddrLabelSymbols.begin(), E = AddrLabelSymbols.end(); I != E; ++I)
+ if (I->second.Symbols.is<std::vector<MCSymbol*>*>())
+ delete I->second.Symbols.get<std::vector<MCSymbol*>*>();
}
- MCSymbol *getAddrLabelSymbol(BasicBlock *BB);
+ MCSymbol *getAddrLabelSymbol(BasicBlock *BB);
+ std::vector<MCSymbol*> getAddrLabelSymbolToEmit(BasicBlock *BB);
+
void takeDeletedSymbolsForFunction(Function *F,
std::vector<MCSymbol*> &Result);
@@ -92,9 +104,11 @@ MCSymbol *MMIAddrLabelMap::getAddrLabelSymbol(BasicBlock *BB) {
AddrLabelSymEntry &Entry = AddrLabelSymbols[BB];
// If we already had an entry for this block, just return it.
- if (Entry.Sym) {
+ if (!Entry.Symbols.isNull()) {
assert(BB->getParent() == Entry.Fn && "Parent changed");
- return Entry.Sym;
+ if (Entry.Symbols.is<MCSymbol*>())
+ return Entry.Symbols.get<MCSymbol*>();
+ return (*Entry.Symbols.get<std::vector<MCSymbol*>*>())[0];
}
// Otherwise, this is a new entry, create a new symbol for it and add an
@@ -103,9 +117,30 @@ MCSymbol *MMIAddrLabelMap::getAddrLabelSymbol(BasicBlock *BB) {
BBCallbacks.back().setMap(this);
Entry.Index = BBCallbacks.size()-1;
Entry.Fn = BB->getParent();
- return Entry.Sym = Context.CreateTempSymbol();
+ MCSymbol *Result = Context.CreateTempSymbol();
+ Entry.Symbols = Result;
+ return Result;
+}
+
+std::vector<MCSymbol*>
+MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) {
+ assert(BB->hasAddressTaken() &&
+ "Shouldn't get label for block without address taken");
+ AddrLabelSymEntry &Entry = AddrLabelSymbols[BB];
+
+ std::vector<MCSymbol*> Result;
+
+ // If we already had an entry for this block, just return it.
+ if (Entry.Symbols.isNull())
+ Result.push_back(getAddrLabelSymbol(BB));
+ else if (MCSymbol *Sym = Entry.Symbols.dyn_cast<MCSymbol*>())
+ Result.push_back(Sym);
+ else
+ Result = *Entry.Symbols.get<std::vector<MCSymbol*>*>();
+ return Result;
}
+
/// takeDeletedSymbolsForFunction - If we have any deleted symbols for F, return
/// them.
void MMIAddrLabelMap::
@@ -128,36 +163,80 @@ void MMIAddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) {
// queue it up for later emission when the function is output.
AddrLabelSymEntry Entry = AddrLabelSymbols[BB];
AddrLabelSymbols.erase(BB);
- assert(Entry.Sym && "Didn't have a symbol, why a callback?");
+ assert(!Entry.Symbols.isNull() && "Didn't have a symbol, why a callback?");
BBCallbacks[Entry.Index] = 0; // Clear the callback.
- if (Entry.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'.
assert((BB->getParent() == 0 || BB->getParent() == Entry.Fn) &&
"Block/parent mismatch");
+
+ // Handle both the single and the multiple symbols cases.
+ if (MCSymbol *Sym = Entry.Symbols.dyn_cast<MCSymbol*>()) {
+ if (Sym->isDefined())
+ return;
- DeletedAddrLabelsNeedingEmission[Entry.Fn].push_back(Entry.Sym);
+ // 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);
+ } else {
+ std::vector<MCSymbol*> *Syms = Entry.Symbols.get<std::vector<MCSymbol*>*>();
+
+ for (unsigned i = 0, e = Syms->size(); i != e; ++i) {
+ MCSymbol *Sym = (*Syms)[i];
+ if (Sym->isDefined()) continue; // Ignore already emitted labels.
+
+ // 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);
+ }
+
+ // The entry is deleted, free the memory associated with the symbol list.
+ delete Syms;
+ }
}
void MMIAddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) {
// Get the entry for the RAUW'd block and remove it from our map.
AddrLabelSymEntry OldEntry = AddrLabelSymbols[Old];
AddrLabelSymbols.erase(Old);
- assert(OldEntry.Sym && "Didn't have a symbol, why a callback?");
-
+ assert(!OldEntry.Symbols.isNull() && "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 (!AddrLabelSymbols.count(New)) {
+ if (NewEntry.Symbols.isNull()) {
BBCallbacks[OldEntry.Index] = New; // Update the callback.
- AddrLabelSymbols[New] = OldEntry; // Set New's entry.
- } else {
- assert(0 && "Case not handled yet!");
- abort();
+ NewEntry = OldEntry; // Set New's entry.
+ return;
}
+
+ BBCallbacks[OldEntry.Index] = 0; // Update the callback.
+
+ // Otherwise, we need to add the old symbol to the new block's set. If it is
+ // just a single entry, upgrade it to a symbol list.
+ if (MCSymbol *PrevSym = NewEntry.Symbols.dyn_cast<MCSymbol*>()) {
+ std::vector<MCSymbol*> *SymList = new std::vector<MCSymbol*>();
+ SymList->push_back(PrevSym);
+ NewEntry.Symbols = SymList;
+ }
+
+ std::vector<MCSymbol*> *SymList =
+ NewEntry.Symbols.get<std::vector<MCSymbol*>*>();
+
+ // If the old entry was a single symbol, add it.
+ if (MCSymbol *Sym = OldEntry.Symbols.dyn_cast<MCSymbol*>()) {
+ SymList->push_back(Sym);
+ return;
+ }
+
+ // Otherwise, concatenate the list.
+ std::vector<MCSymbol*> *Syms =OldEntry.Symbols.get<std::vector<MCSymbol*>*>();
+ SymList->insert(SymList->end(), Syms->begin(), Syms->end());
+ delete Syms;
}
@@ -260,6 +339,18 @@ MCSymbol *MachineModuleInfo::getAddrLabelSymbol(const BasicBlock *BB) {
return AddrLabelSymbols->getAddrLabelSymbol(const_cast<BasicBlock*>(BB));
}
+/// getAddrLabelSymbolToEmit - 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.
+std::vector<MCSymbol*> MachineModuleInfo::
+getAddrLabelSymbolToEmit(const BasicBlock *BB) {
+ // Lazily create AddrLabelSymbols.
+ if (AddrLabelSymbols == 0)
+ AddrLabelSymbols = new MMIAddrLabelMap(Context);
+ return AddrLabelSymbols->getAddrLabelSymbolToEmit(const_cast<BasicBlock*>(BB));
+}
+
+
/// takeDeletedSymbolsForFunction - 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