[llvm-commits] [llvm] r58954 - in /llvm/trunk: include/llvm/Analysis/DebugInfo.h lib/Analysis/DebugInfo.cpp
Chris Lattner
sabre at nondot.org
Sun Nov 9 18:56:27 PST 2008
Author: lattner
Date: Sun Nov 9 20:56:27 2008
New Revision: 58954
URL: http://llvm.org/viewvc/llvm-project?rev=58954&view=rev
Log:
Add a new set of helper classes for creating and reading debug
information. This logically replaces the "Desc" classes in
MachineModuleInfo. Nice features of these classes are that they:
1. Are much more efficient than MMI because they don't create a
temporary parallel data structure for debug info that has to be
'serialized' and 'deserialized' into/out of the module.
2. These provide a much cleaner abstraction for debug info than
MMI, which will make it easier to change the implementation in
the future (to be MDNode-based).
3. These are much easier to use than the MMI interfaces, requiring
a lot less code in the front-ends.
4. These can be used to both create (for frontends) and read (for
codegen) debug information. DebugInfoBuilder can only be used
to create the nodes.
So far, this is implemented just enough to support the debug info
generation needs of clang. This can and should be extended to
support the full set of debug info constructs, and we should switch
llvm-gcc and llc over to using this in the near future.
This code also has a ton of FIXMEs in it, because the way we
currently represent debug info in LLVM IR is basically insane in a
variety of details. This sort of issue should be fixed when we
eventually reimplement debug info on top of MDNodes.
Added:
llvm/trunk/include/llvm/Analysis/DebugInfo.h
llvm/trunk/lib/Analysis/DebugInfo.cpp
Added: llvm/trunk/include/llvm/Analysis/DebugInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/DebugInfo.h?rev=58954&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Analysis/DebugInfo.h (added)
+++ llvm/trunk/include/llvm/Analysis/DebugInfo.h Sun Nov 9 20:56:27 2008
@@ -0,0 +1,394 @@
+//===--- llvm/Analysis/DebugInfo.h - Debug Information Helpers --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a bunch of datatypes that are useful for creating and
+// walking debug info in LLVM IR form.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_DEBUGINFO_H
+#define LLVM_SUPPORT_DEBUGINFO_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+ class BasicBlock;
+ class Constant;
+ class Function;
+ class GlobalVariable;
+ class Module;
+ class Value;
+
+ class DIDescriptor {
+ public:
+ enum {
+ Version6 = 6 << 16, // Current version of debug information.
+ Version5 = 5 << 16, // Constant for version 5.
+ Version4 = 4 << 16, // Constant for version 4.
+ VersionMask = 0xffff0000 // Mask for version number.
+ };
+
+ protected:
+ GlobalVariable *GV;
+
+ /// DIDescriptor constructor. If the specified GV is non-null, this checks
+ /// to make sure that the tag in the descriptor matches 'RequiredTag'. If
+ /// not, the debug info is corrupt and we ignore it.
+ DIDescriptor(GlobalVariable *GV, unsigned RequiredTag);
+
+ unsigned getTag() const {
+ return getUnsignedField(0) & ~VersionMask;
+ }
+ unsigned getVersion() const {
+ return getUnsignedField(0) & VersionMask;
+ }
+
+ std::string getStringField(unsigned Elt) const;
+ unsigned getUnsignedField(unsigned Elt) const {
+ return (unsigned)getUInt64Field(Elt);
+ }
+ uint64_t getUInt64Field(unsigned Elt) const;
+ DIDescriptor getDescriptorField(unsigned Elt) const;
+
+ template <typename DescTy>
+ DescTy getFieldAs(unsigned Elt) const {
+ return DescTy(getDescriptorField(6).getGV());
+ }
+
+ GlobalVariable *getGlobalVariableField(unsigned Elt) const;
+
+ public:
+ explicit DIDescriptor() : GV(0) {}
+ explicit DIDescriptor(GlobalVariable *gv) : GV(gv) {}
+
+ bool isNull() const { return GV == 0; }
+
+ GlobalVariable *getGV() const { return GV; }
+
+ /// getCastToEmpty - Return this descriptor as a Constant* with type '{}*'.
+ Constant *getCastToEmpty() const;
+ };
+
+ /// DIAnchor - A wrapper for various anchor descriptors.
+ class DIAnchor : public DIDescriptor {
+ public:
+ explicit DIAnchor(GlobalVariable *GV = 0);
+
+ unsigned getAnchorTag() const { return getUnsignedField(1); }
+ };
+
+ /// DIArray - This descriptor holds an array of descriptors.
+ class DIArray : public DIDescriptor {
+ public:
+ explicit DIArray(GlobalVariable *GV = 0) : DIDescriptor(GV) {}
+
+ unsigned getNumElements() const;
+ DIDescriptor getElement(unsigned Idx) const;
+ };
+
+ /// DICompileUnit - A wrapper for a compile unit.
+ class DICompileUnit : public DIDescriptor {
+ public:
+ explicit DICompileUnit(GlobalVariable *GV = 0);
+
+ unsigned getLanguage() const { return getUnsignedField(2); }
+ std::string getFilename() const { return getStringField(3); }
+ std::string getDirectory() const { return getStringField(4); }
+ std::string getProducer() const { return getStringField(5); }
+ };
+
+ /// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}').
+ /// FIXME: it seems strange that this doesn't have either a reference to the
+ /// type/precision or a file/line pair for location info.
+ class DIEnumerator : public DIDescriptor {
+ public:
+ explicit DIEnumerator(GlobalVariable *GV = 0);
+
+ std::string getName() const { return getStringField(1); }
+ uint64_t getLanguage() const { return getUInt64Field(2); }
+ };
+
+ /// DISubrange - This is used to represent ranges, for array bounds.
+ class DISubrange : public DIDescriptor {
+ public:
+ explicit DISubrange(GlobalVariable *GV = 0);
+
+ int64_t getLo() const { return (int64_t)getUInt64Field(1); }
+ int64_t getHi() const { return (int64_t)getUInt64Field(2); }
+ };
+
+ /// DIType - This is a wrapper for a type.
+ /// FIXME: Types should be factored much better so that CV qualifiers and
+ /// others do not require a huge and empty descriptor full of zeros.
+ class DIType : public DIDescriptor {
+ protected:
+ DIType(GlobalVariable *GV, unsigned Tag) : DIDescriptor(GV, Tag) {}
+ // This ctor is used when the Tag has already been validated by a derived
+ // ctor.
+ DIType(GlobalVariable *GV, bool, bool) : DIDescriptor(GV) {}
+ public:
+ explicit DIType(GlobalVariable *GV);
+ explicit DIType() {}
+
+ DIDescriptor getContext() const { return getDescriptorField(1); }
+ std::string getName() const { return getStringField(2); }
+ DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
+ unsigned getLineNumber() const { return getUnsignedField(4); }
+ uint64_t getSizeInBits() const { return getUInt64Field(5); }
+ uint64_t getAlignInBits() const { return getUInt64Field(6); }
+ // FIXME: Offset is only used for DW_TAG_member nodes. Making every type
+ // carry this is just plain insane.
+ uint64_t getOffsetInBits() const { return getUInt64Field(7); }
+ unsigned getFlags() const { return getUnsignedField(8); }
+ };
+
+ /// DIBasicType - A basic type, like 'int' or 'float'.
+ class DIBasicType : public DIType {
+ public:
+ explicit DIBasicType(GlobalVariable *GV);
+
+ unsigned getEncoding() const { return getUnsignedField(9); }
+ };
+
+ /// DIDerivedType - A simple derived type, like a const qualified type,
+ /// a typedef, a pointer or reference, etc.
+ class DIDerivedType : public DIType {
+ protected:
+ explicit DIDerivedType(GlobalVariable *GV, bool, bool)
+ : DIType(GV, true, true) {}
+ public:
+ explicit DIDerivedType(GlobalVariable *GV);
+
+ DIType getTypeDerivedFrom() const { return getFieldAs<DIType>(9); }
+
+ /// isDerivedType - Return true if the specified tag is legal for
+ /// DIDerivedType.
+ static bool isDerivedType(unsigned TAG);
+ };
+
+
+ /// DICompositeType - This descriptor holds a type that can refer to multiple
+ /// other types, like a function or struct.
+ /// FIXME: Why is this a DIDerivedType??
+ class DICompositeType : public DIDerivedType {
+ public:
+ explicit DICompositeType(GlobalVariable *GV);
+
+ DIArray getTypeArray() const { return getFieldAs<DIArray>(10); }
+
+ /// isCompositeType - Return true if the specified tag is legal for
+ /// DICompositeType.
+ static bool isCompositeType(unsigned TAG);
+ };
+
+ /// DIGlobal - This is a common class for global variables and subprograms.
+ class DIGlobal : public DIDescriptor {
+ protected:
+ explicit DIGlobal(GlobalVariable *GV = 0, unsigned RequiredTag)
+ : DIDescriptor(GV, RequiredTag) {}
+ public:
+
+ DIDescriptor getContext() const { return getDescriptorField(2); }
+ std::string getName() const { return getStringField(3); }
+ std::string getDisplayName() const { return getStringField(4); }
+ std::string getLinkageName() const { return getStringField(5); }
+
+ DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(6); }
+ unsigned getLineNumber() const { return getUnsignedField(7); }
+ DIType getType() const { return getFieldAs<DIType>(8); }
+
+ /// isLocalToUnit - Return true if this subprogram is local to the current
+ /// compile unit, like 'static' in C.
+ unsigned isLocalToUnit() const { return getUnsignedField(9); }
+ unsigned isDefinition() const { return getUnsignedField(10); }
+ };
+
+
+ /// DISubprogram - This is a wrapper for a subprogram (e.g. a function).
+ class DISubprogram : public DIGlobal {
+ public:
+ explicit DISubprogram(GlobalVariable *GV = 0);
+
+ };
+
+ /// DIGlobalVariable - This is a wrapper for a global variable.
+ class DIGlobalVariable : public DIGlobal {
+ public:
+ explicit DIGlobalVariable(GlobalVariable *GV = 0);
+
+ GlobalVariable *getGlobal() const { return getGlobalVariableField(11); }
+ };
+
+
+ /// DIVariable - This is a wrapper for a variable (e.g. parameter, local,
+ /// global etc).
+ class DIVariable : public DIDescriptor {
+ public:
+ explicit DIVariable(GlobalVariable *GV = 0);
+
+ DIDescriptor getContext() const { return getDescriptorField(1); }
+ std::string getName() const { return getStringField(2); }
+
+ DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); }
+ unsigned getLineNumber() const { return getUnsignedField(4); }
+ DIType getType() const { return getFieldAs<DIType>(5); }
+
+ /// isVariable - Return true if the specified tag is legal for DIVariable.
+ static bool isVariable(unsigned Tag);
+ };
+
+
+ /// DIBlock - This is a wrapper for a block (e.g. a function, scope, etc).
+ class DIBlock : public DIDescriptor {
+ public:
+ explicit DIBlock(GlobalVariable *GV = 0);
+
+ DIDescriptor getContext() const { return getDescriptorField(1); }
+ };
+
+ /// DIFactory - This object assists with the construction of the various
+ /// descriptors.
+ class DIFactory {
+ Module &M;
+ // Cached values for uniquing and faster lookups.
+ DIAnchor CompileUnitAnchor, SubProgramAnchor, GlobalVariableAnchor;
+ Function *StopPointFn; // llvm.dbg.stoppoint
+ Function *FuncStartFn; // llvm.dbg.func.start
+ Function *RegionStartFn; // llvm.dbg.region.start
+ Function *RegionEndFn; // llvm.dbg.region.end
+ Function *DeclareFn; // llvm.dbg.declare
+ StringMap<Constant*> StringCache;
+ DenseMap<Constant*, DIDescriptor> SimpleConstantCache;
+
+ DIFactory(const DIFactory &); // DO NOT IMPLEMENT
+ void operator=(const DIFactory&); // DO NOT IMPLEMENT
+ public:
+ explicit DIFactory(Module &m) : M(m) {
+ StopPointFn = FuncStartFn = RegionStartFn = RegionEndFn = DeclareFn = 0;
+ }
+
+ /// GetOrCreateCompileUnitAnchor - Return the anchor for compile units,
+ /// creating a new one if there isn't already one in the module.
+ DIAnchor GetOrCreateCompileUnitAnchor();
+
+ /// GetOrCreateSubprogramAnchor - Return the anchor for subprograms,
+ /// creating a new one if there isn't already one in the module.
+ DIAnchor GetOrCreateSubprogramAnchor();
+
+ /// GetOrCreateGlobalVariableAnchor - Return the anchor for globals,
+ /// creating a new one if there isn't already one in the module.
+ DIAnchor GetOrCreateGlobalVariableAnchor();
+
+ /// GetOrCreateArray - Create an descriptor for an array of descriptors.
+ /// This implicitly uniques the arrays created.
+ DIArray GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys);
+
+ /// GetOrCreateSubrange - Create a descriptor for a value range. This
+ /// implicitly uniques the values returned.
+ DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi);
+
+
+ /// CreateCompileUnit - Create a new descriptor for the specified compile
+ /// unit.
+ DICompileUnit CreateCompileUnit(unsigned LangID,
+ const std::string &Filename,
+ const std::string &Directory,
+ const std::string &Producer);
+
+ /// CreateEnumerator - Create a single enumerator value.
+ DIEnumerator CreateEnumerator(const std::string &Name, uint64_t Val);
+
+ /// CreateBasicType - Create a basic type like int, float, etc.
+ DIBasicType CreateBasicType(DIDescriptor Context, const std::string &Name,
+ DICompileUnit CompileUnit, unsigned LineNumber,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ unsigned Encoding);
+
+ /// CreateDerivedType - Create a derived type like const qualified type,
+ /// pointer, typedef, etc.
+ DIDerivedType CreateDerivedType(unsigned Tag, DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit,
+ unsigned LineNumber,
+ uint64_t SizeInBits, uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ DIType DerivedFrom);
+
+ /// CreateCompositeType - Create a composite type like array, struct, etc.
+ DICompositeType CreateCompositeType(unsigned Tag, DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit,
+ unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ DIType DerivedFrom,
+ DIArray Elements);
+
+ /// CreateSubprogram - Create a new descriptor for the specified subprogram.
+ /// See comments in DISubprogram for descriptions of these fields.
+ DISubprogram CreateSubprogram(DIDescriptor Context, const std::string &Name,
+ const std::string &DisplayName,
+ const std::string &LinkageName,
+ DICompileUnit CompileUnit, unsigned LineNo,
+ DIType Type, bool isLocalToUnit,
+ bool isDefinition);
+
+ /// CreateGlobalVariable - Create a new descriptor for the specified global.
+ DIGlobalVariable
+ CreateGlobalVariable(DIDescriptor Context, const std::string &Name,
+ const std::string &DisplayName,
+ const std::string &LinkageName,
+ DICompileUnit CompileUnit,
+ unsigned LineNo, DIType Type, bool isLocalToUnit,
+ bool isDefinition, llvm::GlobalVariable *GV);
+
+
+ /// CreateVariable - Create a new descriptor for the specified variable.
+ DIVariable CreateVariable(unsigned Tag, DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit, unsigned LineNo,
+ DIType Type);
+
+ /// CreateBlock - This creates a descriptor for a lexical block with the
+ /// specified parent context.
+ DIBlock CreateBlock(DIDescriptor Context);
+
+ /// InsertStopPoint - Create a new llvm.dbg.stoppoint intrinsic invocation,
+ /// inserting it at the end of the specified basic block.
+ void InsertStopPoint(DICompileUnit CU, unsigned LineNo, unsigned ColNo,
+ BasicBlock *BB);
+
+ /// InsertSubprogramStart - Create a new llvm.dbg.func.start intrinsic to
+ /// mark the start of the specified subprogram.
+ void InsertSubprogramStart(DISubprogram SP, BasicBlock *BB);
+
+ /// InsertRegionStart - Insert a new llvm.dbg.region.start intrinsic call to
+ /// mark the start of a region for the specified scoping descriptor.
+ void InsertRegionStart(DIDescriptor D, BasicBlock *BB);
+
+ /// InsertRegionEnd - Insert a new llvm.dbg.region.end intrinsic call to
+ /// mark the end of a region for the specified scoping descriptor.
+ void InsertRegionEnd(DIDescriptor D, BasicBlock *BB);
+
+ /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
+ void InsertDeclare(llvm::Value *Storage, DIVariable D, BasicBlock *BB);
+
+ private:
+ Constant *GetTagConstant(unsigned TAG);
+ Constant *GetStringConstant(const std::string &String);
+ DIAnchor GetOrCreateAnchor(unsigned TAG, const char *Name);
+ };
+
+
+} // end namespace llvm
+
+#endif
Added: llvm/trunk/lib/Analysis/DebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/DebugInfo.cpp?rev=58954&view=auto
==============================================================================
--- llvm/trunk/lib/Analysis/DebugInfo.cpp (added)
+++ llvm/trunk/lib/Analysis/DebugInfo.cpp Sun Nov 9 20:56:27 2008
@@ -0,0 +1,662 @@
+//===--- DebugInfo.cpp - Debug Information Helper Classes -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the helper classes used to build and interpret debug
+// information in LLVM IR form.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Instructions.h"
+#include "llvm/Module.h"
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/Support/Dwarf.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// DIDescriptor
+//===----------------------------------------------------------------------===//
+
+DIDescriptor::DIDescriptor(GlobalVariable *gv, unsigned RequiredTag) {
+ GV = gv;
+
+ // If this is non-null, check to see if the Tag matches. If not, set to null.
+ if (GV && getTag() != RequiredTag)
+ GV = 0;
+}
+
+
+std::string DIDescriptor::getStringField(unsigned Elt) const {
+ if (GV == 0) return "";
+ Constant *C = GV->getInitializer();
+ if (C == 0 || Elt >= C->getNumOperands())
+ return "";
+
+ std::string Result;
+ // Fills in the string if it succeeds
+ if (!GetConstantStringInfo(C->getOperand(Elt), Result))
+ Result.clear();
+ return Result;
+}
+
+uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const {
+ if (GV == 0) return 0;
+ Constant *C = GV->getInitializer();
+ if (C == 0 || Elt >= C->getNumOperands())
+ return 0;
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(C->getOperand(Elt)))
+ return CI->getZExtValue();
+ return 0;
+}
+
+
+DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const {
+ if (GV == 0) return DIDescriptor();
+ Constant *C = GV->getInitializer();
+ if (C == 0 || Elt >= C->getNumOperands())
+ return DIDescriptor();
+ C = C->getOperand(Elt);
+ return DIDescriptor(dyn_cast<GlobalVariable>(C->stripPointerCasts()));
+}
+
+GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const {
+ if (GV == 0) return 0;
+ Constant *C = GV->getInitializer();
+ if (C == 0 || Elt >= C->getNumOperands())
+ return 0;
+ C = C->getOperand(Elt);
+
+ return dyn_cast<GlobalVariable>(C->stripPointerCasts());
+}
+
+
+
+/// getCastToEmpty - Return this descriptor as a Constant* with type '{}*'.
+/// This is only valid when the descriptor is non-null.
+Constant *DIDescriptor::getCastToEmpty() const {
+ const Type *DestTy = PointerType::getUnqual(StructType::get(NULL, NULL));
+ if (isNull()) return Constant::getNullValue(DestTy);
+ return ConstantExpr::getBitCast(GV, DestTy);
+}
+
+//===----------------------------------------------------------------------===//
+// Simple Descriptor Constructors and other Methods
+//===----------------------------------------------------------------------===//
+
+DIAnchor::DIAnchor(GlobalVariable *GV)
+ : DIDescriptor(GV, dwarf::DW_TAG_anchor) {}
+DIEnumerator::DIEnumerator(GlobalVariable *GV)
+ : DIDescriptor(GV, dwarf::DW_TAG_enumerator) {}
+DISubrange::DISubrange(GlobalVariable *GV)
+ : DIDescriptor(GV, dwarf::DW_TAG_subrange_type) {}
+DICompileUnit::DICompileUnit(GlobalVariable *GV)
+ : DIDescriptor(GV, dwarf::DW_TAG_compile_unit) {}
+DIBasicType::DIBasicType(GlobalVariable *GV)
+ : DIType(GV, dwarf::DW_TAG_base_type) {}
+DISubprogram::DISubprogram(GlobalVariable *GV)
+ : DIGlobal(GV, dwarf::DW_TAG_subprogram) {}
+DIGlobalVariable::DIGlobalVariable(GlobalVariable *GV)
+ : DIGlobal(GV, dwarf::DW_TAG_variable) {}
+DIBlock::DIBlock(GlobalVariable *GV)
+ : DIDescriptor(GV, dwarf::DW_TAG_lexical_block) {}
+
+/// isDerivedType - Return true if the specified tag is legal for
+/// DIDerivedType.
+bool DIDerivedType::isDerivedType(unsigned Tag) {
+ switch (Tag) {
+ case dwarf::DW_TAG_typedef:
+ case dwarf::DW_TAG_pointer_type:
+ case dwarf::DW_TAG_reference_type:
+ case dwarf::DW_TAG_const_type:
+ case dwarf::DW_TAG_volatile_type:
+ case dwarf::DW_TAG_restrict_type:
+ case dwarf::DW_TAG_member:
+ case dwarf::DW_TAG_inheritance:
+ return true;
+ default:
+ // FIXME: Even though it doesn't make sense, CompositeTypes are current
+ // modelled as DerivedTypes, this should return true for them as well.
+ return false;
+ }
+}
+
+DIDerivedType::DIDerivedType(GlobalVariable *GV) : DIType(GV, true, true) {
+ if (GV && !isDerivedType(getTag()))
+ GV = 0;
+}
+
+/// isCompositeType - Return true if the specified tag is legal for
+/// DICompositeType.
+bool DICompositeType::isCompositeType(unsigned TAG) {
+ switch (TAG) {
+ case dwarf::DW_TAG_array_type:
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_union_type:
+ case dwarf::DW_TAG_enumeration_type:
+ case dwarf::DW_TAG_vector_type:
+ case dwarf::DW_TAG_subroutine_type:
+ return true;
+ default:
+ return false;
+ }
+}
+
+DICompositeType::DICompositeType(GlobalVariable *GV)
+ : DIDerivedType(GV, true, true) {
+ if (GV && !isCompositeType(getTag()))
+ GV = 0;
+}
+
+/// isVariable - Return true if the specified tag is legal for DIVariable.
+bool DIVariable::isVariable(unsigned Tag) {
+ switch (Tag) {
+ case dwarf::DW_TAG_auto_variable:
+ case dwarf::DW_TAG_arg_variable:
+ case dwarf::DW_TAG_return_variable:
+ return true;
+ default:
+ return false;
+ }
+}
+
+DIVariable::DIVariable(GlobalVariable *GV) : DIDescriptor(GV) {
+ if (GV && !isVariable(getTag()))
+ GV = 0;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// DIFactory: Basic Helpers
+//===----------------------------------------------------------------------===//
+
+Constant *DIFactory::GetTagConstant(unsigned TAG) {
+ assert((TAG & DIDescriptor::VersionMask) == 0 &&
+ "Tag too large for debug encoding!");
+ return ConstantInt::get(Type::Int32Ty, TAG | DIDescriptor::Version6);
+}
+
+Constant *DIFactory::GetStringConstant(const std::string &String) {
+ // Check string cache for previous edition.
+ Constant *&Slot = StringCache[String];
+
+ // Return Constant if previously defined.
+ if (Slot) return Slot;
+
+ const PointerType *DestTy = PointerType::getUnqual(Type::Int8Ty);
+
+ // If empty string then use a sbyte* null instead.
+ if (String.empty())
+ return Slot = ConstantPointerNull::get(DestTy);
+
+ // 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");
+ return Slot = ConstantExpr::getBitCast(StrGV, DestTy);
+}
+
+/// GetOrCreateAnchor - Look up an anchor for the specified tag and name. If it
+/// already exists, return it. If not, create a new one and return it.
+DIAnchor DIFactory::GetOrCreateAnchor(unsigned TAG, const char *Name) {
+ const Type *EltTy = StructType::get(Type::Int32Ty, Type::Int32Ty, NULL);
+
+ // Otherwise, create the global or return it if already in the module.
+ Constant *C = M.getOrInsertGlobal(Name, EltTy);
+ assert(isa<GlobalVariable>(C) && "Incorrectly typed anchor?");
+ GlobalVariable *GV = cast<GlobalVariable>(C);
+
+ // If it has an initializer, it is already in the module.
+ if (GV->hasInitializer())
+ return SubProgramAnchor = DIAnchor(GV);
+
+ GV->setLinkage(GlobalValue::LinkOnceLinkage);
+ GV->setSection("llvm.metadata");
+ GV->setConstant(true);
+ M.addTypeName("llvm.dbg.anchor.type", EltTy);
+
+ // Otherwise, set the initializer.
+ Constant *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_anchor),
+ ConstantInt::get(Type::Int32Ty, TAG)
+ };
+
+ GV->setInitializer(ConstantStruct::get(Elts, 2));
+ return DIAnchor(GV);
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// DIFactory: Primary Constructors
+//===----------------------------------------------------------------------===//
+
+/// GetOrCreateCompileUnitAnchor - Return the anchor for compile units,
+/// creating a new one if there isn't already one in the module.
+DIAnchor DIFactory::GetOrCreateCompileUnitAnchor() {
+ // If we already created one, just return it.
+ if (!CompileUnitAnchor.isNull())
+ return CompileUnitAnchor;
+ return CompileUnitAnchor = GetOrCreateAnchor(dwarf::DW_TAG_compile_unit,
+ "llvm.dbg.compile_units");
+}
+
+/// GetOrCreateSubprogramAnchor - Return the anchor for subprograms,
+/// creating a new one if there isn't already one in the module.
+DIAnchor DIFactory::GetOrCreateSubprogramAnchor() {
+ // If we already created one, just return it.
+ if (!SubProgramAnchor.isNull())
+ return SubProgramAnchor;
+ return SubProgramAnchor = GetOrCreateAnchor(dwarf::DW_TAG_subprogram,
+ "llvm.dbg.subprograms");
+}
+
+/// GetOrCreateGlobalVariableAnchor - Return the anchor for globals,
+/// creating a new one if there isn't already one in the module.
+DIAnchor DIFactory::GetOrCreateGlobalVariableAnchor() {
+ // If we already created one, just return it.
+ if (!GlobalVariableAnchor.isNull())
+ return GlobalVariableAnchor;
+ return GlobalVariableAnchor = GetOrCreateAnchor(dwarf::DW_TAG_variable,
+ "llvm.dbg.global_variables");
+}
+
+/// GetOrCreateArray - Create an descriptor for an array of descriptors.
+/// This implicitly uniques the arrays created.
+DIArray DIFactory::GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys) {
+ SmallVector<Constant*, 16> Elts;
+
+ for (unsigned i = 0; i != NumTys; ++i)
+ Elts.push_back(Tys[i].getCastToEmpty());
+
+ const Type *EltTy = PointerType::getUnqual(StructType::get(NULL,NULL));
+
+ Constant *Init = ConstantArray::get(ArrayType::get(EltTy, Elts.size()),
+ &Elts[0], Elts.size());
+ // If we already have this array, just return the uniqued version.
+ DIDescriptor &Entry = SimpleConstantCache[Init];
+ if (!Entry.isNull()) return DIArray(Entry.getGV());
+
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.array", &M);
+ GV->setSection("llvm.metadata");
+ Entry = DIDescriptor(GV);
+ return DIArray(GV);
+}
+
+/// GetOrCreateSubrange - Create a descriptor for a value range. This
+/// implicitly uniques the values returned.
+DISubrange DIFactory::GetOrCreateSubrange(int64_t Lo, int64_t Hi) {
+ Constant *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_subrange_type),
+ ConstantInt::get(Type::Int64Ty, Lo),
+ ConstantInt::get(Type::Int64Ty, Hi)
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ // If we already have this range, just return the uniqued version.
+ DIDescriptor &Entry = SimpleConstantCache[Init];
+ if (!Entry.isNull()) return DISubrange(Entry.getGV());
+
+ M.addTypeName("llvm.dbg.subrange.type", Init->getType());
+
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.subrange", &M);
+ GV->setSection("llvm.metadata");
+ Entry = DIDescriptor(GV);
+ return DISubrange(GV);
+}
+
+
+
+/// CreateCompileUnit - Create a new descriptor for the specified compile
+/// unit. Note that this does not unique compile units within the module.
+DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID,
+ const std::string &Filename,
+ const std::string &Directory,
+ const std::string &Producer) {
+ Constant *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_compile_unit),
+ GetOrCreateCompileUnitAnchor().getCastToEmpty(),
+ ConstantInt::get(Type::Int32Ty, LangID),
+ GetStringConstant(Filename),
+ GetStringConstant(Directory),
+ GetStringConstant(Producer)
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.compile_unit.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.compile_unit", &M);
+ GV->setSection("llvm.metadata");
+ return DICompileUnit(GV);
+}
+
+/// CreateEnumerator - Create a single enumerator value.
+DIEnumerator DIFactory::CreateEnumerator(const std::string &Name, uint64_t Val){
+ Constant *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_enumerator),
+ GetStringConstant(Name),
+ ConstantInt::get(Type::Int64Ty, Val)
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.enumerator.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.enumerator", &M);
+ GV->setSection("llvm.metadata");
+ return DIEnumerator(GV);
+}
+
+
+/// CreateBasicType - Create a basic type like int, float, etc.
+DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit,
+ unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ unsigned Encoding) {
+ Constant *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_base_type),
+ Context.getCastToEmpty(),
+ GetStringConstant(Name),
+ CompileUnit.getCastToEmpty(),
+ ConstantInt::get(Type::Int32Ty, LineNumber),
+ ConstantInt::get(Type::Int64Ty, SizeInBits),
+ ConstantInt::get(Type::Int64Ty, AlignInBits),
+ ConstantInt::get(Type::Int64Ty, OffsetInBits),
+ ConstantInt::get(Type::Int32Ty, Flags),
+ ConstantInt::get(Type::Int32Ty, Encoding)
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.basictype.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.basictype", &M);
+ GV->setSection("llvm.metadata");
+ return DIBasicType(GV);
+}
+
+/// CreateDerivedType - Create a derived type like const qualified type,
+/// pointer, typedef, etc.
+DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
+ DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit,
+ unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits,
+ uint64_t OffsetInBits,
+ unsigned Flags,
+ DIType DerivedFrom) {
+ Constant *Elts[] = {
+ GetTagConstant(Tag),
+ Context.getCastToEmpty(),
+ GetStringConstant(Name),
+ CompileUnit.getCastToEmpty(),
+ ConstantInt::get(Type::Int32Ty, LineNumber),
+ ConstantInt::get(Type::Int64Ty, SizeInBits),
+ ConstantInt::get(Type::Int64Ty, AlignInBits),
+ ConstantInt::get(Type::Int64Ty, OffsetInBits),
+ ConstantInt::get(Type::Int32Ty, Flags),
+ DerivedFrom.getCastToEmpty()
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.derivedtype.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.derivedtype", &M);
+ GV->setSection("llvm.metadata");
+ return DIDerivedType(GV);
+}
+
+/// CreateCompositeType - Create a composite type like array, struct, etc.
+DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
+ DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit,
+ unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits,
+ uint64_t OffsetInBits,
+ unsigned Flags,
+ DIType DerivedFrom,
+ DIArray Elements) {
+ Constant *Elts[] = {
+ GetTagConstant(Tag),
+ Context.getCastToEmpty(),
+ GetStringConstant(Name),
+ CompileUnit.getCastToEmpty(),
+ ConstantInt::get(Type::Int32Ty, LineNumber),
+ ConstantInt::get(Type::Int64Ty, SizeInBits),
+ ConstantInt::get(Type::Int64Ty, AlignInBits),
+ ConstantInt::get(Type::Int64Ty, OffsetInBits),
+ ConstantInt::get(Type::Int32Ty, Flags),
+ DerivedFrom.getCastToEmpty(),
+ Elements.getCastToEmpty()
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.composite.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.composite", &M);
+ GV->setSection("llvm.metadata");
+ return DICompositeType(GV);
+}
+
+
+/// CreateSubprogram - Create a new descriptor for the specified subprogram.
+/// See comments in DISubprogram for descriptions of these fields. This
+/// method does not unique the generated descriptors.
+DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
+ const std::string &Name,
+ const std::string &DisplayName,
+ const std::string &LinkageName,
+ DICompileUnit CompileUnit,
+ unsigned LineNo, DIType Type,
+ bool isLocalToUnit,
+ bool isDefinition) {
+ Constant *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_subprogram),
+ GetOrCreateSubprogramAnchor().getCastToEmpty(),
+ Context.getCastToEmpty(),
+ GetStringConstant(Name),
+ GetStringConstant(DisplayName),
+ GetStringConstant(LinkageName),
+ CompileUnit.getCastToEmpty(),
+ ConstantInt::get(Type::Int32Ty, LineNo),
+ Type.getCastToEmpty(),
+ ConstantInt::get(Type::Int1Ty, isLocalToUnit),
+ ConstantInt::get(Type::Int1Ty, isDefinition)
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.subprogram.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.subprogram", &M);
+ GV->setSection("llvm.metadata");
+ return DISubprogram(GV);
+}
+
+/// CreateGlobalVariable - Create a new descriptor for the specified global.
+DIGlobalVariable
+DIFactory::CreateGlobalVariable(DIDescriptor Context, const std::string &Name,
+ const std::string &DisplayName,
+ const std::string &LinkageName,
+ DICompileUnit CompileUnit,
+ unsigned LineNo, DIType Type,bool isLocalToUnit,
+ bool isDefinition, llvm::GlobalVariable *Val) {
+
+ Constant *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_variable),
+ GetOrCreateGlobalVariableAnchor().getCastToEmpty(),
+ Context.getCastToEmpty(),
+ GetStringConstant(Name),
+ GetStringConstant(DisplayName),
+ GetStringConstant(LinkageName),
+ CompileUnit.getCastToEmpty(),
+ ConstantInt::get(Type::Int32Ty, LineNo),
+ Type.getCastToEmpty(),
+ ConstantInt::get(Type::Int1Ty, isLocalToUnit),
+ ConstantInt::get(Type::Int1Ty, isDefinition),
+ ConstantExpr::getBitCast(Val,
+ PointerType::getUnqual(StructType::get(NULL,NULL)))
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.global_variable.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.global_variable", &M);
+ GV->setSection("llvm.metadata");
+ return DIGlobalVariable(GV);
+}
+
+
+/// CreateVariable - Create a new descriptor for the specified variable.
+DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
+ const std::string &Name,
+ DICompileUnit CompileUnit, unsigned LineNo,
+ DIType Type) {
+
+ Constant *Elts[] = {
+ GetTagConstant(Tag),
+ Context.getCastToEmpty(),
+ GetStringConstant(Name),
+ CompileUnit.getCastToEmpty(),
+ ConstantInt::get(Type::Int32Ty, LineNo),
+ Type.getCastToEmpty(),
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.variable.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.variable", &M);
+ GV->setSection("llvm.metadata");
+ return DIVariable(GV);
+}
+
+
+/// CreateBlock - This creates a descriptor for a lexical block with the
+/// specified parent context.
+DIBlock DIFactory::CreateBlock(DIDescriptor Context) {
+ Constant *Elts[] = {
+ GetTagConstant(dwarf::DW_TAG_lexical_block),
+ Context.getCastToEmpty()
+ };
+
+ Constant *Init = ConstantStruct::get(Elts, sizeof(Elts)/sizeof(Elts[0]));
+
+ M.addTypeName("llvm.dbg.block.type", Init->getType());
+ GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
+ GlobalValue::InternalLinkage,
+ Init, "llvm.dbg.block", &M);
+ GV->setSection("llvm.metadata");
+ return DIBlock(GV);
+}
+
+
+//===----------------------------------------------------------------------===//
+// DIFactory: Routines for inserting code into a function
+//===----------------------------------------------------------------------===//
+
+/// InsertStopPoint - Create a new llvm.dbg.stoppoint intrinsic invocation,
+/// inserting it at the end of the specified basic block.
+void DIFactory::InsertStopPoint(DICompileUnit CU, unsigned LineNo,
+ unsigned ColNo, BasicBlock *BB) {
+
+ // Lazily construct llvm.dbg.stoppoint function.
+ if (!StopPointFn)
+ StopPointFn = llvm::Intrinsic::getDeclaration(&M,
+ llvm::Intrinsic::dbg_stoppoint);
+
+ // Invoke llvm.dbg.stoppoint
+ Value *Args[] = {
+ llvm::ConstantInt::get(llvm::Type::Int32Ty, LineNo),
+ llvm::ConstantInt::get(llvm::Type::Int32Ty, ColNo),
+ CU.getCastToEmpty()
+ };
+ CallInst::Create(StopPointFn, Args, Args+3, "", BB);
+}
+
+/// InsertSubprogramStart - Create a new llvm.dbg.func.start intrinsic to
+/// mark the start of the specified subprogram.
+void DIFactory::InsertSubprogramStart(DISubprogram SP, BasicBlock *BB) {
+ // Lazily construct llvm.dbg.func.start.
+ if (!FuncStartFn)
+ FuncStartFn = llvm::Intrinsic::getDeclaration(&M,
+ llvm::Intrinsic::dbg_func_start);
+
+ // Call llvm.dbg.func.start which also implicitly sets a stoppoint.
+ CallInst::Create(FuncStartFn, SP.getCastToEmpty(), "", BB);
+}
+
+/// InsertRegionStart - Insert a new llvm.dbg.region.start intrinsic call to
+/// mark the start of a region for the specified scoping descriptor.
+void DIFactory::InsertRegionStart(DIDescriptor D, BasicBlock *BB) {
+ // Lazily construct llvm.dbg.region.start function.
+ if (!RegionStartFn)
+ RegionStartFn = llvm::Intrinsic::getDeclaration(&M,
+ llvm::Intrinsic::dbg_region_start);
+ // Call llvm.dbg.func.start.
+ CallInst::Create(RegionStartFn, D.getCastToEmpty(), "", BB);
+}
+
+
+/// InsertRegionEnd - Insert a new llvm.dbg.region.end intrinsic call to
+/// mark the end of a region for the specified scoping descriptor.
+void DIFactory::InsertRegionEnd(DIDescriptor D, BasicBlock *BB) {
+ // Lazily construct llvm.dbg.region.end function.
+ if (!RegionEndFn)
+ RegionEndFn = llvm::Intrinsic::getDeclaration(&M,
+ llvm::Intrinsic::dbg_region_end);
+
+ CallInst::Create(RegionEndFn, D.getCastToEmpty(), "", BB);
+}
+
+/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
+void DIFactory::InsertDeclare(llvm::Value *Storage, DIVariable D,
+ BasicBlock *BB) {
+ // Cast the storage to a {}* for the call to llvm.dbg.declare.
+ const Type *DestTy = PointerType::getUnqual(StructType::get(NULL, NULL));
+ Storage = new llvm::BitCastInst(Storage, DestTy, Storage->getName(), BB);
+
+ if (!DeclareFn)
+ DeclareFn = llvm::Intrinsic::getDeclaration(&M,
+ llvm::Intrinsic::dbg_declare);
+ Value *Args[] = { Storage, D.getCastToEmpty() };
+ CallInst::Create(DeclareFn, Args, Args+2, "", BB);
+}
More information about the llvm-commits
mailing list