From 9ca36b66410f2f9155df9d573f6da3114ac685a2 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Thu, 26 Feb 2009 21:10:26 +0000 Subject: [PATCH] Add support to emit debug info for objective-c interfaces. (This is not yet used.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65573 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDebugInfo.cpp | 116 +++++++++++++++++++++++++++++++++++- lib/CodeGen/CGDebugInfo.h | 8 ++- 2 files changed, 121 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 3a49fcf927..5e78c5817d 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -14,7 +14,7 @@ #include "CGDebugInfo.h" #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/SourceManager.h" @@ -290,6 +290,91 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, return RealDecl; } +/// CreateType - get objective-c interface type. +llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, + llvm::DICompileUnit Unit) { + ObjCInterfaceDecl *Decl = Ty->getDecl(); + + unsigned Tag = llvm::dwarf::DW_TAG_structure_type; + SourceManager &SM = M->getContext().getSourceManager(); + + // Get overall information about the record type for the debug info. + std::string Name = Decl->getNameAsString(); + + llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(Decl->getLocation()); + unsigned Line = SM.getInstantiationLineNumber(Decl->getLocation()); + + + // To handle recursive interface, 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->isForwardDecl()) + 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().getASTObjCInterfaceLayout(Decl); + + unsigned FieldNo = 0; + for (ObjCInterfaceDecl::ivar_iterator I = Decl->ivar_begin(), + E = Decl->ivar_end(); I != E; ++I, ++FieldNo) { + ObjCIvarDecl *Field = *I; + llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); + + std::string FieldName = Field->getNameAsString(); + + // Get the location for the field. + SourceLocation FieldDefLoc = Field->getLocation(); + llvm::DICompileUnit FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc); + unsigned FieldLine = SM.getInstantiationLineNumber(FieldDefLoc); + + // Bit size, align and offset of the type. + uint64_t FieldSize = M->getContext().getTypeSize(Ty); + unsigned 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); + EltTys.push_back(FieldTy); + } + + llvm::DIArray Elements = + DebugFactory.GetOrCreateArray(&EltTys[0], EltTys.size()); + + // 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; +} + llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, llvm::DICompileUnit Unit) { EnumDecl *Decl = Ty->getDecl(); @@ -559,3 +644,32 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, true/*definition*/, Var); } +/// EmitGlobalVariable - Emit information about an objective-c interface. +void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, + ObjCInterfaceDecl *Decl) { + // Create global variable debug descriptor. + llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation()); + SourceManager &SM = M->getContext().getSourceManager(); + unsigned LineNo = SM.getInstantiationLineNumber(Decl->getLocation()); + + std::string Name = Decl->getNameAsString(); + + QualType T = M->getContext().buildObjCInterfaceType(Decl); + if (T->isIncompleteArrayType()) { + + // CodeGen turns int[] into int[1] so we'll do the same here. + llvm::APSInt ConstVal(32); + + ConstVal = 1; + QualType ET = M->getContext().getAsArrayType(T)->getElementType(); + + T = M->getContext().getConstantArrayType(ET, ConstVal, + ArrayType::Normal, 0); + } + + DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo, + getOrCreateType(T, Unit), + Var->hasInternalLinkage(), + true/*definition*/, Var); +} + diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 88702dd60a..e9529c4565 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -24,6 +24,7 @@ namespace clang { class VarDecl; + class ObjCInterfaceDecl; namespace CodeGen { class CodeGenModule; @@ -54,6 +55,7 @@ class CGDebugInfo { 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 ObjCInterfaceType *Ty, llvm::DICompileUnit U); llvm::DIType CreateType(const EnumType *Ty, llvm::DICompileUnit U); llvm::DIType CreateType(const ArrayType *Ty, llvm::DICompileUnit U); @@ -94,8 +96,10 @@ public: /// EmitGlobalVariable - Emit information about a global variable. void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); - - + + /// EmitGlobalVariable - Emit information about an objective-c interface. + void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl); + private: /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration. void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI, -- 2.40.0