//
// 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.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/Constants.h"
+#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineLocation.h"
+#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm::dwarf;
// Handle the Pass registration stuff necessary to use TargetData's.
-namespace {
- RegisterPass<MachineModuleInfo> X("machinemoduleinfo", "Module Information");
-}
+static RegisterPass<MachineModuleInfo>
+X("machinemoduleinfo", "Module Information");
char MachineModuleInfo::ID = 0;
//===----------------------------------------------------------------------===//
/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the
/// named GlobalVariable.
-static std::vector<GlobalVariable*>
-getGlobalVariablesUsing(Module &M, const std::string &RootName) {
- std::vector<GlobalVariable*> Result; // GlobalVariables matching criteria.
-
+static void
+getGlobalVariablesUsing(Module &M, const std::string &RootName,
+ std::vector<GlobalVariable*> &Result) {
std::vector<const Type*> FieldTypes;
FieldTypes.push_back(Type::Int32Ty);
FieldTypes.push_back(Type::Int32Ty);
StructType::get(FieldTypes));
// If present and linkonce then scan for users.
- if (UseRoot && UseRoot->hasLinkOnceLinkage()) {
+ if (UseRoot && UseRoot->hasLinkOnceLinkage())
getGlobalVariablesUsing(UseRoot, Result);
- }
-
- return Result;
}
/// isStringValue - Return true if the given value can be coerced to a string.
} 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;
//===----------------------------------------------------------------------===//
+static unsigned CountFields(DebugInfoDesc *DD) {
+ unsigned Count = 0;
+
+ switch (DD->getTag()) {
+ case DW_TAG_anchor: // AnchorDesc
+ // Tag
+ // AnchorTag
+ Count = 2;
+ break;
+ case DW_TAG_compile_unit: // CompileUnitDesc
+ // [DW_TAG_anchor]
+ // if (Version == 0) DebugVersion
+ // Language
+ // FileName
+ // Directory
+ // Producer
+ Count = 6;
+
+ // Handle cases out of sync with compiler.
+ if (DD->getVersion() == 0)
+ ++Count;
+
+ break;
+ case DW_TAG_variable: // GlobalVariableDesc
+ // [DW_TAG_anchor]
+ // Context
+ // Name
+ // FullName
+ // LinkageName
+ // File
+ // Line
+ // TyDesc
+ // IsStatic
+ // IsDefinition
+ // Global
+ Count = 12;
+ break;
+ case DW_TAG_subprogram: // SubprogramDesc
+ // [DW_TAG_anchor]
+ // Context
+ // Name
+ // FullName
+ // LinkageName
+ // File
+ // Line
+ // TyDesc
+ // IsStatic
+ // IsDefinition
+ Count = 11;
+ break;
+ case DW_TAG_lexical_block: // BlockDesc
+ // Tag
+ // Context
+ Count = 2;
+ break;
+ case DW_TAG_base_type: // BasicTypeDesc
+ // Tag
+ // Context
+ // Name
+ // File
+ // Line
+ // Size
+ // Align
+ // Offset
+ // if (Version > LLVMDebugVersion4) Flags
+ // Encoding
+ Count = 9;
+
+ if (DD->getVersion() > LLVMDebugVersion4)
+ ++Count;
+
+ break;
+ case DW_TAG_typedef:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_const_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_restrict_type:
+ case DW_TAG_member:
+ case DW_TAG_inheritance: // DerivedTypeDesc
+ // Tag
+ // Context
+ // Name
+ // File
+ // Line
+ // Size
+ // Align
+ // Offset
+ // if (Version > LLVMDebugVersion4) Flags
+ // FromType
+ Count = 9;
+
+ if (DD->getVersion() > LLVMDebugVersion4)
+ ++Count;
+
+ break;
+ case DW_TAG_array_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_vector_type:
+ case DW_TAG_subroutine_type: // CompositeTypeDesc
+ // Tag
+ // Context
+ // Name
+ // File
+ // Line
+ // Size
+ // Align
+ // Offset
+ // if (Version > LLVMDebugVersion4) Flags
+ // FromType
+ // Elements
+ Count = 10;
+
+ if (DD->getVersion() > LLVMDebugVersion4)
+ ++Count;
+
+ break;
+ case DW_TAG_subrange_type: // SubrangeDesc
+ // Tag
+ // Lo
+ // Hi
+ Count = 3;
+ break;
+ case DW_TAG_enumerator: // EnumeratorDesc
+ // Tag
+ // Name
+ // Value
+ Count = 3;
+ break;
+ case DW_TAG_return_variable:
+ case DW_TAG_arg_variable:
+ case DW_TAG_auto_variable: // VariableDesc
+ // Tag
+ // Context
+ // Name
+ // File
+ // Line
+ // TyDesc
+ Count = 6;
+ break;
+ default:
+ break;
+ }
+
+ return Count;
+}
+
+//===----------------------------------------------------------------------===//
+
/// ApplyToFields - Target the visitor to each field of the debug information
/// descriptor.
void DIVisitor::ApplyToFields(DebugInfoDesc *DD) {
DD->ApplyToFields(this);
}
-//===----------------------------------------------------------------------===//
-/// DICountVisitor - This DIVisitor counts all the fields in the supplied debug
-/// the supplied DebugInfoDesc.
-class DICountVisitor : public DIVisitor {
-private:
- unsigned Count; // Running count of fields.
-
-public:
- DICountVisitor() : DIVisitor(), Count(0) {}
-
- // Accessors.
- unsigned getCount() const { return Count; }
-
- /// Apply - Count each of the fields.
- ///
- virtual void Apply(int &Field) { ++Count; }
- virtual void Apply(unsigned &Field) { ++Count; }
- virtual void Apply(int64_t &Field) { ++Count; }
- virtual void Apply(uint64_t &Field) { ++Count; }
- virtual void Apply(bool &Field) { ++Count; }
- virtual void Apply(std::string &Field) { ++Count; }
- virtual void Apply(DebugInfoDesc *&Field) { ++Count; }
- virtual void Apply(GlobalVariable *&Field) { ++Count; }
- virtual void Apply(std::vector<DebugInfoDesc *> &Field) {
- ++Count;
- }
-};
+namespace {
//===----------------------------------------------------------------------===//
/// DIDeserializeVisitor - This DIVisitor deserializes all the fields in the
public:
DIDeserializeVisitor(DIDeserializer &D, GlobalVariable *GV)
- : DIVisitor()
- , DR(D)
- , I(0)
- , CI(cast<ConstantStruct>(GV->getInitializer()))
+ : DIVisitor(), DR(D), I(0), CI(cast<ConstantStruct>(GV->getInitializer()))
{}
/// Apply - Set the value of each of the fields.
}
virtual void Apply(std::string &Field) {
Constant *C = CI->getOperand(I++);
- Field = C->getStringValue();
+ // Fills in the string if it succeeds
+ if (!GetConstantStringInfo(C, Field))
+ Field.clear();
}
virtual void Apply(DebugInfoDesc *&Field) {
Constant *C = CI->getOperand(I++);
Elements.push_back(ConstantInt::get(Type::Int1Ty, Field));
}
virtual void Apply(std::string &Field) {
- Elements.push_back(SR.getString(Field));
+ Elements.push_back(SR.getString(Field));
}
virtual void Apply(DebugInfoDesc *&Field) {
GlobalVariable *GV = NULL;
}
};
+}
//===----------------------------------------------------------------------===//
/// 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 PointerType *DISerializer::getEmptyStructPtrType() {
// If not already defined.
- if (!EmptyStructPtrTy) {
- // Construct the empty structure type.
- const StructType *EmptyStructTy =
- StructType::get(std::vector<const Type*>());
- // Construct the pointer to empty structure type.
- EmptyStructPtrTy = PointerType::get(EmptyStructTy);
- }
-
+ if (EmptyStructPtrTy) return EmptyStructPtrTy;
+
+ // Construct the pointer to empty structure type.
+ const StructType *EmptyStructTy = StructType::get(NULL, NULL);
+
+ // Construct the pointer to empty structure type.
+ EmptyStructPtrTy = PointerType::getUnqual(EmptyStructTy);
return EmptyStructPtrTy;
}
Constant *DISerializer::getString(const std::string &String) {
// Check string cache for previous edition.
Constant *&Slot = StringCache[String];
+
// Return Constant if previously defined.
if (Slot) return Slot;
+
// If empty string then use a sbyte* null instead.
if (String.empty()) {
Slot = ConstantPointerNull::get(getStrPtrType());
} else {
// Construct string as an llvm constant.
Constant *ConstStr = ConstantArray::get(String);
+
// Otherwise create and return a new string global.
GlobalVariable *StrGV = new GlobalVariable(ConstStr->getType(), true,
GlobalVariable::InternalLinkage,
ConstStr, ".str", M);
StrGV->setSection("llvm.metadata");
+
// Convert to generic string pointer.
Slot = ConstantExpr::getBitCast(StrGV, getStrPtrType());
}
+
return Slot;
}
// Add fields.
DISerializeVisitor SRAM(*this, Elements);
SRAM.ApplyToFields(DD);
-
+
// Set the globals initializer.
GV->setInitializer(ConstantStruct::get(Ty, Elements));
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
// Get the field count.
unsigned &CountSlot = Counts[Tag];
- if (!CountSlot) {
+
+ if (!CountSlot)
// Check the operand count to the field count
- DICountVisitor CTAM;
- CTAM.ApplyToFields(DD);
- CountSlot = CTAM.getCount();
- }
+ CountSlot = CountFields(DD);
// Field count must be at most equal operand count.
if (CountSlot > N) {
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() {
//===----------------------------------------------------------------------===//
MachineModuleInfo::MachineModuleInfo()
-: ImmutablePass((intptr_t)&ID)
+: ImmutablePass(&ID)
, DR()
, VR()
, CompileUnits()
, FrameMoves()
, LandingPads()
, Personalities()
+, CallsEHReturn(0)
+, CallsUnwindInit(0)
{
// Always emit "no personality" info
Personalities.push_back(NULL);
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.
///
void MachineModuleInfo::SetupCompileUnits(Module &M) {
- std::vector<CompileUnitDesc *>CU = getAnchoredDescriptors<CompileUnitDesc>(M);
+ std::vector<CompileUnitDesc *> CU;
+ getAnchoredDescriptors<CompileUnitDesc>(M, CU);
for (unsigned i = 0, N = CU.size(); i < N; i++) {
CompileUnits.insert(CU[i]);
/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the
/// named GlobalVariable.
-std::vector<GlobalVariable*>
+void
MachineModuleInfo::getGlobalVariablesUsing(Module &M,
- const std::string &RootName) {
- return ::getGlobalVariablesUsing(M, RootName);
+ const std::string &RootName,
+ std::vector<GlobalVariable*>&Result){
+ return ::getGlobalVariablesUsing(M, RootName, Result);
}
-/// 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::addFilterTypeInfo(MachineBasicBlock *LandingPad,
std::vector<GlobalVariable *> &TyInfo) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
- std::vector<unsigned> IdsInFilter (TyInfo.size());
+ 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
/// pads.
void MachineModuleInfo::TidyLandingPads() {
LandingPadInfo &LandingPad = LandingPads[i];
LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel);
- if (!LandingPad.LandingPadBlock)
- // Must not have cleanups if no landing pad.
- LandingPad.TypeIds.clear();
-
// Special case: we *should* emit LPs with null LP MBB. This indicates
- // "rethrow" case.
+ // "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);
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;
}
}
/// getFilterIDFor - Return the filter id for the specified typeinfos. This is
/// function wide.
int MachineModuleInfo::getFilterIDFor(std::vector<unsigned> &TyIds) {
- // TODO: map duplicate filters to the same filter id; a filter equal to the
- // tail of an existing filter also need not be added; re-order filters and
- // filter elements to maximize this kind of sharing.
+ // 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;
}
struct DebugLabelFolder : public MachineFunctionPass {
static char ID;
- DebugLabelFolder() : MachineFunctionPass((intptr_t)&ID) {}
+ DebugLabelFolder() : MachineFunctionPass(&ID) {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addPreservedID(MachineLoopInfoID);
+ AU.addPreservedID(MachineDominatorsID);
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
virtual bool runOnMachineFunction(MachineFunction &MF);
virtual const char *getPassName() const { return "Label Folder"; }
// 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();