//
// The LLVM Compiler Infrastructure
//
-// This file was developed by James M. Laskey and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
using namespace llvm::dwarf;
// Handle the Pass registration stuff necessary to use TargetData's.
-namespace {
- const int MachineModuleInfo::ID = 0;
- RegisterPass<MachineModuleInfo> X("machinemoduleinfo", "Module Information");
-}
+static RegisterPass<MachineModuleInfo>
+X("machinemoduleinfo", "Module Information");
+char MachineModuleInfo::ID = 0;
//===----------------------------------------------------------------------===//
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::BitCast) {
return dyn_cast<GlobalVariable>(CE->getOperand(0));
+ } else if (CE->getOpcode() == Instruction::GetElementPtr) {
+ for (unsigned int i=1; i<CE->getNumOperands(); i++) {
+ if (!CE->getOperand(i)->isNullValue())
+ return NULL;
+ }
+ return dyn_cast<GlobalVariable>(CE->getOperand(0));
}
}
return NULL;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::BitCast) {
return isa<GlobalVariable>(CE->getOperand(0));
+ } else if (CE->getOpcode() == Instruction::GetElementPtr) {
+ for (unsigned int i=1; i<CE->getNumOperands(); i++) {
+ if (!CE->getOperand(i)->isNullValue())
+ return false;
+ }
+ return isa<GlobalVariable>(CE->getOperand(0));
}
}
return false;
DD->ApplyToFields(this);
}
+namespace {
+
//===----------------------------------------------------------------------===//
/// DICountVisitor - This DIVisitor counts all the fields in the supplied debug
/// the supplied DebugInfoDesc.
}
};
+}
//===----------------------------------------------------------------------===//
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
-const char *CompileUnitDesc::AnchorString = "llvm.dbg.compile_units";
+const char *const CompileUnitDesc::AnchorString = "llvm.dbg.compile_units";
const char *CompileUnitDesc::getAnchorString() const {
return AnchorString;
}
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
-const char *GlobalVariableDesc::AnchorString = "llvm.dbg.global_variables";
+const char *const GlobalVariableDesc::AnchorString = "llvm.dbg.global_variables";
const char *GlobalVariableDesc::getAnchorString() const {
return AnchorString;
}
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
-const char *SubprogramDesc::AnchorString = "llvm.dbg.subprograms";
+const char *const SubprogramDesc::AnchorString = "llvm.dbg.subprograms";
const char *SubprogramDesc::getAnchorString() const {
return AnchorString;
}
// If not already defined.
if (!StrPtrTy) {
// Construct the pointer to signed bytes.
- StrPtrTy = PointerType::get(Type::Int8Ty);
+ StrPtrTy = PointerType::getUnqual(Type::Int8Ty);
}
return StrPtrTy;
const StructType *EmptyStructTy =
StructType::get(std::vector<const Type*>());
// Construct the pointer to empty structure type.
- EmptyStructPtrTy = PointerType::get(EmptyStructTy);
+ EmptyStructPtrTy = PointerType::getUnqual(EmptyStructTy);
}
return EmptyStructPtrTy;
// Otherwise create and return a new string global.
GlobalVariable *StrGV = new GlobalVariable(ConstStr->getType(), true,
GlobalVariable::InternalLinkage,
- ConstStr, "str", M);
+ ConstStr, ".str", M);
StrGV->setSection("llvm.metadata");
// Convert to generic string pointer.
Slot = ConstantExpr::getBitCast(StrGV, getStrPtrType());
return GV;
}
+/// addDescriptor - Directly connect DD with existing GV.
+void DISerializer::addDescriptor(DebugInfoDesc *DD,
+ GlobalVariable *GV) {
+ DescGlobals[DD] = GV;
+}
+
//===----------------------------------------------------------------------===//
/// Verify - Return true if the GlobalVariable appears to be a valid
return true;
}
+/// isVerified - Return true if the specified GV has already been
+/// verified as a debug information descriptor.
+bool DIVerifier::isVerified(GlobalVariable *GV) {
+ unsigned &ValiditySlot = Validity[GV];
+ if (ValiditySlot) return ValiditySlot == Valid;
+ return false;
+}
+
//===----------------------------------------------------------------------===//
DebugScope::~DebugScope() {
, RootScope(NULL)
, FrameMoves()
, LandingPads()
-{}
+, Personalities()
+, CallsEHReturn(0)
+, CallsUnwindInit(0)
+{
+ // Always emit "no personality" info
+ Personalities.push_back(NULL);
+}
MachineModuleInfo::~MachineModuleInfo() {
}
// Clean up exception info.
LandingPads.clear();
TypeInfos.clear();
+ FilterIds.clear();
+ FilterEnds.clear();
+ CallsEHReturn = 0;
+ CallsUnwindInit = 0;
}
/// getDescFor - Convert a Value to a debug information descriptor.
return DR.Deserialize(V);
}
-/// Verify - Verify that a Value is debug information descriptor.
-///
-bool MachineModuleInfo::Verify(Value *V) {
- return VR.Verify(V);
-}
-
/// AnalyzeModule - Scan the module for global debug information.
///
void MachineModuleInfo::AnalyzeModule(Module &M) {
SetupCompileUnits(M);
-}
-/// needsFrameInfo - Returns true if we need to gather callee-saved register
-/// move info for the frame.
-bool MachineModuleInfo::needsFrameInfo() const {
- return hasDebugInfo() || ExceptionHandling;
+ // Insert functions in the llvm.used array into UsedFunctions.
+ GlobalVariable *GV = M.getGlobalVariable("llvm.used");
+ if (!GV || !GV->hasInitializer()) return;
+
+ // Should be an array of 'i8*'.
+ ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
+ if (InitList == 0) return;
+
+ for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(InitList->getOperand(i)))
+ if (CE->getOpcode() == Instruction::BitCast)
+ if (Function *F = dyn_cast<Function>(CE->getOperand(0)))
+ UsedFunctions.insert(F);
+ }
}
/// SetupCompileUnits - Set up the unique vector of compile units.
return ::getGlobalVariablesUsing(M, RootName);
}
-/// RecordLabel - Records location information and associates it with a
+/// RecordSourceLine - Records location information and associates it with a
/// debug label. Returns a unique label ID used to generate a label and
/// provide correspondence to the source line list.
-unsigned MachineModuleInfo::RecordLabel(unsigned Line, unsigned Column,
- unsigned Source) {
+unsigned MachineModuleInfo::RecordSourceLine(unsigned Line, unsigned Column,
+ unsigned Source) {
unsigned ID = NextLabelID();
Lines.push_back(SourceLineInfo(Line, Column, Source, ID));
return ID;
/// RecordVariable - Indicate the declaration of a local variable.
///
-void MachineModuleInfo::RecordVariable(Value *V, unsigned FrameIndex) {
- VariableDesc *VD = cast<VariableDesc>(DR.Deserialize(V));
+void MachineModuleInfo::RecordVariable(GlobalValue *GV, unsigned FrameIndex) {
+ VariableDesc *VD = cast<VariableDesc>(DR.Deserialize(GV));
DebugScope *Scope = getOrCreateScope(VD->getContext());
DebugVariable *DV = new DebugVariable(VD, FrameIndex);
Scope->AddVariable(DV);
void MachineModuleInfo::addInvoke(MachineBasicBlock *LandingPad,
unsigned BeginLabel, unsigned EndLabel) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
- if (!LP.BeginLabel) LP.BeginLabel = BeginLabel;
- LP.EndLabel = EndLabel;
+ LP.BeginLabels.push_back(BeginLabel);
+ LP.EndLabels.push_back(EndLabel);
}
/// addLandingPad - Provide the label of a try LandingPad block.
Function *Personality) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
LP.Personality = Personality;
+
+ for (unsigned i = 0; i < Personalities.size(); ++i)
+ if (Personalities[i] == Personality)
+ return;
+
+ Personalities.push_back(Personality);
}
/// addCatchTypeInfo - Provide the catch typeinfo for a landing pad.
for (unsigned N = TyInfo.size(); N; --N)
LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1]));
}
-
-/// setIsFilterLandingPad - Indicates that the landing pad is a throw filter.
+
+/// addFilterTypeInfo - Provide the filter typeinfo for a landing pad.
///
-void MachineModuleInfo::setIsFilterLandingPad(MachineBasicBlock *LandingPad) {
+void MachineModuleInfo::addFilterTypeInfo(MachineBasicBlock *LandingPad,
+ std::vector<GlobalVariable *> &TyInfo) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
- LP.IsFilter = true;
+ 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));
+}
+
+/// addCleanup - Add a cleanup action for a landing pad.
+///
+void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) {
+ LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
+ LP.TypeIds.push_back(0);
}
/// TidyLandingPads - Remap landing pad labels and remove any deleted landing
void MachineModuleInfo::TidyLandingPads() {
for (unsigned i = 0; i != LandingPads.size(); ) {
LandingPadInfo &LandingPad = LandingPads[i];
- LandingPad.BeginLabel = MappedLabel(LandingPad.BeginLabel);
- LandingPad.EndLabel = MappedLabel(LandingPad.EndLabel);
LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel);
-
- if (!LandingPad.BeginLabel ||
- !LandingPad.EndLabel ||
- !LandingPad.LandingPadLabel) {
+
+ // Special case: we *should* emit LPs with null LP MBB. This indicates
+ // "nounwind" case.
+ if (!LandingPad.LandingPadLabel && LandingPad.LandingPadBlock) {
LandingPads.erase(LandingPads.begin() + i);
continue;
}
-
+
+ for (unsigned j=0; j != LandingPads[i].BeginLabels.size(); ) {
+ unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]);
+ unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]);
+
+ if (!BeginLabel || !EndLabel) {
+ LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j);
+ LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j);
+ continue;
+ }
+
+ LandingPad.BeginLabels[j] = BeginLabel;
+ LandingPad.EndLabels[j] = EndLabel;
+ ++j;
+ }
+
+ // Remove landing pads with no try-ranges.
+ if (LandingPads[i].BeginLabels.empty()) {
+ LandingPads.erase(LandingPads.begin() + i);
+ continue;
+ }
+
+ // If there is no landing pad, ensure that the list of typeids is empty.
+ // If the only typeid is a cleanup, this is the same as having no typeids.
+ if (!LandingPad.LandingPadBlock ||
+ (LandingPad.TypeIds.size() == 1 && !LandingPad.TypeIds[0]))
+ LandingPad.TypeIds.clear();
+
++i;
}
}
return TypeInfos.size();
}
-/// getLandingPadInfos - Return a reference to the landing pad info for the
-/// current function.
+/// getFilterIDFor - Return the filter id for the specified typeinfos. This is
+/// function wide.
+int MachineModuleInfo::getFilterIDFor(std::vector<unsigned> &TyIds) {
+ // If the new filter coincides with the tail of an existing filter, then
+ // re-use the existing filter. Folding filters more than this requires
+ // re-ordering filters and/or their elements - probably not worth it.
+ 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)
+ // The new filter coincides with range [i, end) of the existing filter.
+ return -(1 + i);
+
+try_next:;
+ }
+
+ // Add the new filter.
+ int FilterID = -(1 + FilterIds.size());
+ FilterIds.reserve(FilterIds.size() + TyIds.size() + 1);
+ for (unsigned I = 0, N = TyIds.size(); I != N; ++I)
+ FilterIds.push_back(TyIds[I]);
+ FilterEnds.push_back(FilterIds.size());
+ FilterIds.push_back(0); // terminator
+ return FilterID;
+}
+
+/// getPersonality - Return the personality function for the current function.
Function *MachineModuleInfo::getPersonality() const {
+ // FIXME: Until PR1414 will be fixed, we're using 1 personality function per
+ // function
return !LandingPads.empty() ? LandingPads[0].Personality : NULL;
}
+/// getPersonalityIndex - Return unique index for current personality
+/// function. NULL personality function should always get zero index.
+unsigned MachineModuleInfo::getPersonalityIndex() const {
+ const Function* Personality = NULL;
+
+ // Scan landing pads. If there is at least one non-NULL personality - use it.
+ for (unsigned i = 0; i != LandingPads.size(); ++i)
+ if (LandingPads[i].Personality) {
+ Personality = LandingPads[i].Personality;
+ break;
+ }
+
+ for (unsigned i = 0; i < Personalities.size(); ++i) {
+ if (Personalities[i] == Personality)
+ return i;
+ }
+
+ // This should never happen
+ assert(0 && "Personality function should be set!");
+ return 0;
+}
//===----------------------------------------------------------------------===//
/// DebugLabelFolding pass - This pass prunes out redundant labels. This allows
namespace llvm {
struct DebugLabelFolder : public MachineFunctionPass {
- static const int ID;
+ static char ID;
DebugLabelFolder() : MachineFunctionPass((intptr_t)&ID) {}
virtual bool runOnMachineFunction(MachineFunction &MF);
virtual const char *getPassName() const { return "Label Folder"; }
};
-const int DebugLabelFolder::ID = 0;
+char DebugLabelFolder::ID = 0;
bool DebugLabelFolder::runOnMachineFunction(MachineFunction &MF) {
// Get machine module info.
MachineModuleInfo *MMI = getAnalysisToUpdate<MachineModuleInfo>();
if (!MMI) return false;
- // Get target instruction info.
- const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
- if (!TII) return false;
// Track if change is made.
bool MadeChange = false;
// Iterate through instructions.
for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
// Is it a label.
- if ((unsigned)I->getOpcode() == TargetInstrInfo::LABEL) {
+ if (I->isDebugLabel()) {
// The label ID # is always operand #0, an immediate.
unsigned NextLabel = I->getOperand(0).getImm();