forked from OSchip/llvm-project
[codeview] Improve names of types in scopes and member function ids
We now include namespace scope info in LF_FUNC_ID records and we emit LF_MFUNC_ID records for member functions as we should. Class names are now fully qualified, which is what MSVC does. Add a little bit of scaffolding to handle ThisAdjustment when it arrives in DISubprogram. llvm-svn: 273358
This commit is contained in:
parent
46fb2b903e
commit
0c5d874bea
|
@ -123,6 +123,57 @@ CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
|
|||
return *Site;
|
||||
}
|
||||
|
||||
static const DISubprogram *getQualifiedNameComponents(
|
||||
const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
|
||||
const DISubprogram *ClosestSubprogram = nullptr;
|
||||
while (Scope != nullptr) {
|
||||
if (ClosestSubprogram == nullptr)
|
||||
ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
|
||||
StringRef ScopeName = Scope->getName();
|
||||
if (!ScopeName.empty())
|
||||
QualifiedNameComponents.push_back(ScopeName);
|
||||
Scope = Scope->getScope().resolve();
|
||||
}
|
||||
return ClosestSubprogram;
|
||||
}
|
||||
|
||||
static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
|
||||
StringRef TypeName) {
|
||||
std::string FullyQualifiedName;
|
||||
for (StringRef QualifiedNameComponent : reverse(QualifiedNameComponents)) {
|
||||
FullyQualifiedName.append(QualifiedNameComponent);
|
||||
FullyQualifiedName.append("::");
|
||||
}
|
||||
FullyQualifiedName.append(TypeName);
|
||||
return FullyQualifiedName;
|
||||
}
|
||||
|
||||
static std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name) {
|
||||
SmallVector<StringRef, 5> QualifiedNameComponents;
|
||||
getQualifiedNameComponents(Scope, QualifiedNameComponents);
|
||||
return getQualifiedName(QualifiedNameComponents, Name);
|
||||
}
|
||||
|
||||
TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
|
||||
// No scope means global scope and that uses the zero index.
|
||||
if (!Scope || isa<DIFile>(Scope))
|
||||
return TypeIndex();
|
||||
|
||||
assert(!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type");
|
||||
|
||||
// Check if we've already translated this scope.
|
||||
auto I = TypeIndices.find({Scope, nullptr});
|
||||
if (I != TypeIndices.end())
|
||||
return I->second;
|
||||
|
||||
// Build the fully qualified name of the scope.
|
||||
std::string ScopeName =
|
||||
getFullyQualifiedName(Scope->getScope().resolve(), Scope->getName());
|
||||
TypeIndex TI =
|
||||
TypeTable.writeStringId(StringIdRecord(TypeIndex(), ScopeName));
|
||||
return recordTypeIndexForDINode(Scope, TI);
|
||||
}
|
||||
|
||||
TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
|
||||
// It's possible to ask for the FuncId of a function which doesn't have a
|
||||
// subprogram: inlining a function with debug info into a function with none.
|
||||
|
@ -134,22 +185,51 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
|
|||
if (I != TypeIndices.end())
|
||||
return I->second;
|
||||
|
||||
TypeIndex ParentScope = TypeIndex(0);
|
||||
// The display name includes function template arguments. Drop them to match
|
||||
// MSVC.
|
||||
StringRef DisplayName = SP->getDisplayName().split('<').first;
|
||||
FuncIdRecord FuncId(ParentScope, lowerSubprogramType(SP), DisplayName);
|
||||
TypeIndex TI = TypeTable.writeFuncId(FuncId);
|
||||
|
||||
recordTypeIndexForDINode(SP, TI);
|
||||
return TI;
|
||||
const DIScope *Scope = SP->getScope().resolve();
|
||||
TypeIndex TI;
|
||||
if (const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
|
||||
// If the scope is a DICompositeType, then this must be a method. Member
|
||||
// function types take some special handling, and require access to the
|
||||
// subprogram.
|
||||
TypeIndex ClassType = getTypeIndex(Class);
|
||||
MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
|
||||
DisplayName);
|
||||
TI = TypeTable.writeMemberFuncId(MFuncId);
|
||||
} else {
|
||||
// Otherwise, this must be a free function.
|
||||
TypeIndex ParentScope = getScopeIndex(Scope);
|
||||
FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
|
||||
TI = TypeTable.writeFuncId(FuncId);
|
||||
}
|
||||
|
||||
return recordTypeIndexForDINode(SP, TI);
|
||||
}
|
||||
|
||||
void CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI,
|
||||
TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP,
|
||||
const DICompositeType *Class) {
|
||||
// Key the MemberFunctionRecord into the map as {SP, Class}. It won't collide
|
||||
// with the MemberFuncIdRecord, which is keyed in as {SP, nullptr}.
|
||||
auto I = TypeIndices.find({SP, nullptr});
|
||||
if (I != TypeIndices.end())
|
||||
return I->second;
|
||||
|
||||
// FIXME: Get the ThisAdjustment off of SP when it is available.
|
||||
TypeIndex TI =
|
||||
lowerTypeMemberFunction(SP->getType(), Class, /*ThisAdjustment=*/0);
|
||||
|
||||
return recordTypeIndexForDINode(SP, TI, Class);
|
||||
}
|
||||
|
||||
TypeIndex CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI,
|
||||
const DIType *ClassTy) {
|
||||
auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI});
|
||||
(void)InsertResult;
|
||||
assert(InsertResult.second && "DINode was already assigned a type index");
|
||||
return TI;
|
||||
}
|
||||
|
||||
unsigned CodeViewDebug::getPointerSizeInBytes() {
|
||||
|
@ -458,31 +538,6 @@ void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
|
|||
emitCodeViewMagicVersion();
|
||||
}
|
||||
|
||||
static const DISubprogram *getQualifiedNameComponents(
|
||||
const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
|
||||
const DISubprogram *ClosestSubprogram = nullptr;
|
||||
while (Scope != nullptr) {
|
||||
if (ClosestSubprogram == nullptr)
|
||||
ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
|
||||
StringRef ScopeName = Scope->getName();
|
||||
if (!ScopeName.empty())
|
||||
QualifiedNameComponents.push_back(ScopeName);
|
||||
Scope = Scope->getScope().resolve();
|
||||
}
|
||||
return ClosestSubprogram;
|
||||
}
|
||||
|
||||
static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
|
||||
StringRef TypeName) {
|
||||
std::string FullyQualifiedName;
|
||||
for (StringRef QualifiedNameComponent : reverse(QualifiedNameComponents)) {
|
||||
FullyQualifiedName.append(QualifiedNameComponent);
|
||||
FullyQualifiedName.append("::");
|
||||
}
|
||||
FullyQualifiedName.append(TypeName);
|
||||
return FullyQualifiedName;
|
||||
}
|
||||
|
||||
void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
|
||||
FunctionInfo &FI) {
|
||||
// For each function there is a separate subsection
|
||||
|
@ -499,12 +554,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
|
|||
|
||||
// If we have a display name, build the fully qualified name by walking the
|
||||
// chain of scopes.
|
||||
if (SP != nullptr && !SP->getDisplayName().empty()) {
|
||||
SmallVector<StringRef, 5> QualifiedNameComponents;
|
||||
getQualifiedNameComponents(SP->getScope().resolve(),
|
||||
QualifiedNameComponents);
|
||||
FuncName = getQualifiedName(QualifiedNameComponents, SP->getDisplayName());
|
||||
}
|
||||
if (SP != nullptr && !SP->getDisplayName().empty())
|
||||
FuncName =
|
||||
getFullyQualifiedName(SP->getScope().resolve(), SP->getDisplayName());
|
||||
|
||||
// If our DISubprogram name is empty, use the mangled name.
|
||||
if (FuncName.empty())
|
||||
|
@ -792,8 +844,12 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
|
|||
case dwarf::DW_TAG_volatile_type:
|
||||
return lowerTypeModifier(cast<DIDerivedType>(Ty));
|
||||
case dwarf::DW_TAG_subroutine_type:
|
||||
if (ClassTy)
|
||||
return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy);
|
||||
if (ClassTy) {
|
||||
// The member function type of a member function pointer has no
|
||||
// ThisAdjustment.
|
||||
return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
|
||||
/*ThisAdjustment=*/0);
|
||||
}
|
||||
return lowerTypeFunction(cast<DISubroutineType>(Ty));
|
||||
case dwarf::DW_TAG_enumeration_type:
|
||||
return lowerTypeEnum(cast<DICompositeType>(Ty));
|
||||
|
@ -1113,7 +1169,8 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
|
|||
}
|
||||
|
||||
TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
|
||||
const DIType *ClassTy) {
|
||||
const DIType *ClassTy,
|
||||
int ThisAdjustment) {
|
||||
// Lower the containing class type.
|
||||
TypeIndex ClassType = getTypeIndex(ClassTy);
|
||||
|
||||
|
@ -1150,14 +1207,7 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
|
|||
// ThisPointerAdjustment.
|
||||
TypeIndex TI = TypeTable.writeMemberFunction(MemberFunctionRecord(
|
||||
ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FunctionOptions::None,
|
||||
ArgTypeIndices.size(), ArgListIndex, 0));
|
||||
|
||||
return TI;
|
||||
}
|
||||
|
||||
TypeIndex CodeViewDebug::lowerSubprogramType(const DISubprogram *SP) {
|
||||
auto ClassType = dyn_cast_or_null<DIType>(SP->getScope().resolve());
|
||||
TypeIndex TI = getTypeIndex(SP->getType(), ClassType);
|
||||
ArgTypeIndices.size(), ArgListIndex, ThisAdjustment));
|
||||
|
||||
return TI;
|
||||
}
|
||||
|
@ -1243,7 +1293,10 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
|
|||
FTI = TypeTable.writeFieldList(Fields);
|
||||
}
|
||||
|
||||
return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, Ty->getName(),
|
||||
std::string FullName =
|
||||
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
|
||||
|
||||
return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, FullName,
|
||||
Ty->getIdentifier(),
|
||||
getTypeIndex(Ty->getBaseType())));
|
||||
}
|
||||
|
@ -1353,9 +1406,11 @@ TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
|
|||
TypeRecordKind Kind = getRecordKind(Ty);
|
||||
ClassOptions CO =
|
||||
ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty);
|
||||
std::string FullName =
|
||||
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
|
||||
TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord(
|
||||
Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(),
|
||||
TypeIndex(), TypeIndex(), 0, Ty->getName(), Ty->getIdentifier()));
|
||||
TypeIndex(), TypeIndex(), 0, FullName, Ty->getIdentifier()));
|
||||
return FwdDeclTI;
|
||||
}
|
||||
|
||||
|
@ -1369,19 +1424,24 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
|
|||
unsigned FieldCount;
|
||||
std::tie(FieldTI, VShapeTI, FieldCount) = lowerRecordFieldList(Ty);
|
||||
|
||||
std::string FullName =
|
||||
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
|
||||
|
||||
uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
|
||||
return TypeTable.writeClass(ClassRecord(
|
||||
Kind, FieldCount, CO, HfaKind::None, WindowsRTClassKind::None, FieldTI,
|
||||
TypeIndex(), VShapeTI, SizeInBytes, Ty->getName(), Ty->getIdentifier()));
|
||||
TypeIndex(), VShapeTI, SizeInBytes, FullName, Ty->getIdentifier()));
|
||||
// FIXME: Make an LF_UDT_SRC_LINE record.
|
||||
}
|
||||
|
||||
TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
|
||||
ClassOptions CO =
|
||||
ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty);
|
||||
std::string FullName =
|
||||
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
|
||||
TypeIndex FwdDeclTI =
|
||||
TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0,
|
||||
Ty->getName(), Ty->getIdentifier()));
|
||||
FullName, Ty->getIdentifier()));
|
||||
return FwdDeclTI;
|
||||
}
|
||||
|
||||
|
@ -1391,8 +1451,10 @@ TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
|
|||
unsigned FieldCount;
|
||||
std::tie(FieldTI, std::ignore, FieldCount) = lowerRecordFieldList(Ty);
|
||||
uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
|
||||
std::string FullName =
|
||||
getFullyQualifiedName(Ty->getScope().resolve(), Ty->getName());
|
||||
return TypeTable.writeUnion(UnionRecord(FieldCount, CO, HfaKind::None,
|
||||
FieldTI, SizeInBytes, Ty->getName(),
|
||||
FieldTI, SizeInBytes, FullName,
|
||||
Ty->getIdentifier()));
|
||||
// FIXME: Make an LF_UDT_SRC_LINE record.
|
||||
}
|
||||
|
@ -1484,8 +1546,7 @@ TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
|
|||
|
||||
TypeIndex TI = lowerType(Ty, ClassTy);
|
||||
|
||||
recordTypeIndexForDINode(Ty, TI, ClassTy);
|
||||
return TI;
|
||||
return recordTypeIndexForDINode(Ty, TI, ClassTy);
|
||||
}
|
||||
|
||||
TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
|
||||
|
|
|
@ -218,6 +218,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
|
|||
codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,
|
||||
DITypeRef ClassTyRef = DITypeRef());
|
||||
|
||||
codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP,
|
||||
const DICompositeType *Class);
|
||||
|
||||
codeview::TypeIndex getScopeIndex(const DIScope *Scope);
|
||||
|
||||
codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy);
|
||||
codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
|
||||
codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty);
|
||||
|
@ -227,7 +232,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
|
|||
codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
|
||||
codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
|
||||
codeview::TypeIndex lowerTypeMemberFunction(const DISubroutineType *Ty,
|
||||
const DIType *ClassTy);
|
||||
const DIType *ClassTy,
|
||||
int ThisAdjustment);
|
||||
codeview::TypeIndex lowerTypeEnum(const DICompositeType *Ty);
|
||||
codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty);
|
||||
codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty);
|
||||
|
@ -242,8 +248,6 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
|
|||
codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty);
|
||||
codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty);
|
||||
|
||||
codeview::TypeIndex lowerSubprogramType(const DISubprogram *SP);
|
||||
|
||||
void collectMemberInfo(ClassInfo &Info, const DIDerivedType *DDTy);
|
||||
ClassInfo &collectClassInfo(const DICompositeType *Ty);
|
||||
|
||||
|
@ -254,8 +258,9 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
|
|||
lowerRecordFieldList(const DICompositeType *Ty);
|
||||
|
||||
/// Inserts {{Node, ClassTy}, TI} into TypeIndices and checks for duplicates.
|
||||
void recordTypeIndexForDINode(const DINode *Node, codeview::TypeIndex TI,
|
||||
const DIType *ClassTy = nullptr);
|
||||
codeview::TypeIndex recordTypeIndexForDINode(const DINode *Node,
|
||||
codeview::TypeIndex TI,
|
||||
const DIType *ClassTy = nullptr);
|
||||
|
||||
unsigned getPointerSizeInBytes();
|
||||
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
|
||||
|
||||
; Check that we keep namespace scopes around the same way MSVC does.
|
||||
; We do function scopes slightly differently, but everything should be alright.
|
||||
|
||||
; C++ source to regenerate:
|
||||
; namespace foo {
|
||||
; namespace bar {
|
||||
; void baz() {
|
||||
; struct LocalRecord {
|
||||
; int x;
|
||||
; } l;
|
||||
; };
|
||||
; struct GlobalRecord {
|
||||
; int x;
|
||||
; void method();
|
||||
; } g;
|
||||
; void GlobalRecord::method() {}
|
||||
; }
|
||||
; }
|
||||
|
||||
; CHECK-LABEL: FuncId ({{.*}}) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_FUNC_ID (0x1601)
|
||||
; CHECK-NEXT: ParentScope: foo::bar ({{.*}})
|
||||
; CHECK-NEXT: FunctionType: void () ({{.*}})
|
||||
; CHECK-NEXT: Name: baz
|
||||
; CHECK-NEXT: }
|
||||
|
||||
; CHECK: Struct ({{.*}}) {
|
||||
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
|
||||
; CHECK: MemberCount: 0
|
||||
; CHECK: Properties [ (0x80)
|
||||
; CHECK: ForwardReference (0x80)
|
||||
; CHECK: ]
|
||||
; CHECK: FieldList: 0x0
|
||||
; CHECK: DerivedFrom: 0x0
|
||||
; CHECK: VShape: 0x0
|
||||
; CHECK: SizeOf: 0
|
||||
; CHECK: Name: foo::bar::baz::LocalRecord
|
||||
; CHECK: }
|
||||
|
||||
; CHECK: Struct ({{.*}}) {
|
||||
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
|
||||
; CHECK: MemberCount: 1
|
||||
; CHECK: Properties [ (0x0)
|
||||
; CHECK: ]
|
||||
; CHECK: Name: foo::bar::baz::LocalRecord
|
||||
; CHECK: }
|
||||
|
||||
; CHECK: Struct ({{.*}}) {
|
||||
; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
|
||||
; CHECK: MemberCount: 0
|
||||
; CHECK: Properties [ (0x280)
|
||||
; CHECK: ForwardReference (0x80)
|
||||
; CHECK: HasUniqueName (0x200)
|
||||
; CHECK: ]
|
||||
; CHECK: FieldList: 0x0
|
||||
; CHECK: DerivedFrom: 0x0
|
||||
; CHECK: VShape: 0x0
|
||||
; CHECK: SizeOf: 0
|
||||
; CHECK: Name: foo::bar::GlobalRecord
|
||||
; CHECK: }
|
||||
|
||||
; CHECK-LABEL: MemberFuncId ({{.*}}) {
|
||||
; CHECK-NEXT: TypeLeafKind: LF_MFUNC_ID (0x1602)
|
||||
; CHECK-NEXT: ClassType: foo::bar::GlobalRecord ({{.*}})
|
||||
; CHECK-NEXT: FunctionType: void foo::bar::GlobalRecord::() ({{.*}})
|
||||
; CHECK-NEXT: Name: method
|
||||
; CHECK-NEXT: }
|
||||
|
||||
|
||||
; ModuleID = 't.cpp'
|
||||
source_filename = "t.cpp"
|
||||
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-windows-msvc19.0.23918"
|
||||
|
||||
%"struct.foo::bar::GlobalRecord" = type { i32 }
|
||||
%struct.LocalRecord = type { i32 }
|
||||
|
||||
@"\01?g@bar@foo@@3UGlobalRecord@12@A" = global %"struct.foo::bar::GlobalRecord" zeroinitializer, align 4
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define void @"\01?baz@bar@foo@@YAXXZ"() #0 !dbg !19 {
|
||||
entry:
|
||||
%l = alloca %struct.LocalRecord, align 4
|
||||
call void @llvm.dbg.declare(metadata %struct.LocalRecord* %l, metadata !22, metadata !26), !dbg !27
|
||||
ret void, !dbg !28
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define void @"\01?method@GlobalRecord@bar@foo@@QEAAXXZ"(%"struct.foo::bar::GlobalRecord"* %this) #0 align 2 !dbg !29 {
|
||||
entry:
|
||||
%this.addr = alloca %"struct.foo::bar::GlobalRecord"*, align 8
|
||||
store %"struct.foo::bar::GlobalRecord"* %this, %"struct.foo::bar::GlobalRecord"** %this.addr, align 8
|
||||
call void @llvm.dbg.declare(metadata %"struct.foo::bar::GlobalRecord"** %this.addr, metadata !30, metadata !26), !dbg !32
|
||||
%this1 = load %"struct.foo::bar::GlobalRecord"*, %"struct.foo::bar::GlobalRecord"** %this.addr, align 8
|
||||
ret void, !dbg !33
|
||||
}
|
||||
|
||||
attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
attributes #1 = { nounwind readnone }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!15, !16, !17}
|
||||
!llvm.ident = !{!18}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
|
||||
!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
|
||||
!2 = !{}
|
||||
!3 = !{!4}
|
||||
!4 = distinct !DIGlobalVariable(name: "g", linkageName: "\01?g@bar@foo@@3UGlobalRecord@12@A", scope: !5, file: !1, line: 12, type: !7, isLocal: false, isDefinition: true, variable: %"struct.foo::bar::GlobalRecord"* @"\01?g@bar@foo@@3UGlobalRecord@12@A")
|
||||
!5 = !DINamespace(name: "bar", scope: !6, file: !1, line: 2)
|
||||
!6 = !DINamespace(name: "foo", scope: null, file: !1, line: 1)
|
||||
!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "GlobalRecord", scope: !5, file: !1, line: 9, size: 32, align: 32, elements: !8, identifier: ".?AUGlobalRecord@bar@foo@@")
|
||||
!8 = !{!9, !11}
|
||||
!9 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !7, file: !1, line: 10, baseType: !10, size: 32, align: 32)
|
||||
!10 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
|
||||
!11 = !DISubprogram(name: "method", linkageName: "\01?method@GlobalRecord@bar@foo@@QEAAXXZ", scope: !7, file: !1, line: 11, type: !12, isLocal: false, isDefinition: false, scopeLine: 11, flags: DIFlagPrototyped, isOptimized: false)
|
||||
!12 = !DISubroutineType(types: !13)
|
||||
!13 = !{null, !14}
|
||||
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
|
||||
!15 = !{i32 2, !"CodeView", i32 1}
|
||||
!16 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!17 = !{i32 1, !"PIC Level", i32 2}
|
||||
!18 = !{!"clang version 3.9.0 "}
|
||||
!19 = distinct !DISubprogram(name: "baz", linkageName: "\01?baz@bar@foo@@YAXXZ", scope: !5, file: !1, line: 3, type: !20, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
|
||||
!20 = !DISubroutineType(types: !21)
|
||||
!21 = !{null}
|
||||
!22 = !DILocalVariable(name: "l", scope: !19, file: !1, line: 6, type: !23)
|
||||
!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "LocalRecord", scope: !19, file: !1, line: 4, size: 32, align: 32, elements: !24)
|
||||
!24 = !{!25}
|
||||
!25 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !23, file: !1, line: 5, baseType: !10, size: 32, align: 32)
|
||||
!26 = !DIExpression()
|
||||
!27 = !DILocation(line: 6, column: 5, scope: !19)
|
||||
!28 = !DILocation(line: 7, column: 1, scope: !19)
|
||||
!29 = distinct !DISubprogram(name: "method", linkageName: "\01?method@GlobalRecord@bar@foo@@QEAAXXZ", scope: !7, file: !1, line: 13, type: !12, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !11, variables: !2)
|
||||
!30 = !DILocalVariable(name: "this", arg: 1, scope: !29, type: !31, flags: DIFlagArtificial | DIFlagObjectPointer)
|
||||
!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64)
|
||||
!32 = !DILocation(line: 0, scope: !29)
|
||||
!33 = !DILocation(line: 13, column: 30, scope: !29)
|
|
@ -56,8 +56,8 @@
|
|||
; CHECK: ArgListType: () (0x1002)
|
||||
; CHECK: }
|
||||
; CHECK: FuncId (0x1004) {
|
||||
; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
|
||||
; CHECK: ParentScope: 0x0
|
||||
; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602)
|
||||
; CHECK: ClassType: A (0x1000)
|
||||
; CHECK: FunctionType: void A::() (0x1003)
|
||||
; CHECK: Name: A::thiscallcc
|
||||
; CHECK: }
|
||||
|
|
|
@ -288,7 +288,7 @@
|
|||
; CHECK: DerivedFrom: 0x0
|
||||
; CHECK: VShape: 0x0
|
||||
; CHECK: SizeOf: 0
|
||||
; CHECK: Name: Nested
|
||||
; CHECK: Name: Class::Nested
|
||||
; CHECK: LinkageName: .?AUNested@Class@@
|
||||
; CHECK: }
|
||||
; CHECK: FieldList (0x1014) {
|
||||
|
@ -310,7 +310,7 @@
|
|||
; CHECK: DerivedFrom: 0x0
|
||||
; CHECK: VShape: 0x0
|
||||
; CHECK: SizeOf: 4
|
||||
; CHECK: Name: Nested
|
||||
; CHECK: Name: Class::Nested
|
||||
; CHECK: LinkageName: .?AUNested@Class@@
|
||||
; CHECK: }
|
||||
; CHECK: Pointer (0x1016) {
|
||||
|
@ -337,8 +337,8 @@
|
|||
; CHECK: ThisAdjustment: 0
|
||||
; CHECK: }
|
||||
; CHECK: FuncId (0x1018) {
|
||||
; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
|
||||
; CHECK: ParentScope: 0x0
|
||||
; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602)
|
||||
; CHECK: ClassType: DerivedClass (0x100D)
|
||||
; CHECK: FunctionType: void DerivedClass::() (0x1017)
|
||||
; CHECK: Name: DerivedClass::DerivedClass
|
||||
; CHECK: }
|
||||
|
|
Loading…
Reference in New Issue