2008-05-08 16:54:20 +08:00
|
|
|
//===--- 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 "CodeGenModule.h"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-02-27 05:10:26 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2008-11-11 15:01:36 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2009-07-19 03:43:29 +08:00
|
|
|
#include "clang/AST/RecordLayout.h"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
#include "clang/Basic/FileManager.h"
|
2009-03-28 07:16:32 +08:00
|
|
|
#include "clang/Frontend/CompileOptions.h"
|
2008-05-08 16:54:20 +08:00
|
|
|
#include "llvm/Constants.h"
|
|
|
|
#include "llvm/DerivedTypes.h"
|
|
|
|
#include "llvm/Instructions.h"
|
|
|
|
#include "llvm/Intrinsics.h"
|
|
|
|
#include "llvm/Module.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "llvm/Support/Dwarf.h"
|
2009-04-18 05:06:59 +08:00
|
|
|
#include "llvm/System/Path.h"
|
2008-05-25 13:15:42 +08:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2008-05-08 16:54:20 +08:00
|
|
|
using namespace clang;
|
|
|
|
using namespace clang::CodeGen;
|
|
|
|
|
2009-07-15 05:31:22 +08:00
|
|
|
CGDebugInfo::CGDebugInfo(CodeGenModule *m)
|
2009-05-14 10:03:51 +08:00
|
|
|
: M(m), isMainCompileUnitCreated(false), DebugFactory(M->getModule()),
|
|
|
|
BlockLiteralGenericSet(false) {
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
CGDebugInfo::~CGDebugInfo() {
|
2008-10-18 00:15:48 +08:00
|
|
|
assert(RegionStack.empty() && "Region stack mismatch, stack not empty!");
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::setLocation(SourceLocation Loc) {
|
|
|
|
if (Loc.isValid())
|
2009-01-16 15:36:28 +08:00
|
|
|
CurLoc = M->getContext().getSourceManager().getInstantiationLoc(Loc);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
|
2008-10-24 16:38:36 +08:00
|
|
|
/// one if necessary. This returns null for invalid source locations.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
|
2009-04-18 05:06:59 +08:00
|
|
|
// Get source file information.
|
|
|
|
const char *FileName = "<unknown>";
|
2009-02-25 07:16:03 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-19 14:50:29 +08:00
|
|
|
unsigned FID = 0;
|
2009-01-22 08:09:25 +08:00
|
|
|
if (Loc.isValid()) {
|
2009-04-18 05:06:59 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
|
|
|
|
FileName = PLoc.getFilename();
|
|
|
|
FID = PLoc.getIncludeLoc().getRawEncoding();
|
2009-01-22 08:09:25 +08:00
|
|
|
}
|
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
// See if this compile unit has been used before.
|
2009-04-18 05:06:59 +08:00
|
|
|
llvm::DICompileUnit &Unit = CompileUnitCache[FID];
|
2008-11-10 14:08:34 +08:00
|
|
|
if (!Unit.isNull()) return Unit;
|
2009-04-08 13:11:16 +08:00
|
|
|
|
2009-04-18 05:06:59 +08:00
|
|
|
// Get absolute path name.
|
|
|
|
llvm::sys::Path AbsFileName(FileName);
|
|
|
|
if (!AbsFileName.isAbsolute()) {
|
|
|
|
llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory();
|
|
|
|
tmp.appendComponent(FileName);
|
|
|
|
AbsFileName = tmp;
|
|
|
|
}
|
|
|
|
|
2009-06-27 02:32:22 +08:00
|
|
|
// See if thie compile unit is representing main source file. Each source
|
|
|
|
// file has corresponding compile unit. There is only one main source
|
|
|
|
// file at a time.
|
|
|
|
bool isMain = false;
|
|
|
|
const LangOptions &LO = M->getLangOptions();
|
|
|
|
const char *MainFileName = LO.getMainFileName();
|
|
|
|
if (isMainCompileUnitCreated == false) {
|
|
|
|
if (MainFileName) {
|
|
|
|
if (!strcmp(AbsFileName.getLast().c_str(), MainFileName))
|
|
|
|
isMain = true;
|
|
|
|
} else {
|
|
|
|
if (Loc.isValid() && SM.isFromMainFile(Loc))
|
|
|
|
isMain = true;
|
|
|
|
}
|
|
|
|
if (isMain)
|
|
|
|
isMainCompileUnitCreated = true;
|
2009-04-18 05:06:59 +08:00
|
|
|
}
|
2009-04-08 13:11:16 +08:00
|
|
|
|
2009-03-25 11:28:08 +08:00
|
|
|
unsigned LangTag;
|
|
|
|
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) {
|
2009-03-25 04:35:51 +08:00
|
|
|
LangTag = llvm::dwarf::DW_LANG_ObjC;
|
2009-03-25 11:28:08 +08:00
|
|
|
} else if (LO.C99) {
|
2009-03-25 04:35:51 +08:00
|
|
|
LangTag = llvm::dwarf::DW_LANG_C99;
|
2009-03-25 11:28:08 +08:00
|
|
|
} else {
|
|
|
|
LangTag = llvm::dwarf::DW_LANG_C89;
|
|
|
|
}
|
2009-04-18 05:06:59 +08:00
|
|
|
|
2009-05-02 09:04:13 +08:00
|
|
|
std::string Producer = "clang 1.0";// FIXME: clang version.
|
|
|
|
bool isOptimized = LO.Optimize;
|
2009-05-02 09:00:04 +08:00
|
|
|
const char *Flags = ""; // FIXME: Encode command line options.
|
|
|
|
|
|
|
|
// Figure out which version of the ObjC runtime we have.
|
|
|
|
unsigned RuntimeVers = 0;
|
|
|
|
if (LO.ObjC1)
|
|
|
|
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create new compile unit.
|
2009-06-27 02:32:22 +08:00
|
|
|
return Unit = DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
|
|
|
|
AbsFileName.getDirname(),
|
|
|
|
Producer, isMain, isOptimized,
|
|
|
|
Flags, RuntimeVers);
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2009-02-25 09:36:11 +08:00
|
|
|
/// CreateType - Get the Basic type from the cache or create a new
|
2008-05-25 13:15:42 +08:00
|
|
|
/// one if necessary.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
|
2009-02-25 09:36:11 +08:00
|
|
|
llvm::DICompileUnit Unit) {
|
2008-05-25 13:15:42 +08:00
|
|
|
unsigned Encoding = 0;
|
2008-11-10 14:08:34 +08:00
|
|
|
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;
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
// Bit size, align and offset of the type.
|
2008-11-10 14:08:34 +08:00
|
|
|
uint64_t Size = M->getContext().getTypeSize(BT);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(BT);
|
2008-05-25 13:15:42 +08:00
|
|
|
uint64_t Offset = 0;
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2009-05-30 04:38:28 +08:00
|
|
|
return DebugFactory.CreateBasicType(Unit,
|
2009-06-30 09:26:17 +08:00
|
|
|
BT->getName(M->getContext().getLangOptions()),
|
2009-05-30 04:38:28 +08:00
|
|
|
Unit, 0, Size, Align,
|
2008-11-10 14:08:34 +08:00
|
|
|
Offset, /*flags*/ 0, Encoding);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2009-04-23 14:13:01 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
// 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 = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
uint64_t Offset = 0;
|
|
|
|
|
|
|
|
return DebugFactory.CreateBasicType(Unit, "complex",
|
|
|
|
Unit, 0, Size, Align,
|
|
|
|
Offset, /*flags*/ 0, Encoding);
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
/// 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);
|
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2009-07-14 09:20:56 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), Unit);
|
|
|
|
|
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
|
|
|
|
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
|
|
|
"", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0, EltTy);
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), Unit);
|
2008-05-25 13:15:42 +08:00
|
|
|
|
|
|
|
// Bit size, align and offset of the type.
|
2008-11-10 14:08:34 +08:00
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
|
|
|
"", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0, EltTy);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2009-05-14 10:03:51 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
if (BlockLiteralGenericSet)
|
|
|
|
return BlockLiteralGeneric;
|
|
|
|
|
|
|
|
llvm::DICompileUnit DefUnit;
|
|
|
|
unsigned Tag = llvm::dwarf::DW_TAG_structure_type;
|
|
|
|
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 5> EltTys;
|
|
|
|
|
|
|
|
llvm::DIType FieldTy;
|
|
|
|
|
|
|
|
QualType FType;
|
|
|
|
uint64_t FieldSize, FieldOffset;
|
|
|
|
unsigned FieldAlign;
|
|
|
|
|
|
|
|
llvm::DIArray Elements;
|
|
|
|
llvm::DIType EltTy, DescTy;
|
|
|
|
|
|
|
|
FieldOffset = 0;
|
|
|
|
FType = M->getContext().UnsignedLongTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"reserved", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().UnsignedLongTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"Size", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2009-05-27 03:40:20 +08:00
|
|
|
Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-05-14 10:03:51 +08:00
|
|
|
EltTys.clear();
|
|
|
|
|
|
|
|
EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_descriptor",
|
|
|
|
DefUnit, 0, FieldOffset, 0, 0, 0,
|
|
|
|
llvm::DIType(), Elements);
|
|
|
|
|
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
|
|
|
|
DescTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
|
|
|
|
Unit, "", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0, EltTy);
|
|
|
|
|
|
|
|
FieldOffset = 0;
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__isa", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().IntTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__flags", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().IntTy;
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__reserved", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__FuncPtr", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
|
|
|
FType = M->getContext().getPointerType(M->getContext().VoidTy);
|
|
|
|
FieldTy = DescTy;
|
|
|
|
FieldSize = M->getContext().getTypeSize(Ty);
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(Ty);
|
|
|
|
FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
|
|
|
|
"__descriptor", DefUnit,
|
|
|
|
0, FieldSize, FieldAlign,
|
|
|
|
FieldOffset, 0, FieldTy);
|
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
|
|
|
|
FieldOffset += FieldSize;
|
2009-05-27 03:40:20 +08:00
|
|
|
Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-05-14 10:03:51 +08:00
|
|
|
|
|
|
|
EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_literal_generic",
|
|
|
|
DefUnit, 0, FieldOffset, 0, 0, 0,
|
|
|
|
llvm::DIType(), Elements);
|
|
|
|
|
|
|
|
BlockLiteralGenericSet = true;
|
|
|
|
BlockLiteralGeneric
|
|
|
|
= DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
|
|
|
|
"", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0, EltTy);
|
|
|
|
return BlockLiteralGeneric;
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
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.
|
2008-11-24 11:54:41 +08:00
|
|
|
std::string TyName = Ty->getDecl()->getNameAsString();
|
2008-11-10 14:08:34 +08:00
|
|
|
SourceLocation DefLoc = Ty->getDecl()->getLocation();
|
|
|
|
llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
|
2008-05-25 13:15:42 +08:00
|
|
|
|
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(DefLoc);
|
|
|
|
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
|
|
|
|
TyName, DefUnit, Line, 0, 0, 0, 0, Src);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// 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 '...'!
|
2009-02-27 07:50:07 +08:00
|
|
|
if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) {
|
2008-11-10 14:08:34 +08:00
|
|
|
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.
|
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIArray EltTypeArray =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
|
|
|
|
Unit, "", llvm::DICompileUnit(),
|
|
|
|
0, 0, 0, 0, 0,
|
|
|
|
llvm::DIType(), EltTypeArray);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
2009-02-25 09:36:11 +08:00
|
|
|
/// CreateType - get structure or union type.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
2008-12-12 01:59:21 +08:00
|
|
|
RecordDecl *Decl = Ty->getDecl();
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
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;
|
2008-06-07 12:46:53 +08:00
|
|
|
}
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-06-07 12:46:53 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get overall information about the record type for the debug info.
|
2008-11-24 11:54:41 +08:00
|
|
|
std::string Name = Decl->getNameAsString();
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
2009-05-05 13:16:17 +08:00
|
|
|
llvm::DICompileUnit DefUnit;
|
|
|
|
unsigned Line = 0;
|
|
|
|
if (!PLoc.isInvalid()) {
|
|
|
|
DefUnit = getOrCreateCompileUnit(Decl->getLocation());
|
|
|
|
Line = PLoc.getLine();
|
|
|
|
}
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// 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.
|
2009-07-23 02:57:00 +08:00
|
|
|
llvm::DICompositeType FwdDecl =
|
2008-11-10 14:08:34 +08:00
|
|
|
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<llvm::DIDescriptor, 16> EltTys;
|
|
|
|
|
|
|
|
const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(Decl);
|
|
|
|
|
|
|
|
unsigned FieldNo = 0;
|
2009-06-30 10:36:12 +08:00
|
|
|
for (RecordDecl::field_iterator I = Decl->field_begin(),
|
|
|
|
E = Decl->field_end();
|
2008-12-12 01:59:21 +08:00
|
|
|
I != E; ++I, ++FieldNo) {
|
2008-11-10 14:08:34 +08:00
|
|
|
FieldDecl *Field = *I;
|
|
|
|
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
|
2008-11-24 11:54:41 +08:00
|
|
|
|
|
|
|
std::string FieldName = Field->getNameAsString();
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2009-04-28 06:40:36 +08:00
|
|
|
// Ignore unnamed fields.
|
|
|
|
if (FieldName.empty())
|
|
|
|
continue;
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get the location for the field.
|
|
|
|
SourceLocation FieldDefLoc = Field->getLocation();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc);
|
2009-05-05 13:16:17 +08:00
|
|
|
llvm::DICompileUnit FieldDefUnit;
|
|
|
|
unsigned FieldLine = 0;
|
|
|
|
|
|
|
|
if (!PLoc.isInvalid()) {
|
|
|
|
FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc);
|
|
|
|
FieldLine = PLoc.getLine();
|
|
|
|
}
|
2009-03-17 07:47:53 +08:00
|
|
|
|
|
|
|
QualType FType = Field->getType();
|
|
|
|
uint64_t FieldSize = 0;
|
|
|
|
unsigned FieldAlign = 0;
|
|
|
|
if (!FType->isIncompleteArrayType()) {
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2009-03-17 07:47:53 +08:00
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
2009-04-27 03:19:15 +08:00
|
|
|
FieldSize = BitWidth->EvaluateAsInt(M->getContext()).getZExtValue();
|
2009-03-17 07:47:53 +08:00
|
|
|
|
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
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);
|
2008-06-07 12:46:53 +08:00
|
|
|
}
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
llvm::DIArray Elements =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
|
2009-07-23 02:57:00 +08:00
|
|
|
llvm::DICompositeType RealDecl =
|
2008-11-10 14:08:34 +08:00
|
|
|
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.
|
2009-07-23 02:57:00 +08:00
|
|
|
FwdDecl.replaceAllUsesWith(RealDecl);
|
2009-07-14 01:03:14 +08:00
|
|
|
|
|
|
|
// Update TypeCache.
|
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
|
2008-11-10 14:08:34 +08:00
|
|
|
return RealDecl;
|
2008-06-07 12:46:53 +08:00
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
/// 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());
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
|
|
|
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2009-05-19 04:51:58 +08:00
|
|
|
unsigned RuntimeLang = DefUnit.getLanguage();
|
2009-05-02 09:13:16 +08:00
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// 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.
|
2009-07-28 02:42:03 +08:00
|
|
|
llvm::DICompositeType FwdDecl =
|
2009-02-27 05:10:26 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, 0, 0, 0, 0,
|
2009-05-02 09:13:16 +08:00
|
|
|
llvm::DIType(), llvm::DIArray(),
|
|
|
|
RuntimeLang);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// 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<llvm::DIDescriptor, 16> EltTys;
|
|
|
|
|
2009-03-11 05:30:26 +08:00
|
|
|
ObjCInterfaceDecl *SClass = Decl->getSuperClass();
|
|
|
|
if (SClass) {
|
|
|
|
llvm::DIType SClassTy =
|
|
|
|
getOrCreateType(M->getContext().getObjCInterfaceType(SClass), Unit);
|
|
|
|
llvm::DIType InhTag =
|
|
|
|
DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance,
|
2009-05-05 13:05:36 +08:00
|
|
|
Unit, "", llvm::DICompileUnit(), 0, 0, 0,
|
2009-03-11 05:30:26 +08:00
|
|
|
0 /* offset */, 0, SClassTy);
|
|
|
|
EltTys.push_back(InhTag);
|
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
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();
|
|
|
|
|
2009-04-28 06:40:36 +08:00
|
|
|
// Ignore unnamed fields.
|
|
|
|
if (FieldName.empty())
|
|
|
|
continue;
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// Get the location for the field.
|
|
|
|
SourceLocation FieldDefLoc = Field->getLocation();
|
|
|
|
llvm::DICompileUnit FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc);
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc);
|
|
|
|
unsigned FieldLine = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
|
|
|
|
2009-03-21 02:24:39 +08:00
|
|
|
|
|
|
|
QualType FType = Field->getType();
|
|
|
|
uint64_t FieldSize = 0;
|
|
|
|
unsigned FieldAlign = 0;
|
|
|
|
|
|
|
|
if (!FType->isIncompleteArrayType()) {
|
2009-02-27 05:10:26 +08:00
|
|
|
|
2009-03-21 02:24:39 +08:00
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
FieldSize = M->getContext().getTypeSize(FType);
|
|
|
|
Expr *BitWidth = Field->getBitWidth();
|
|
|
|
if (BitWidth)
|
2009-04-27 03:19:15 +08:00
|
|
|
FieldSize = BitWidth->EvaluateAsInt(M->getContext()).getZExtValue();
|
|
|
|
|
2009-03-21 02:24:39 +08:00
|
|
|
FieldAlign = M->getContext().getTypeAlign(FType);
|
|
|
|
}
|
2009-03-19 08:23:53 +08:00
|
|
|
|
2009-03-21 02:24:39 +08:00
|
|
|
uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
|
|
|
|
|
2009-03-19 08:23:53 +08:00
|
|
|
unsigned Flags = 0;
|
|
|
|
if (Field->getAccessControl() == ObjCIvarDecl::Protected)
|
|
|
|
Flags = llvm::DIType::FlagProtected;
|
|
|
|
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
|
|
|
|
Flags = llvm::DIType::FlagPrivate;
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
// 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,
|
2009-03-19 08:23:53 +08:00
|
|
|
FieldOffset, Flags, FieldTy);
|
2009-02-27 05:10:26 +08:00
|
|
|
EltTys.push_back(FieldTy);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::DIArray Elements =
|
2009-05-21 17:52:38 +08:00
|
|
|
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// Bit size, align and offset of the type.
|
|
|
|
uint64_t Size = M->getContext().getTypeSize(Ty);
|
|
|
|
uint64_t Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
|
2009-07-28 02:42:03 +08:00
|
|
|
llvm::DICompositeType RealDecl =
|
2009-02-27 05:10:26 +08:00
|
|
|
DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size,
|
2009-05-02 09:13:16 +08:00
|
|
|
Align, 0, 0, llvm::DIType(), Elements,
|
|
|
|
RuntimeLang);
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
// 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.
|
2009-07-28 02:42:03 +08:00
|
|
|
FwdDecl.replaceAllUsesWith(RealDecl);
|
2009-07-14 01:03:14 +08:00
|
|
|
|
|
|
|
// Update TypeCache.
|
|
|
|
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
|
2009-02-27 05:10:26 +08:00
|
|
|
return RealDecl;
|
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
EnumDecl *Decl = Ty->getDecl();
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create DIEnumerator elements for each enumerator.
|
2009-04-10 05:40:53 +08:00
|
|
|
for (EnumDecl::enumerator_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
Enum = Decl->enumerator_begin(), EnumEnd = Decl->enumerator_end();
|
2008-12-12 00:49:14 +08:00
|
|
|
Enum != EnumEnd; ++Enum) {
|
|
|
|
Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(),
|
|
|
|
Enum->getInitVal().getZExtValue()));
|
2008-11-10 14:08:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return a CompositeType for the enum itself.
|
|
|
|
llvm::DIArray EltArray =
|
2009-05-21 17:52:38 +08:00
|
|
|
DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size());
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-24 11:54:41 +08:00
|
|
|
std::string EnumName = Decl->getNameAsString();
|
2008-11-10 14:08:34 +08:00
|
|
|
SourceLocation DefLoc = Decl->getLocation();
|
|
|
|
llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
|
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(DefLoc);
|
|
|
|
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
// Size and align of the type.
|
2009-05-04 12:39:55 +08:00
|
|
|
uint64_t Size = 0;
|
|
|
|
unsigned Align = 0;
|
|
|
|
if (!Ty->isIncompleteType()) {
|
|
|
|
Size = M->getContext().getTypeSize(Ty);
|
|
|
|
Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
}
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
|
|
|
|
Unit, EnumName, DefUnit, Line,
|
|
|
|
Size, Align, 0, 0,
|
|
|
|
llvm::DIType(), EltArray);
|
|
|
|
}
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
if (const RecordType *RT = dyn_cast<RecordType>(Ty))
|
|
|
|
return CreateType(RT, Unit);
|
|
|
|
else if (const EnumType *ET = dyn_cast<EnumType>(Ty))
|
|
|
|
return CreateType(ET, Unit);
|
|
|
|
|
|
|
|
return llvm::DIType();
|
|
|
|
}
|
2008-06-09 18:47:41 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
2009-01-05 09:23:29 +08:00
|
|
|
uint64_t Size;
|
|
|
|
uint64_t Align;
|
|
|
|
|
|
|
|
|
2009-01-28 08:35:17 +08:00
|
|
|
// FIXME: make getTypeAlign() aware of VLAs and incomplete array types
|
2009-01-05 09:23:29 +08:00
|
|
|
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(Ty)) {
|
|
|
|
Size = 0;
|
|
|
|
Align =
|
2009-01-28 08:35:17 +08:00
|
|
|
M->getContext().getTypeAlign(M->getContext().getBaseElementType(VAT));
|
|
|
|
} else if (Ty->isIncompleteArrayType()) {
|
|
|
|
Size = 0;
|
|
|
|
Align = M->getContext().getTypeAlign(Ty->getElementType());
|
2009-01-05 09:23:29 +08:00
|
|
|
} else {
|
|
|
|
// Size and align of the whole array, not the element type.
|
|
|
|
Size = M->getContext().getTypeSize(Ty);
|
|
|
|
Align = M->getContext().getTypeAlign(Ty);
|
|
|
|
}
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
// 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<llvm::DIDescriptor, 8> Subscripts;
|
|
|
|
QualType EltTy(Ty, 0);
|
|
|
|
while ((Ty = dyn_cast<ArrayType>(EltTy))) {
|
2008-06-09 18:47:41 +08:00
|
|
|
uint64_t Upper = 0;
|
2009-08-15 04:57:45 +08:00
|
|
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
|
|
|
|
if (CAT->getSize().getZExtValue())
|
|
|
|
Upper = CAT->getSize().getZExtValue() - 1;
|
2008-11-10 14:08:34 +08:00
|
|
|
// FIXME: Verify this is right for VLAs.
|
|
|
|
Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, Upper));
|
|
|
|
EltTy = Ty->getElementType();
|
2008-06-09 18:47:41 +08:00
|
|
|
}
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
llvm::DIArray SubscriptArray =
|
2009-05-27 03:40:20 +08:00
|
|
|
DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
|
|
|
|
Unit, "", llvm::DICompileUnit(),
|
|
|
|
0, Size, Align, 0, 0,
|
|
|
|
getOrCreateType(EltTy, Unit),
|
|
|
|
SubscriptArray);
|
2008-06-09 18:47:41 +08:00
|
|
|
}
|
|
|
|
|
2008-06-07 12:46:53 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
/// getOrCreateType - Get the type from the cache or create a new
|
|
|
|
/// one if necessary.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
|
|
|
|
llvm::DICompileUnit Unit) {
|
|
|
|
if (Ty.isNull())
|
|
|
|
return llvm::DIType();
|
|
|
|
|
2009-07-14 00:15:54 +08:00
|
|
|
// Check TypeCache first.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DIType &Slot = TypeCache[Ty.getAsOpaquePtr()];
|
|
|
|
if (!Slot.isNull()) return Slot;
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Handle CVR qualifiers, which recursively handles what they refer to.
|
|
|
|
if (Ty.getCVRQualifiers())
|
|
|
|
return Slot = CreateCVRType(Ty, Unit);
|
2008-05-25 13:15:42 +08:00
|
|
|
|
|
|
|
// Work out details of type.
|
2008-11-10 14:08:34 +08:00
|
|
|
switch (Ty->getTypeClass()) {
|
2009-02-27 07:50:07 +08:00
|
|
|
#define TYPE(Class, Base)
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#define NON_CANONICAL_TYPE(Class, Base)
|
|
|
|
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
assert(false && "Dependent types cannot show up in debug information");
|
2009-08-19 09:28:17 +08:00
|
|
|
|
2009-03-17 07:22:08 +08:00
|
|
|
case Type::LValueReference:
|
|
|
|
case Type::RValueReference:
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::Vector:
|
|
|
|
case Type::ExtVector:
|
2009-02-18 02:27:45 +08:00
|
|
|
case Type::ExtQual:
|
2009-02-28 07:15:07 +08:00
|
|
|
case Type::FixedWidthInt:
|
|
|
|
case Type::MemberPointer:
|
2009-03-31 06:58:21 +08:00
|
|
|
case Type::TemplateSpecialization:
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
case Type::QualifiedName:
|
2009-02-28 07:15:07 +08:00
|
|
|
// Unsupported types
|
2008-11-10 14:08:34 +08:00
|
|
|
return llvm::DIType();
|
2009-07-14 09:20:56 +08:00
|
|
|
case Type::ObjCObjectPointer:
|
|
|
|
return Slot = CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
|
2009-03-03 01:58:28 +08:00
|
|
|
case Type::ObjCInterface:
|
2009-04-22 14:58:56 +08:00
|
|
|
return Slot = CreateType(cast<ObjCInterfaceType>(Ty), Unit);
|
|
|
|
case Type::Builtin: return Slot = CreateType(cast<BuiltinType>(Ty), Unit);
|
2009-04-23 14:13:01 +08:00
|
|
|
case Type::Complex: return Slot = CreateType(cast<ComplexType>(Ty), Unit);
|
2009-04-22 14:58:56 +08:00
|
|
|
case Type::Pointer: return Slot = CreateType(cast<PointerType>(Ty), Unit);
|
2009-05-14 10:03:51 +08:00
|
|
|
case Type::BlockPointer:
|
|
|
|
return Slot = CreateType(cast<BlockPointerType>(Ty), Unit);
|
2009-04-22 14:58:56 +08:00
|
|
|
case Type::Typedef: return Slot = CreateType(cast<TypedefType>(Ty), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::Record:
|
|
|
|
case Type::Enum:
|
2009-04-22 14:58:56 +08:00
|
|
|
return Slot = CreateType(cast<TagType>(Ty), Unit);
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::FunctionProto:
|
|
|
|
case Type::FunctionNoProto:
|
2008-11-11 15:01:36 +08:00
|
|
|
return Slot = CreateType(cast<FunctionType>(Ty), Unit);
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
case Type::ConstantArray:
|
2009-07-06 23:59:29 +08:00
|
|
|
case Type::ConstantArrayWithExpr:
|
|
|
|
case Type::ConstantArrayWithoutExpr:
|
2008-11-10 14:08:34 +08:00
|
|
|
case Type::VariableArray:
|
|
|
|
case Type::IncompleteArray:
|
2008-11-11 15:01:36 +08:00
|
|
|
return Slot = CreateType(cast<ArrayType>(Ty), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::TypeOfExpr:
|
|
|
|
return Slot = getOrCreateType(cast<TypeOfExprType>(Ty)->getUnderlyingExpr()
|
2008-11-11 15:01:36 +08:00
|
|
|
->getType(), Unit);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::TypeOf:
|
2008-11-11 15:01:36 +08:00
|
|
|
return Slot = getOrCreateType(cast<TypeOfType>(Ty)->getUnderlyingType(),
|
|
|
|
Unit);
|
2009-06-25 03:06:50 +08:00
|
|
|
case Type::Decltype:
|
2009-07-11 03:20:26 +08:00
|
|
|
return Slot = getOrCreateType(cast<DecltypeType>(Ty)->getUnderlyingType(),
|
|
|
|
Unit);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
2008-11-10 14:08:34 +08:00
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
return Slot;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitFunctionStart - Constructs the debug code for entering a function -
|
|
|
|
/// "llvm.dbg.func.start.".
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
|
2008-05-25 13:15:42 +08:00
|
|
|
llvm::Function *Fn,
|
2008-11-10 14:08:34 +08:00
|
|
|
CGBuilderTy &Builder) {
|
2009-07-15 05:31:22 +08:00
|
|
|
const char *LinkageName = Name;
|
|
|
|
|
2009-05-14 07:08:57 +08:00
|
|
|
// Skip the asm prefix if it exists.
|
2009-05-14 09:45:24 +08:00
|
|
|
//
|
|
|
|
// FIXME: This should probably be the unmangled name?
|
2009-05-14 07:08:57 +08:00
|
|
|
if (Name[0] == '\01')
|
|
|
|
++Name;
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// FIXME: Why is this using CurLoc???
|
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc);
|
2008-05-25 13:15:42 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-09 03:47:04 +08:00
|
|
|
unsigned LineNo = SM.getPresumedLoc(CurLoc).getLine();
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
llvm::DISubprogram SP =
|
2009-07-15 05:31:22 +08:00
|
|
|
DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo,
|
2008-11-10 14:08:34 +08:00
|
|
|
getOrCreateType(ReturnType, Unit),
|
|
|
|
Fn->hasInternalLinkage(), true/*definition*/);
|
|
|
|
|
|
|
|
DebugFactory.InsertSubprogramStart(SP, Builder.GetInsertBlock());
|
|
|
|
|
2008-05-25 13:15:42 +08:00
|
|
|
// Push function on region stack.
|
2008-11-10 14:08:34 +08:00
|
|
|
RegionStack.push_back(SP);
|
2008-05-25 13:15:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) {
|
2008-05-22 09:40:10 +08:00
|
|
|
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
|
2008-05-25 13:15:42 +08:00
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
// Don't bother if things are the same as last time.
|
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
|
|
|
if (CurLoc == PrevLoc
|
2009-02-04 09:06:56 +08:00
|
|
|
|| (SM.getInstantiationLineNumber(CurLoc) ==
|
|
|
|
SM.getInstantiationLineNumber(PrevLoc)
|
2008-05-08 16:54:20 +08:00
|
|
|
&& SM.isFromSameFile(CurLoc, PrevLoc)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Update last state.
|
|
|
|
PrevLoc = CurLoc;
|
|
|
|
|
|
|
|
// Get the appropriate compile unit.
|
2008-11-10 14:08:34 +08:00
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc);
|
2009-04-09 03:47:04 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(CurLoc);
|
|
|
|
DebugFactory.InsertStopPoint(Unit, PLoc.getLine(), PLoc.getColumn(),
|
2008-11-10 14:08:34 +08:00
|
|
|
Builder.GetInsertBlock());
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitRegionStart- Constructs the debug code for entering a declarative
|
|
|
|
/// region - "llvm.dbg.region.start.".
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) {
|
|
|
|
llvm::DIDescriptor D;
|
2008-10-17 09:07:56 +08:00
|
|
|
if (!RegionStack.empty())
|
2008-11-10 14:08:34 +08:00
|
|
|
D = RegionStack.back();
|
2009-09-01 06:00:32 +08:00
|
|
|
D = DebugFactory.CreateLexicalBlock(D);
|
2008-11-10 14:08:34 +08:00
|
|
|
RegionStack.push_back(D);
|
|
|
|
DebugFactory.InsertRegionStart(D, Builder.GetInsertBlock());
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitRegionEnd - Constructs the debug code for exiting a declarative
|
|
|
|
/// region - "llvm.dbg.region.end."
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder) {
|
2008-10-17 09:07:56 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2008-05-08 16:54:20 +08:00
|
|
|
// Provide an region stop point.
|
|
|
|
EmitStopPoint(Fn, Builder);
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
DebugFactory.InsertRegionEnd(RegionStack.back(), Builder.GetInsertBlock());
|
2008-05-25 13:15:42 +08:00
|
|
|
RegionStack.pop_back();
|
2008-05-08 16:54:20 +08:00
|
|
|
}
|
|
|
|
|
2008-05-30 18:30:31 +08:00
|
|
|
/// EmitDeclare - Emit local variable declaration debug info.
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag,
|
|
|
|
llvm::Value *Storage, CGBuilderTy &Builder) {
|
2008-10-17 09:07:56 +08:00
|
|
|
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
|
|
|
|
|
2009-03-28 07:16:32 +08:00
|
|
|
// Do not emit variable debug information while generating optimized code.
|
|
|
|
// The llvm optimizer and code generator are not yet ready to support
|
|
|
|
// optimized code debugging.
|
|
|
|
const CompileOptions &CO = M->getCompileOpts();
|
|
|
|
if (CO.OptimizationLevel)
|
|
|
|
return;
|
|
|
|
|
2009-05-05 12:57:08 +08:00
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
|
|
|
|
llvm::DIType Ty = getOrCreateType(Decl->getType(), Unit);
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Get location information.
|
2008-05-30 18:30:31 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
2009-05-05 12:57:08 +08:00
|
|
|
unsigned Line = 0;
|
|
|
|
if (!PLoc.isInvalid())
|
|
|
|
Line = PLoc.getLine();
|
|
|
|
else
|
|
|
|
Unit = llvm::DICompileUnit();
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
|
|
|
|
// Create the descriptor for the variable.
|
|
|
|
llvm::DIVariable D =
|
2008-11-24 13:29:24 +08:00
|
|
|
DebugFactory.CreateVariable(Tag, RegionStack.back(),Decl->getNameAsString(),
|
2009-05-05 12:57:08 +08:00
|
|
|
Unit, Line, Ty);
|
2008-11-10 14:08:34 +08:00
|
|
|
// Insert an llvm.dbg.declare into the current block.
|
|
|
|
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
|
2008-05-30 18:30:31 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *Decl,
|
|
|
|
llvm::Value *Storage,
|
|
|
|
CGBuilderTy &Builder) {
|
|
|
|
EmitDeclare(Decl, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder);
|
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
/// 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);
|
|
|
|
}
|
2008-06-05 16:59:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
/// EmitGlobalVariable - Emit information about a global variable.
|
|
|
|
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
|
|
|
|
const VarDecl *Decl) {
|
2009-03-28 07:16:32 +08:00
|
|
|
|
|
|
|
// Do not emit variable debug information while generating optimized code.
|
|
|
|
// The llvm optimizer and code generator are not yet ready to support
|
|
|
|
// optimized code debugging.
|
|
|
|
const CompileOptions &CO = M->getCompileOpts();
|
|
|
|
if (CO.OptimizationLevel)
|
|
|
|
return;
|
|
|
|
|
2008-11-10 14:08:34 +08:00
|
|
|
// Create global variable debug descriptor.
|
|
|
|
llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
|
2008-06-05 16:59:10 +08:00
|
|
|
SourceManager &SM = M->getContext().getSourceManager();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
|
|
|
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2008-11-24 11:54:41 +08:00
|
|
|
|
|
|
|
std::string Name = Decl->getNameAsString();
|
2008-11-27 01:40:42 +08:00
|
|
|
|
|
|
|
QualType T = Decl->getType();
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-07-15 05:31:22 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo,
|
2008-11-27 01:40:42 +08:00
|
|
|
getOrCreateType(T, Unit),
|
2008-11-10 14:08:34 +08:00
|
|
|
Var->hasInternalLinkage(),
|
|
|
|
true/*definition*/, Var);
|
2008-06-05 16:59:10 +08:00
|
|
|
}
|
|
|
|
|
2009-02-27 05:10:26 +08:00
|
|
|
/// 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();
|
2009-04-18 05:35:15 +08:00
|
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
|
|
|
|
unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine();
|
2009-02-27 05:10:26 +08:00
|
|
|
|
|
|
|
std::string Name = Decl->getNameAsString();
|
|
|
|
|
2009-04-01 14:23:52 +08:00
|
|
|
QualType T = M->getContext().getObjCInterfaceType(Decl);
|
2009-02-27 05:10:26 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-07-15 05:31:22 +08:00
|
|
|
DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo,
|
2009-02-27 05:10:26 +08:00
|
|
|
getOrCreateType(T, Unit),
|
|
|
|
Var->hasInternalLinkage(),
|
|
|
|
true/*definition*/, Var);
|
|
|
|
}
|
|
|
|
|