mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 00:11:00 +00:00
57810cdac4
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
1921 lines
57 KiB
C++
1921 lines
57 KiB
C++
//===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===//
|
|
//
|
|
// 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
|
|
#include "llvm/Constants.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineLocation.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.
|
|
namespace {
|
|
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 std::vector<GlobalVariable*>
|
|
getGlobalVariablesUsing(Module &M, const std::string &RootName) {
|
|
std::vector<GlobalVariable*> Result; // GlobalVariables matching criteria.
|
|
|
|
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);
|
|
}
|
|
|
|
return 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));
|
|
}
|
|
}
|
|
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));
|
|
}
|
|
}
|
|
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));
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// 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;
|
|
}
|
|
};
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
/// 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++);
|
|
Field = C->getStringValue();
|
|
}
|
|
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->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 *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 *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 *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::get(Type::Int8Ty);
|
|
}
|
|
|
|
return StrPtrTy;
|
|
}
|
|
|
|
/// getEmptyStructPtrType - Return a "{ }*" type.
|
|
///
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// 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
|
|
DICountVisitor CTAM;
|
|
CTAM.ApplyToFields(DD);
|
|
CountSlot = CTAM.getCount();
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
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((intptr_t)&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);
|
|
}
|
|
|
|
/// 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;
|
|
}
|
|
|
|
/// SetupCompileUnits - Set up the unique vector of compile units.
|
|
///
|
|
void MachineModuleInfo::SetupCompileUnits(Module &M) {
|
|
std::vector<CompileUnitDesc *>CU = getAnchoredDescriptors<CompileUnitDesc>(M);
|
|
|
|
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.
|
|
std::vector<GlobalVariable*>
|
|
MachineModuleInfo::getGlobalVariablesUsing(Module &M,
|
|
const std::string &RootName) {
|
|
return ::getGlobalVariablesUsing(M, RootName);
|
|
}
|
|
|
|
/// RecordLabel - 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 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(Value *V, unsigned FrameIndex) {
|
|
VariableDesc *VD = cast<VariableDesc>(DR.Deserialize(V));
|
|
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));
|
|
}
|
|
|
|
/// 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
|
|
// "rethrow" 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.size()) {
|
|
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((intptr_t)&ID) {}
|
|
|
|
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;
|
|
// Get target instruction info.
|
|
const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
|
|
if (!TII) 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 ((unsigned)I->getOpcode() == TargetInstrInfo::LABEL) {
|
|
// 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(); }
|
|
|
|
}
|
|
|