From 9c85ba33ac85bbf5915f300a4b228bad7c693ee7 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 10 Nov 2008 06:08:34 +0000 Subject: [PATCH] reimplement debug info generation in terms of DebugInfo.h instead of using MachineModuleInfo. This runs at about the same speed as the old code, but fixes a bunch of bugs and is simpler and shorter. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58971 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 1009 +++++++++++++---------------------- lib/CodeGen/CGDebugInfo.h | 109 ++-- lib/CodeGen/CGDecl.cpp | 14 +- 3 files changed, 410 insertions(+), 722 deletions(-) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index d246c56a9c..4b3ef0ebd0 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -25,622 +25,415 @@ #include "llvm/Module.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/Support/Dwarf.h" #include "llvm/Target/TargetMachine.h" using namespace clang; using namespace clang::CodeGen; CGDebugInfo::CGDebugInfo(CodeGenModule *m) -: M(m) -, CurLoc() -, PrevLoc() -, CompileUnitCache() -, TypeCache() -, StopPointFn(NULL) -, FuncStartFn(NULL) -, DeclareFn(NULL) -, RegionStartFn(NULL) -, RegionEndFn(NULL) -, CompileUnitAnchor(NULL) -, SubprogramAnchor(NULL) -, GlobalVariableAnchor(NULL) -, RegionStack() -, VariableDescList() -, GlobalVarDescList() -, EnumDescList() -, SubrangeDescList() -, Subprogram(NULL) -{ - SR = new llvm::DISerializer(); - SR->setModule (&M->getModule()); + : M(m), DebugFactory(M->getModule()) { } -CGDebugInfo::~CGDebugInfo() -{ +CGDebugInfo::~CGDebugInfo() { assert(RegionStack.empty() && "Region stack mismatch, stack not empty!"); - - delete SR; - - // Free CompileUnitCache. - for (std::map::iterator I - = CompileUnitCache.begin(); I != CompileUnitCache.end(); ++I) { - delete I->second; - } - CompileUnitCache.clear(); - - // Free TypeCache. - for (std::map::iterator I - = TypeCache.begin(); I != TypeCache.end(); ++I) { - delete I->second; - } - TypeCache.clear(); - - // Free region descriptors. - for (std::vector::iterator I - = RegionStack.begin(); I != RegionStack.end(); ++I) { - delete *I; - } - - // Free local var descriptors. - for (std::vector::iterator I - = VariableDescList.begin(); I != VariableDescList.end(); ++I) { - delete *I; - } - - // Free global var descriptors. - for (std::vector::iterator I - = GlobalVarDescList.begin(); I != GlobalVarDescList.end(); ++I) { - delete *I; - } - - // Free enum constants descriptors. - for (std::vector::iterator I - = EnumDescList.begin(); I != EnumDescList.end(); ++I) { - delete *I; - } - - // Free subrange descriptors. - for (std::vector::iterator I - = SubrangeDescList.begin(); I != SubrangeDescList.end(); ++I) { - delete *I; - } - - delete CompileUnitAnchor; - delete SubprogramAnchor; - delete GlobalVariableAnchor; -} - -void CGDebugInfo::setLocation(SourceLocation loc) { - if (loc.isValid()) - CurLoc = M->getContext().getSourceManager().getLogicalLoc(loc); -} - -/// getCastValueFor - Return a llvm representation for a given debug information -/// descriptor cast to an empty struct pointer. -llvm::Value *CGDebugInfo::getCastValueFor(llvm::DebugInfoDesc *DD) { - return llvm::ConstantExpr::getBitCast(SR->Serialize(DD), - SR->getEmptyStructPtrType()); } -/// getValueFor - Return a llvm representation for a given debug information -/// descriptor. -llvm::Value *CGDebugInfo::getValueFor(llvm::DebugInfoDesc *DD) { - return SR->Serialize(DD); +void CGDebugInfo::setLocation(SourceLocation Loc) { + if (Loc.isValid()) + CurLoc = M->getContext().getSourceManager().getLogicalLoc(Loc); } /// getOrCreateCompileUnit - Get the compile unit from the cache or create a new /// one if necessary. This returns null for invalid source locations. -llvm::CompileUnitDesc* -CGDebugInfo::getOrCreateCompileUnit(const SourceLocation Loc) { +llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { if (Loc.isInvalid()) - return NULL; + return llvm::DICompileUnit(); SourceManager &SM = M->getContext().getSourceManager(); const FileEntry *FE = SM.getFileEntryForLoc(Loc); - + if (FE == 0) return llvm::DICompileUnit(); + // See if this compile unit has been used before. - llvm::CompileUnitDesc *&Unit = CompileUnitCache[FE]; - if (Unit) return Unit; + llvm::DICompileUnit &Unit = CompileUnitCache[FE]; + if (!Unit.isNull()) return Unit; - // Create new compile unit. - // FIXME: Where to free these? - // One way is to iterate over the CompileUnitCache in ~CGDebugInfo. - Unit = new llvm::CompileUnitDesc(); - - // Make sure we have an anchor. - if (!CompileUnitAnchor) { - CompileUnitAnchor = new llvm::AnchorDesc(Unit); - } - // Get source file information. - const char *FileName, *DirName; - if (FE) { - FileName = FE->getName(); - DirName = FE->getDir()->getName(); - } else { - FileName = SM.getSourceName(Loc); - DirName = ""; - } - - Unit->setAnchor(CompileUnitAnchor); - Unit->setFileName(FileName); - Unit->setDirectory(DirName); - - // Set up producer name. + const char *FileName = FE->getName(); + const char *DirName = FE->getDir()->getName(); + + // Create new compile unit. + // FIXME: Handle other language IDs as well. // FIXME: Do not know how to get clang version yet. - Unit->setProducer("clang"); - - // Set up Language number. - // FIXME: Handle other languages as well. - Unit->setLanguage(llvm::dwarf::DW_LANG_C89); - - return Unit; + return Unit = DebugFactory.CreateCompileUnit(llvm::dwarf::DW_LANG_C89, + FileName, DirName, "clang"); } - -/// getOrCreateCVRType - Get the CVR qualified type from the cache or create -/// a new one if necessary. -llvm::TypeDesc * -CGDebugInfo::getOrCreateCVRType(QualType type, llvm::CompileUnitDesc *Unit) -{ - // We will create a Derived type. - llvm::DerivedTypeDesc *DTy = NULL; - llvm::TypeDesc *FromTy = NULL; - - if (type.isConstQualified()) { - DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_const_type); - type.removeConst(); - FromTy = getOrCreateType(type, Unit); - } else if (type.isVolatileQualified()) { - DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_volatile_type); - type.removeVolatile(); - FromTy = getOrCreateType(type, Unit); - } else if (type.isRestrictQualified()) { - DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_restrict_type); - type.removeRestrict(); - FromTy = getOrCreateType(type, Unit); - } - - // No need to fill in the Name, Line, Size, Alignment, Offset in case of - // CVR derived types. - DTy->setContext(Unit); - DTy->setFromType(FromTy); - - return DTy; -} - - /// getOrCreateBuiltinType - Get the Basic type from the cache or create a new /// one if necessary. -llvm::TypeDesc * -CGDebugInfo::getOrCreateBuiltinType(const BuiltinType *type, - llvm::CompileUnitDesc *Unit) { +llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, + llvm::DICompileUnit Unit){ unsigned Encoding = 0; - switch (type->getKind()) - { - case BuiltinType::Void: - return NULL; - case BuiltinType::UChar: - case BuiltinType::Char_U: - Encoding = llvm::dwarf::DW_ATE_unsigned_char; - break; - case BuiltinType::Char_S: - case BuiltinType::SChar: - Encoding = llvm::dwarf::DW_ATE_signed_char; - break; - case BuiltinType::UShort: - case BuiltinType::UInt: - case BuiltinType::ULong: - case BuiltinType::ULongLong: - Encoding = llvm::dwarf::DW_ATE_unsigned; - break; - case BuiltinType::Short: - case BuiltinType::Int: - case BuiltinType::Long: - case BuiltinType::LongLong: - Encoding = llvm::dwarf::DW_ATE_signed; - break; - case BuiltinType::Bool: - Encoding = llvm::dwarf::DW_ATE_boolean; - break; - case BuiltinType::Float: - case BuiltinType::Double: - Encoding = llvm::dwarf::DW_ATE_float; - break; - default: - Encoding = llvm::dwarf::DW_ATE_signed; - break; + switch (BT->getKind()) { + default: + case BuiltinType::Void: + return llvm::DIType(); + case BuiltinType::UChar: + case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break; + case BuiltinType::Char_S: + case BuiltinType::SChar: Encoding = llvm::dwarf::DW_ATE_signed_char; break; + case BuiltinType::UShort: + case BuiltinType::UInt: + case BuiltinType::ULong: + case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break; + case BuiltinType::Short: + case BuiltinType::Int: + case BuiltinType::Long: + case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break; + case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break; + case BuiltinType::Float: + case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break; } - - // Ty will have contain the resulting type. - llvm::BasicTypeDesc *BTy = new llvm::BasicTypeDesc(); - - // Get the name and location early to assist debugging. - const char *TyName = type->getName(); - // Bit size, align and offset of the type. - uint64_t Size = M->getContext().getTypeSize(type); - uint64_t Align = M->getContext().getTypeAlign(type); + uint64_t Size = M->getContext().getTypeSize(BT); + uint64_t Align = M->getContext().getTypeAlign(BT); uint64_t Offset = 0; - - // If the type is defined, fill in the details. - if (BTy) { - BTy->setContext(Unit); - BTy->setName(TyName); - BTy->setSize(Size); - BTy->setAlign(Align); - BTy->setOffset(Offset); - BTy->setEncoding(Encoding); - } - - return BTy; + + return DebugFactory.CreateBasicType(Unit, BT->getName(), Unit, 0, Size, Align, + Offset, /*flags*/ 0, Encoding); } -llvm::TypeDesc * -CGDebugInfo::getOrCreatePointerType(const PointerType *type, - llvm::CompileUnitDesc *Unit) { - // type* - llvm::DerivedTypeDesc *DTy = - new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_pointer_type); +/// getOrCreateCVRType - Get the CVR qualified type from the cache or create +/// a new one if necessary. +llvm::DIType CGDebugInfo::CreateCVRType(QualType Ty, llvm::DICompileUnit Unit) { + // We will create one Derived type for one qualifier and recurse to handle any + // additional ones. + llvm::DIType FromTy; + unsigned Tag; + if (Ty.isConstQualified()) { + Tag = llvm::dwarf::DW_TAG_const_type; + Ty.removeConst(); + FromTy = getOrCreateType(Ty, Unit); + } else if (Ty.isVolatileQualified()) { + Tag = llvm::dwarf::DW_TAG_volatile_type; + Ty.removeVolatile(); + FromTy = getOrCreateType(Ty, Unit); + } else { + assert(Ty.isRestrictQualified() && "Unknown type qualifier for debug info"); + Tag = llvm::dwarf::DW_TAG_restrict_type; + Ty.removeRestrict(); + FromTy = getOrCreateType(Ty, Unit); + } + + // No need to fill in the Name, Line, Size, Alignment, Offset in case of + // CVR derived types. + return DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(), + 0, 0, 0, 0, 0, FromTy); +} - // Handle the derived type. - llvm::TypeDesc *FromTy = getOrCreateType(type->getPointeeType(), Unit); +llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, + llvm::DICompileUnit Unit) { + llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), Unit); - // Get the name and location early to assist debugging. - SourceManager &SM = M->getContext().getSourceManager(); - uint64_t Line = SM.getLogicalLineNumber(CurLoc); - // Bit size, align and offset of the type. - uint64_t Size = M->getContext().getTypeSize(type); - uint64_t Align = M->getContext().getTypeAlign(type); - uint64_t Offset = 0; + uint64_t Size = M->getContext().getTypeSize(Ty); + uint64_t Align = M->getContext().getTypeAlign(Ty); - // If the type is defined, fill in the details. - if (DTy) { - DTy->setContext(Unit); - DTy->setLine(Line); - DTy->setSize(Size); - DTy->setAlign(Align); - DTy->setOffset(Offset); - DTy->setFromType(FromTy); - } - - return DTy; + return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, + "", llvm::DICompileUnit(), + 0, Size, Align, 0, 0, EltTy); } -llvm::TypeDesc * -CGDebugInfo::getOrCreateTypedefType(const TypedefType *TDT, - llvm::CompileUnitDesc *Unit) { - // typedefs are derived from some other type. - llvm::DerivedTypeDesc *DTy = - new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_typedef); - - // Handle derived type. - llvm::TypeDesc *FromTy = getOrCreateType(TDT->LookThroughTypedefs(), - Unit); +llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, + llvm::DICompileUnit Unit) { + // Typedefs are derived from some other type. If we have a typedef of a + // typedef, make sure to emit the whole chain. + llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit); + + // We don't set size information, but do specify where the typedef was + // declared. + const char *TyName = Ty->getDecl()->getName(); + SourceLocation DefLoc = Ty->getDecl()->getLocation(); + llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc); - // Get the name and location early to assist debugging. - const char *TyName = TDT->getDecl()->getName(); SourceManager &SM = M->getContext().getSourceManager(); - uint64_t Line = SM.getLogicalLineNumber(TDT->getDecl()->getLocation()); - - // If the type is defined, fill in the details. - if (DTy) { - DTy->setContext(Unit); - DTy->setFile(getOrCreateCompileUnit(TDT->getDecl()->getLocation())); - DTy->setLine(Line); - DTy->setName(TyName); - DTy->setFromType(FromTy); - } + uint64_t Line = SM.getLogicalLineNumber(DefLoc); - return DTy; + return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit, + TyName, DefUnit, Line, 0, 0, 0, 0, Src); } -llvm::TypeDesc * -CGDebugInfo::getOrCreateFunctionType(QualType type, llvm::CompileUnitDesc *Unit) -{ - llvm::CompositeTypeDesc *SubrTy = - new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_subroutine_type); - - // Prepare to add the arguments for the subroutine. - std::vector &Elements = SubrTy->getElements(); - - // Get result type. - const FunctionType *FT = type->getAsFunctionType(); - llvm::TypeDesc *ArgTy = getOrCreateType(FT->getResultType(), Unit); - Elements.push_back(ArgTy); - - // Set up remainder of arguments. - if (type->getTypeClass() == Type::FunctionProto) { - const FunctionTypeProto *FTPro = dyn_cast(type); - for (unsigned int i =0; i < FTPro->getNumArgs(); i++) { - QualType ParamType = FTPro->getArgType(i); - ArgTy = getOrCreateType(ParamType, Unit); - // FIXME: Remove once we support all types. - if (ArgTy) Elements.push_back(ArgTy); - } - } +llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, + llvm::DICompileUnit Unit) { + llvm::SmallVector EltTys; - // FIXME: set other fields file, line here. - SubrTy->setContext(Unit); + // Add the result type at least. + EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit)); + + // Set up remainder of arguments if there is a prototype. + // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'! + if (const FunctionTypeProto *FTP = dyn_cast(Ty)) { + for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) + EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit)); + } else { + // FIXME: Handle () case in C. llvm-gcc doesn't do it either. + } - return SubrTy; + llvm::DIArray EltTypeArray = + DebugFactory.GetOrCreateArray(&EltTys[0], EltTys.size()); + + return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, + Unit, "", llvm::DICompileUnit(), + 0, 0, 0, 0, 0, + llvm::DIType(), EltTypeArray); } /// getOrCreateRecordType - get structure or union type. -void CGDebugInfo::getOrCreateRecordType(const RecordType *type, - llvm::CompileUnitDesc *Unit, - llvm::TypeDesc *&Slot) -{ - // Prevent recursing in type generation by initializing the slot - // here. - llvm::CompositeTypeDesc *RecType; - if (type->isStructureType()) - Slot = RecType = - new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_structure_type); - else if (type->isUnionType()) - Slot = RecType = - new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_union_type); - else - return; - - RecordDecl *RecDecl = type->getDecl(); - // We can not get the type for forward declarations. - // FIXME: What *should* we be doing here? - if (!RecDecl->getDefinition(M->getContext())) - return; - const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(RecDecl); - - SourceManager &SM = M->getContext().getSourceManager(); - uint64_t Line = SM.getLogicalLineNumber(RecDecl->getLocation()); - - std::vector &Elements = RecType->getElements(); - - // Add the members. - int NumMembers = RecDecl->getNumMembers(); - for (int i = 0; i < NumMembers; i++) { - FieldDecl *Member = RecDecl->getMember(i); - llvm::TypeDesc *MemberTy = getOrCreateType(Member->getType(), Unit); - // FIXME: Remove once we support all types. - if (MemberTy) { - MemberTy->setOffset(RL.getFieldOffset(i)); - Elements.push_back(MemberTy); - } - } - - // Fill in the blanks. - if (RecType) { - RecType->setContext(Unit); - RecType->setName(RecDecl->getName()); - RecType->setFile(getOrCreateCompileUnit(RecDecl->getLocation())); - RecType->setLine(Line); - RecType->setSize(RL.getSize()); - RecType->setAlign(RL.getAlignment()); - RecType->setOffset(0); +llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, + llvm::DICompileUnit Unit) { + const RecordDecl *Decl = Ty->getDecl(); + + if (!Decl->getDefinition(M->getContext())) + return llvm::DIType(); + + unsigned Tag; + if (Decl->isStruct()) + Tag = llvm::dwarf::DW_TAG_structure_type; + else if (Decl->isUnion()) + Tag = llvm::dwarf::DW_TAG_union_type; + else { + assert(Decl->isClass() && "Unknown RecordType!"); + Tag = llvm::dwarf::DW_TAG_class_type; } -} - -/// getOrCreateEnumType - get Enum type. -llvm::TypeDesc * -CGDebugInfo::getOrCreateEnumType(const EnumType *type, - llvm::CompileUnitDesc *Unit) { - llvm::CompositeTypeDesc *EnumTy - = new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_enumeration_type); - EnumDecl *EDecl = type->getDecl(); SourceManager &SM = M->getContext().getSourceManager(); - uint64_t Line = SM.getLogicalLineNumber(EDecl->getLocation()); - // Size, align and offset of the type. - uint64_t Size = M->getContext().getTypeSize(type); - uint64_t Align = M->getContext().getTypeAlign(type); + // Get overall information about the record type for the debug info. + const char *Name = Decl->getName(); + if (Name == 0) Name = ""; + + llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(Decl->getLocation()); + uint64_t Line = SM.getLogicalLineNumber(Decl->getLocation()); + - // Create descriptors for enum members. - std::vector &Elements = EnumTy->getElements(); - EnumConstantDecl *ElementList = EDecl->getEnumConstantList(); - while (ElementList) { - llvm::EnumeratorDesc *EnumDesc = new llvm::EnumeratorDesc(); - // push it to the enum desc list so that we can free it later. - EnumDescList.push_back(EnumDesc); - - const char *ElementName = ElementList->getName(); - uint64_t Value = ElementList->getInitVal().getZExtValue(); - - EnumDesc->setName(ElementName); - EnumDesc->setValue(Value); - Elements.push_back(EnumDesc); - if (ElementList->getNextDeclarator()) - ElementList - = dyn_cast(ElementList->getNextDeclarator()); - else - break; + // Records and classes and unions can all be recursive. To handle them, we + // first generate a debug descriptor for the struct as a forward declaration. + // Then (if it is a definition) we go through and get debug info for all of + // its members. Finally, we create a descriptor for the complete type (which + // may refer to the forward decl if the struct is recursive) and replace all + // uses of the forward declaration with the final definition. + llvm::DIType FwdDecl = + DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, 0, 0, 0, 0, + llvm::DIType(), llvm::DIArray()); + + // If this is just a forward declaration, return it. + if (!Decl->getDefinition(M->getContext())) + return FwdDecl; + + // Otherwise, insert it into the TypeCache so that recursive uses will find + // it. + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; + + // Convert all the elements. + llvm::SmallVector EltTys; + + const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(Decl); + + unsigned FieldNo = 0; + for (RecordDecl::field_const_iterator I = Decl->field_begin(), + E = Decl->field_end(); I != E; ++I, ++FieldNo) { + FieldDecl *Field = *I; + llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); + +#if 0 + const char *FieldName = Field->getName(); + if (FieldName == 0) FieldName = ""; + + // Get the location for the field. + SourceLocation FieldDefLoc = Field->getLocation(); + llvm::DICompileUnit FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc); + uint64_t FieldLine = SM.getLogicalLineNumber(FieldDefLoc); + + // Bit size, align and offset of the type. + uint64_t FieldSize = M->getContext().getTypeSize(Ty); + uint64_t FieldAlign = M->getContext().getTypeAlign(Ty); + uint64_t FieldOffset = RL.getFieldOffset(FieldNo); + + // Create a DW_TAG_member node to remember the offset of this field in the + // struct. FIXME: This is an absolutely insane way to capture this + // information. When we gut debug info, this should be fixed. + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + FieldName, FieldDefUnit, + FieldLine, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); +#endif + EltTys.push_back(FieldTy); } + + llvm::DIArray Elements = + DebugFactory.GetOrCreateArray(&EltTys[0], EltTys.size()); - // Fill in the blanks. - if (EnumTy) { - EnumTy->setContext(Unit); - EnumTy->setName(EDecl->getName()); - EnumTy->setSize(Size); - EnumTy->setAlign(Align); - EnumTy->setOffset(0); - EnumTy->setFile(getOrCreateCompileUnit(EDecl->getLocation())); - EnumTy->setLine(Line); - } - return EnumTy; + // Bit size, align and offset of the type. + uint64_t Size = M->getContext().getTypeSize(Ty); + uint64_t Align = M->getContext().getTypeAlign(Ty); + + llvm::DIType RealDecl = + DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size, + Align, 0, 0, llvm::DIType(), Elements); + + // Now that we have a real decl for the struct, replace anything using the + // old decl with the new one. This will recursively update the debug info. + FwdDecl.getGV()->replaceAllUsesWith(RealDecl.getGV()); + FwdDecl.getGV()->eraseFromParent(); + + return RealDecl; } -/// getOrCreateArrayType - get or create array types. -llvm::TypeDesc * -CGDebugInfo::getOrCreateArrayType(QualType type, - llvm::CompileUnitDesc *Unit) { - llvm::CompositeTypeDesc *ArrayTy - = new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_array_type); +llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, + llvm::DICompileUnit Unit) { + EnumDecl *Decl = Ty->getDecl(); - // Size, align and offset of the type. - uint64_t Size = M->getContext().getTypeSize(type); - uint64_t Align = M->getContext().getTypeAlign(type); + llvm::SmallVector Enumerators; - SourceManager &SM = M->getContext().getSourceManager(); - uint64_t Line = SM.getLogicalLineNumber(CurLoc); + // Create DIEnumerator elements for each enumerator. + for (EnumConstantDecl *Elt = Decl->getEnumConstantList(); Elt; + Elt = dyn_cast_or_null(Elt->getNextDeclarator())) { + Enumerators.push_back(DebugFactory.CreateEnumerator(Elt->getName(), + Elt->getInitVal().getZExtValue())); + } + + // Return a CompositeType for the enum itself. + llvm::DIArray EltArray = + DebugFactory.GetOrCreateArray(&Enumerators[0], Enumerators.size()); - // Add the dimensions of the array. - std::vector &Elements = ArrayTy->getElements(); - do { - const ArrayType *AT = M->getContext().getAsArrayType(type); - llvm::SubrangeDesc *Subrange = new llvm::SubrangeDesc(); + const char *EnumName = Decl->getName() ? Decl->getName() : ""; + SourceLocation DefLoc = Decl->getLocation(); + llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc); + SourceManager &SM = M->getContext().getSourceManager(); + uint64_t Line = SM.getLogicalLineNumber(DefLoc); + + // Size and align of the type. + uint64_t Size = M->getContext().getTypeSize(Ty); + uint64_t Align = M->getContext().getTypeAlign(Ty); + + return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type, + Unit, EnumName, DefUnit, Line, + Size, Align, 0, 0, + llvm::DIType(), EltArray); +} - // push it back on the subrange desc list so that we can free it later. - SubrangeDescList.push_back(Subrange); +llvm::DIType CGDebugInfo::CreateType(const TagType *Ty, + llvm::DICompileUnit Unit) { + if (const RecordType *RT = dyn_cast(Ty)) + return CreateType(RT, Unit); + else if (const EnumType *ET = dyn_cast(Ty)) + return CreateType(ET, Unit); + + return llvm::DIType(); +} +llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, + llvm::DICompileUnit Unit) { + // Size and align of the whole array, not the element type. + uint64_t Size = M->getContext().getTypeSize(Ty); + uint64_t Align = M->getContext().getTypeAlign(Ty); + + // Add the dimensions of the array. FIXME: This loses CV qualifiers from + // interior arrays, do we care? Why aren't nested arrays represented the + // obvious/recursive way? + llvm::SmallVector Subscripts; + QualType EltTy(Ty, 0); + while ((Ty = dyn_cast(EltTy))) { uint64_t Upper = 0; - if (const ConstantArrayType *ConstArrTy = dyn_cast(AT)) { - Upper = ConstArrTy->getSize().getZExtValue() - 1; - } - Subrange->setLo(0); - Subrange->setHi(Upper); - Elements.push_back(Subrange); - type = AT->getElementType(); - } while (type->isArrayType()); - - ArrayTy->setFromType(getOrCreateType(type, Unit)); - - if (ArrayTy) { - ArrayTy->setContext(Unit); - ArrayTy->setSize(Size); - ArrayTy->setAlign(Align); - ArrayTy->setOffset(0); - ArrayTy->setFile(getOrCreateCompileUnit(CurLoc)); - ArrayTy->setLine(Line); + if (const ConstantArrayType *CAT = dyn_cast(Ty)) + Upper = CAT->getSize().getZExtValue() - 1; + // FIXME: Verify this is right for VLAs. + Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, Upper)); + EltTy = Ty->getElementType(); } - return ArrayTy; + + llvm::DIArray SubscriptArray = + DebugFactory.GetOrCreateArray(&Subscripts[0], Subscripts.size()); + + return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type, + Unit, "", llvm::DICompileUnit(), + 0, Size, Align, 0, 0, + getOrCreateType(EltTy, Unit), + SubscriptArray); } -/// getOrCreateTaggedType - get or create structure/union/Enum type. -void CGDebugInfo::getOrCreateTagType(const TagType *type, - llvm::CompileUnitDesc *Unit, - llvm::TypeDesc *&Slot) { - if (const RecordType *RT = dyn_cast(type)) - getOrCreateRecordType(RT, Unit, Slot); - else if (const EnumType *ET = dyn_cast(type)) - Slot = getOrCreateEnumType(ET, Unit); -} - /// getOrCreateType - Get the type from the cache or create a new /// one if necessary. -llvm::TypeDesc * -CGDebugInfo::getOrCreateType(QualType type, llvm::CompileUnitDesc *Unit) { - if (type.isNull()) - return NULL; - +llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, + llvm::DICompileUnit Unit) { + if (Ty.isNull()) + return llvm::DIType(); + // Check to see if the compile unit already has created this type. - llvm::TypeDesc *&Slot = TypeCache[type.getAsOpaquePtr()]; - if (Slot) return Slot; + llvm::DIType &Slot = TypeCache[Ty.getAsOpaquePtr()]; + if (!Slot.isNull()) return Slot; - // We need to check for the CVR qualifiers as the first thing. - if (type.getCVRQualifiers()) { - Slot = getOrCreateCVRType(type, Unit); - return Slot; - } + // Handle CVR qualifiers, which recursively handles what they refer to. + if (Ty.getCVRQualifiers()) + return Slot = CreateCVRType(Ty, Unit); // Work out details of type. - switch (type->getTypeClass()) { - case Type::Complex: - case Type::Reference: - case Type::Vector: - case Type::ExtVector: - case Type::ASQual: - case Type::ObjCInterface: - case Type::ObjCQualifiedInterface: - case Type::ObjCQualifiedId: - case Type::TypeOfExp: - case Type::TypeOfTyp: - default: - return NULL; - - case Type::TypeName: - Slot = getOrCreateTypedefType(cast(type), Unit); - break; - - case Type::FunctionProto: - case Type::FunctionNoProto: - Slot = getOrCreateFunctionType(type, Unit); - break; - - case Type::Builtin: - Slot = getOrCreateBuiltinType(cast(type), Unit); - break; - - case Type::Pointer: - Slot = getOrCreatePointerType(cast(type), Unit); - break; - - case Type::Tagged: - getOrCreateTagType(cast(type), Unit, Slot); - break; - - case Type::ConstantArray: - case Type::VariableArray: - case Type::IncompleteArray: - Slot = getOrCreateArrayType(type, Unit); - break; + switch (Ty->getTypeClass()) { + case Type::Complex: + case Type::Reference: + case Type::Vector: + case Type::ExtVector: + case Type::ASQual: + case Type::ObjCInterface: + case Type::ObjCQualifiedInterface: + case Type::ObjCQualifiedId: + case Type::TypeOfExp: + case Type::TypeOfTyp: + default: + return llvm::DIType(); + + case Type::Builtin: Slot = CreateType(cast(Ty), Unit); break; + case Type::Pointer: Slot = CreateType(cast(Ty), Unit); break; + case Type::TypeName: Slot = CreateType(cast(Ty), Unit); break; + case Type::Tagged: Slot = CreateType(cast(Ty), Unit); break; + case Type::FunctionProto: + case Type::FunctionNoProto: + Slot = CreateType(cast(Ty), Unit); + break; + + case Type::ConstantArray: + case Type::VariableArray: + case Type::IncompleteArray: + Slot = CreateType(cast(Ty), Unit); + break; } - + return Slot; } /// EmitFunctionStart - Constructs the debug code for entering a function - /// "llvm.dbg.func.start.". -void CGDebugInfo::EmitFunctionStart(const char *Name, - QualType ReturnType, +void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType, llvm::Function *Fn, - CGBuilderTy &Builder) -{ - // Create subprogram descriptor. - Subprogram = new llvm::SubprogramDesc(); - - // Make sure we have an anchor. - if (!SubprogramAnchor) { - SubprogramAnchor = new llvm::AnchorDesc(Subprogram); - } - - // Get name information. - Subprogram->setName(Name); - Subprogram->setFullName(Name); - - // Gather location information. - llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc); + CGBuilderTy &Builder) { + // FIXME: Why is this using CurLoc??? + llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc); SourceManager &SM = M->getContext().getSourceManager(); - uint64_t Loc = SM.getLogicalLineNumber(CurLoc); - - // Get Function Type. - llvm::TypeDesc *SPTy = getOrCreateType(ReturnType, Unit); - - Subprogram->setAnchor(SubprogramAnchor); - Subprogram->setContext(Unit); - Subprogram->setFile(Unit); - Subprogram->setLine(Loc); - Subprogram->setType(SPTy); - Subprogram->setIsStatic(Fn->hasInternalLinkage()); - Subprogram->setIsDefinition(true); - - // Lazily construct llvm.dbg.func.start. - if (!FuncStartFn) - FuncStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(), - llvm::Intrinsic::dbg_func_start); - - // Call llvm.dbg.func.start which also implicitly calls llvm.dbg.stoppoint. - Builder.CreateCall(FuncStartFn, getCastValueFor(Subprogram), ""); - + uint64_t LineNo = SM.getLogicalLineNumber(CurLoc); + + llvm::DISubprogram SP = + DebugFactory.CreateSubprogram(Unit, Name, Name, "", Unit, LineNo, + getOrCreateType(ReturnType, Unit), + Fn->hasInternalLinkage(), true/*definition*/); + + DebugFactory.InsertSubprogramStart(SP, Builder.GetInsertBlock()); + // Push function on region stack. - RegionStack.push_back(Subprogram); + RegionStack.push_back(SP); } -void -CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) -{ +void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) { if (CurLoc.isInvalid() || CurLoc.isMacroID()) return; // Don't bother if things are the same as last time. @@ -654,141 +447,81 @@ CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) PrevLoc = CurLoc; // Get the appropriate compile unit. - llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc); - - // Lazily construct llvm.dbg.stoppoint function. - if (!StopPointFn) - StopPointFn = llvm::Intrinsic::getDeclaration(&M->getModule(), - llvm::Intrinsic::dbg_stoppoint); - - uint64_t CurLineNo = SM.getLogicalLineNumber(CurLoc); - uint64_t ColumnNo = SM.getLogicalColumnNumber(CurLoc); - - // Invoke llvm.dbg.stoppoint - Builder.CreateCall3(StopPointFn, - llvm::ConstantInt::get(llvm::Type::Int32Ty, CurLineNo), - llvm::ConstantInt::get(llvm::Type::Int32Ty, ColumnNo), - getCastValueFor(Unit), ""); + llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc); + DebugFactory.InsertStopPoint(Unit, SM.getLogicalLineNumber(CurLoc), + SM.getLogicalColumnNumber(CurLoc), + Builder.GetInsertBlock()); } /// EmitRegionStart- Constructs the debug code for entering a declarative /// region - "llvm.dbg.region.start.". -void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, - CGBuilderTy &Builder) -{ - llvm::BlockDesc *Block = new llvm::BlockDesc(); +void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) { + llvm::DIDescriptor D; if (!RegionStack.empty()) - Block->setContext(RegionStack.back()); - RegionStack.push_back(Block); - - // Lazily construct llvm.dbg.region.start function. - if (!RegionStartFn) - RegionStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(), - llvm::Intrinsic::dbg_region_start); - - // Call llvm.dbg.func.start. - Builder.CreateCall(RegionStartFn, getCastValueFor(Block), ""); + D = RegionStack.back(); + D = DebugFactory.CreateBlock(D); + RegionStack.push_back(D); + DebugFactory.InsertRegionStart(D, Builder.GetInsertBlock()); } /// EmitRegionEnd - Constructs the debug code for exiting a declarative /// region - "llvm.dbg.region.end." -void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder) -{ +void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder) { assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); - // Lazily construct llvm.dbg.region.end function. - if (!RegionEndFn) - RegionEndFn =llvm::Intrinsic::getDeclaration(&M->getModule(), - llvm::Intrinsic::dbg_region_end); - // Provide an region stop point. EmitStopPoint(Fn, Builder); - // Call llvm.dbg.func.end. - llvm::DebugInfoDesc *DID = RegionStack.back(); - Builder.CreateCall(RegionEndFn, getCastValueFor(DID), ""); + DebugFactory.InsertRegionEnd(RegionStack.back(), Builder.GetInsertBlock()); RegionStack.pop_back(); - // FIXME: Should be freeing here? } /// EmitDeclare - Emit local variable declaration debug info. -void CGDebugInfo::EmitDeclare(const VarDecl *decl, unsigned Tag, - llvm::Value *AI, - CGBuilderTy &Builder) -{ +void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag, + llvm::Value *Storage, CGBuilderTy &Builder) { assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); - // FIXME: If it is a compiler generated temporary then return. - - // Construct llvm.dbg.declare function. - if (!DeclareFn) - DeclareFn = llvm::Intrinsic::getDeclaration(&M->getModule(), - llvm::Intrinsic::dbg_declare); - - // Get type information. - llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc); - llvm::TypeDesc *TyDesc = getOrCreateType(decl->getType(), Unit); - + // Get location information. SourceManager &SM = M->getContext().getSourceManager(); - uint64_t Loc = SM.getLogicalLineNumber(CurLoc); - - // Construct variable. - llvm::VariableDesc *Variable = new llvm::VariableDesc(Tag); - Variable->setContext(RegionStack.back()); - Variable->setName(decl->getName()); - Variable->setFile(Unit); - Variable->setLine(Loc); - Variable->setType(TyDesc); - - // Push it onto the list so that we can free it. - VariableDescList.push_back(Variable); - - // Cast the AllocA result to a {}* for the call to llvm.dbg.declare. - // These bit cast instructions will get freed when the basic block is - // deleted. So do not need to free them explicity. - const llvm::PointerType *EmpPtr = SR->getEmptyStructPtrType(); - llvm::Value *AllocACast = new llvm::BitCastInst(AI, EmpPtr, decl->getName(), - Builder.GetInsertBlock()); - - // Call llvm.dbg.declare. - Builder.CreateCall2(DeclareFn, AllocACast, getCastValueFor(Variable), ""); + uint64_t Line = SM.getLogicalLineNumber(Decl->getLocation()); + llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation()); + + // Create the descriptor for the variable. + llvm::DIVariable D = + DebugFactory.CreateVariable(Tag, RegionStack.back(), Decl->getName(), + Unit, Line, + getOrCreateType(Decl->getType(), Unit)); + // Insert an llvm.dbg.declare into the current block. + DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock()); } -/// EmitGlobalVariable - Emit information about a global variable. -void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *GV, - const VarDecl *decl) -{ - // Create global variable debug descriptor. - llvm::GlobalVariableDesc *Global = new llvm::GlobalVariableDesc(); +void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *Decl, + llvm::Value *Storage, + CGBuilderTy &Builder) { + EmitDeclare(Decl, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder); +} - // Push it onto the list so that we can free it. - GlobalVarDescList.push_back(Global); +/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument +/// variable declaration. +void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, + CGBuilderTy &Builder) { + EmitDeclare(Decl, llvm::dwarf::DW_TAG_arg_variable, AI, Builder); +} - // Make sure we have an anchor. - if (!GlobalVariableAnchor) - GlobalVariableAnchor = new llvm::AnchorDesc(Global); - // Get name information. - Global->setName(decl->getName()); - Global->setFullName(decl->getName()); - llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc); +/// EmitGlobalVariable - Emit information about a global variable. +void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, + const VarDecl *Decl) { + // Create global variable debug descriptor. + llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation()); SourceManager &SM = M->getContext().getSourceManager(); - uint64_t Loc = SM.getLogicalLineNumber(CurLoc); - - llvm::TypeDesc *TyD = getOrCreateType(decl->getType(), Unit); - - // Fill in the Global information. - Global->setAnchor(GlobalVariableAnchor); - Global->setContext(Unit); - Global->setFile(Unit); - Global->setLine(Loc); - Global->setType(TyD); - Global->setIsDefinition(true); - Global->setIsStatic(GV->hasInternalLinkage()); - Global->setGlobalVariable(GV); - - // Make sure global is created if needed. - getValueFor(Global); + uint64_t LineNo = SM.getLogicalLineNumber(Decl->getLocation()); + const char *Name = Decl->getName(); + + DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo, + getOrCreateType(Decl->getType(), Unit), + Var->hasInternalLinkage(), + true/*definition*/, Var); } diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 17db496c23..88702dd60a 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -16,30 +16,13 @@ #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Analysis/DebugInfo.h" #include -#include #include "CGBuilder.h" -namespace llvm { - class Function; - class DISerializer; - class CompileUnitDesc; - class BasicBlock; - class AnchorDesc; - class DebugInfoDesc; - class Value; - class TypeDesc; - class VariableDesc; - class SubprogramDesc; - class GlobalVariable; - class GlobalVariableDesc; - class EnumeratorDesc; - class SubrangeDesc; -} - namespace clang { - class FunctionDecl; class VarDecl; namespace CodeGen { @@ -49,54 +32,30 @@ namespace CodeGen { /// and is responsible for emitting to llvm globals or pass directly to /// the backend. class CGDebugInfo { -private: CodeGenModule *M; - llvm::DISerializer *SR; - SourceLocation CurLoc; - SourceLocation PrevLoc; + llvm::DIFactory DebugFactory; + + SourceLocation CurLoc, PrevLoc; /// CompileUnitCache - Cache of previously constructed CompileUnits. - std::map CompileUnitCache; + llvm::DenseMap CompileUnitCache; /// TypeCache - Cache of previously constructed Types. - std::map TypeCache; + // FIXME: Eliminate this map. Be careful of iterator invalidation. + std::map TypeCache; - llvm::Function *StopPointFn; - llvm::Function *FuncStartFn; - llvm::Function *DeclareFn; - llvm::Function *RegionStartFn; - llvm::Function *RegionEndFn; - llvm::AnchorDesc *CompileUnitAnchor; - llvm::AnchorDesc *SubprogramAnchor; - llvm::AnchorDesc *GlobalVariableAnchor; - std::vector RegionStack; - std::vector VariableDescList; - std::vector GlobalVarDescList; - std::vector EnumDescList; - std::vector SubrangeDescList; - llvm::SubprogramDesc *Subprogram; + std::vector RegionStack; /// Helper functions for getOrCreateType. - llvm::TypeDesc *getOrCreateCVRType(QualType type, - llvm::CompileUnitDesc *unit); - llvm::TypeDesc *getOrCreateBuiltinType(const BuiltinType *type, - llvm::CompileUnitDesc *unit); - llvm::TypeDesc *getOrCreateTypedefType(const TypedefType *type, - llvm::CompileUnitDesc *unit); - llvm::TypeDesc *getOrCreatePointerType(const PointerType *type, - llvm::CompileUnitDesc *unit); - llvm::TypeDesc *getOrCreateFunctionType(QualType type, - llvm::CompileUnitDesc *unit); - void getOrCreateRecordType(const RecordType *type, - llvm::CompileUnitDesc *unit, - llvm::TypeDesc *&Slot); - llvm::TypeDesc *getOrCreateEnumType(const EnumType *type, - llvm::CompileUnitDesc *unit); - void getOrCreateTagType(const TagType *type, - llvm::CompileUnitDesc *unit, - llvm::TypeDesc *&Slot); - llvm::TypeDesc *getOrCreateArrayType(QualType type, - llvm::CompileUnitDesc *unit); + llvm::DIType CreateType(const BuiltinType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateCVRType(QualType Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const TypedefType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const PointerType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const FunctionType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const TagType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const RecordType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const EnumType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const ArrayType *Ty, llvm::DICompileUnit U); public: CGDebugInfo(CodeGenModule *m); @@ -104,7 +63,7 @@ public: /// setLocation - Update the current source location. If \arg loc is /// invalid it is ignored. - void setLocation(SourceLocation loc); + void setLocation(SourceLocation Loc); /// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of /// source line. @@ -123,31 +82,33 @@ public: /// block. void EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder); - /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration. - void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI, - CGBuilderTy &Builder); + /// EmitDeclareOfAutoVariable - Emit call to llvm.dbg.declare for an automatic + /// variable declaration. + void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI, + CGBuilderTy &Builder); + /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument + /// variable declaration. + void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, + CGBuilderTy &Builder); + /// EmitGlobalVariable - Emit information about a global variable. - void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *decl); + void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); private: + /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration. + void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI, + CGBuilderTy &Builder); + /// getOrCreateCompileUnit - Get the compile unit from the cache or create a /// new one if necessary. - llvm::CompileUnitDesc *getOrCreateCompileUnit(SourceLocation loc); + llvm::DICompileUnit getOrCreateCompileUnit(SourceLocation Loc); /// getOrCreateType - Get the type from the cache or create a new type if /// necessary. - llvm::TypeDesc *getOrCreateType(QualType type, llvm::CompileUnitDesc *unit); - - /// getCastValueFor - Return a llvm representation for a given debug - /// information descriptor cast to an empty struct pointer. - llvm::Value *getCastValueFor(llvm::DebugInfoDesc *DD); - - /// getValueFor - Return a llvm representation for a given debug information - /// descriptor. - llvm::Value *getValueFor(llvm::DebugInfoDesc *DD); + llvm::DIType getOrCreateType(QualType Ty, llvm::DICompileUnit Unit); }; } // namespace CodeGen } // namespace clang diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 788beb4410..e54c4b386d 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -21,7 +21,6 @@ #include "clang/Basic/TargetInfo.h" #include "llvm/GlobalVariable.h" #include "llvm/Type.h" -#include "llvm/Support/Dwarf.h" using namespace clang; using namespace CodeGen; @@ -174,11 +173,9 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { DMEntry = DeclPtr; // Emit debug info for local var declaration. - CGDebugInfo *DI = CGM.getDebugInfo(); - if(DI) { + if (CGDebugInfo *DI = CGM.getDebugInfo()) { DI->setLocation(D.getLocation()); - DI->EmitDeclare(&D, llvm::dwarf::DW_TAG_auto_variable, - DeclPtr, Builder); + DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder); } // If this local has an initializer, emit it now. @@ -231,12 +228,9 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { DMEntry = DeclPtr; // Emit debug info for param declaration. - CGDebugInfo *DI = CGM.getDebugInfo(); - if(DI) { + if (CGDebugInfo *DI = CGM.getDebugInfo()) { DI->setLocation(D.getLocation()); - DI->EmitDeclare(&D, llvm::dwarf::DW_TAG_arg_variable, - DeclPtr, Builder); + DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder); } - } -- 2.40.0