diff options
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 5636 |
1 files changed, 2834 insertions, 2802 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 844514be27..c16081fb98 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1,2802 +1,2834 @@ -//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This coordinates the debug information generation while generating code. -// -//===----------------------------------------------------------------------===// - -#include "CGDebugInfo.h" -#include "CGBlocks.h" -#include "CGObjCRuntime.h" -#include "CodeGenFunction.h" -#include "CodeGenModule.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclFriend.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -#include "clang/AST/RecordLayout.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/Version.h" -#include "clang/Frontend/CodeGenOptions.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Constants.h" -#include "llvm/DataLayout.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" -#include "llvm/Module.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/FileSystem.h" -using namespace clang; -using namespace clang::CodeGen; - -CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) - : CGM(CGM), DBuilder(CGM.getModule()), - BlockLiteralGenericSet(false) { - CreateCompileUnit(); -} - -CGDebugInfo::~CGDebugInfo() { - assert(LexicalBlockStack.empty() && - "Region stack mismatch, stack not empty!"); -} - -void CGDebugInfo::setLocation(SourceLocation Loc) { - // If the new location isn't valid return. - if (!Loc.isValid()) return; - - CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc); - - // If we've changed files in the middle of a lexical scope go ahead - // and create a new lexical scope with file node if it's different - // from the one in the scope. - if (LexicalBlockStack.empty()) return; - - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc); - PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc); - - if (PCLoc.isInvalid() || PPLoc.isInvalid() || - !strcmp(PPLoc.getFilename(), PCLoc.getFilename())) - return; - - llvm::MDNode *LB = LexicalBlockStack.back(); - llvm::DIScope Scope = llvm::DIScope(LB); - if (Scope.isLexicalBlockFile()) { - llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(LB); - llvm::DIDescriptor D - = DBuilder.createLexicalBlockFile(LBF.getScope(), - getOrCreateFile(CurLoc)); - llvm::MDNode *N = D; - LexicalBlockStack.pop_back(); - LexicalBlockStack.push_back(N); - } else if (Scope.isLexicalBlock()) { - llvm::DIDescriptor D - = DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc)); - llvm::MDNode *N = D; - LexicalBlockStack.pop_back(); - LexicalBlockStack.push_back(N); - } -} - -/// getContextDescriptor - Get context info for the decl. -llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context) { - if (!Context) - return TheCU; - - llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator - I = RegionMap.find(Context); - if (I != RegionMap.end()) { - llvm::Value *V = I->second; - return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V)); - } - - // Check namespace. - if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context)) - return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl)); - - if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) { - if (!RDecl->isDependentType()) { - llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl), - getOrCreateMainFile()); - return llvm::DIDescriptor(Ty); - } - } - return TheCU; -} - -/// getFunctionName - Get function name for the given FunctionDecl. If the -/// name is constructred on demand (e.g. C++ destructor) then the name -/// is stored on the side. -StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { - assert (FD && "Invalid FunctionDecl!"); - IdentifierInfo *FII = FD->getIdentifier(); - FunctionTemplateSpecializationInfo *Info - = FD->getTemplateSpecializationInfo(); - if (!Info && FII) - return FII->getName(); - - // Otherwise construct human readable name for debug info. - std::string NS = FD->getNameAsString(); - - // Add any template specialization args. - if (Info) { - const TemplateArgumentList *TArgs = Info->TemplateArguments; - const TemplateArgument *Args = TArgs->data(); - unsigned NumArgs = TArgs->size(); - PrintingPolicy Policy(CGM.getLangOpts()); - NS += TemplateSpecializationType::PrintTemplateArgumentList(Args, - NumArgs, - Policy); - } - - // Copy this name on the side and use its reference. - char *StrPtr = DebugInfoNames.Allocate<char>(NS.length()); - memcpy(StrPtr, NS.data(), NS.length()); - return StringRef(StrPtr, NS.length()); -} - -StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { - SmallString<256> MethodName; - llvm::raw_svector_ostream OS(MethodName); - OS << (OMD->isInstanceMethod() ? '-' : '+') << '['; - const DeclContext *DC = OMD->getDeclContext(); - if (const ObjCImplementationDecl *OID = - dyn_cast<const ObjCImplementationDecl>(DC)) { - OS << OID->getName(); - } else if (const ObjCInterfaceDecl *OID = - dyn_cast<const ObjCInterfaceDecl>(DC)) { - OS << OID->getName(); - } else if (const ObjCCategoryImplDecl *OCD = - dyn_cast<const ObjCCategoryImplDecl>(DC)){ - OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' << - OCD->getIdentifier()->getNameStart() << ')'; - } - OS << ' ' << OMD->getSelector().getAsString() << ']'; - - char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell()); - memcpy(StrPtr, MethodName.begin(), OS.tell()); - return StringRef(StrPtr, OS.tell()); -} - -/// getSelectorName - Return selector name. This is used for debugging -/// info. -StringRef CGDebugInfo::getSelectorName(Selector S) { - const std::string &SName = S.getAsString(); - char *StrPtr = DebugInfoNames.Allocate<char>(SName.size()); - memcpy(StrPtr, SName.data(), SName.size()); - return StringRef(StrPtr, SName.size()); -} - -/// getClassName - Get class name including template argument list. -StringRef -CGDebugInfo::getClassName(const RecordDecl *RD) { - const ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(RD); - if (!Spec) - return RD->getName(); - - const TemplateArgument *Args; - unsigned NumArgs; - if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) { - const TemplateSpecializationType *TST = - cast<TemplateSpecializationType>(TAW->getType()); - Args = TST->getArgs(); - NumArgs = TST->getNumArgs(); - } else { - const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - Args = TemplateArgs.data(); - NumArgs = TemplateArgs.size(); - } - StringRef Name = RD->getIdentifier()->getName(); - PrintingPolicy Policy(CGM.getLangOpts()); - std::string TemplateArgList = - TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs, Policy); - - // Copy this name on the side and use its reference. - size_t Length = Name.size() + TemplateArgList.size(); - char *StrPtr = DebugInfoNames.Allocate<char>(Length); - memcpy(StrPtr, Name.data(), Name.size()); - memcpy(StrPtr + Name.size(), TemplateArgList.data(), TemplateArgList.size()); - return StringRef(StrPtr, Length); -} - -/// getOrCreateFile - Get the file debug info descriptor for the input location. -llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { - if (!Loc.isValid()) - // If Location is not valid then use main input file. - return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); - - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Loc); - - if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty()) - // If the location is not valid then use main input file. - return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); - - // Cache the results. - const char *fname = PLoc.getFilename(); - llvm::DenseMap<const char *, llvm::WeakVH>::iterator it = - DIFileCache.find(fname); - - if (it != DIFileCache.end()) { - // Verify that the information still exists. - if (llvm::Value *V = it->second) - return llvm::DIFile(cast<llvm::MDNode>(V)); - } - - llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname()); - - DIFileCache[fname] = F; - return F; -} - -/// getOrCreateMainFile - Get the file info for main compile unit. -llvm::DIFile CGDebugInfo::getOrCreateMainFile() { - return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); -} - -/// getLineNumber - Get line number for the location. If location is invalid -/// then use current location. -unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { - if (Loc.isInvalid() && CurLoc.isInvalid()) - return 0; - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); - return PLoc.isValid()? PLoc.getLine() : 0; -} - -/// getColumnNumber - Get column number for the location. -unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) { - // We may not want column information at all. - if (!CGM.getCodeGenOpts().DebugColumnInfo) - return 0; - - // If the location is invalid then use the current column. - if (Loc.isInvalid() && CurLoc.isInvalid()) - return 0; - SourceManager &SM = CGM.getContext().getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); - return PLoc.isValid()? PLoc.getColumn() : 0; -} - -StringRef CGDebugInfo::getCurrentDirname() { - if (!CGM.getCodeGenOpts().DebugCompilationDir.empty()) - return CGM.getCodeGenOpts().DebugCompilationDir; - - if (!CWDName.empty()) - return CWDName; - SmallString<256> CWD; - llvm::sys::fs::current_path(CWD); - char *CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size()); - memcpy(CompDirnamePtr, CWD.data(), CWD.size()); - return CWDName = StringRef(CompDirnamePtr, CWD.size()); -} - -/// CreateCompileUnit - Create new compile unit. -void CGDebugInfo::CreateCompileUnit() { - - // Get absolute path name. - SourceManager &SM = CGM.getContext().getSourceManager(); - std::string MainFileName = CGM.getCodeGenOpts().MainFileName; - if (MainFileName.empty()) - MainFileName = "<unknown>"; - - // The main file name provided via the "-main-file-name" option contains just - // the file name itself with no path information. This file name may have had - // a relative path, so we look into the actual file entry for the main - // file to determine the real absolute path for the file. - std::string MainFileDir; - if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - MainFileDir = MainFile->getDir()->getName(); - if (MainFileDir != ".") - MainFileName = MainFileDir + "/" + MainFileName; - } - - // Save filename string. - char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length()); - memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length()); - StringRef Filename(FilenamePtr, MainFileName.length()); - - unsigned LangTag; - const LangOptions &LO = CGM.getLangOpts(); - if (LO.CPlusPlus) { - if (LO.ObjC1) - LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; - else - LangTag = llvm::dwarf::DW_LANG_C_plus_plus; - } else if (LO.ObjC1) { - LangTag = llvm::dwarf::DW_LANG_ObjC; - } else if (LO.C99) { - LangTag = llvm::dwarf::DW_LANG_C99; - } else { - LangTag = llvm::dwarf::DW_LANG_C89; - } - - std::string Producer = getClangFullVersion(); - - // Figure out which version of the ObjC runtime we have. - unsigned RuntimeVers = 0; - if (LO.ObjC1) - RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1; - - // Create new compile unit. - DBuilder.createCompileUnit( - LangTag, Filename, getCurrentDirname(), - Producer, - LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers); - // FIXME - Eliminate TheCU. - TheCU = llvm::DICompileUnit(DBuilder.getCU()); -} - -/// CreateType - Get the Basic type from the cache or create a new -/// one if necessary. -llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { - unsigned Encoding = 0; - StringRef BTName; - switch (BT->getKind()) { -#define BUILTIN_TYPE(Id, SingletonId) -#define PLACEHOLDER_TYPE(Id, SingletonId) \ - case BuiltinType::Id: -#include "clang/AST/BuiltinTypes.def" - case BuiltinType::Dependent: - llvm_unreachable("Unexpected builtin type"); - case BuiltinType::NullPtr: - return DBuilder. - createNullPtrType(BT->getName(CGM.getLangOpts())); - case BuiltinType::Void: - return llvm::DIType(); - case BuiltinType::ObjCClass: - if (ClassTy.Verify()) - return ClassTy; - ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_class", TheCU, - getOrCreateMainFile(), 0); - return ClassTy; - case BuiltinType::ObjCId: { - // typedef struct objc_class *Class; - // typedef struct objc_object { - // Class isa; - // } *id; - - if (ObjTy.Verify()) - return ObjTy; - - if (!ClassTy.Verify()) - ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_class", TheCU, - getOrCreateMainFile(), 0); - - unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - - llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size); - - llvm::DIType FwdTy = DBuilder.createStructType(TheCU, "objc_object", - getOrCreateMainFile(), - 0, 0, 0, 0, - llvm::DIArray()); - - llvm::TrackingVH<llvm::MDNode> ObjNode(FwdTy); - SmallVector<llvm::Value *, 1> EltTys; - llvm::DIType FieldTy = - DBuilder.createMemberType(llvm::DIDescriptor(ObjNode), "isa", - getOrCreateMainFile(), 0, Size, - 0, 0, 0, ISATy); - EltTys.push_back(FieldTy); - llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); - - ObjNode->replaceOperandWith(10, Elements); - ObjTy = llvm::DIType(ObjNode); - return ObjTy; - } - case BuiltinType::ObjCSel: { - if (SelTy.Verify()) - return SelTy; - SelTy = - DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, - "objc_selector", TheCU, getOrCreateMainFile(), - 0); - return SelTy; - } - 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::Char16: - case BuiltinType::Char32: Encoding = llvm::dwarf::DW_ATE_UTF; break; - case BuiltinType::UShort: - case BuiltinType::UInt: - case BuiltinType::UInt128: - case BuiltinType::ULong: - case BuiltinType::WChar_U: - case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break; - case BuiltinType::Short: - case BuiltinType::Int: - case BuiltinType::Int128: - case BuiltinType::Long: - case BuiltinType::WChar_S: - case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break; - case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break; - case BuiltinType::Half: - case BuiltinType::Float: - case BuiltinType::LongDouble: - case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break; - } - - switch (BT->getKind()) { - case BuiltinType::Long: BTName = "long int"; break; - case BuiltinType::LongLong: BTName = "long long int"; break; - case BuiltinType::ULong: BTName = "long unsigned int"; break; - case BuiltinType::ULongLong: BTName = "long long unsigned int"; break; - default: - BTName = BT->getName(CGM.getLangOpts()); - break; - } - // Bit size, align and offset of the type. - uint64_t Size = CGM.getContext().getTypeSize(BT); - uint64_t Align = CGM.getContext().getTypeAlign(BT); - llvm::DIType DbgTy = - DBuilder.createBasicType(BTName, Size, Align, Encoding); - return DbgTy; -} - -llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) { - // Bit size, align and offset of the type. - unsigned Encoding = llvm::dwarf::DW_ATE_complex_float; - if (Ty->isComplexIntegerType()) - Encoding = llvm::dwarf::DW_ATE_lo_user; - - uint64_t Size = CGM.getContext().getTypeSize(Ty); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); - llvm::DIType DbgTy = - DBuilder.createBasicType("complex", Size, Align, Encoding); - - return DbgTy; -} - -/// CreateCVRType - Get the qualified type from the cache or create -/// a new one if necessary. -llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) { - QualifierCollector Qc; - const Type *T = Qc.strip(Ty); - - // Ignore these qualifiers for now. - Qc.removeObjCGCAttr(); - Qc.removeAddressSpace(); - Qc.removeObjCLifetime(); - - // We will create one Derived type for one qualifier and recurse to handle any - // additional ones. - unsigned Tag; - if (Qc.hasConst()) { - Tag = llvm::dwarf::DW_TAG_const_type; - Qc.removeConst(); - } else if (Qc.hasVolatile()) { - Tag = llvm::dwarf::DW_TAG_volatile_type; - Qc.removeVolatile(); - } else if (Qc.hasRestrict()) { - Tag = llvm::dwarf::DW_TAG_restrict_type; - Qc.removeRestrict(); - } else { - assert(Qc.empty() && "Unknown type qualifier for debug info"); - return getOrCreateType(QualType(T, 0), Unit); - } - - llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit); - - // No need to fill in the Name, Line, Size, Alignment, Offset in case of - // CVR derived types. - llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy); - - return DbgTy; -} - -llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty, - llvm::DIFile Unit) { - llvm::DIType DbgTy = - CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, - Ty->getPointeeType(), Unit); - return DbgTy; -} - -llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, - llvm::DIFile Unit) { - return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty, - Ty->getPointeeType(), Unit); -} - -// Creates a forward declaration for a RecordDecl in the given context. -llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD, - llvm::DIDescriptor Ctx) { - llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); - unsigned Line = getLineNumber(RD->getLocation()); - StringRef RDName = getClassName(RD); - - unsigned Tag = 0; - if (RD->isStruct() || RD->isInterface()) - Tag = llvm::dwarf::DW_TAG_structure_type; - else if (RD->isUnion()) - Tag = llvm::dwarf::DW_TAG_union_type; - else { - assert(RD->isClass()); - Tag = llvm::dwarf::DW_TAG_class_type; - } - - // Create the type. - return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line); -} - -// Walk up the context chain and create forward decls for record decls, -// and normal descriptors for namespaces. -llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) { - if (!Context) - return TheCU; - - // See if we already have the parent. - llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator - I = RegionMap.find(Context); - if (I != RegionMap.end()) { - llvm::Value *V = I->second; - return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V)); - } - - // Check namespace. - if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context)) - return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl)); - - if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) { - if (!RD->isDependentType()) { - llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD), - getOrCreateMainFile()); - return llvm::DIDescriptor(Ty); - } - } - return TheCU; -} - -/// CreatePointeeType - Create Pointee type. If Pointee is a record -/// then emit record's fwd if debug info size reduction is enabled. -llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy, - llvm::DIFile Unit) { - if (CGM.getCodeGenOpts().getDebugInfo() != CodeGenOptions::LimitedDebugInfo) - return getOrCreateType(PointeeTy, Unit); - - // Limit debug info for the pointee type. - - // If we have an existing type, use that, it's still smaller than creating - // a new type. - llvm::DIType Ty = getTypeOrNull(PointeeTy); - if (Ty.Verify()) return Ty; - - // Handle qualifiers. - if (PointeeTy.hasLocalQualifiers()) - return CreateQualifiedType(PointeeTy, Unit); - - if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) { - RecordDecl *RD = RTy->getDecl(); - llvm::DIDescriptor FDContext = - getContextDescriptor(cast<Decl>(RD->getDeclContext())); - llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext); - TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy; - return RetTy; - } - return getOrCreateType(PointeeTy, Unit); - -} - -llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, - const Type *Ty, - QualType PointeeTy, - llvm::DIFile Unit) { - if (Tag == llvm::dwarf::DW_TAG_reference_type || - Tag == llvm::dwarf::DW_TAG_rvalue_reference_type) - return DBuilder.createReferenceType(Tag, - CreatePointeeType(PointeeTy, Unit)); - - // Bit size, align and offset of the type. - // Size is always the size of a pointer. We can't use getTypeSize here - // because that does not return the correct value for references. - unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); - uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); - - return DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), - Size, Align); -} - -llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, - llvm::DIFile Unit) { - if (BlockLiteralGenericSet) - return BlockLiteralGeneric; - - SmallVector<llvm::Value *, 8> EltTys; - llvm::DIType FieldTy; - QualType FType; - uint64_t FieldSize, FieldOffset; - unsigned FieldAlign; - llvm::DIArray Elements; - llvm::DIType EltTy, DescTy; - - FieldOffset = 0; - FType = CGM.getContext().UnsignedLongTy; - EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset)); - EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset)); - - Elements = DBuilder.getOrCreateArray(EltTys); - EltTys.clear(); - - unsigned Flags = llvm::DIDescriptor::FlagAppleBlock; - unsigned LineNo = getLineNumber(CurLoc); - - EltTy = DBuilder.createStructType(Unit, "__block_descriptor", - Unit, LineNo, FieldOffset, 0, - Flags, Elements); - - // Bit size, align and offset of the type. - uint64_t Size = CGM.getContext().getTypeSize(Ty); - - DescTy = DBuilder.createPointerType(EltTy, Size); - - FieldOffset = 0; - FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); - EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset)); - FType = CGM.getContext().IntTy; - EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset)); - EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset)); - FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); - EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset)); - - FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); - FieldTy = DescTy; - FieldSize = CGM.getContext().getTypeSize(Ty); - FieldAlign = CGM.getContext().getTypeAlign(Ty); - FieldTy = DBuilder.createMemberType(Unit, "__descriptor", Unit, - LineNo, FieldSize, FieldAlign, - FieldOffset, 0, FieldTy); - EltTys.push_back(FieldTy); - - FieldOffset += FieldSize; - Elements = DBuilder.getOrCreateArray(EltTys); - - EltTy = DBuilder.createStructType(Unit, "__block_literal_generic", - Unit, LineNo, FieldOffset, 0, - Flags, Elements); - - BlockLiteralGenericSet = true; - BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size); - return BlockLiteralGeneric; -} - -llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile 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); - if (!Src.Verify()) - return llvm::DIType(); - // We don't set size information, but do specify where the typedef was - // declared. - unsigned Line = getLineNumber(Ty->getDecl()->getLocation()); - const TypedefNameDecl *TyDecl = Ty->getDecl(); - - llvm::DIDescriptor TypedefContext = - getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext())); - - return - DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext); -} - -llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, - llvm::DIFile Unit) { - SmallVector<llvm::Value *, 16> EltTys; - - // 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 (isa<FunctionNoProtoType>(Ty)) - EltTys.push_back(DBuilder.createUnspecifiedParameter()); - else if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Ty)) { - for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i) - EltTys.push_back(getOrCreateType(FPT->getArgType(i), Unit)); - } - - llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys); - return DBuilder.createSubroutineType(Unit, EltTypeArray); -} - - -void CGDebugInfo:: -CollectRecordStaticVars(const RecordDecl *RD, llvm::DIType FwdDecl) { - - for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end(); - I != E; ++I) - if (const VarDecl *V = dyn_cast<VarDecl>(*I)) { - if (V->getInit()) { - const APValue *Value = V->evaluateValue(); - if (Value && Value->isInt()) { - llvm::ConstantInt *CI - = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt()); - - // Create the descriptor for static variable. - llvm::DIFile VUnit = getOrCreateFile(V->getLocation()); - StringRef VName = V->getName(); - llvm::DIType VTy = getOrCreateType(V->getType(), VUnit); - // Do not use DIGlobalVariable for enums. - if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) { - DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit, - getLineNumber(V->getLocation()), - VTy, true, CI); - } - } - } - } -} - -llvm::DIType CGDebugInfo::createFieldType(StringRef name, - QualType type, - uint64_t sizeInBitsOverride, - SourceLocation loc, - AccessSpecifier AS, - uint64_t offsetInBits, - llvm::DIFile tunit, - llvm::DIDescriptor scope) { - llvm::DIType debugType = getOrCreateType(type, tunit); - - // Get the location for the field. - llvm::DIFile file = getOrCreateFile(loc); - unsigned line = getLineNumber(loc); - - uint64_t sizeInBits = 0; - unsigned alignInBits = 0; - if (!type->isIncompleteArrayType()) { - llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type); - - if (sizeInBitsOverride) - sizeInBits = sizeInBitsOverride; - } - - unsigned flags = 0; - if (AS == clang::AS_private) - flags |= llvm::DIDescriptor::FlagPrivate; - else if (AS == clang::AS_protected) - flags |= llvm::DIDescriptor::FlagProtected; - - return DBuilder.createMemberType(scope, name, file, line, sizeInBits, - alignInBits, offsetInBits, flags, debugType); -} - -/// CollectRecordFields - A helper function to collect debug info for -/// record fields. This is used while creating debug info entry for a Record. -void CGDebugInfo:: -CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, - SmallVectorImpl<llvm::Value *> &elements, - llvm::DIType RecordTy) { - unsigned fieldNo = 0; - const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); - const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record); - - // For C++11 Lambdas a Field will be the same as a Capture, but the Capture - // has the name and the location of the variable so we should iterate over - // both concurrently. - if (CXXDecl && CXXDecl->isLambda()) { - RecordDecl::field_iterator Field = CXXDecl->field_begin(); - unsigned fieldno = 0; - for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(), - E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) { - const LambdaExpr::Capture C = *I; - if (C.capturesVariable()) { - VarDecl *V = C.getCapturedVar(); - llvm::DIFile VUnit = getOrCreateFile(C.getLocation()); - StringRef VName = V->getName(); - uint64_t SizeInBitsOverride = 0; - if (Field->isBitField()) { - SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext()); - assert(SizeInBitsOverride && "found named 0-width bitfield"); - } - llvm::DIType fieldType - = createFieldType(VName, Field->getType(), SizeInBitsOverride, C.getLocation(), - Field->getAccess(), layout.getFieldOffset(fieldno), - VUnit, RecordTy); - elements.push_back(fieldType); - } else { - // TODO: Need to handle 'this' in some way by probably renaming the - // this of the lambda class and having a field member of 'this' or - // by using AT_object_pointer for the function and having that be - // used as 'this' for semantic references. - assert(C.capturesThis() && "Field that isn't captured and isn't this?"); - FieldDecl *f = *Field; - llvm::DIFile VUnit = getOrCreateFile(f->getLocation()); - QualType type = f->getType(); - llvm::DIType fieldType - = createFieldType("this", type, 0, f->getLocation(), f->getAccess(), - layout.getFieldOffset(fieldNo), VUnit, RecordTy); - - elements.push_back(fieldType); - } - } - } else { - bool IsMsStruct = record->isMsStruct(CGM.getContext()); - const FieldDecl *LastFD = 0; - for (RecordDecl::field_iterator I = record->field_begin(), - E = record->field_end(); - I != E; ++I, ++fieldNo) { - FieldDecl *field = *I; - - if (IsMsStruct) { - // Zero-length bitfields following non-bitfield members are ignored - if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) { - --fieldNo; - continue; - } - LastFD = field; - } - - StringRef name = field->getName(); - QualType type = field->getType(); - - // Ignore unnamed fields unless they're anonymous structs/unions. - if (name.empty() && !type->isRecordType()) { - LastFD = field; - continue; - } - - uint64_t SizeInBitsOverride = 0; - if (field->isBitField()) { - SizeInBitsOverride = field->getBitWidthValue(CGM.getContext()); - assert(SizeInBitsOverride && "found named 0-width bitfield"); - } - - llvm::DIType fieldType - = createFieldType(name, type, SizeInBitsOverride, - field->getLocation(), field->getAccess(), - layout.getFieldOffset(fieldNo), tunit, RecordTy); - - elements.push_back(fieldType); - } - } -} - -/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This -/// function type is not updated to include implicit "this" pointer. Use this -/// routine to get a method type which includes "this" pointer. -llvm::DIType -CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, - llvm::DIFile Unit) { - llvm::DIType FnTy - = getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(), - 0), - Unit); - - // Add "this" pointer. - llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray(); - assert (Args.getNumElements() && "Invalid number of arguments!"); - - SmallVector<llvm::Value *, 16> Elts; - - // First element is always return type. For 'void' functions it is NULL. - Elts.push_back(Args.getElement(0)); - - if (!Method->isStatic()) { - // "this" pointer is always first argument. - QualType ThisPtr = Method->getThisType(CGM.getContext()); - - const CXXRecordDecl *RD = Method->getParent(); - if (isa<ClassTemplateSpecializationDecl>(RD)) { - // Create pointer type directly in this case. - const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr); - QualType PointeeTy = ThisPtrTy->getPointeeType(); - unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); - uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS); - uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy); - llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit); - llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align); - TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; - // TODO: This and the artificial type below are misleading, the - // types aren't artificial the argument is, but the current - // metadata doesn't represent that. - ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); - Elts.push_back(ThisPtrType); - } else { - llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit); - TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; - ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType); - Elts.push_back(ThisPtrType); - } - } - - // Copy rest of the arguments. - for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i) - Elts.push_back(Args.getElement(i)); - - llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); - - return DBuilder.createSubroutineType(Unit, EltTypeArray); -} - -/// isFunctionLocalClass - Return true if CXXRecordDecl is defined -/// inside a function. -static bool isFunctionLocalClass(const CXXRecordDecl *RD) { - if (const CXXRecordDecl *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext())) - return isFunctionLocalClass(NRD); - if (isa<FunctionDecl>(RD->getDeclContext())) - return true; - return false; -} - -/// CreateCXXMemberFunction - A helper function to create a DISubprogram for -/// a single member function GlobalDecl. -llvm::DISubprogram -CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, - llvm::DIFile Unit, - llvm::DIType RecordTy) { - bool IsCtorOrDtor = - isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method); - - StringRef MethodName = getFunctionName(Method); - llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit); - - // Since a single ctor/dtor corresponds to multiple functions, it doesn't - // make sense to give a single ctor/dtor a linkage name. - StringRef MethodLinkageName; - if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent())) - MethodLinkageName = CGM.getMangledName(Method); - - // Get the location for the method. - llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation()); - unsigned MethodLine = getLineNumber(Method->getLocation()); - - // Collect virtual method info. - llvm::DIType ContainingType; - unsigned Virtuality = 0; - unsigned VIndex = 0; - - if (Method->isVirtual()) { - if (Method->isPure()) - Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual; - else - Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual; - |