llvm/lib/CodeGen/MachineModuleInfo.cpp

2077 lines
60 KiB
C++
Raw Normal View History

//===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// 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/Passes.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Streams.h"
using namespace llvm;
using namespace llvm::dwarf;
// Handle the Pass registration stuff necessary to use TargetData's.
static RegisterPass<MachineModuleInfo>
X("machinemoduleinfo", "Module Information");
char MachineModuleInfo::ID = 0;
//===----------------------------------------------------------------------===//
/// getGlobalVariablesUsing - Return all of the GlobalVariables which have the
/// specified value in their initializer somewhere.
static void
getGlobalVariablesUsing(Value *V, std::vector<GlobalVariable*> &Result) {
// Scan though value users.
for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) {
// If the user is a GlobalVariable then add to result.
Result.push_back(GV);
} else if (Constant *C = dyn_cast<Constant>(*I)) {
// If the user is a constant variable then scan its users
getGlobalVariablesUsing(C, Result);
}
}
}
/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the
/// named GlobalVariable.
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);
// Get the GlobalVariable root.
GlobalVariable *UseRoot = M.getGlobalVariable(RootName,
StructType::get(FieldTypes));
// If present and linkonce then scan for users.
if (UseRoot && UseRoot->hasLinkOnceLinkage())
getGlobalVariablesUsing(UseRoot, Result);
}
/// isStringValue - Return true if the given value can be coerced to a string.
///
static bool isStringValue(Value *V) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) {
ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
return Init->isString();
}
} else if (Constant *C = dyn_cast<Constant>(V)) {
if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
return isStringValue(GV);
else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
if (CE->getOpcode() == Instruction::GetElementPtr) {
if (CE->getNumOperands() == 3 &&
cast<Constant>(CE->getOperand(1))->isNullValue() &&
isa<ConstantInt>(CE->getOperand(2))) {
return isStringValue(CE->getOperand(0));
}
}
}
}
return false;
}
/// getGlobalVariable - Return either a direct or cast Global value.
///
static GlobalVariable *getGlobalVariable(Value *V) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
return GV;
} 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;
}
/// isGlobalVariable - Return true if the given value can be coerced to a
/// GlobalVariable.
static bool isGlobalVariable(Value *V) {
if (isa<GlobalVariable>(V) || isa<ConstantPointerNull>(V)) {
return true;
} 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;
}
/// getUIntOperand - Return ith operand if it is an unsigned integer.
///
static ConstantInt *getUIntOperand(GlobalVariable *GV, unsigned i) {
// Make sure the GlobalVariable has an initializer.
if (!GV->hasInitializer()) return NULL;
// Get the initializer constant.
ConstantStruct *CI = dyn_cast<ConstantStruct>(GV->getInitializer());
if (!CI) return NULL;
// Check if there is at least i + 1 operands.
unsigned N = CI->getNumOperands();
if (i >= N) return NULL;
// Check constant.
return dyn_cast<ConstantInt>(CI->getOperand(i));
}
//===----------------------------------------------------------------------===//
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);
}
namespace {
//===----------------------------------------------------------------------===//
/// DIDeserializeVisitor - This DIVisitor deserializes all the fields in the
/// supplied DebugInfoDesc.
class DIDeserializeVisitor : public DIVisitor {
private:
DIDeserializer &DR; // Active deserializer.
unsigned I; // Current operand index.
ConstantStruct *CI; // GlobalVariable constant initializer.
public:
DIDeserializeVisitor(DIDeserializer &D, GlobalVariable *GV)
: DIVisitor(), DR(D), I(0), CI(cast<ConstantStruct>(GV->getInitializer()))
{}
/// Apply - Set the value of each of the fields.
///
virtual void Apply(int &Field) {
Constant *C = CI->getOperand(I++);
Field = cast<ConstantInt>(C)->getSExtValue();
}
virtual void Apply(unsigned &Field) {
Constant *C = CI->getOperand(I++);
Field = cast<ConstantInt>(C)->getZExtValue();
}
virtual void Apply(int64_t &Field) {
Constant *C = CI->getOperand(I++);
Field = cast<ConstantInt>(C)->getSExtValue();
}
virtual void Apply(uint64_t &Field) {
Constant *C = CI->getOperand(I++);
Field = cast<ConstantInt>(C)->getZExtValue();
}
virtual void Apply(bool &Field) {
Constant *C = CI->getOperand(I++);
Field = cast<ConstantInt>(C)->getZExtValue();
}
virtual void Apply(std::string &Field) {
Constant *C = CI->getOperand(I++);
// Fills in the string if it succeeds
if (!GetConstantStringInfo(C, Field))
Field.clear();
}
virtual void Apply(DebugInfoDesc *&Field) {
Constant *C = CI->getOperand(I++);
Field = DR.Deserialize(C);
}
virtual void Apply(GlobalVariable *&Field) {
Constant *C = CI->getOperand(I++);
Field = getGlobalVariable(C);
}
virtual void Apply(std::vector<DebugInfoDesc *> &Field) {
Field.resize(0);
Constant *C = CI->getOperand(I++);
GlobalVariable *GV = getGlobalVariable(C);
if (GV && GV->hasInitializer()) {
if (ConstantArray *CA = dyn_cast<ConstantArray>(GV->getInitializer())) {
for (unsigned i = 0, N = CA->getNumOperands(); i < N; ++i) {
GlobalVariable *GVE = getGlobalVariable(CA->getOperand(i));
DebugInfoDesc *DE = DR.Deserialize(GVE);
Field.push_back(DE);
}
} else if (GV->getInitializer()->isNullValue()) {
if (const ArrayType *T =
dyn_cast<ArrayType>(GV->getType()->getElementType())) {
Field.resize(T->getNumElements());
}
}
}
}
};
//===----------------------------------------------------------------------===//
/// DISerializeVisitor - This DIVisitor serializes all the fields in
/// the supplied DebugInfoDesc.
class DISerializeVisitor : public DIVisitor {
private:
DISerializer &SR; // Active serializer.
std::vector<Constant*> &Elements; // Element accumulator.
public:
DISerializeVisitor(DISerializer &S, std::vector<Constant*> &E)
: DIVisitor()
, SR(S)
, Elements(E)
{}
/// Apply - Set the value of each of the fields.
///
virtual void Apply(int &Field) {
Elements.push_back(ConstantInt::get(Type::Int32Ty, int32_t(Field)));
}
virtual void Apply(unsigned &Field) {
Elements.push_back(ConstantInt::get(Type::Int32Ty, uint32_t(Field)));
}
virtual void Apply(int64_t &Field) {
Elements.push_back(ConstantInt::get(Type::Int64Ty, int64_t(Field)));
}
virtual void Apply(uint64_t &Field) {
Elements.push_back(ConstantInt::get(Type::Int64Ty, uint64_t(Field)));
}
virtual void Apply(bool &Field) {
Elements.push_back(ConstantInt::get(Type::Int1Ty, Field));
}
virtual void Apply(std::string &Field) {
Elements.push_back(SR.getString(Field));
}
virtual void Apply(DebugInfoDesc *&Field) {
GlobalVariable *GV = NULL;
// If non-NULL then convert to global.
if (Field) GV = SR.Serialize(Field);
// FIXME - At some point should use specific type.
const PointerType *EmptyTy = SR.getEmptyStructPtrType();
if (GV) {
// Set to pointer to global.
Elements.push_back(ConstantExpr::getBitCast(GV, EmptyTy));
} else {
// Use NULL.
Elements.push_back(ConstantPointerNull::get(EmptyTy));
}
}
virtual void Apply(GlobalVariable *&Field) {
const PointerType *EmptyTy = SR.getEmptyStructPtrType();
if (Field) {
Elements.push_back(ConstantExpr::getBitCast(Field, EmptyTy));
} else {
Elements.push_back(ConstantPointerNull::get(EmptyTy));
}
}
virtual void Apply(std::vector<DebugInfoDesc *> &Field) {
const PointerType *EmptyTy = SR.getEmptyStructPtrType();
unsigned N = Field.size();
ArrayType *AT = ArrayType::get(EmptyTy, N);
std::vector<Constant *> ArrayElements;
for (unsigned i = 0, N = Field.size(); i < N; ++i) {
if (DebugInfoDesc *Element = Field[i]) {
GlobalVariable *GVE = SR.Serialize(Element);
Constant *CE = ConstantExpr::getBitCast(GVE, EmptyTy);
ArrayElements.push_back(cast<Constant>(CE));
} else {
ArrayElements.push_back(ConstantPointerNull::get(EmptyTy));
}
}
Constant *CA = ConstantArray::get(AT, ArrayElements);
GlobalVariable *CAGV = new GlobalVariable(AT, true,
GlobalValue::InternalLinkage,
CA, "llvm.dbg.array",
SR.getModule());
CAGV->setSection("llvm.metadata");
Constant *CAE = ConstantExpr::getBitCast(CAGV, EmptyTy);
Elements.push_back(CAE);
}
};
//===----------------------------------------------------------------------===//
/// DIGetTypesVisitor - This DIVisitor gathers all the field types in
/// the supplied DebugInfoDesc.
class DIGetTypesVisitor : public DIVisitor {
private:
DISerializer &SR; // Active serializer.
std::vector<const Type*> &Fields; // Type accumulator.
public:
DIGetTypesVisitor(DISerializer &S, std::vector<const Type*> &F)
: DIVisitor()
, SR(S)
, Fields(F)
{}
/// Apply - Set the value of each of the fields.
///
virtual void Apply(int &Field) {
Fields.push_back(Type::Int32Ty);
}
virtual void Apply(unsigned &Field) {
Fields.push_back(Type::Int32Ty);
}
virtual void Apply(int64_t &Field) {
Fields.push_back(Type::Int64Ty);
}
virtual void Apply(uint64_t &Field) {
Fields.push_back(Type::Int64Ty);
}
virtual void Apply(bool &Field) {
Fields.push_back(Type::Int1Ty);
}
virtual void Apply(std::string &Field) {
Fields.push_back(SR.getStrPtrType());
}
virtual void Apply(DebugInfoDesc *&Field) {
// FIXME - At some point should use specific type.
const PointerType *EmptyTy = SR.getEmptyStructPtrType();
Fields.push_back(EmptyTy);
}
virtual void Apply(GlobalVariable *&Field) {
const PointerType *EmptyTy = SR.getEmptyStructPtrType();
Fields.push_back(EmptyTy);
}
virtual void Apply(std::vector<DebugInfoDesc *> &Field) {
const PointerType *EmptyTy = SR.getEmptyStructPtrType();
Fields.push_back(EmptyTy);
}
};
//===----------------------------------------------------------------------===//
/// DIVerifyVisitor - This DIVisitor verifies all the field types against
/// a constant initializer.
class DIVerifyVisitor : public DIVisitor {
private:
DIVerifier &VR; // Active verifier.
bool IsValid; // Validity status.
unsigned I; // Current operand index.
ConstantStruct *CI; // GlobalVariable constant initializer.
public:
DIVerifyVisitor(DIVerifier &V, GlobalVariable *GV)
: DIVisitor()
, VR(V)
, IsValid(true)
, I(0)
, CI(cast<ConstantStruct>(GV->getInitializer()))
{
}
// Accessors.
bool isValid() const { return IsValid; }
/// Apply - Set the value of each of the fields.
///
virtual void Apply(int &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isa<ConstantInt>(C);
}
virtual void Apply(unsigned &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isa<ConstantInt>(C);
}
virtual void Apply(int64_t &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isa<ConstantInt>(C);
}
virtual void Apply(uint64_t &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isa<ConstantInt>(C);
}
virtual void Apply(bool &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isa<ConstantInt>(C) && C->getType() == Type::Int1Ty;
}
virtual void Apply(std::string &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid &&
(!C || isStringValue(C) || C->isNullValue());
}
virtual void Apply(DebugInfoDesc *&Field) {
// FIXME - Prepare the correct descriptor.
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isGlobalVariable(C);
}
virtual void Apply(GlobalVariable *&Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isGlobalVariable(C);
}
virtual void Apply(std::vector<DebugInfoDesc *> &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isGlobalVariable(C);
if (!IsValid) return;
GlobalVariable *GV = getGlobalVariable(C);
IsValid = IsValid && GV && GV->hasInitializer();
if (!IsValid) return;
ConstantArray *CA = dyn_cast<ConstantArray>(GV->getInitializer());
IsValid = IsValid && CA;
if (!IsValid) return;
for (unsigned i = 0, N = CA->getNumOperands(); IsValid && i < N; ++i) {
IsValid = IsValid && isGlobalVariable(CA->getOperand(i));
if (!IsValid) return;
GlobalVariable *GVE = getGlobalVariable(CA->getOperand(i));
VR.Verify(GVE);
}
}
};
}
//===----------------------------------------------------------------------===//
/// TagFromGlobal - Returns the tag number from a debug info descriptor
/// GlobalVariable. Return DIIValid if operand is not an unsigned int.
unsigned DebugInfoDesc::TagFromGlobal(GlobalVariable *GV) {
ConstantInt *C = getUIntOperand(GV, 0);
return C ? ((unsigned)C->getZExtValue() & ~LLVMDebugVersionMask) :
(unsigned)DW_TAG_invalid;
}
/// VersionFromGlobal - Returns the version number from a debug info
/// descriptor GlobalVariable. Return DIIValid if operand is not an unsigned
/// int.
unsigned DebugInfoDesc::VersionFromGlobal(GlobalVariable *GV) {
ConstantInt *C = getUIntOperand(GV, 0);
return C ? ((unsigned)C->getZExtValue() & LLVMDebugVersionMask) :
(unsigned)DW_TAG_invalid;
}
/// DescFactory - Create an instance of debug info descriptor based on Tag.
/// Return NULL if not a recognized Tag.
DebugInfoDesc *DebugInfoDesc::DescFactory(unsigned Tag) {
switch (Tag) {
case DW_TAG_anchor: return new AnchorDesc();
case DW_TAG_compile_unit: return new CompileUnitDesc();
case DW_TAG_variable: return new GlobalVariableDesc();
case DW_TAG_subprogram: return new SubprogramDesc();
case DW_TAG_lexical_block: return new BlockDesc();
case DW_TAG_base_type: return new BasicTypeDesc();
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: return new DerivedTypeDesc(Tag);
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: return new CompositeTypeDesc(Tag);
case DW_TAG_subrange_type: return new SubrangeDesc();
case DW_TAG_enumerator: return new EnumeratorDesc();
case DW_TAG_return_variable:
case DW_TAG_arg_variable:
case DW_TAG_auto_variable: return new VariableDesc(Tag);
default: break;
}
return NULL;
}
/// getLinkage - get linkage appropriate for this type of descriptor.
///
GlobalValue::LinkageTypes DebugInfoDesc::getLinkage() const {
return GlobalValue::InternalLinkage;
}
/// ApplyToFields - Target the vistor to the fields of the descriptor.
///
void DebugInfoDesc::ApplyToFields(DIVisitor *Visitor) {
Visitor->Apply(Tag);
}
//===----------------------------------------------------------------------===//
AnchorDesc::AnchorDesc()
: DebugInfoDesc(DW_TAG_anchor)
, AnchorTag(0)
{}
AnchorDesc::AnchorDesc(AnchoredDesc *D)
: DebugInfoDesc(DW_TAG_anchor)
, AnchorTag(D->getTag())
{}
// Implement isa/cast/dyncast.
bool AnchorDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_anchor;
}
/// getLinkage - get linkage appropriate for this type of descriptor.
///
GlobalValue::LinkageTypes AnchorDesc::getLinkage() const {
return GlobalValue::LinkOnceLinkage;
}
/// ApplyToFields - Target the visitor to the fields of the TransUnitDesc.
///
void AnchorDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(AnchorTag);
}
/// getDescString - Return a string used to compose global names and labels. A
/// A global variable name needs to be defined for each debug descriptor that is
/// anchored. NOTE: that each global variable named here also needs to be added
/// to the list of names left external in the internalizer.
/// ExternalNames.insert("llvm.dbg.compile_units");
/// ExternalNames.insert("llvm.dbg.global_variables");
/// ExternalNames.insert("llvm.dbg.subprograms");
const char *AnchorDesc::getDescString() const {
switch (AnchorTag) {
case DW_TAG_compile_unit: return CompileUnitDesc::AnchorString;
case DW_TAG_variable: return GlobalVariableDesc::AnchorString;
case DW_TAG_subprogram: return SubprogramDesc::AnchorString;
default: break;
}
assert(0 && "Tag does not have a case for anchor string");
return "";
}
/// getTypeString - Return a string used to label this descriptors type.
///
const char *AnchorDesc::getTypeString() const {
return "llvm.dbg.anchor.type";
}
#ifndef NDEBUG
void AnchorDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "AnchorTag(" << AnchorTag << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
AnchoredDesc::AnchoredDesc(unsigned T)
: DebugInfoDesc(T)
, Anchor(NULL)
{}
/// ApplyToFields - Target the visitor to the fields of the AnchoredDesc.
///
void AnchoredDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(Anchor);
}
//===----------------------------------------------------------------------===//
CompileUnitDesc::CompileUnitDesc()
: AnchoredDesc(DW_TAG_compile_unit)
, Language(0)
, FileName("")
, Directory("")
, Producer("")
{}
// Implement isa/cast/dyncast.
bool CompileUnitDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_compile_unit;
}
/// ApplyToFields - Target the visitor to the fields of the CompileUnitDesc.
///
void CompileUnitDesc::ApplyToFields(DIVisitor *Visitor) {
AnchoredDesc::ApplyToFields(Visitor);
// Handle cases out of sync with compiler.
if (getVersion() == 0) {
unsigned DebugVersion;
Visitor->Apply(DebugVersion);
}
Visitor->Apply(Language);
Visitor->Apply(FileName);
Visitor->Apply(Directory);
Visitor->Apply(Producer);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *CompileUnitDesc::getDescString() const {
return "llvm.dbg.compile_unit";
}
/// getTypeString - Return a string used to label this descriptors type.
///
const char *CompileUnitDesc::getTypeString() const {
return "llvm.dbg.compile_unit.type";
}
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
const char *const CompileUnitDesc::AnchorString = "llvm.dbg.compile_units";
const char *CompileUnitDesc::getAnchorString() const {
return AnchorString;
}
#ifndef NDEBUG
void CompileUnitDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Anchor(" << getAnchor() << "), "
<< "Language(" << Language << "), "
<< "FileName(\"" << FileName << "\"), "
<< "Directory(\"" << Directory << "\"), "
<< "Producer(\"" << Producer << "\")\n";
}
#endif
//===----------------------------------------------------------------------===//
TypeDesc::TypeDesc(unsigned T)
: DebugInfoDesc(T)
, Context(NULL)
, Name("")
, File(NULL)
, Line(0)
, Size(0)
, Align(0)
, Offset(0)
, Flags(0)
{}
/// ApplyToFields - Target the visitor to the fields of the TypeDesc.
///
void TypeDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(Context);
Visitor->Apply(Name);
Visitor->Apply(File);
Visitor->Apply(Line);
Visitor->Apply(Size);
Visitor->Apply(Align);
Visitor->Apply(Offset);
if (getVersion() > LLVMDebugVersion4) Visitor->Apply(Flags);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *TypeDesc::getDescString() const {
return "llvm.dbg.type";
}
/// getTypeString - Return a string used to label this descriptor's type.
///
const char *TypeDesc::getTypeString() const {
return "llvm.dbg.type.type";
}
#ifndef NDEBUG
void TypeDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Context(" << Context << "), "
<< "Name(\"" << Name << "\"), "
<< "File(" << File << "), "
<< "Line(" << Line << "), "
<< "Size(" << Size << "), "
<< "Align(" << Align << "), "
<< "Offset(" << Offset << "), "
<< "Flags(" << Flags << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
BasicTypeDesc::BasicTypeDesc()
: TypeDesc(DW_TAG_base_type)
, Encoding(0)
{}
// Implement isa/cast/dyncast.
bool BasicTypeDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_base_type;
}
/// ApplyToFields - Target the visitor to the fields of the BasicTypeDesc.
///
void BasicTypeDesc::ApplyToFields(DIVisitor *Visitor) {
TypeDesc::ApplyToFields(Visitor);
Visitor->Apply(Encoding);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *BasicTypeDesc::getDescString() const {
return "llvm.dbg.basictype";
}
/// getTypeString - Return a string used to label this descriptor's type.
///
const char *BasicTypeDesc::getTypeString() const {
return "llvm.dbg.basictype.type";
}
#ifndef NDEBUG
void BasicTypeDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Context(" << getContext() << "), "
<< "Name(\"" << getName() << "\"), "
<< "Size(" << getSize() << "), "
<< "Encoding(" << Encoding << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
DerivedTypeDesc::DerivedTypeDesc(unsigned T)
: TypeDesc(T)
, FromType(NULL)
{}
// Implement isa/cast/dyncast.
bool DerivedTypeDesc::classof(const DebugInfoDesc *D) {
unsigned T = D->getTag();
switch (T) {
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:
return true;
default: break;
}
return false;
}
/// ApplyToFields - Target the visitor to the fields of the DerivedTypeDesc.
///
void DerivedTypeDesc::ApplyToFields(DIVisitor *Visitor) {
TypeDesc::ApplyToFields(Visitor);
Visitor->Apply(FromType);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *DerivedTypeDesc::getDescString() const {
return "llvm.dbg.derivedtype";
}
/// getTypeString - Return a string used to label this descriptor's type.
///
const char *DerivedTypeDesc::getTypeString() const {
return "llvm.dbg.derivedtype.type";
}
#ifndef NDEBUG
void DerivedTypeDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Context(" << getContext() << "), "
<< "Name(\"" << getName() << "\"), "
<< "Size(" << getSize() << "), "
<< "File(" << getFile() << "), "
<< "Line(" << getLine() << "), "
<< "FromType(" << FromType << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
CompositeTypeDesc::CompositeTypeDesc(unsigned T)
: DerivedTypeDesc(T)
, Elements()
{}
// Implement isa/cast/dyncast.
bool CompositeTypeDesc::classof(const DebugInfoDesc *D) {
unsigned T = D->getTag();
switch (T) {
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:
return true;
default: break;
}
return false;
}
/// ApplyToFields - Target the visitor to the fields of the CompositeTypeDesc.
///
void CompositeTypeDesc::ApplyToFields(DIVisitor *Visitor) {
DerivedTypeDesc::ApplyToFields(Visitor);
Visitor->Apply(Elements);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *CompositeTypeDesc::getDescString() const {
return "llvm.dbg.compositetype";
}
/// getTypeString - Return a string used to label this descriptor's type.
///
const char *CompositeTypeDesc::getTypeString() const {
return "llvm.dbg.compositetype.type";
}
#ifndef NDEBUG
void CompositeTypeDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Context(" << getContext() << "), "
<< "Name(\"" << getName() << "\"), "
<< "Size(" << getSize() << "), "
<< "File(" << getFile() << "), "
<< "Line(" << getLine() << "), "
<< "FromType(" << getFromType() << "), "
<< "Elements.size(" << Elements.size() << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
SubrangeDesc::SubrangeDesc()
: DebugInfoDesc(DW_TAG_subrange_type)
, Lo(0)
, Hi(0)
{}
// Implement isa/cast/dyncast.
bool SubrangeDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_subrange_type;
}
/// ApplyToFields - Target the visitor to the fields of the SubrangeDesc.
///
void SubrangeDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(Lo);
Visitor->Apply(Hi);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *SubrangeDesc::getDescString() const {
return "llvm.dbg.subrange";
}
/// getTypeString - Return a string used to label this descriptor's type.
///
const char *SubrangeDesc::getTypeString() const {
return "llvm.dbg.subrange.type";
}
#ifndef NDEBUG
void SubrangeDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Lo(" << Lo << "), "
<< "Hi(" << Hi << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
EnumeratorDesc::EnumeratorDesc()
: DebugInfoDesc(DW_TAG_enumerator)
, Name("")
, Value(0)
{}
// Implement isa/cast/dyncast.
bool EnumeratorDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_enumerator;
}
/// ApplyToFields - Target the visitor to the fields of the EnumeratorDesc.
///
void EnumeratorDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(Name);
Visitor->Apply(Value);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *EnumeratorDesc::getDescString() const {
return "llvm.dbg.enumerator";
}
/// getTypeString - Return a string used to label this descriptor's type.
///
const char *EnumeratorDesc::getTypeString() const {
return "llvm.dbg.enumerator.type";
}
#ifndef NDEBUG
void EnumeratorDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Name(" << Name << "), "
<< "Value(" << Value << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
VariableDesc::VariableDesc(unsigned T)
: DebugInfoDesc(T)
, Context(NULL)
, Name("")
, File(NULL)
, Line(0)
, TyDesc(0)
{}
// Implement isa/cast/dyncast.
bool VariableDesc::classof(const DebugInfoDesc *D) {
unsigned T = D->getTag();
switch (T) {
case DW_TAG_auto_variable:
case DW_TAG_arg_variable:
case DW_TAG_return_variable:
return true;
default: break;
}
return false;
}
/// ApplyToFields - Target the visitor to the fields of the VariableDesc.
///
void VariableDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(Context);
Visitor->Apply(Name);
Visitor->Apply(File);
Visitor->Apply(Line);
Visitor->Apply(TyDesc);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *VariableDesc::getDescString() const {
return "llvm.dbg.variable";
}
/// getTypeString - Return a string used to label this descriptor's type.
///
const char *VariableDesc::getTypeString() const {
return "llvm.dbg.variable.type";
}
#ifndef NDEBUG
void VariableDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Context(" << Context << "), "
<< "Name(\"" << Name << "\"), "
<< "File(" << File << "), "
<< "Line(" << Line << "), "
<< "TyDesc(" << TyDesc << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
GlobalDesc::GlobalDesc(unsigned T)
: AnchoredDesc(T)
, Context(0)
, Name("")
, FullName("")
, LinkageName("")
, File(NULL)
, Line(0)
, TyDesc(NULL)
, IsStatic(false)
, IsDefinition(false)
{}
/// ApplyToFields - Target the visitor to the fields of the global.
///
void GlobalDesc::ApplyToFields(DIVisitor *Visitor) {
AnchoredDesc::ApplyToFields(Visitor);
Visitor->Apply(Context);
Visitor->Apply(Name);
Visitor->Apply(FullName);
Visitor->Apply(LinkageName);
Visitor->Apply(File);
Visitor->Apply(Line);
Visitor->Apply(TyDesc);
Visitor->Apply(IsStatic);
Visitor->Apply(IsDefinition);
}
//===----------------------------------------------------------------------===//
GlobalVariableDesc::GlobalVariableDesc()
: GlobalDesc(DW_TAG_variable)
, Global(NULL)
{}
// Implement isa/cast/dyncast.
bool GlobalVariableDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_variable;
}
/// ApplyToFields - Target the visitor to the fields of the GlobalVariableDesc.
///
void GlobalVariableDesc::ApplyToFields(DIVisitor *Visitor) {
GlobalDesc::ApplyToFields(Visitor);
Visitor->Apply(Global);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *GlobalVariableDesc::getDescString() const {
return "llvm.dbg.global_variable";
}
/// getTypeString - Return a string used to label this descriptors type.
///
const char *GlobalVariableDesc::getTypeString() const {
return "llvm.dbg.global_variable.type";
}
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
const char *const GlobalVariableDesc::AnchorString = "llvm.dbg.global_variables";
const char *GlobalVariableDesc::getAnchorString() const {
return AnchorString;
}
#ifndef NDEBUG
void GlobalVariableDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Anchor(" << getAnchor() << "), "
<< "Name(\"" << getName() << "\"), "
<< "FullName(\"" << getFullName() << "\"), "
<< "LinkageName(\"" << getLinkageName() << "\"), "
<< "File(" << getFile() << "),"
<< "Line(" << getLine() << "),"
<< "Type(" << getType() << "), "
<< "IsStatic(" << (isStatic() ? "true" : "false") << "), "
<< "IsDefinition(" << (isDefinition() ? "true" : "false") << "), "
<< "Global(" << Global << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
SubprogramDesc::SubprogramDesc()
: GlobalDesc(DW_TAG_subprogram)
{}
// Implement isa/cast/dyncast.
bool SubprogramDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_subprogram;
}
/// ApplyToFields - Target the visitor to the fields of the
/// SubprogramDesc.
void SubprogramDesc::ApplyToFields(DIVisitor *Visitor) {
GlobalDesc::ApplyToFields(Visitor);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *SubprogramDesc::getDescString() const {
return "llvm.dbg.subprogram";
}
/// getTypeString - Return a string used to label this descriptors type.
///
const char *SubprogramDesc::getTypeString() const {
return "llvm.dbg.subprogram.type";
}
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
const char *const SubprogramDesc::AnchorString = "llvm.dbg.subprograms";
const char *SubprogramDesc::getAnchorString() const {
return AnchorString;
}
#ifndef NDEBUG
void SubprogramDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Anchor(" << getAnchor() << "), "
<< "Name(\"" << getName() << "\"), "
<< "FullName(\"" << getFullName() << "\"), "
<< "LinkageName(\"" << getLinkageName() << "\"), "
<< "File(" << getFile() << "),"
<< "Line(" << getLine() << "),"
<< "Type(" << getType() << "), "
<< "IsStatic(" << (isStatic() ? "true" : "false") << "), "
<< "IsDefinition(" << (isDefinition() ? "true" : "false") << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
BlockDesc::BlockDesc()
: DebugInfoDesc(DW_TAG_lexical_block)
, Context(NULL)
{}
// Implement isa/cast/dyncast.
bool BlockDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_lexical_block;
}
/// ApplyToFields - Target the visitor to the fields of the BlockDesc.
///
void BlockDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(Context);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *BlockDesc::getDescString() const {
return "llvm.dbg.block";
}
/// getTypeString - Return a string used to label this descriptors type.
///
const char *BlockDesc::getTypeString() const {
return "llvm.dbg.block.type";
}
#ifndef NDEBUG
void BlockDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "),"
<< "Context(" << Context << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
DebugInfoDesc *DIDeserializer::Deserialize(Value *V) {
return Deserialize(getGlobalVariable(V));
}
DebugInfoDesc *DIDeserializer::Deserialize(GlobalVariable *GV) {
// Handle NULL.
if (!GV) return NULL;
// Check to see if it has been already deserialized.
DebugInfoDesc *&Slot = GlobalDescs[GV];
if (Slot) return Slot;
// Get the Tag from the global.
unsigned Tag = DebugInfoDesc::TagFromGlobal(GV);
// Create an empty instance of the correct sort.
Slot = DebugInfoDesc::DescFactory(Tag);
// If not a user defined descriptor.
if (Slot) {
// Deserialize the fields.
DIDeserializeVisitor DRAM(*this, GV);
DRAM.ApplyToFields(Slot);
}
return Slot;
}
//===----------------------------------------------------------------------===//
/// getStrPtrType - Return a "sbyte *" type.
///
const PointerType *DISerializer::getStrPtrType() {
// If not already defined.
if (!StrPtrTy) {
// Construct the pointer to signed bytes.
StrPtrTy = PointerType::getUnqual(Type::Int8Ty);
}
return StrPtrTy;
}
/// getEmptyStructPtrType - Return a "{ }*" type.
///
const PointerType *DISerializer::getEmptyStructPtrType() {
// If not already defined.
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;
}
/// getTagType - Return the type describing the specified descriptor (via tag.)
///
const StructType *DISerializer::getTagType(DebugInfoDesc *DD) {
// Attempt to get the previously defined type.
StructType *&Ty = TagTypes[DD->getTag()];
// If not already defined.
if (!Ty) {
// Set up fields vector.
std::vector<const Type*> Fields;
// Get types of fields.
DIGetTypesVisitor GTAM(*this, Fields);
GTAM.ApplyToFields(DD);
// Construct structured type.
Ty = StructType::get(Fields);
// Register type name with module.
M->addTypeName(DD->getTypeString(), Ty);
}
return Ty;
}
/// getString - Construct the string as constant string global.
///
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;
}
/// Serialize - Recursively cast the specified descriptor into a GlobalVariable
/// so that it can be serialized to a .bc or .ll file.
GlobalVariable *DISerializer::Serialize(DebugInfoDesc *DD) {
// Check if the DebugInfoDesc is already in the map.
GlobalVariable *&Slot = DescGlobals[DD];
// See if DebugInfoDesc exists, if so return prior GlobalVariable.
if (Slot) return Slot;
// Get the type associated with the Tag.
const StructType *Ty = getTagType(DD);
// Create the GlobalVariable early to prevent infinite recursion.
GlobalVariable *GV = new GlobalVariable(Ty, true, DD->getLinkage(),
NULL, DD->getDescString(), M);
GV->setSection("llvm.metadata");
// Insert new GlobalVariable in DescGlobals map.
Slot = GV;
// Set up elements vector
std::vector<Constant*> Elements;
// 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
/// serialization of a DebugInfoDesc.
bool DIVerifier::Verify(Value *V) {
return !V || Verify(getGlobalVariable(V));
}
bool DIVerifier::Verify(GlobalVariable *GV) {
// NULLs are valid.
if (!GV) return true;
// Check prior validity.
unsigned &ValiditySlot = Validity[GV];
// If visited before then use old state.
if (ValiditySlot) return ValiditySlot == Valid;
// Assume validity for the time being (recursion.)
ValiditySlot = Valid;
// Make sure the global is internal or link once (anchor.)
if (GV->getLinkage() != GlobalValue::InternalLinkage &&
GV->getLinkage() != GlobalValue::LinkOnceLinkage) {
ValiditySlot = Invalid;
return false;
}
// Get the Tag.
unsigned Tag = DebugInfoDesc::TagFromGlobal(GV);
// Check for user defined descriptors.
if (Tag == DW_TAG_invalid) {
ValiditySlot = Valid;
return true;
}
// Get the Version.
unsigned Version = DebugInfoDesc::VersionFromGlobal(GV);
// Check for version mismatch.
if (Version != LLVMDebugVersion) {
ValiditySlot = Invalid;
return false;
}
// Construct an empty DebugInfoDesc.
DebugInfoDesc *DD = DebugInfoDesc::DescFactory(Tag);
// Allow for user defined descriptors.
if (!DD) return true;
// Get the initializer constant.
ConstantStruct *CI = cast<ConstantStruct>(GV->getInitializer());
// Get the operand count.
unsigned N = CI->getNumOperands();
// Get the field count.
unsigned &CountSlot = Counts[Tag];
if (!CountSlot)
// Check the operand count to the field count
CountSlot = CountFields(DD);
// Field count must be at most equal operand count.
if (CountSlot > N) {
delete DD;
ValiditySlot = Invalid;
return false;
}
// Check each field for valid type.
DIVerifyVisitor VRAM(*this, GV);
VRAM.ApplyToFields(DD);
// Release empty DebugInfoDesc.
delete DD;
// If fields are not valid.
if (!VRAM.isValid()) {
ValiditySlot = Invalid;
return false;
}
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() {
for (unsigned i = 0, N = Scopes.size(); i < N; ++i) delete Scopes[i];
for (unsigned j = 0, M = Variables.size(); j < M; ++j) delete Variables[j];
}
//===----------------------------------------------------------------------===//
MachineModuleInfo::MachineModuleInfo()
: ImmutablePass(&ID)
, DR()
, VR()
, CompileUnits()
, Directories()
, SourceFiles()
, Lines()
, LabelIDList()
, ScopeMap()
, RootScope(NULL)
, FrameMoves()
, LandingPads()
, Personalities()
, CallsEHReturn(0)
, CallsUnwindInit(0)
{
// Always emit "no personality" info
Personalities.push_back(NULL);
}
MachineModuleInfo::~MachineModuleInfo() {
}
/// doInitialization - Initialize the state for a new module.
///
bool MachineModuleInfo::doInitialization() {
return false;
}
/// doFinalization - Tear down the state after completion of a module.
///
bool MachineModuleInfo::doFinalization() {
return false;
}
/// BeginFunction - Begin gathering function meta information.
///
void MachineModuleInfo::BeginFunction(MachineFunction *MF) {
// Coming soon.
}
/// EndFunction - Discard function meta information.
///
void MachineModuleInfo::EndFunction() {
// Clean up scope information.
if (RootScope) {
delete RootScope;
ScopeMap.clear();
RootScope = NULL;
}
// Clean up line info.
Lines.clear();
// Clean up frame info.
FrameMoves.clear();
// 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.
///
// FIXME - use new Value type when available.
DebugInfoDesc *MachineModuleInfo::getDescFor(Value *V) {
return DR.Deserialize(V);
}
/// AnalyzeModule - Scan the module for global debug information.
///
void MachineModuleInfo::AnalyzeModule(Module &M) {
SetupCompileUnits(M);
// 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, CU);
for (unsigned i = 0, N = CU.size(); i < N; i++) {
CompileUnits.insert(CU[i]);
}
}
/// getCompileUnits - Return a vector of debug compile units.
///
const UniqueVector<CompileUnitDesc *> MachineModuleInfo::getCompileUnits()const{
return CompileUnits;
}
/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the
/// named GlobalVariable.
void
MachineModuleInfo::getGlobalVariablesUsing(Module &M,
const std::string &RootName,
std::vector<GlobalVariable*>&Result){
return ::getGlobalVariablesUsing(M, RootName, Result);
}
/// 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::RecordSourceLine(unsigned Line, unsigned Column,
unsigned Source) {
unsigned ID = NextLabelID();
Lines.push_back(SourceLineInfo(Line, Column, Source, ID));
return ID;
}
/// RecordSource - Register a source file with debug info. Returns an source
/// ID.
unsigned MachineModuleInfo::RecordSource(const std::string &Directory,
const std::string &Source) {
unsigned DirectoryID = Directories.insert(Directory);
return SourceFiles.insert(SourceFileInfo(DirectoryID, Source));
}
unsigned MachineModuleInfo::RecordSource(const CompileUnitDesc *CompileUnit) {
return RecordSource(CompileUnit->getDirectory(),
CompileUnit->getFileName());
}
/// RecordRegionStart - Indicate the start of a region.
///
unsigned MachineModuleInfo::RecordRegionStart(Value *V) {
// FIXME - need to be able to handle split scopes because of bb cloning.
DebugInfoDesc *ScopeDesc = DR.Deserialize(V);
DebugScope *Scope = getOrCreateScope(ScopeDesc);
unsigned ID = NextLabelID();
if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
return ID;
}
/// RecordRegionEnd - Indicate the end of a region.
///
unsigned MachineModuleInfo::RecordRegionEnd(Value *V) {
// FIXME - need to be able to handle split scopes because of bb cloning.
DebugInfoDesc *ScopeDesc = DR.Deserialize(V);
DebugScope *Scope = getOrCreateScope(ScopeDesc);
unsigned ID = NextLabelID();
Scope->setEndLabelID(ID);
return ID;
}
/// RecordVariable - Indicate the declaration of a local variable.
///
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);
}
/// getOrCreateScope - Returns the scope associated with the given descriptor.
///
DebugScope *MachineModuleInfo::getOrCreateScope(DebugInfoDesc *ScopeDesc) {
DebugScope *&Slot = ScopeMap[ScopeDesc];
if (!Slot) {
// FIXME - breaks down when the context is an inlined function.
DebugInfoDesc *ParentDesc = NULL;
if (BlockDesc *Block = dyn_cast<BlockDesc>(ScopeDesc)) {
ParentDesc = Block->getContext();
}
DebugScope *Parent = ParentDesc ? getOrCreateScope(ParentDesc) : NULL;
Slot = new DebugScope(Parent, ScopeDesc);
if (Parent) {
Parent->AddScope(Slot);
} else if (RootScope) {
// FIXME - Add inlined function scopes to the root so we can delete
// them later. Long term, handle inlined functions properly.
RootScope->AddScope(Slot);
} else {
// First function is top level function.
RootScope = Slot;
}
}
return Slot;
}
//===-EH-------------------------------------------------------------------===//
/// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the
/// specified MachineBasicBlock.
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];
}
/// addInvoke - Provide the begin and end labels of an invoke style call and
/// associate it with a try landing pad block.
void MachineModuleInfo::addInvoke(MachineBasicBlock *LandingPad,
unsigned BeginLabel, unsigned EndLabel) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
LP.BeginLabels.push_back(BeginLabel);
LP.EndLabels.push_back(EndLabel);
}
/// addLandingPad - Provide the label of a try LandingPad block.
///
unsigned MachineModuleInfo::addLandingPad(MachineBasicBlock *LandingPad) {
unsigned LandingPadLabel = NextLabelID();
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
LP.LandingPadLabel = LandingPadLabel;
return LandingPadLabel;
}
/// addPersonality - Provide the personality function for the exception
/// information.
void MachineModuleInfo::addPersonality(MachineBasicBlock *LandingPad,
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.
///
void MachineModuleInfo::addCatchTypeInfo(MachineBasicBlock *LandingPad,
std::vector<GlobalVariable *> &TyInfo) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
for (unsigned N = TyInfo.size(); N; --N)
LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1]));
}
/// addFilterTypeInfo - Provide the filter typeinfo for a landing pad.
///
void MachineModuleInfo::addFilterTypeInfo(MachineBasicBlock *LandingPad,
std::vector<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));
}
There is an impedance matching problem between LLVM and gcc exception handling: if an exception unwinds through an invoke, then execution must branch to the invoke's unwind target. We previously tried to enforce this by appending a cleanup action to every selector, however this does not always work correctly due to an optimization in the C++ unwinding runtime: if only cleanups would be run while unwinding an exception, then the program just terminates without actually executing the cleanups, as invoke semantics would require. I was hoping this wouldn't be a problem, but in fact it turns out to be the cause of all the remaining failures in the LLVM testsuite (these also fail with -enable-correct-eh-support, so turning on -enable-eh didn't make things worse!). Instead we need to append a full-blown catch-all to the end of each selector. The correct way of doing this depends on the personality function, i.e. it is language dependent, so can only be done by gcc. Thus this patch which generalizes the eh.selector intrinsic so that it can handle all possible kinds of action table entries (before it didn't accomodate cleanups): now 0 indicates a cleanup, and filters have to be specified using the number of type infos plus one rather than the number of type infos. Related gcc patches will cause Ada to pass a cleanup (0) to force the selector to always fire, while C++ will use a C++ catch-all (null). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41484 91177308-0d34-0410-b5e6-96231b3b80d8
2007-08-27 15:47:50 +00:00
/// 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() {
for (unsigned i = 0; i != LandingPads.size(); ) {
LandingPadInfo &LandingPad = LandingPads[i];
LandingPad.LandingPadLabel = MappedLabel(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;
}
Fix PR1628. When exception handling is turned on, labels are generated bracketing each call (not just invokes). This is used to generate entries in the exception table required by the C++ personality. However it gets in the way of tail-merging. This patch solves the problem by no longer placing labels around ordinary calls. Instead we generate entries in the exception table that cover every instruction in the function that wasn't covered by an invoke range (the range given by the labels around the invoke). As an optimization, such entries are only generated for parts of the function that contain a call, since for the moment those are the only instructions that can throw an exception [1]. As a happy consequence, we now get a smaller exception table, since the same region can cover many calls. While there, I also implemented folding of invoke ranges - successive ranges are merged when safe to do so. Finally, if a selector contains only a cleanup, there's a special shorthand for it - place a 0 in the call-site entry. I implemented this while there. As a result, the exception table output (excluding filters) is now optimal - it cannot be made smaller [2]. The problem with throw filters is that folding them optimally is hard, and the benefit of folding them is minimal. [1] I tested that having trapping instructions (eg divide by zero) in such a region doesn't cause trouble. [2] It could be made smaller with the help of higher layers, eg by having branch folding reorder basic blocks ending in invokes with the same landing pad so they follow each other. I don't know if this is worth doing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41718 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-05 11:27:52 +00:00
for (unsigned j=0; j != LandingPads[i].BeginLabels.size(); ) {
unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]);
unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]);
Fix PR1628. When exception handling is turned on, labels are generated bracketing each call (not just invokes). This is used to generate entries in the exception table required by the C++ personality. However it gets in the way of tail-merging. This patch solves the problem by no longer placing labels around ordinary calls. Instead we generate entries in the exception table that cover every instruction in the function that wasn't covered by an invoke range (the range given by the labels around the invoke). As an optimization, such entries are only generated for parts of the function that contain a call, since for the moment those are the only instructions that can throw an exception [1]. As a happy consequence, we now get a smaller exception table, since the same region can cover many calls. While there, I also implemented folding of invoke ranges - successive ranges are merged when safe to do so. Finally, if a selector contains only a cleanup, there's a special shorthand for it - place a 0 in the call-site entry. I implemented this while there. As a result, the exception table output (excluding filters) is now optimal - it cannot be made smaller [2]. The problem with throw filters is that folding them optimally is hard, and the benefit of folding them is minimal. [1] I tested that having trapping instructions (eg divide by zero) in such a region doesn't cause trouble. [2] It could be made smaller with the help of higher layers, eg by having branch folding reorder basic blocks ending in invokes with the same landing pad so they follow each other. I don't know if this is worth doing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41718 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-05 11:27:52 +00:00
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;
}
Fix PR1628. When exception handling is turned on, labels are generated bracketing each call (not just invokes). This is used to generate entries in the exception table required by the C++ personality. However it gets in the way of tail-merging. This patch solves the problem by no longer placing labels around ordinary calls. Instead we generate entries in the exception table that cover every instruction in the function that wasn't covered by an invoke range (the range given by the labels around the invoke). As an optimization, such entries are only generated for parts of the function that contain a call, since for the moment those are the only instructions that can throw an exception [1]. As a happy consequence, we now get a smaller exception table, since the same region can cover many calls. While there, I also implemented folding of invoke ranges - successive ranges are merged when safe to do so. Finally, if a selector contains only a cleanup, there's a special shorthand for it - place a 0 in the call-site entry. I implemented this while there. As a result, the exception table output (excluding filters) is now optimal - it cannot be made smaller [2]. The problem with throw filters is that folding them optimally is hard, and the benefit of folding them is minimal. [1] I tested that having trapping instructions (eg divide by zero) in such a region doesn't cause trouble. [2] It could be made smaller with the help of higher layers, eg by having branch folding reorder basic blocks ending in invokes with the same landing pad so they follow each other. I don't know if this is worth doing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41718 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-05 11:27:52 +00:00
// Remove landing pads with no try-ranges.
if (LandingPads[i].BeginLabels.empty()) {
Fix PR1628. When exception handling is turned on, labels are generated bracketing each call (not just invokes). This is used to generate entries in the exception table required by the C++ personality. However it gets in the way of tail-merging. This patch solves the problem by no longer placing labels around ordinary calls. Instead we generate entries in the exception table that cover every instruction in the function that wasn't covered by an invoke range (the range given by the labels around the invoke). As an optimization, such entries are only generated for parts of the function that contain a call, since for the moment those are the only instructions that can throw an exception [1]. As a happy consequence, we now get a smaller exception table, since the same region can cover many calls. While there, I also implemented folding of invoke ranges - successive ranges are merged when safe to do so. Finally, if a selector contains only a cleanup, there's a special shorthand for it - place a 0 in the call-site entry. I implemented this while there. As a result, the exception table output (excluding filters) is now optimal - it cannot be made smaller [2]. The problem with throw filters is that folding them optimally is hard, and the benefit of folding them is minimal. [1] I tested that having trapping instructions (eg divide by zero) in such a region doesn't cause trouble. [2] It could be made smaller with the help of higher layers, eg by having branch folding reorder basic blocks ending in invokes with the same landing pad so they follow each other. I don't know if this is worth doing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41718 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-05 11:27:52 +00:00
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;
}
}
/// getTypeIDFor - Return the type id for the specified typeinfo. This is
/// function wide.
unsigned MachineModuleInfo::getTypeIDFor(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();
}
/// 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
/// a info consumer to determine if the range of two labels is empty, by seeing
/// if the labels map to the same reduced label.
namespace llvm {
struct DebugLabelFolder : public MachineFunctionPass {
static char 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"; }
};
char DebugLabelFolder::ID = 0;
bool DebugLabelFolder::runOnMachineFunction(MachineFunction &MF) {
// Get machine module info.
MachineModuleInfo *MMI = getAnalysisToUpdate<MachineModuleInfo>();
if (!MMI) return false;
// Track if change is made.
bool MadeChange = false;
// No prior label to begin.
unsigned PriorLabel = 0;
// Iterate through basic blocks.
for (MachineFunction::iterator BB = MF.begin(), E = MF.end();
BB != E; ++BB) {
// Iterate through instructions.
for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
// Is it a label.
if (I->isDebugLabel()) {
// The label ID # is always operand #0, an immediate.
unsigned NextLabel = I->getOperand(0).getImm();
// If there was an immediate prior label.
if (PriorLabel) {
// Remap the current label to prior label.
MMI->RemapLabel(NextLabel, PriorLabel);
// Delete the current label.
I = BB->erase(I);
// Indicate a change has been made.
MadeChange = true;
continue;
} else {
// Start a new round.
PriorLabel = NextLabel;
}
} else {
// No consecutive labels.
PriorLabel = 0;
}
++I;
}
}
return MadeChange;
}
FunctionPass *createDebugLabelFoldingPass() { return new DebugLabelFolder(); }
}