MachineModuleInfo.cpp [plain text]
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
using namespace llvm::dwarf;
INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo",
"Machine Module Information", false, false)
char MachineModuleInfo::ID = 0;
MachineModuleInfoImpl::~MachineModuleInfoImpl() {}
namespace llvm {
class MMIAddrLabelMapCallbackPtr : CallbackVH {
MMIAddrLabelMap *Map;
public:
MMIAddrLabelMapCallbackPtr() : Map(0) {}
MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V), Map(0) {}
void setPtr(BasicBlock *BB) {
ValueHandleBase::operator=(BB);
}
void setMap(MMIAddrLabelMap *map) { Map = map; }
virtual void deleted();
virtual void allUsesReplacedWith(Value *V2);
};
class MMIAddrLabelMap {
MCContext &Context;
struct AddrLabelSymEntry {
PointerUnion<MCSymbol *, std::vector<MCSymbol*>*> Symbols;
Function *Fn; unsigned Index; };
DenseMap<AssertingVH<BasicBlock>, AddrLabelSymEntry> AddrLabelSymbols;
std::vector<MMIAddrLabelMapCallbackPtr> BBCallbacks;
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");
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);
std::vector<MCSymbol*> getAddrLabelSymbolToEmit(BasicBlock *BB);
void takeDeletedSymbolsForFunction(Function *F,
std::vector<MCSymbol*> &Result);
void UpdateForDeletedBlock(BasicBlock *BB);
void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New);
};
}
MCSymbol *MMIAddrLabelMap::getAddrLabelSymbol(BasicBlock *BB) {
assert(BB->hasAddressTaken() &&
"Shouldn't get label for block without address taken");
AddrLabelSymEntry &Entry = AddrLabelSymbols[BB];
if (!Entry.Symbols.isNull()) {
assert(BB->getParent() == Entry.Fn && "Parent changed");
if (Entry.Symbols.is<MCSymbol*>())
return Entry.Symbols.get<MCSymbol*>();
return (*Entry.Symbols.get<std::vector<MCSymbol*>*>())[0];
}
BBCallbacks.push_back(BB);
BBCallbacks.back().setMap(this);
Entry.Index = BBCallbacks.size()-1;
Entry.Fn = BB->getParent();
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 (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;
}
void MMIAddrLabelMap::
takeDeletedSymbolsForFunction(Function *F, std::vector<MCSymbol*> &Result) {
DenseMap<AssertingVH<Function>, std::vector<MCSymbol*> >::iterator I =
DeletedAddrLabelsNeedingEmission.find(F);
if (I == DeletedAddrLabelsNeedingEmission.end()) return;
std::swap(Result, I->second);
DeletedAddrLabelsNeedingEmission.erase(I);
}
void MMIAddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) {
AddrLabelSymEntry Entry = AddrLabelSymbols[BB];
AddrLabelSymbols.erase(BB);
assert(!Entry.Symbols.isNull() && "Didn't have a symbol, why a callback?");
BBCallbacks[Entry.Index] = 0;
assert((BB->getParent() == 0 || BB->getParent() == Entry.Fn) &&
"Block/parent mismatch");
if (MCSymbol *Sym = Entry.Symbols.dyn_cast<MCSymbol*>()) {
if (Sym->isDefined())
return;
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;
DeletedAddrLabelsNeedingEmission[Entry.Fn].push_back(Sym);
}
delete Syms;
}
}
void MMIAddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) {
AddrLabelSymEntry OldEntry = AddrLabelSymbols[Old];
AddrLabelSymbols.erase(Old);
assert(!OldEntry.Symbols.isNull() && "Didn't have a symbol, why a callback?");
AddrLabelSymEntry &NewEntry = AddrLabelSymbols[New];
if (NewEntry.Symbols.isNull()) {
BBCallbacks[OldEntry.Index].setPtr(New); NewEntry = OldEntry; return;
}
BBCallbacks[OldEntry.Index] = 0;
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 (MCSymbol *Sym = OldEntry.Symbols.dyn_cast<MCSymbol*>()) {
SymList->push_back(Sym);
return;
}
std::vector<MCSymbol*> *Syms =OldEntry.Symbols.get<std::vector<MCSymbol*>*>();
SymList->insert(SymList->end(), Syms->begin(), Syms->end());
delete Syms;
}
void MMIAddrLabelMapCallbackPtr::deleted() {
Map->UpdateForDeletedBlock(cast<BasicBlock>(getValPtr()));
}
void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) {
Map->UpdateForRAUWBlock(cast<BasicBlock>(getValPtr()), cast<BasicBlock>(V2));
}
MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI,
const MCRegisterInfo &MRI,
const MCObjectFileInfo *MOFI)
: ImmutablePass(ID), Context(&MAI, &MRI, MOFI, 0, false) {
initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry());
}
MachineModuleInfo::MachineModuleInfo()
: ImmutablePass(ID), Context(0, 0, 0) {
llvm_unreachable("This MachineModuleInfo constructor should never be called, "
"MMI should always be explicitly constructed by "
"LLVMTargetMachine");
}
MachineModuleInfo::~MachineModuleInfo() {
}
bool MachineModuleInfo::doInitialization(Module &M) {
ObjFileMMI = 0;
CompactUnwindEncoding = 0;
CurCallSite = 0;
CallsEHReturn = 0;
CallsUnwindInit = 0;
DbgInfoAvailable = UsesVAFloatArgument = false;
Personalities.push_back(NULL);
AddrLabelSymbols = 0;
TheModule = 0;
return false;
}
bool MachineModuleInfo::doFinalization(Module &M) {
Personalities.clear();
delete AddrLabelSymbols;
AddrLabelSymbols = 0;
Context.reset();
delete ObjFileMMI;
ObjFileMMI = 0;
return false;
}
void MachineModuleInfo::EndFunction() {
FrameInstructions.clear();
LandingPads.clear();
CallSiteMap.clear();
TypeInfos.clear();
FilterIds.clear();
FilterEnds.clear();
CallsEHReturn = 0;
CallsUnwindInit = 0;
CompactUnwindEncoding = 0;
VariableDbgInfo.clear();
}
void MachineModuleInfo::AnalyzeModule(const Module &M) {
const GlobalVariable *GV = M.getGlobalVariable("llvm.used");
if (!GV || !GV->hasInitializer()) return;
const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer());
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
if (const Function *F =
dyn_cast<Function>(InitList->getOperand(i)->stripPointerCasts()))
UsedFunctions.insert(F);
}
MCSymbol *MachineModuleInfo::getAddrLabelSymbol(const BasicBlock *BB) {
if (AddrLabelSymbols == 0)
AddrLabelSymbols = new MMIAddrLabelMap(Context);
return AddrLabelSymbols->getAddrLabelSymbol(const_cast<BasicBlock*>(BB));
}
std::vector<MCSymbol*> MachineModuleInfo::
getAddrLabelSymbolToEmit(const BasicBlock *BB) {
if (AddrLabelSymbols == 0)
AddrLabelSymbols = new MMIAddrLabelMap(Context);
return AddrLabelSymbols->getAddrLabelSymbolToEmit(const_cast<BasicBlock*>(BB));
}
void MachineModuleInfo::
takeDeletedSymbolsForFunction(const Function *F,
std::vector<MCSymbol*> &Result) {
if (AddrLabelSymbols == 0) return;
return AddrLabelSymbols->
takeDeletedSymbolsForFunction(const_cast<Function*>(F), Result);
}
LandingPadInfo &MachineModuleInfo::getOrCreateLandingPadInfo
(MachineBasicBlock *LandingPad) {
unsigned N = LandingPads.size();
for (unsigned i = 0; i < N; ++i) {
LandingPadInfo &LP = LandingPads[i];
if (LP.LandingPadBlock == LandingPad)
return LP;
}
LandingPads.push_back(LandingPadInfo(LandingPad));
return LandingPads[N];
}
void MachineModuleInfo::addInvoke(MachineBasicBlock *LandingPad,
MCSymbol *BeginLabel, MCSymbol *EndLabel) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
LP.BeginLabels.push_back(BeginLabel);
LP.EndLabels.push_back(EndLabel);
}
MCSymbol *MachineModuleInfo::addLandingPad(MachineBasicBlock *LandingPad) {
MCSymbol *LandingPadLabel = Context.CreateTempSymbol();
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
LP.LandingPadLabel = LandingPadLabel;
return LandingPadLabel;
}
void MachineModuleInfo::addPersonality(MachineBasicBlock *LandingPad,
const Function *Personality) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
LP.Personality = Personality;
for (unsigned i = 0; i < Personalities.size(); ++i)
if (Personalities[i] == Personality)
return;
if (Personalities[0] == NULL)
Personalities[0] = Personality;
else
Personalities.push_back(Personality);
}
void MachineModuleInfo::
addCatchTypeInfo(MachineBasicBlock *LandingPad,
ArrayRef<const GlobalVariable *> TyInfo) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
for (unsigned N = TyInfo.size(); N; --N)
LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1]));
}
void MachineModuleInfo::
addFilterTypeInfo(MachineBasicBlock *LandingPad,
ArrayRef<const GlobalVariable *> TyInfo) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
std::vector<unsigned> IdsInFilter(TyInfo.size());
for (unsigned I = 0, E = TyInfo.size(); I != E; ++I)
IdsInFilter[I] = getTypeIDFor(TyInfo[I]);
LP.TypeIds.push_back(getFilterIDFor(IdsInFilter));
}
void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
LP.TypeIds.push_back(0);
}
void MachineModuleInfo::TidyLandingPads(DenseMap<MCSymbol*, uintptr_t> *LPMap) {
for (unsigned i = 0; i != LandingPads.size(); ) {
LandingPadInfo &LandingPad = LandingPads[i];
if (LandingPad.LandingPadLabel &&
!LandingPad.LandingPadLabel->isDefined() &&
(!LPMap || (*LPMap)[LandingPad.LandingPadLabel] == 0))
LandingPad.LandingPadLabel = 0;
if (!LandingPad.LandingPadLabel && LandingPad.LandingPadBlock) {
LandingPads.erase(LandingPads.begin() + i);
continue;
}
for (unsigned j = 0, e = LandingPads[i].BeginLabels.size(); j != e; ++j) {
MCSymbol *BeginLabel = LandingPad.BeginLabels[j];
MCSymbol *EndLabel = LandingPad.EndLabels[j];
if ((BeginLabel->isDefined() ||
(LPMap && (*LPMap)[BeginLabel] != 0)) &&
(EndLabel->isDefined() ||
(LPMap && (*LPMap)[EndLabel] != 0))) continue;
LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j);
LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j);
--j, --e;
}
if (LandingPads[i].BeginLabels.empty()) {
LandingPads.erase(LandingPads.begin() + i);
continue;
}
if (!LandingPad.LandingPadBlock ||
(LandingPad.TypeIds.size() == 1 && !LandingPad.TypeIds[0]))
LandingPad.TypeIds.clear();
++i;
}
}
void MachineModuleInfo::setCallSiteLandingPad(MCSymbol *Sym,
ArrayRef<unsigned> Sites) {
LPadToCallSiteMap[Sym].append(Sites.begin(), Sites.end());
}
unsigned MachineModuleInfo::getTypeIDFor(const GlobalVariable *TI) {
for (unsigned i = 0, N = TypeInfos.size(); i != N; ++i)
if (TypeInfos[i] == TI) return i + 1;
TypeInfos.push_back(TI);
return TypeInfos.size();
}
int MachineModuleInfo::getFilterIDFor(std::vector<unsigned> &TyIds) {
for (std::vector<unsigned>::iterator I = FilterEnds.begin(),
E = FilterEnds.end(); I != E; ++I) {
unsigned i = *I, j = TyIds.size();
while (i && j)
if (FilterIds[--i] != TyIds[--j])
goto try_next;
if (!j)
return -(1 + i);
try_next:;
}
int FilterID = -(1 + FilterIds.size());
FilterIds.reserve(FilterIds.size() + TyIds.size() + 1);
FilterIds.insert(FilterIds.end(), TyIds.begin(), TyIds.end());
FilterEnds.push_back(FilterIds.size());
FilterIds.push_back(0); return FilterID;
}
const Function *MachineModuleInfo::getPersonality() const {
return !LandingPads.empty() ? LandingPads[0].Personality : NULL;
}
unsigned MachineModuleInfo::getPersonalityIndex() const {
const Function* Personality = NULL;
for (unsigned i = 0, e = LandingPads.size(); i != e; ++i)
if (LandingPads[i].Personality) {
Personality = LandingPads[i].Personality;
break;
}
for (unsigned i = 0, e = Personalities.size(); i < e; ++i) {
if (Personalities[i] == Personality)
return i;
}
return 0;
}