Newer
Older
//===-- llvm/CodeGen/MachineDebugInfo.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/MachineDebugInfo.h"
#include "llvm/Constants.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 <iostream>
using namespace llvm;
// Handle the Pass registration stuff necessary to use TargetData's.
namespace {
RegisterPass<MachineDebugInfo> X("machinedebuginfo", "Debug Information");
//===----------------------------------------------------------------------===//
/// 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.
Jim Laskey
committed
std::vector<const Type*> FieldTypes;
FieldTypes.push_back(Type::UIntTy);
FieldTypes.push_back(PointerType::get(Type::SByteTy));
// Get the GlobalVariable root.
GlobalVariable *UseRoot = M.getGlobalVariable(RootName,
Jim Laskey
committed
StructType::get(FieldTypes));
// If present and linkonce then scan for users.
if (UseRoot && UseRoot->hasLinkOnceLinkage()) {
getGlobalVariablesUsing(UseRoot, Result);
}
return Result;
}
/// getStringValue - Turn an LLVM constant pointer that eventually points to a
/// global into a string value. Return an empty string if we can't do it.
///
static const std::string getStringValue(Value *V, unsigned Offset = 0) {
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) {
ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
if (Init->isString()) {
std::string Result = Init->getAsString();
if (Offset < Result.size()) {
// If we are pointing INTO The string, erase the beginning...
Result.erase(Result.begin(), Result.begin()+Offset);
// Take off the null terminator, and any string fragments after it.
std::string::size_type NullPos = Result.find_first_of((char)0);
if (NullPos != std::string::npos)
Result.erase(Result.begin()+NullPos, Result.end());
return Result;
}
}
}
} else if (Constant *C = dyn_cast<Constant>(V)) {
if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
return getStringValue(GV, Offset);
else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
if (CE->getOpcode() == Instruction::GetElementPtr) {
// Turn a gep into the specified offset.
if (CE->getNumOperands() == 3 &&
cast<Constant>(CE->getOperand(1))->isNullValue() &&
isa<ConstantInt>(CE->getOperand(2))) {
return getStringValue(CE->getOperand(0),
Offset+cast<ConstantInt>(CE->getOperand(2))->getRawValue());
}
}
}
}
return "";
}
/// 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::Cast) {
return dyn_cast<GlobalVariable>(CE->getOperand(0));
}
}
return NULL;
}
/// isGlobalVariable - Return true if the given value can be coerced to a
/// GlobalVariable.
if (isa<GlobalVariable>(V) || isa<ConstantPointerNull>(V)) {
return true;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (CE->getOpcode() == Instruction::Cast) {
return isa<GlobalVariable>(CE->getOperand(0));
}
}
return false;
}
/// getUIntOperand - Return ith operand if it is an unsigned integer.
static ConstantUInt *getUIntOperand(GlobalVariable *GV, unsigned i) {
// Make sure the GlobalVariable has an initializer.
// Get the initializer constant.
ConstantStruct *CI = dyn_cast<ConstantStruct>(GV->getInitializer());
// Check if there is at least i + 1 operands.
unsigned N = CI->getNumOperands();
// Check constant.
return dyn_cast<ConstantUInt>(CI->getOperand(i));
}
//===----------------------------------------------------------------------===//
/// ApplyToFields - Target the visitor to each field of the debug information
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:
Jim Laskey
committed
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(bool &Field) { ++Count; }
virtual void Apply(std::string &Field) { ++Count; }
virtual void Apply(DebugInfoDesc *&Field) { ++Count; }
virtual void Apply(GlobalVariable *&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()
Jim Laskey
committed
, I(0)
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
, 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<ConstantSInt>(C)->getValue();
}
virtual void Apply(unsigned &Field) {
Constant *C = CI->getOperand(I++);
Field = cast<ConstantUInt>(C)->getValue();
}
virtual void Apply(bool &Field) {
Constant *C = CI->getOperand(I++);
Field = cast<ConstantBool>(C)->getValue();
}
virtual void Apply(std::string &Field) {
Constant *C = CI->getOperand(I++);
Field = getStringValue(C);
}
virtual void Apply(DebugInfoDesc *&Field) {
Constant *C = CI->getOperand(I++);
Field = DR.Deserialize(C);
}
virtual void Apply(GlobalVariable *&Field) {
Constant *C = CI->getOperand(I++);
//===----------------------------------------------------------------------===//
/// DISerializeVisitor - This DIVisitor serializes all the fields in
/// the supplied DebugInfoDesc.
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) {
Jim Laskey
committed
Elements.push_back(ConstantSInt::get(Type::IntTy, Field));
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
}
virtual void Apply(unsigned &Field) {
Elements.push_back(ConstantUInt::get(Type::UIntTy, Field));
}
virtual void Apply(bool &Field) {
Elements.push_back(ConstantBool::get(Field));
}
virtual void Apply(std::string &Field) {
Elements.push_back(SR.getString(Field));
}
virtual void Apply(DebugInfoDesc *&Field) {
GlobalVariable *GV = NULL;
// If non-NULL the 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::getCast(GV, EmptyTy));
} else {
// Use NULL.
Elements.push_back(ConstantPointerNull::get(EmptyTy));
}
}
virtual void Apply(GlobalVariable *&Field) {
const PointerType *EmptyTy = SR.getEmptyStructPtrType();
Jim Laskey
committed
if (Field) {
Elements.push_back(ConstantExpr::getCast(Field, EmptyTy));
} else {
Elements.push_back(ConstantPointerNull::get(EmptyTy));
}
}
};
//===----------------------------------------------------------------------===//
/// DIGetTypesVisitor - This DIVisitor gathers all the field types in
/// the supplied DebugInfoDesc.
private:
DISerializer &SR; // Active serializer.
std::vector<const Type*> &Fields; // Type accumulator.
public:
DIGetTypesVisitor(DISerializer &S, std::vector<const Type*> &F)
: DIVisitor()
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
, SR(S)
, Fields(F)
{}
/// Apply - Set the value of each of the fields.
///
virtual void Apply(int &Field) {
Fields.push_back(Type::IntTy);
}
virtual void Apply(unsigned &Field) {
Fields.push_back(Type::UIntTy);
}
virtual void Apply(bool &Field) {
Fields.push_back(Type::BoolTy);
}
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);
}
};
//===----------------------------------------------------------------------===//
/// DIVerifyVisitor - This DIVisitor verifies all the field types against
/// a constant initializer.
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)
Jim Laskey
committed
, I(0)
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
, 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(bool &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isa<ConstantBool>(C);
}
virtual void Apply(std::string &Field) {
Constant *C = CI->getOperand(I++);
IsValid = IsValid && isStringValue(C);
}
virtual void Apply(DebugInfoDesc *&Field) {
// FIXME - Prepare the correct descriptor.
Constant *C = CI->getOperand(I++);
}
virtual void Apply(GlobalVariable *&Field) {
Constant *C = CI->getOperand(I++);
Jim Laskey
committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
//===----------------------------------------------------------------------===//
/// TagFromGlobal - Returns the Tag number from a debug info descriptor
/// GlobalVariable.
unsigned DebugInfoDesc::TagFromGlobal(GlobalVariable *GV) {
ConstantUInt *C = getUIntOperand(GV, 0);
return C ? (unsigned)C->getValue() : (unsigned)DIInvalid;
}
/// 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 DI_TAG_anchor: return new AnchorDesc();
case DI_TAG_compile_unit: return new CompileUnitDesc();
case DI_TAG_global_variable: return new GlobalVariableDesc();
case DI_TAG_subprogram: return new SubprogramDesc();
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);
}
//===----------------------------------------------------------------------===//
/// 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(Name);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *AnchorDesc::getDescString() const {
return Name.c_str();
}
/// 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() {
std::cerr << getDescString() << " "
<< "Tag(" << getTag() << "), "
<< "Name(" << Name << ")\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((DebugInfoDesc *&)Anchor);
}
//===----------------------------------------------------------------------===//
Jim Laskey
committed
CompileUnitDesc::CompileUnitDesc()
: AnchoredDesc(DI_TAG_compile_unit)
, DebugVersion(LLVMDebugVersion)
, Language(0)
, FileName("")
, Directory("")
, Producer("")
{}
/// DebugVersionFromGlobal - Returns the version number from a compile unit
/// GlobalVariable.
unsigned CompileUnitDesc::DebugVersionFromGlobal(GlobalVariable *GV) {
Jim Laskey
committed
ConstantUInt *C = getUIntOperand(GV, 2);
return C ? (unsigned)C->getValue() : (unsigned)DIInvalid;
/// ApplyToFields - Target the visitor to the fields of the CompileUnitDesc.
///
void CompileUnitDesc::ApplyToFields(DIVisitor *Visitor) {
Jim Laskey
committed
AnchoredDesc::ApplyToFields(Visitor);
Visitor->Apply(DebugVersion);
Visitor->Apply(Language);
Visitor->Apply(FileName);
Visitor->Apply(Directory);
Visitor->Apply(Producer);
}
Jim Laskey
committed
/// 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.
Jim Laskey
committed
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::getAnchorString() const {
return "llvm.dbg.compile_units";
}
#ifndef NDEBUG
void CompileUnitDesc::dump() {
Jim Laskey
committed
std::cerr << getDescString() << " "
<< "Tag(" << getTag() << "), "
Jim Laskey
committed
<< "Anchor(" << getAnchor() << "), "
<< "DebugVersion(" << DebugVersion << "), "
<< "Language(" << Language << "), "
<< "FileName(\"" << FileName << "\"), "
<< "Directory(\"" << Directory << "\"), "
<< "Producer(\"" << Producer << "\")\n";
}
//===----------------------------------------------------------------------===//
Jim Laskey
committed
GlobalDesc::GlobalDesc(unsigned T)
: AnchoredDesc(T)
, Context(0)
, Name("")
, TyDesc(NULL)
, IsStatic(false)
, IsDefinition(false)
{}
/// ApplyToFields - Target the visitor to the fields of the global.
Jim Laskey
committed
void GlobalDesc::ApplyToFields(DIVisitor *Visitor) {
AnchoredDesc::ApplyToFields(Visitor);
Visitor->Apply(Context);
Visitor->Apply(Name);
Visitor->Apply(TyDesc);
Visitor->Apply(IsStatic);
Visitor->Apply(IsDefinition);
Jim Laskey
committed
}
//===----------------------------------------------------------------------===//
GlobalVariableDesc::GlobalVariableDesc()
: GlobalDesc(DI_TAG_global_variable)
, Global(NULL)
{}
/// ApplyToFields - Target the visitor to the fields of the GlobalVariableDesc.
///
void GlobalVariableDesc::ApplyToFields(DIVisitor *Visitor) {
GlobalDesc::ApplyToFields(Visitor);
}
Jim Laskey
committed
/// getDescString - Return a string used to compose global names and labels.
///
Jim Laskey
committed
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::getAnchorString() const {
return "llvm.dbg.global_variables";
}
#ifndef NDEBUG
void GlobalVariableDesc::dump() {
Jim Laskey
committed
std::cerr << getDescString() << " "
<< "Tag(" << getTag() << "), "
Jim Laskey
committed
<< "Anchor(" << getAnchor() << "), "
<< "Name(\"" << getName() << "\"), "
<< "IsStatic(" << (isStatic() ? "true" : "false") << "), "
<< "IsDefinition(" << (isDefinition() ? "true" : "false") << "), "
<< "Global(" << Global << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
Jim Laskey
committed
SubprogramDesc::SubprogramDesc()
: GlobalDesc(DI_TAG_subprogram)
{}
/// ApplyToFields - Target the visitor to the fields of the
/// SubprogramDesc.
void SubprogramDesc::ApplyToFields(DIVisitor *Visitor) {
Jim Laskey
committed
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";
Jim Laskey
committed
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
Jim Laskey
committed
const char *SubprogramDesc::getAnchorString() const {
return "llvm.dbg.subprograms";
}
#ifndef NDEBUG
void SubprogramDesc::dump() {
Jim Laskey
committed
std::cerr << getDescString() << " "
<< "Tag(" << getTag() << "), "
Jim Laskey
committed
<< "Anchor(" << getAnchor() << "), "
<< "Name(\"" << getName() << "\"), "
<< "IsStatic(" << (isStatic() ? "true" : "false") << "), "
<< "IsDefinition(" << (isDefinition() ? "true" : "false") << ")\n";
//===----------------------------------------------------------------------===//
DebugInfoDesc *DIDeserializer::Deserialize(Value *V) {
Jim Laskey
committed
return Deserialize(getGlobalVariable(V));
}
DebugInfoDesc *DIDeserializer::Deserialize(GlobalVariable *GV) {
Jim Laskey
committed
// 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);
// Get the debug version if a compile unit.
if (Tag == DI_TAG_compile_unit) {
DebugVersion = CompileUnitDesc::DebugVersionFromGlobal(GV);
}
// Create an empty instance of the correct sort.
Slot = DebugInfoDesc::DescFactory(Tag);
assert(Slot && "Unknown Tag");
// Deserialize the fields.
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::SByteTy);
}
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;
Jim Laskey
committed
// Get types of fields.
GTAM.ApplyToFields(DD);
// Construct structured type.
Ty = StructType::get(Fields);
// Register type name with module.
Jim Laskey
committed
M->addTypeName(DD->getTypeString(), Ty);
}
return Ty;
}
/// getString - Construct the string as constant string global.
///
Jim Laskey
committed
Constant *DISerializer::getString(const std::string &String) {
// Check string cache for previous edition.
Jim Laskey
committed
Constant *&Slot = StringCache[String];
// return Constant if previously defined.
if (Slot) return Slot;
Jim Laskey
committed
// Construct string as an llvm constant.
Constant *ConstStr = ConstantArray::get(String);
// Otherwise create and return a new string global.
Jim Laskey
committed
GlobalVariable *StrGV = new GlobalVariable(ConstStr->getType(), true,
GlobalVariable::InternalLinkage,
ConstStr, "str", M);
// Convert to generic string pointer.
Slot = ConstantExpr::getCast(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.
Jim Laskey
committed
GlobalVariable *GV = new GlobalVariable(Ty, true, DD->getLinkage(),
NULL, DD->getDescString(), M);
// Insert new GlobalVariable in DescGlobals map.
Slot = GV;
// Set up elements vector
std::vector<Constant*> Elements;
Jim Laskey
committed
// Add fields.
SRAM.ApplyToFields(DD);
// Set the globals initializer.
GV->setInitializer(ConstantStruct::get(Ty, Elements));
return GV;
}
//===----------------------------------------------------------------------===//
/// markVisited - Return true if the GlobalVariable hase been "seen" before.
/// Mark visited otherwise.
bool DIVerifier::markVisited(GlobalVariable *GV) {
// Check if the GlobalVariable is already in the Visited set.
std::set<GlobalVariable *>::iterator VI = Visited.lower_bound(GV);
// See if GlobalVariable exists.
bool Exists = VI != Visited.end() && *VI == GV;
// Insert in set.
if (!Exists) Visited.insert(VI, GV);
return Exists;
}
/// Verify - Return true if the GlobalVariable appears to be a valid
/// serialization of a DebugInfoDesc.
Jim Laskey
committed
bool DIVerifier::Verify(Value *V) {
return Verify(getGlobalVariable(V));
}
bool DIVerifier::Verify(GlobalVariable *GV) {
// Check if seen before.
if (markVisited(GV)) return true;
// Get the Tag
// If a compile unit we need the debug version.
if (Tag == DI_TAG_compile_unit) {
DebugVersion = CompileUnitDesc::DebugVersionFromGlobal(GV);
}
// Construct an empty DebugInfoDesc.
DebugInfoDesc *DD = DebugInfoDesc::DescFactory(Tag);
if (!DD) return false;
// Get the initializer constant.
ConstantStruct *CI = cast<ConstantStruct>(GV->getInitializer());
// Get the operand count.
unsigned N = CI->getNumOperands();
// Get the field count.
unsigned &Slot = Counts[Tag];
if (!Slot) {
// Check the operand count to the field count
CTAM.ApplyToFields(DD);
Slot = CTAM.getCount();
}
// Field count must equal operand count.
if (Slot != N) {
delete DD;
return false;
}
// Check each field for valid type.
VRAM.ApplyToFields(DD);
// Release empty DebugInfoDesc.
delete DD;
// Return result of field tests.
return VRAM.isValid();
}
//===----------------------------------------------------------------------===//
MachineDebugInfo::MachineDebugInfo()
Jim Laskey
committed
: DR()
, Directories()
, SourceFiles()
, Lines()
{
}
MachineDebugInfo::~MachineDebugInfo() {
}
/// doInitialization - Initialize the debug state for a new module.
///
bool MachineDebugInfo::doInitialization() {
return false;
}
/// doFinalization - Tear down the debug state after completion of a module.
///
bool MachineDebugInfo::doFinalization() {
return false;
}
/// getDescFor - Convert a Value to a debug information descriptor.
Jim Laskey
committed
///
// FIXME - use new Value type when available.
DebugInfoDesc *MachineDebugInfo::getDescFor(Value *V) {
Jim Laskey
committed
return DR.Deserialize(V);
}
/// Verify - Verify that a Value is debug information descriptor.
///
bool MachineDebugInfo::Verify(Value *V) {
DIVerifier VR;
return VR.Verify(V);
}
/// AnalyzeModule - Scan the module for global debug information.
///
void MachineDebugInfo::AnalyzeModule(Module &M) {
SetupCompileUnits(M);
}
/// SetupCompileUnits - Set up the unique vector of compile units.
///
void MachineDebugInfo::SetupCompileUnits(Module &M) {
// Get vector of all debug compile units.
Jim Laskey
committed
CompileUnitDesc CompileUnit;
std::vector<GlobalVariable*> Globals =
Jim Laskey
committed
getGlobalVariablesUsing(M, CompileUnit.getAnchorString());
// Scan all compile unit globals.
for (unsigned i = 0, N = Globals.size(); i < N; ++i) {
// Add compile unit to result.
CompileUnits.insert(
static_cast<CompileUnitDesc *>(DR.Deserialize(Globals[i])));
}
}
/// getCompileUnits - Return a vector of debug compile units.
///
const UniqueVector<CompileUnitDesc *> MachineDebugInfo::getCompileUnits()const{
return CompileUnits;
}
/// getGlobalVariables - Return a vector of debug GlobalVariables.
///
std::vector<GlobalVariableDesc *>
MachineDebugInfo::getGlobalVariables(Module &M) {
// Get vector of all debug global objects.
Jim Laskey
committed
GlobalVariableDesc Global;
std::vector<GlobalVariable*> Globals =
Jim Laskey
committed
getGlobalVariablesUsing(M, Global.getAnchorString());
// Accumulation of GlobalVariables.
std::vector<GlobalVariableDesc *> GlobalVariables;
// Scan all globals.
for (unsigned i = 0, N = Globals.size(); i < N; ++i) {
GlobalVariable *GV = Globals[i];
Jim Laskey
committed
GlobalVariableDesc *GVD =
static_cast<GlobalVariableDesc *>(DR.Deserialize(GV));
GlobalVariables.push_back(GVD);
}
return GlobalVariables;
}