| //===--- DIBuilder.cpp - Debug Information Builder ------------------------===// | |
| // | |
| // 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 DIBuilder. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Analysis/DIBuilder.h" | |
| #include "llvm/Analysis/DebugInfo.h" | |
| #include "llvm/Constants.h" | |
| #include "llvm/IntrinsicInst.h" | |
| #include "llvm/Module.h" | |
| #include "llvm/ADT/STLExtras.h" | |
| #include "llvm/Support/Dwarf.h" | |
| using namespace llvm; | |
| using namespace llvm::dwarf; | |
| static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) { | |
| assert((Tag & LLVMDebugVersionMask) == 0 && | |
| "Tag too large for debug encoding!"); | |
| return ConstantInt::get(Type::getInt32Ty(VMContext), Tag | LLVMDebugVersion); | |
| } | |
| DIBuilder::DIBuilder(Module &m) | |
| : M(m), VMContext(M.getContext()), TheCU(0), TempEnumTypes(0), | |
| TempRetainTypes(0), TempSubprograms(0), TempGVs(0), DeclareFn(0), | |
| ValueFn(0) | |
| {} | |
| /// finalize - Construct any deferred debug info descriptors. | |
| void DIBuilder::finalize() { | |
| DIArray Enums = getOrCreateArray(AllEnumTypes); | |
| DIType(TempEnumTypes).replaceAllUsesWith(Enums); | |
| DIArray RetainTypes = getOrCreateArray(AllRetainTypes); | |
| DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes); | |
| DIArray SPs = getOrCreateArray(AllSubprograms); | |
| DIType(TempSubprograms).replaceAllUsesWith(SPs); | |
| for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { | |
| DISubprogram SP(SPs.getElement(i)); | |
| if (NamedMDNode *NMD = getFnSpecificMDNode(M, SP)) { | |
| SmallVector<Value *, 4> Variables; | |
| for (unsigned ii = 0, ee = NMD->getNumOperands(); ii != ee; ++ii) | |
| Variables.push_back(NMD->getOperand(ii)); | |
| if (MDNode *Temp = SP.getVariablesNodes()) { | |
| DIArray AV = getOrCreateArray(Variables); | |
| DIType(Temp).replaceAllUsesWith(AV); | |
| } | |
| NMD->eraseFromParent(); | |
| } | |
| } | |
| DIArray GVs = getOrCreateArray(AllGVs); | |
| DIType(TempGVs).replaceAllUsesWith(GVs); | |
| } | |
| /// getNonCompileUnitScope - If N is compile unit return NULL otherwise return | |
| /// N. | |
| static MDNode *getNonCompileUnitScope(MDNode *N) { | |
| if (DIDescriptor(N).isCompileUnit()) | |
| return NULL; | |
| return N; | |
| } | |
| /// createCompileUnit - A CompileUnit provides an anchor for all debugging | |
| /// information generated during this instance of compilation. | |
| void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, | |
| StringRef Directory, StringRef Producer, | |
| bool isOptimized, StringRef Flags, | |
| unsigned RunTimeVer) { | |
| assert (Lang <= dwarf::DW_LANG_D && Lang >= dwarf::DW_LANG_C89 | |
| && "Invalid Language tag"); | |
| assert (!Filename.empty() | |
| && "Unable to create compile unit without filename"); | |
| Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; | |
| TempEnumTypes = MDNode::getTemporary(VMContext, TElts); | |
| Value *THElts[] = { TempEnumTypes }; | |
| MDNode *EnumHolder = MDNode::get(VMContext, THElts); | |
| TempRetainTypes = MDNode::getTemporary(VMContext, TElts); | |
| Value *TRElts[] = { TempRetainTypes }; | |
| MDNode *RetainHolder = MDNode::get(VMContext, TRElts); | |
| TempSubprograms = MDNode::getTemporary(VMContext, TElts); | |
| Value *TSElts[] = { TempSubprograms }; | |
| MDNode *SPHolder = MDNode::get(VMContext, TSElts); | |
| TempGVs = MDNode::getTemporary(VMContext, TElts); | |
| Value *TVElts[] = { TempGVs }; | |
| MDNode *GVHolder = MDNode::get(VMContext, TVElts); | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Lang), | |
| MDString::get(VMContext, Filename), | |
| MDString::get(VMContext, Directory), | |
| MDString::get(VMContext, Producer), | |
| // Deprecate isMain field. | |
| ConstantInt::get(Type::getInt1Ty(VMContext), true), // isMain | |
| ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), | |
| MDString::get(VMContext, Flags), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer), | |
| EnumHolder, | |
| RetainHolder, | |
| SPHolder, | |
| GVHolder | |
| }; | |
| TheCU = DICompileUnit(MDNode::get(VMContext, Elts)); | |
| // Create a named metadata so that it is easier to find cu in a module. | |
| NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); | |
| NMD->addOperand(TheCU); | |
| } | |
| /// createFile - Create a file descriptor to hold debugging information | |
| /// for a file. | |
| DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { | |
| assert(TheCU && "Unable to create DW_TAG_file_type without CompileUnit"); | |
| assert(!Filename.empty() && "Unable to create file without name"); | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_file_type), | |
| MDString::get(VMContext, Filename), | |
| MDString::get(VMContext, Directory), | |
| NULL // TheCU | |
| }; | |
| return DIFile(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createEnumerator - Create a single enumerator value. | |
| DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { | |
| assert(!Name.empty() && "Unable to create enumerator without name"); | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_enumerator), | |
| MDString::get(VMContext, Name), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), Val) | |
| }; | |
| return DIEnumerator(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createNullPtrType - Create C++0x nullptr type. | |
| DIType DIBuilder::createNullPtrType(StringRef Name) { | |
| assert(!Name.empty() && "Unable to create type without name"); | |
| // nullptr is encoded in DIBasicType format. Line number, filename, | |
| // ,size, alignment, offset and flags are always empty here. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_type), | |
| NULL, //TheCU, | |
| MDString::get(VMContext, Name), | |
| NULL, // Filename | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Encoding | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createBasicType - Create debugging information entry for a basic | |
| /// type, e.g 'char'. | |
| DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, | |
| uint64_t AlignInBits, | |
| unsigned Encoding) { | |
| assert(!Name.empty() && "Unable to create type without name"); | |
| // Basic types are encoded in DIBasicType format. Line number, filename, | |
| // offset and flags are always empty here. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_base_type), | |
| NULL, //TheCU, | |
| MDString::get(VMContext, Name), | |
| NULL, // Filename | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line | |
| ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createQaulifiedType - Create debugging information entry for a qualified | |
| /// type, e.g. 'const int'. | |
| DIType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { | |
| // Qualified types are encoded in DIDerivedType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, Tag), | |
| NULL, //TheCU, | |
| MDString::get(VMContext, StringRef()), // Empty name. | |
| NULL, // Filename | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags | |
| FromTy | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createPointerType - Create debugging information entry for a pointer. | |
| DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, | |
| uint64_t AlignInBits, StringRef Name) { | |
| // Pointer types are encoded in DIDerivedType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_pointer_type), | |
| NULL, //TheCU, | |
| MDString::get(VMContext, Name), | |
| NULL, // Filename | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line | |
| ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags | |
| PointeeTy | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createReferenceType - Create debugging information entry for a reference. | |
| DIType DIBuilder::createReferenceType(DIType RTy) { | |
| assert(RTy.Verify() && "Unable to create reference type"); | |
| // References are encoded in DIDerivedType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_reference_type), | |
| NULL, // TheCU, | |
| NULL, // Name | |
| NULL, // Filename | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags | |
| RTy | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createTypedef - Create debugging information entry for a typedef. | |
| DIType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, | |
| unsigned LineNo, DIDescriptor Context) { | |
| // typedefs are encoded in DIDerivedType format. | |
| assert(Ty.Verify() && "Invalid typedef type!"); | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_typedef), | |
| getNonCompileUnitScope(Context), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags | |
| Ty | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createFriend - Create debugging information entry for a 'friend'. | |
| DIType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { | |
| // typedefs are encoded in DIDerivedType format. | |
| assert(Ty.Verify() && "Invalid type!"); | |
| assert(FriendTy.Verify() && "Invalid friend type!"); | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_friend), | |
| Ty, | |
| NULL, // Name | |
| Ty.getFile(), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags | |
| FriendTy | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createInheritance - Create debugging information entry to establish | |
| /// inheritance relationship between two types. | |
| DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, | |
| uint64_t BaseOffset, unsigned Flags) { | |
| assert(Ty.Verify() && "Unable to create inheritance"); | |
| // TAG_inheritance is encoded in DIDerivedType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_inheritance), | |
| Ty, | |
| NULL, // Name | |
| Ty.getFile(), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align | |
| ConstantInt::get(Type::getInt64Ty(VMContext), BaseOffset), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| BaseTy | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createMemberType - Create debugging information entry for a member. | |
| DIType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, | |
| DIFile File, unsigned LineNumber, | |
| uint64_t SizeInBits, uint64_t AlignInBits, | |
| uint64_t OffsetInBits, unsigned Flags, | |
| DIType Ty) { | |
| // TAG_member is encoded in DIDerivedType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_member), | |
| getNonCompileUnitScope(Scope), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| Ty | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createObjCIVar - Create debugging information entry for Objective-C | |
| /// instance variable. | |
| DIType DIBuilder::createObjCIVar(StringRef Name, | |
| DIFile File, unsigned LineNumber, | |
| uint64_t SizeInBits, uint64_t AlignInBits, | |
| uint64_t OffsetInBits, unsigned Flags, | |
| DIType Ty, StringRef PropertyName, | |
| StringRef GetterName, StringRef SetterName, | |
| unsigned PropertyAttributes) { | |
| // TAG_member is encoded in DIDerivedType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_member), | |
| getNonCompileUnitScope(File), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| Ty, | |
| MDString::get(VMContext, PropertyName), | |
| MDString::get(VMContext, GetterName), | |
| MDString::get(VMContext, SetterName), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes) | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createClassType - Create debugging information entry for a class. | |
| DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, | |
| DIFile File, unsigned LineNumber, | |
| uint64_t SizeInBits, uint64_t AlignInBits, | |
| uint64_t OffsetInBits, unsigned Flags, | |
| DIType DerivedFrom, DIArray Elements, | |
| MDNode *VTableHoder, MDNode *TemplateParams) { | |
| // TAG_class_type is encoded in DICompositeType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_class_type), | |
| getNonCompileUnitScope(Context), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), OffsetInBits), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| DerivedFrom, | |
| Elements, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| VTableHoder, | |
| TemplateParams | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createTemplateTypeParameter - Create debugging information for template | |
| /// type parameter. | |
| DITemplateTypeParameter | |
| DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, | |
| DIType Ty, MDNode *File, unsigned LineNo, | |
| unsigned ColumnNo) { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_template_type_parameter), | |
| getNonCompileUnitScope(Context), | |
| MDString::get(VMContext, Name), | |
| Ty, | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) | |
| }; | |
| return DITemplateTypeParameter(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createTemplateValueParameter - Create debugging information for template | |
| /// value parameter. | |
| DITemplateValueParameter | |
| DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, | |
| DIType Ty, uint64_t Val, | |
| MDNode *File, unsigned LineNo, | |
| unsigned ColumnNo) { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_template_value_parameter), | |
| getNonCompileUnitScope(Context), | |
| MDString::get(VMContext, Name), | |
| Ty, | |
| ConstantInt::get(Type::getInt64Ty(VMContext), Val), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) | |
| }; | |
| return DITemplateValueParameter(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createStructType - Create debugging information entry for a struct. | |
| DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, | |
| DIFile File, unsigned LineNumber, | |
| uint64_t SizeInBits, uint64_t AlignInBits, | |
| unsigned Flags, DIArray Elements, | |
| unsigned RunTimeLang) { | |
| // TAG_structure_type is encoded in DICompositeType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_structure_type), | |
| getNonCompileUnitScope(Context), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| Elements, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createUnionType - Create debugging information entry for an union. | |
| DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, | |
| DIFile File, | |
| unsigned LineNumber, uint64_t SizeInBits, | |
| uint64_t AlignInBits, unsigned Flags, | |
| DIArray Elements, unsigned RunTimeLang) { | |
| // TAG_union_type is encoded in DICompositeType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_union_type), | |
| getNonCompileUnitScope(Scope), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| Elements, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createSubroutineType - Create subroutine type. | |
| DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) { | |
| // TAG_subroutine_type is encoded in DICompositeType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| MDString::get(VMContext, ""), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| ParameterTypes, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createEnumerationType - Create debugging information entry for an | |
| /// enumeration. | |
| DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name, | |
| DIFile File, unsigned LineNumber, | |
| uint64_t SizeInBits, | |
| uint64_t AlignInBits, | |
| DIArray Elements) { | |
| // TAG_enumeration_type is encoded in DICompositeType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type), | |
| getNonCompileUnitScope(Scope), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| Elements, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| }; | |
| MDNode *Node = MDNode::get(VMContext, Elts); | |
| AllEnumTypes.push_back(Node); | |
| return DIType(Node); | |
| } | |
| /// createArrayType - Create debugging information entry for an array. | |
| DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, | |
| DIType Ty, DIArray Subscripts) { | |
| // TAG_array_type is encoded in DICompositeType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_array_type), | |
| NULL, //TheCU, | |
| MDString::get(VMContext, ""), | |
| NULL, //TheCU, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), Size), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| Ty, | |
| Subscripts, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createVectorType - Create debugging information entry for a vector. | |
| DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, | |
| DIType Ty, DIArray Subscripts) { | |
| // TAG_vector_type is encoded in DICompositeType format. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_vector_type), | |
| NULL, //TheCU, | |
| MDString::get(VMContext, ""), | |
| NULL, //TheCU, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), Size), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| Ty, | |
| Subscripts, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| }; | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createArtificialType - Create a new DIType with "artificial" flag set. | |
| DIType DIBuilder::createArtificialType(DIType Ty) { | |
| if (Ty.isArtificial()) | |
| return Ty; | |
| SmallVector<Value *, 9> Elts; | |
| MDNode *N = Ty; | |
| assert (N && "Unexpected input DIType!"); | |
| for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { | |
| if (Value *V = N->getOperand(i)) | |
| Elts.push_back(V); | |
| else | |
| Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))); | |
| } | |
| unsigned CurFlags = Ty.getFlags(); | |
| CurFlags = CurFlags | DIType::FlagArtificial; | |
| // Flags are stored at this slot. | |
| Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); | |
| return DIType(MDNode::get(VMContext, Elts)); | |
| } | |
| /// retainType - Retain DIType in a module even if it is not referenced | |
| /// through debug info anchors. | |
| void DIBuilder::retainType(DIType T) { | |
| AllRetainTypes.push_back(T); | |
| } | |
| /// createUnspecifiedParameter - Create unspeicified type descriptor | |
| /// for the subroutine type. | |
| DIDescriptor DIBuilder::createUnspecifiedParameter() { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) | |
| }; | |
| return DIDescriptor(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createTemporaryType - Create a temporary forward-declared type. | |
| DIType DIBuilder::createTemporaryType() { | |
| // Give the temporary MDNode a tag. It doesn't matter what tag we | |
| // use here as long as DIType accepts it. | |
| Value *Elts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; | |
| MDNode *Node = MDNode::getTemporary(VMContext, Elts); | |
| return DIType(Node); | |
| } | |
| /// createTemporaryType - Create a temporary forward-declared type. | |
| DIType DIBuilder::createTemporaryType(DIFile F) { | |
| // Give the temporary MDNode a tag. It doesn't matter what tag we | |
| // use here as long as DIType accepts it. | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, DW_TAG_base_type), | |
| TheCU, | |
| NULL, | |
| F | |
| }; | |
| MDNode *Node = MDNode::getTemporary(VMContext, Elts); | |
| return DIType(Node); | |
| } | |
| /// getOrCreateArray - Get a DIArray, create one if required. | |
| DIArray DIBuilder::getOrCreateArray(ArrayRef<Value *> Elements) { | |
| if (Elements.empty()) { | |
| Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)); | |
| return DIArray(MDNode::get(VMContext, Null)); | |
| } | |
| return DIArray(MDNode::get(VMContext, Elements)); | |
| } | |
| /// getOrCreateSubrange - Create a descriptor for a value range. This | |
| /// implicitly uniques the values returned. | |
| DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Hi) { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), Lo), | |
| ConstantInt::get(Type::getInt64Ty(VMContext), Hi) | |
| }; | |
| return DISubrange(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createGlobalVariable - Create a new descriptor for the specified global. | |
| DIGlobalVariable DIBuilder:: | |
| createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, | |
| DIType Ty, bool isLocalToUnit, llvm::Value *Val) { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_variable), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| NULL, // TheCU, | |
| MDString::get(VMContext, Name), | |
| MDString::get(VMContext, Name), | |
| MDString::get(VMContext, Name), | |
| F, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), | |
| Ty, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ | |
| Val | |
| }; | |
| MDNode *Node = MDNode::get(VMContext, Elts); | |
| AllGVs.push_back(Node); | |
| return DIGlobalVariable(Node); | |
| } | |
| /// createStaticVariable - Create a new descriptor for the specified static | |
| /// variable. | |
| DIGlobalVariable DIBuilder:: | |
| createStaticVariable(DIDescriptor Context, StringRef Name, | |
| StringRef LinkageName, DIFile F, unsigned LineNumber, | |
| DIType Ty, bool isLocalToUnit, llvm::Value *Val) { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_variable), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| getNonCompileUnitScope(Context), | |
| MDString::get(VMContext, Name), | |
| MDString::get(VMContext, Name), | |
| MDString::get(VMContext, LinkageName), | |
| F, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), | |
| Ty, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ | |
| Val | |
| }; | |
| MDNode *Node = MDNode::get(VMContext, Elts); | |
| AllGVs.push_back(Node); | |
| return DIGlobalVariable(Node); | |
| } | |
| /// createVariable - Create a new descriptor for the specified variable. | |
| DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, | |
| StringRef Name, DIFile File, | |
| unsigned LineNo, DIType Ty, | |
| bool AlwaysPreserve, unsigned Flags, | |
| unsigned ArgNo) { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, Tag), | |
| getNonCompileUnitScope(Scope), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24))), | |
| Ty, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| }; | |
| MDNode *Node = MDNode::get(VMContext, Elts); | |
| if (AlwaysPreserve) { | |
| // The optimizer may remove local variable. If there is an interest | |
| // to preserve variable info in such situation then stash it in a | |
| // named mdnode. | |
| DISubprogram Fn(getDISubprogram(Scope)); | |
| NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, Fn); | |
| FnLocals->addOperand(Node); | |
| } | |
| return DIVariable(Node); | |
| } | |
| /// createComplexVariable - Create a new descriptor for the specified variable | |
| /// which has a complex address expression for its address. | |
| DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, | |
| StringRef Name, DIFile F, | |
| unsigned LineNo, | |
| DIType Ty, ArrayRef<Value *> Addr, | |
| unsigned ArgNo) { | |
| SmallVector<Value *, 15> Elts; | |
| Elts.push_back(GetTagConstant(VMContext, Tag)); | |
| Elts.push_back(getNonCompileUnitScope(Scope)), | |
| Elts.push_back(MDString::get(VMContext, Name)); | |
| Elts.push_back(F); | |
| Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), | |
| (LineNo | (ArgNo << 24)))); | |
| Elts.push_back(Ty); | |
| Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))); | |
| Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))); | |
| Elts.append(Addr.begin(), Addr.end()); | |
| return DIVariable(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createFunction - Create a new descriptor for the specified function. | |
| DISubprogram DIBuilder::createFunction(DIDescriptor Context, | |
| StringRef Name, | |
| StringRef LinkageName, | |
| DIFile File, unsigned LineNo, | |
| DIType Ty, | |
| bool isLocalToUnit, bool isDefinition, | |
| unsigned Flags, bool isOptimized, | |
| Function *Fn, | |
| MDNode *TParams, | |
| MDNode *Decl) { | |
| Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; | |
| MDNode *Temp = MDNode::getTemporary(VMContext, TElts); | |
| Value *TVElts[] = { Temp }; | |
| MDNode *THolder = MDNode::get(VMContext, TVElts); | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| getNonCompileUnitScope(Context), | |
| MDString::get(VMContext, Name), | |
| MDString::get(VMContext, Name), | |
| MDString::get(VMContext, LinkageName), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), | |
| Ty, | |
| ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), | |
| ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), 0), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), | |
| Fn, | |
| TParams, | |
| Decl, | |
| THolder | |
| }; | |
| MDNode *Node = MDNode::get(VMContext, Elts); | |
| // Create a named metadata so that we do not lose this mdnode. | |
| AllSubprograms.push_back(Node); | |
| return DISubprogram(Node); | |
| } | |
| /// createMethod - Create a new descriptor for the specified C++ method. | |
| DISubprogram DIBuilder::createMethod(DIDescriptor Context, | |
| StringRef Name, | |
| StringRef LinkageName, | |
| DIFile F, | |
| unsigned LineNo, DIType Ty, | |
| bool isLocalToUnit, | |
| bool isDefinition, | |
| unsigned VK, unsigned VIndex, | |
| MDNode *VTableHolder, | |
| unsigned Flags, | |
| bool isOptimized, | |
| Function *Fn, | |
| MDNode *TParam) { | |
| Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; | |
| MDNode *Temp = MDNode::getTemporary(VMContext, TElts); | |
| Value *TVElts[] = { Temp }; | |
| MDNode *THolder = MDNode::get(VMContext, TVElts); | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| getNonCompileUnitScope(Context), | |
| MDString::get(VMContext, Name), | |
| MDString::get(VMContext, Name), | |
| MDString::get(VMContext, LinkageName), | |
| F, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), | |
| Ty, | |
| ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), | |
| ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), VIndex), | |
| VTableHolder, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Flags), | |
| ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), | |
| Fn, | |
| TParam, | |
| llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), | |
| THolder | |
| }; | |
| MDNode *Node = MDNode::get(VMContext, Elts); | |
| return DISubprogram(Node); | |
| } | |
| /// createNameSpace - This creates new descriptor for a namespace | |
| /// with the specified parent scope. | |
| DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, | |
| DIFile File, unsigned LineNo) { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_namespace), | |
| getNonCompileUnitScope(Scope), | |
| MDString::get(VMContext, Name), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) | |
| }; | |
| return DINameSpace(MDNode::get(VMContext, Elts)); | |
| } | |
| /// createLexicalBlockFile - This creates a new MDNode that encapsulates | |
| /// an existing scope with a new filename. | |
| DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, | |
| DIFile File) { | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), | |
| Scope, | |
| File | |
| }; | |
| return DILexicalBlockFile(MDNode::get(VMContext, Elts)); | |
| } | |
| DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, | |
| unsigned Line, unsigned Col) { | |
| // Defeat MDNode uniqing for lexical blocks by using unique id. | |
| static unsigned int unique_id = 0; | |
| Value *Elts[] = { | |
| GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), | |
| getNonCompileUnitScope(Scope), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Line), | |
| ConstantInt::get(Type::getInt32Ty(VMContext), Col), | |
| File, | |
| ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++) | |
| }; | |
| return DILexicalBlock(MDNode::get(VMContext, Elts)); | |
| } | |
| /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. | |
| Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, | |
| Instruction *InsertBefore) { | |
| assert(Storage && "no storage passed to dbg.declare"); | |
| assert(VarInfo.Verify() && "empty DIVariable passed to dbg.declare"); | |
| if (!DeclareFn) | |
| DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); | |
| Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; | |
| return CallInst::Create(DeclareFn, Args, "", InsertBefore); | |
| } | |
| /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. | |
| Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, | |
| BasicBlock *InsertAtEnd) { | |
| assert(Storage && "no storage passed to dbg.declare"); | |
| assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.declare"); | |
| if (!DeclareFn) | |
| DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); | |
| Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; | |
| // If this block already has a terminator then insert this intrinsic | |
| // before the terminator. | |
| if (TerminatorInst *T = InsertAtEnd->getTerminator()) | |
| return CallInst::Create(DeclareFn, Args, "", T); | |
| else | |
| return CallInst::Create(DeclareFn, Args, "", InsertAtEnd); | |
| } | |
| /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. | |
| Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, | |
| DIVariable VarInfo, | |
| Instruction *InsertBefore) { | |
| assert(V && "no value passed to dbg.value"); | |
| assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.value"); | |
| if (!ValueFn) | |
| ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); | |
| Value *Args[] = { MDNode::get(V->getContext(), V), | |
| ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), | |
| VarInfo }; | |
| return CallInst::Create(ValueFn, Args, "", InsertBefore); | |
| } | |
| /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. | |
| Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, | |
| DIVariable VarInfo, | |
| BasicBlock *InsertAtEnd) { | |
| assert(V && "no value passed to dbg.value"); | |
| assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.value"); | |
| if (!ValueFn) | |
| ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); | |
| Value *Args[] = { MDNode::get(V->getContext(), V), | |
| ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), | |
| VarInfo }; | |
| return CallInst::Create(ValueFn, Args, "", InsertAtEnd); | |
| } |