llvm.org GIT mirror llvm / 3dbd3c0
[codeview] Add basic record type translation This only translates data members for now. Translating overloaded methods is complicated, so I stopped short of doing that. Reviewers: aaboud Differential Revision: http://reviews.llvm.org/D20924 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271680 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
7 changed file(s) with 948 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
2727 public:
2828 llvm::StringRef str() { return Builder.str(); }
2929
30 void reset(TypeRecordKind K) { Builder.reset(K); }
30 void reset(TypeRecordKind K) {
31 Builder.reset(K);
32 ContinuationOffsets.clear();
33 SubrecordCount = 0;
34 }
35
36 unsigned getSubrecordCount() { return SubrecordCount; }
3137
3238 protected:
3339 void finishSubRecord();
3743 private:
3844 TypeRecordBuilder Builder;
3945 SmallVector ContinuationOffsets;
46 unsigned SubrecordCount = 0;
4047 };
4148 }
4249 }
1212
1313 #include "CodeViewDebug.h"
1414 #include "llvm/DebugInfo/CodeView/CodeView.h"
15 #include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
1516 #include "llvm/DebugInfo/CodeView/Line.h"
1617 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1718 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
137138 FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
138139 TypeIndex TI = TypeTable.writeFuncId(FuncId);
139140
140 auto InsertResult = TypeIndices.insert({SP, TI});
141 recordTypeIndexForDINode(SP, TI);
142 return TI;
143 }
144
145 void CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI) {
146 auto InsertResult = TypeIndices.insert({Node, TI});
141147 (void)InsertResult;
142 assert(InsertResult.second && "DISubprogram lowered twice");
143 return TI;
148 assert(InsertResult.second && "DINode was already assigned a type index");
144149 }
145150
146151 void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
745750 return lowerTypeModifier(cast(Ty));
746751 case dwarf::DW_TAG_subroutine_type:
747752 return lowerTypeFunction(cast(Ty));
753 case dwarf::DW_TAG_class_type:
754 case dwarf::DW_TAG_structure_type:
755 return lowerTypeClass(cast(Ty));
756 case dwarf::DW_TAG_union_type:
757 return lowerTypeUnion(cast(Ty));
748758 default:
749759 // Use the null type index.
750760 return TypeIndex();
960970 return TypeTable.writeProcedure(Procedure);
961971 }
962972
973 static MemberAccess translateAccessFlags(unsigned RecordTag,
974 const DIType *Member) {
975 switch (Member->getFlags() & DINode::FlagAccessibility) {
976 case DINode::FlagPrivate: return MemberAccess::Private;
977 case DINode::FlagPublic: return MemberAccess::Public;
978 case DINode::FlagProtected: return MemberAccess::Protected;
979 case 0:
980 // If there was no explicit access control, provide the default for the tag.
981 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
982 : MemberAccess::Public;
983 }
984 llvm_unreachable("access flags are exclusive");
985 }
986
987 static TypeRecordKind getRecordKind(const DICompositeType *Ty) {
988 switch (Ty->getTag()) {
989 case dwarf::DW_TAG_class_type: return TypeRecordKind::Class;
990 case dwarf::DW_TAG_structure_type: return TypeRecordKind::Struct;
991 }
992 llvm_unreachable("unexpected tag");
993 }
994
995 /// Return the HasUniqueName option if it should be present in ClassOptions, or
996 /// None otherwise.
997 static ClassOptions getRecordUniqueNameOption(const DICompositeType *Ty) {
998 // MSVC always sets this flag now, even for local types. Clang doesn't always
999 // appear to give every type a linkage name, which may be problematic for us.
1000 // FIXME: Investigate the consequences of not following them here.
1001 return !Ty->getIdentifier().empty() ? ClassOptions::HasUniqueName
1002 : ClassOptions::None;
1003 }
1004
1005 TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
1006 // First, construct the forward decl. Don't look into Ty to compute the
1007 // forward decl options, since it might not be available in all TUs.
1008 TypeRecordKind Kind = getRecordKind(Ty);
1009 ClassOptions CO =
1010 ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty);
1011 TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord(
1012 Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(),
1013 TypeIndex(), TypeIndex(), 0, Ty->getName(), Ty->getIdentifier()));
1014 return FwdDeclTI;
1015 }
1016
1017 TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
1018 // Construct the field list and complete type record.
1019 TypeRecordKind Kind = getRecordKind(Ty);
1020 // FIXME: Other ClassOptions, like ContainsNestedClass and NestedClass.
1021 ClassOptions CO = ClassOptions::None | getRecordUniqueNameOption(Ty);
1022 TypeIndex FTI;
1023 unsigned FieldCount;
1024 std::tie(FTI, FieldCount) = lowerRecordFieldList(Ty);
1025
1026 uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
1027 return TypeTable.writeClass(ClassRecord(Kind, FieldCount, CO, HfaKind::None,
1028 WindowsRTClassKind::None, FTI,
1029 TypeIndex(), TypeIndex(), SizeInBytes,
1030 Ty->getName(), Ty->getIdentifier()));
1031 // FIXME: Make an LF_UDT_SRC_LINE record.
1032 }
1033
1034 TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
1035 ClassOptions CO =
1036 ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty);
1037 TypeIndex FwdDeclTI =
1038 TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0,
1039 Ty->getName(), Ty->getIdentifier()));
1040 return FwdDeclTI;
1041 }
1042
1043 TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
1044 ClassOptions CO = ClassOptions::None | getRecordUniqueNameOption(Ty);
1045 TypeIndex FTI;
1046 unsigned FieldCount;
1047 std::tie(FTI, FieldCount) = lowerRecordFieldList(Ty);
1048 uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
1049 return TypeTable.writeUnion(UnionRecord(FieldCount, CO, HfaKind::None, FTI,
1050 SizeInBytes, Ty->getName(),
1051 Ty->getIdentifier()));
1052 // FIXME: Make an LF_UDT_SRC_LINE record.
1053 }
1054
1055 std::pair
1056 CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
1057 // Manually count members. MSVC appears to count everything that generates a
1058 // field list record. Each individual overload in a method overload group
1059 // contributes to this count, even though the overload group is a single field
1060 // list record.
1061 unsigned MemberCount = 0;
1062 FieldListRecordBuilder Fields;
1063 for (const DINode *Element : Ty->getElements()) {
1064 // We assume that the frontend provides all members in source declaration
1065 // order, which is what MSVC does.
1066 if (!Element)
1067 continue;
1068 if (auto *SP = dyn_cast(Element)) {
1069 // C++ method.
1070 // FIXME: Overloaded methods are grouped together, so we'll need two
1071 // passes to group them.
1072 (void)SP;
1073 } else if (auto *Member = dyn_cast(Element)) {
1074 if (Member->getTag() == dwarf::DW_TAG_member) {
1075 if (Member->isStaticMember()) {
1076 // Static data member.
1077 Fields.writeStaticDataMember(StaticDataMemberRecord(
1078 translateAccessFlags(Ty->getTag(), Member),
1079 getTypeIndex(Member->getBaseType()), Member->getName()));
1080 MemberCount++;
1081 } else {
1082 // Data member.
1083 // FIXME: Make a BitFieldRecord for bitfields.
1084 Fields.writeDataMember(DataMemberRecord(
1085 translateAccessFlags(Ty->getTag(), Member),
1086 getTypeIndex(Member->getBaseType()),
1087 Member->getOffsetInBits() / 8, Member->getName()));
1088 MemberCount++;
1089 }
1090 } else if (Member->getTag() == dwarf::DW_TAG_friend) {
1091 // Ignore friend members. It appears that MSVC emitted info about
1092 // friends in the past, but modern versions do not.
1093 }
1094 // FIXME: Get clang to emit nested types here and do something with
1095 // them.
1096 }
1097 // Skip other unrecognized kinds of elements.
1098 }
1099 return {TypeTable.writeFieldList(Fields), MemberCount};
1100 }
1101
9631102 TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef) {
9641103 const DIType *Ty = TypeRef.resolve();
9651104
9671106 if (!Ty)
9681107 return TypeIndex::Void();
9691108
970 // Check if we've already translated this type.
1109 // Check if we've already translated this type. Don't try to do a
1110 // get-or-create style insertion that caches the hash lookup across the
1111 // lowerType call. It will update the TypeIndices map.
9711112 auto I = TypeIndices.find(Ty);
9721113 if (I != TypeIndices.end())
9731114 return I->second;
9741115
9751116 TypeIndex TI = lowerType(Ty);
9761117
977 auto InsertResult = TypeIndices.insert({Ty, TI});
978 (void)InsertResult;
979 assert(InsertResult.second && "DIType lowered twice");
1118 recordTypeIndexForDINode(Ty, TI);
1119 return TI;
1120 }
1121
1122 TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
1123 const DIType *Ty = TypeRef.resolve();
1124
1125 // The null DIType is the void type. Don't try to hash it.
1126 if (!Ty)
1127 return TypeIndex::Void();
1128
1129 // If this is a non-record type, the complete type index is the same as the
1130 // normal type index. Just call getTypeIndex.
1131 switch (Ty->getTag()) {
1132 case dwarf::DW_TAG_class_type:
1133 case dwarf::DW_TAG_structure_type:
1134 case dwarf::DW_TAG_union_type:
1135 break;
1136 default:
1137 return getTypeIndex(Ty);
1138 }
1139
1140 // Check if we've already translated the complete record type. Lowering a
1141 // complete type should never trigger lowering another complete type, so we
1142 // can reuse the hash table lookup result.
1143 const auto *CTy = cast(Ty);
1144 auto InsertResult = CompleteTypeIndices.insert({CTy, TypeIndex()});
1145 if (!InsertResult.second)
1146 return InsertResult.first->second;
1147
1148 // Make sure the forward declaration is emitted first. It's unclear if this
1149 // is necessary, but MSVC does it, and we should follow suit until we can show
1150 // otherwise.
1151 TypeIndex FwdDeclTI = getTypeIndex(CTy);
1152
1153 // Just use the forward decl if we don't have complete type info. This might
1154 // happen if the frontend is using modules and expects the complete definition
1155 // to be emitted elsewhere.
1156 if (CTy->isForwardDecl())
1157 return FwdDeclTI;
1158
1159 TypeIndex TI;
1160 switch (CTy->getTag()) {
1161 case dwarf::DW_TAG_class_type:
1162 case dwarf::DW_TAG_structure_type:
1163 TI = lowerCompleteTypeClass(CTy);
1164 break;
1165 case dwarf::DW_TAG_union_type:
1166 TI = lowerCompleteTypeUnion(CTy);
1167 break;
1168 default:
1169 llvm_unreachable("not a record");
1170 }
1171
1172 InsertResult.first->second = TI;
9801173 return TI;
9811174 }
9821175
9981191 Flags |= LocalSymFlags::IsOptimizedOut;
9991192
10001193 OS.AddComment("TypeIndex");
1001 TypeIndex TI = getTypeIndex(Var.DIVar->getType());
1194 TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType());
10021195 OS.EmitIntValue(TI.getIndex(), 4);
10031196 OS.AddComment("Flags");
10041197 OS.EmitIntValue(static_cast(Flags), 2);
139139 /// DIType* and DISubprogram*.
140140 DenseMap TypeIndices;
141141
142 /// Map from DICompositeType* to complete type index. Non-record types are
143 /// always looked up in the normal TypeIndices map.
144 DenseMap CompleteTypeIndices;
145
142146 typedef std::map FileToFilepathMapTy;
143147 FileToFilepathMapTy FileToFilepathMap;
144148 StringRef getFullFilepath(const DIFile *S);
181185
182186 /// Translates the DIType to codeview if necessary and returns a type index
183187 /// for it.
184 codeview::TypeIndex getTypeIndex(DITypeRef Ty);
188 codeview::TypeIndex getTypeIndex(DITypeRef TypeRef);
185189
186190 codeview::TypeIndex lowerType(const DIType *Ty);
187191 codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
190194 codeview::TypeIndex lowerTypeMemberPointer(const DIDerivedType *Ty);
191195 codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
192196 codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
197 codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty);
198 codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty);
199
200 /// Symbol records should point to complete types, but type records should
201 /// always point to incomplete types to avoid cycles in the type graph. Only
202 /// use this entry point when generating symbol records. The complete and
203 /// incomplete type indices only differ for record types. All other types use
204 /// the same index.
205 codeview::TypeIndex getCompleteTypeIndex(DITypeRef TypeRef);
206
207 codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty);
208 codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty);
209
210 /// Common record member lowering functionality for record types, which are
211 /// structs, classes, and unions. Returns the field list index and the member
212 /// count.
213 std::pair
214 lowerRecordFieldList(const DICompositeType *Ty);
215
216 /// Inserts {Node, TI} into TypeIndices and checks for duplicates.
217 void recordTypeIndexForDINode(const DINode *Node, codeview::TypeIndex TI);
193218
194219 public:
195220 CodeViewDebug(AsmPrinter *Asm);
1414 ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind) : Builder(Kind) {}
1515
1616 void ListRecordBuilder::finishSubRecord() {
17 SubrecordCount++;
18
1719 // The builder starts at offset 2 in the actual CodeView buffer, so add an
1820 // additional offset of 2 before computing the alignment.
1921 uint32_t Remainder = (Builder.size() + 2) % 4;
3232 ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
3333
3434 ; CHECK: CodeViewTypes [
35 ; CHECK: Section: .debug$T (6)
36 ; CHECK: Magic: 0x4
3537 ; CHECK: ArgList (0x1000) {
3638 ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
3739 ; CHECK: NumArgs: 3
7476 ; CHECK: IsVolatile: 0
7577 ; CHECK: IsUnaligned: 0
7678 ; CHECK: }
77 ; CHECK: Pointer (0x1005) {
79 ; CHECK: Struct (0x1005) {
80 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
81 ; CHECK: MemberCount: 0
82 ; CHECK: Properties [ (0x80)
83 ; CHECK: ForwardReference (0x80)
84 ; CHECK: ]
85 ; CHECK: FieldList: 0x0
86 ; CHECK: DerivedFrom: 0x0
87 ; CHECK: VShape: 0x0
88 ; CHECK: SizeOf: 0
89 ; CHECK: Name: A
90 ; CHECK: }
91 ; CHECK: Pointer (0x1006) {
7892 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
7993 ; CHECK: PointeeType: int (0x74)
8094 ; CHECK: PointerAttributes: 0x804C
8498 ; CHECK: IsConst: 0
8599 ; CHECK: IsVolatile: 0
86100 ; CHECK: IsUnaligned: 0
87 ; CHECK: ClassType: 0x0
101 ; CHECK: ClassType: A (0x1005)
88102 ; CHECK: Representation: Unknown (0x0)
89103 ; CHECK: }
90 ; CHECK: ArgList (0x1006) {
104 ; CHECK: Pointer (0x1007) {
105 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
106 ; CHECK: PointeeType: A (0x1005)
107 ; CHECK: PointerAttributes: 0x1000C
108 ; CHECK: PtrType: Near64 (0xC)
109 ; CHECK: PtrMode: Pointer (0x0)
110 ; CHECK: IsFlat: 0
111 ; CHECK: IsConst: 0
112 ; CHECK: IsVolatile: 0
113 ; CHECK: IsUnaligned: 0
114 ; CHECK: }
115 ; CHECK: ArgList (0x1008) {
91116 ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
92117 ; CHECK: NumArgs: 1
93118 ; CHECK: Arguments [
94 ; CHECK: ArgType: (0x600)
95 ; CHECK: ]
96 ; CHECK: }
97 ; CHECK: Procedure (0x1007) {
119 ; CHECK: ArgType: A* (0x1007)
120 ; CHECK: ]
121 ; CHECK: }
122 ; CHECK: Procedure (0x1009) {
98123 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
99124 ; CHECK: ReturnType: void (0x3)
100125 ; CHECK: CallingConvention: NearC (0x0)
101126 ; CHECK: FunctionOptions [ (0x0)
102127 ; CHECK: ]
103128 ; CHECK: NumParameters: 1
104 ; CHECK: ArgListType: () (0x1006)
105 ; CHECK: }
106 ; CHECK: Pointer (0x1008) {
129 ; CHECK: ArgListType: (A*) (0x1008)
130 ; CHECK: }
131 ; CHECK: Pointer (0x100A) {
107132 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
108 ; CHECK: PointeeType: void () (0x1007)
133 ; CHECK: PointeeType: void (A*) (0x1009)
109134 ; CHECK: PointerAttributes: 0x1006C
110135 ; CHECK: PtrType: Near64 (0xC)
111136 ; CHECK: PtrMode: PointerToMemberFunction (0x3)
113138 ; CHECK: IsConst: 0
114139 ; CHECK: IsVolatile: 0
115140 ; CHECK: IsUnaligned: 0
116 ; CHECK: ClassType: 0x0
141 ; CHECK: ClassType: A (0x1005)
117142 ; CHECK: Representation: Unknown (0x0)
118143 ; CHECK: }
119 ; CHECK: Modifier (0x1009) {
144 ; CHECK: Modifier (0x100B) {
120145 ; CHECK: TypeLeafKind: LF_MODIFIER (0x1001)
121146 ; CHECK: ModifiedType: void (0x3)
122147 ; CHECK: Modifiers [ (0x1)
123148 ; CHECK: Const (0x1)
124149 ; CHECK: ]
125150 ; CHECK: }
126 ; CHECK: Pointer (0x100A) {
151 ; CHECK: Pointer (0x100C) {
127152 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
128 ; CHECK: PointeeType: const void (0x1009)
153 ; CHECK: PointeeType: const void (0x100B)
129154 ; CHECK: PointerAttributes: 0x1000C
130155 ; CHECK: PtrType: Near64 (0xC)
131156 ; CHECK: PtrMode: Pointer (0x0)
134159 ; CHECK: IsVolatile: 0
135160 ; CHECK: IsUnaligned: 0
136161 ; CHECK: }
162 ; CHECK: ArgList (0x100D) {
163 ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
164 ; CHECK: NumArgs: 0
165 ; CHECK: Arguments [
166 ; CHECK: ]
167 ; CHECK: }
168 ; CHECK: Procedure (0x100E) {
169 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
170 ; CHECK: ReturnType: void (0x3)
171 ; CHECK: CallingConvention: NearC (0x0)
172 ; CHECK: FunctionOptions [ (0x0)
173 ; CHECK: ]
174 ; CHECK: NumParameters: 0
175 ; CHECK: ArgListType: () (0x100D)
176 ; CHECK: }
177 ; CHECK: FuncId (0x100F) {
178 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
179 ; CHECK: ParentScope: 0x0
180 ; CHECK: FunctionType: void () (0x100E)
181 ; CHECK: Name: CharTypes
182 ; CHECK: }
137183 ; CHECK: ]
184
138185 ; CHECK: CodeViewDebugInfo [
139186 ; CHECK: Subsection [
140187 ; CHECK: SubSectionType: Symbols (0xF1)
187234 ; CHECK: VarName: v3
188235 ; CHECK: }
189236 ; CHECK: Local {
190 ; CHECK: Type: int ::* (0x1005)
237 ; CHECK: Type: int A::* (0x1006)
191238 ; CHECK: VarName: v4
192239 ; CHECK: }
193240 ; CHECK: Local {
194 ; CHECK: Type: void () ::* (0x1008)
241 ; CHECK: Type: void (A*) A::* (0x100A)
195242 ; CHECK: VarName: v5
196243 ; CHECK: }
197244 ; CHECK: Local {
211258 ; CHECK: VarName: l4
212259 ; CHECK: }
213260 ; CHECK: Local {
214 ; CHECK: Type: const void* (0x100A)
261 ; CHECK: Type: const void* (0x100C)
215262 ; CHECK: VarName: v6
216263 ; CHECK: }
217264 ; CHECK: ProcEnd {
219266 ; CHECK: ]
220267 ; CHECK: Subsection [
221268 ; CHECK: ProcStart {
269 ; CHECK: Type: CharTypes (0x100F)
222270 ; CHECK: DisplayName: CharTypes
223271 ; CHECK: LinkageName: ?CharTypes@@YAXXZ
224272 ; CHECK: }
0 ; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
1
2 ; C++ source to regenerate:
3 ; $ cat t.cpp
4 ; struct Struct {
5 ; int s1;
6 ; int s2;
7 ; int s3;
8 ; static const int sdm = 3;
9 ; };
10 ; union Union {
11 ; int a;
12 ; float b;
13 ; };
14 ; class Class {
15 ; public:
16 ; int pub;
17 ; struct Nested;
18 ; private:
19 ; int priv;
20 ; protected:
21 ; int prot;
22 ; };
23 ; struct DerivedClass : Struct, virtual Class {
24 ; int d;
25 ; };
26 ; struct Class::Nested {
27 ; int n;
28 ; };
29 ; void UseTypes() {
30 ; Struct s;
31 ; Union u;
32 ; Class c;
33 ; DerivedClass dc;
34 ; Class::Nested n;
35 ; }
36 ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
37
38 ; CHECK: CodeViewTypes [
39 ; CHECK: Section: .debug$T (10)
40 ; CHECK: Magic: 0x4
41 ; CHECK: ArgList (0x1000) {
42 ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
43 ; CHECK: NumArgs: 0
44 ; CHECK: Arguments [
45 ; CHECK: ]
46 ; CHECK: }
47 ; CHECK: Procedure (0x1001) {
48 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
49 ; CHECK: ReturnType: void (0x3)
50 ; CHECK: CallingConvention: NearC (0x0)
51 ; CHECK: FunctionOptions [ (0x0)
52 ; CHECK: ]
53 ; CHECK: NumParameters: 0
54 ; CHECK: ArgListType: () (0x1000)
55 ; CHECK: }
56 ; CHECK: FuncId (0x1002) {
57 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
58 ; CHECK: ParentScope: 0x0
59 ; CHECK: FunctionType: void () (0x1001)
60 ; CHECK: Name: UseTypes
61 ; CHECK: }
62 ; CHECK: Struct (0x1003) {
63 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
64 ; CHECK: MemberCount: 0
65 ; CHECK: Properties [ (0x80)
66 ; CHECK: ForwardReference (0x80)
67 ; CHECK: ]
68 ; CHECK: FieldList: 0x0
69 ; CHECK: DerivedFrom: 0x0
70 ; CHECK: VShape: 0x0
71 ; CHECK: SizeOf: 0
72 ; CHECK: Name: Struct
73 ; CHECK: }
74 ; CHECK: Modifier (0x1004) {
75 ; CHECK: TypeLeafKind: LF_MODIFIER (0x1001)
76 ; CHECK: ModifiedType: int (0x74)
77 ; CHECK: Modifiers [ (0x1)
78 ; CHECK: Const (0x1)
79 ; CHECK: ]
80 ; CHECK: }
81 ; CHECK: UnknownLeaf (0x1005) {
82 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
83 ; CHECK: DataMember {
84 ; CHECK: AccessSpecifier: Public (0x3)
85 ; CHECK: Type: int (0x74)
86 ; CHECK: FieldOffset: 0x0
87 ; CHECK: Name: s1
88 ; CHECK: }
89 ; CHECK: DataMember {
90 ; CHECK: AccessSpecifier: Public (0x3)
91 ; CHECK: Type: int (0x74)
92 ; CHECK: FieldOffset: 0x4
93 ; CHECK: Name: s2
94 ; CHECK: }
95 ; CHECK: DataMember {
96 ; CHECK: AccessSpecifier: Public (0x3)
97 ; CHECK: Type: int (0x74)
98 ; CHECK: FieldOffset: 0x8
99 ; CHECK: Name: s3
100 ; CHECK: }
101 ; CHECK: StaticDataMember {
102 ; CHECK: AccessSpecifier: Public (0x3)
103 ; CHECK: Type: const int (0x1004)
104 ; CHECK: Name: sdm
105 ; CHECK: }
106 ; CHECK: }
107 ; CHECK: Struct (0x1006) {
108 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
109 ; CHECK: MemberCount: 4
110 ; CHECK: Properties [ (0x0)
111 ; CHECK: ]
112 ; CHECK: FieldList: sdm (0x1005)
113 ; CHECK: DerivedFrom: 0x0
114 ; CHECK: VShape: 0x0
115 ; CHECK: SizeOf: 12
116 ; CHECK: Name: Struct
117 ; CHECK: }
118 ; CHECK: Union (0x1007) {
119 ; CHECK: TypeLeafKind: LF_UNION (0x1506)
120 ; CHECK: MemberCount: 0
121 ; CHECK: Properties [ (0x80)
122 ; CHECK: ForwardReference (0x80)
123 ; CHECK: ]
124 ; CHECK: FieldList: 0x0
125 ; CHECK: SizeOf: 0
126 ; CHECK: Name: Union
127 ; CHECK: }
128 ; CHECK: UnknownLeaf (0x1008) {
129 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
130 ; CHECK: DataMember {
131 ; CHECK: AccessSpecifier: Public (0x3)
132 ; CHECK: Type: int (0x74)
133 ; CHECK: FieldOffset: 0x0
134 ; CHECK: Name: a
135 ; CHECK: }
136 ; CHECK: DataMember {
137 ; CHECK: AccessSpecifier: Public (0x3)
138 ; CHECK: Type: float (0x40)
139 ; CHECK: FieldOffset: 0x0
140 ; CHECK: Name: b
141 ; CHECK: }
142 ; CHECK: }
143 ; CHECK: Union (0x1009) {
144 ; CHECK: TypeLeafKind: LF_UNION (0x1506)
145 ; CHECK: MemberCount: 2
146 ; CHECK: Properties [ (0x0)
147 ; CHECK: ]
148 ; CHECK: FieldList: b (0x1008)
149 ; CHECK: SizeOf: 4
150 ; CHECK: Name: Union
151 ; CHECK: }
152 ; CHECK: Class (0x100A) {
153 ; CHECK: TypeLeafKind: LF_CLASS (0x1504)
154 ; CHECK: MemberCount: 0
155 ; CHECK: Properties [ (0x80)
156 ; CHECK: ForwardReference (0x80)
157 ; CHECK: ]
158 ; CHECK: FieldList: 0x0
159 ; CHECK: DerivedFrom: 0x0
160 ; CHECK: VShape: 0x0
161 ; CHECK: SizeOf: 0
162 ; CHECK: Name: Class
163 ; CHECK: }
164 ; CHECK: UnknownLeaf (0x100B) {
165 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
166 ; CHECK: DataMember {
167 ; CHECK: AccessSpecifier: Public (0x3)
168 ; CHECK: Type: int (0x74)
169 ; CHECK: FieldOffset: 0x0
170 ; CHECK: Name: pub
171 ; CHECK: }
172 ; CHECK: DataMember {
173 ; CHECK: AccessSpecifier: Private (0x1)
174 ; CHECK: Type: int (0x74)
175 ; CHECK: FieldOffset: 0x4
176 ; CHECK: Name: priv
177 ; CHECK: }
178 ; CHECK: DataMember {
179 ; CHECK: AccessSpecifier: Protected (0x2)
180 ; CHECK: Type: int (0x74)
181 ; CHECK: FieldOffset: 0x8
182 ; CHECK: Name: prot
183 ; CHECK: }
184 ; CHECK: }
185 ; CHECK: Class (0x100C) {
186 ; CHECK: TypeLeafKind: LF_CLASS (0x1504)
187 ; CHECK: MemberCount: 3
188 ; CHECK: Properties [ (0x0)
189 ; CHECK: ]
190 ; CHECK: FieldList: prot (0x100B)
191 ; CHECK: DerivedFrom: 0x0
192 ; CHECK: VShape: 0x0
193 ; CHECK: SizeOf: 12
194 ; CHECK: Name: Class
195 ; CHECK: }
196 ; CHECK: Struct (0x100D) {
197 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
198 ; CHECK: MemberCount: 0
199 ; CHECK: Properties [ (0x80)
200 ; CHECK: ForwardReference (0x80)
201 ; CHECK: ]
202 ; CHECK: FieldList: 0x0
203 ; CHECK: DerivedFrom: 0x0
204 ; CHECK: VShape: 0x0
205 ; CHECK: SizeOf: 0
206 ; CHECK: Name: DerivedClass
207 ; CHECK: }
208 ; CHECK: Procedure (0x100E) {
209 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
210 ; CHECK: ReturnType: int (0x74)
211 ; CHECK: CallingConvention: NearC (0x0)
212 ; CHECK: FunctionOptions [ (0x0)
213 ; CHECK: ]
214 ; CHECK: NumParameters: 0
215 ; CHECK: ArgListType: () (0x1000)
216 ; CHECK: }
217 ; CHECK: Pointer (0x100F) {
218 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
219 ; CHECK: PointeeType: int () (0x100E)
220 ; CHECK: PointerAttributes: 0x1000C
221 ; CHECK: PtrType: Near64 (0xC)
222 ; CHECK: PtrMode: Pointer (0x0)
223 ; CHECK: IsFlat: 0
224 ; CHECK: IsConst: 0
225 ; CHECK: IsVolatile: 0
226 ; CHECK: IsUnaligned: 0
227 ; CHECK: }
228 ; CHECK: Pointer (0x1010) {
229 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
230 ; CHECK: PointeeType: int ()* (0x100F)
231 ; CHECK: PointerAttributes: 0x1000C
232 ; CHECK: PtrType: Near64 (0xC)
233 ; CHECK: PtrMode: Pointer (0x0)
234 ; CHECK: IsFlat: 0
235 ; CHECK: IsConst: 0
236 ; CHECK: IsVolatile: 0
237 ; CHECK: IsUnaligned: 0
238 ; CHECK: }
239 ; CHECK: UnknownLeaf (0x1011) {
240 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
241 ; CHECK: DataMember {
242 ; CHECK: AccessSpecifier: Public (0x3)
243 ; CHECK: Type: int ()** (0x1010)
244 ; CHECK: FieldOffset: 0x0
245 ; CHECK: Name: _vptr$DerivedClass
246 ; CHECK: }
247 ; CHECK: DataMember {
248 ; CHECK: AccessSpecifier: Public (0x3)
249 ; CHECK: Type: int (0x74)
250 ; CHECK: FieldOffset: 0x18
251 ; CHECK: Name: d
252 ; CHECK: }
253 ; CHECK: }
254 ; CHECK: Struct (0x1012) {
255 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
256 ; CHECK: MemberCount: 2
257 ; CHECK: Properties [ (0x0)
258 ; CHECK: ]
259 ; CHECK: FieldList: d (0x1011)
260 ; CHECK: DerivedFrom: 0x0
261 ; CHECK: VShape: 0x0
262 ; CHECK: SizeOf: 48
263 ; CHECK: Name: DerivedClass
264 ; CHECK: }
265 ; CHECK: Struct (0x1013) {
266 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
267 ; CHECK: MemberCount: 0
268 ; CHECK: Properties [ (0x80)
269 ; CHECK: ForwardReference (0x80)
270 ; CHECK: ]
271 ; CHECK: FieldList: 0x0
272 ; CHECK: DerivedFrom: 0x0
273 ; CHECK: VShape: 0x0
274 ; CHECK: SizeOf: 0
275 ; CHECK: Name: Nested
276 ; CHECK: }
277 ; CHECK: UnknownLeaf (0x1014) {
278 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
279 ; CHECK: DataMember {
280 ; CHECK: AccessSpecifier: Public (0x3)
281 ; CHECK: Type: int (0x74)
282 ; CHECK: FieldOffset: 0x0
283 ; CHECK: Name: n
284 ; CHECK: }
285 ; CHECK: }
286 ; CHECK: Struct (0x1015) {
287 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
288 ; CHECK: MemberCount: 1
289 ; CHECK: Properties [ (0x0)
290 ; CHECK: ]
291 ; CHECK: FieldList: n (0x1014)
292 ; CHECK: DerivedFrom: 0x0
293 ; CHECK: VShape: 0x0
294 ; CHECK: SizeOf: 4
295 ; CHECK: Name: Nested
296 ; CHECK: }
297 ; CHECK: Pointer (0x1016) {
298 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
299 ; CHECK: PointeeType: DerivedClass (0x100D)
300 ; CHECK: PointerAttributes: 0x1000C
301 ; CHECK: PtrType: Near64 (0xC)
302 ; CHECK: PtrMode: Pointer (0x0)
303 ; CHECK: IsFlat: 0
304 ; CHECK: IsConst: 0
305 ; CHECK: IsVolatile: 0
306 ; CHECK: IsUnaligned: 0
307 ; CHECK: }
308 ; CHECK: ArgList (0x1017) {
309 ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
310 ; CHECK: NumArgs: 1
311 ; CHECK: Arguments [
312 ; CHECK: ArgType: DerivedClass* (0x1016)
313 ; CHECK: ]
314 ; CHECK: }
315 ; CHECK: Procedure (0x1018) {
316 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
317 ; CHECK: ReturnType: void (0x3)
318 ; CHECK: CallingConvention: NearC (0x0)
319 ; CHECK: FunctionOptions [ (0x0)
320 ; CHECK: ]
321 ; CHECK: NumParameters: 1
322 ; CHECK: ArgListType: (DerivedClass*) (0x1017)
323 ; CHECK: }
324 ; CHECK: FuncId (0x1019) {
325 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
326 ; CHECK: ParentScope: 0x0
327 ; CHECK: FunctionType: void (DerivedClass*) (0x1018)
328 ; CHECK: Name: DerivedClass::DerivedClass
329 ; CHECK: }
330 ; CHECK: ]
331
332 ; ModuleID = 'record-types.cpp'
333 source_filename = "record-types.cpp"
334 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
335 target triple = "x86_64-pc-windows-msvc19.0.23918"
336
337 %struct.Struct = type { i32, i32, i32 }
338 %union.Union = type { i32 }
339 %class.Class = type { i32, i32, i32 }
340 %struct.DerivedClass = type { %struct.Struct, i32*, i32, [4 x i8], %class.Class }
341 %"struct.Class::Nested" = type { i32 }
342
343 $"\01??0DerivedClass@@QEAA@XZ" = comdat any
344
345 $"\01??_8DerivedClass@@7B@" = comdat any
346
347 @"\01??_8DerivedClass@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -16, i32 16], comdat
348
349 ; Function Attrs: nounwind uwtable
350 define void @"\01?UseTypes@@YAXXZ"() #0 !dbg !7 {
351 entry:
352 %s = alloca %struct.Struct, align 4
353 %u = alloca %union.Union, align 4
354 %c = alloca %class.Class, align 4
355 %dc = alloca %struct.DerivedClass, align 8
356 %n = alloca %"struct.Class::Nested", align 4
357 call void @llvm.dbg.declare(metadata %struct.Struct* %s, metadata !10, metadata !19), !dbg !20
358 call void @llvm.dbg.declare(metadata %union.Union* %u, metadata !21, metadata !19), !dbg !27
359 call void @llvm.dbg.declare(metadata %class.Class* %c, metadata !28, metadata !19), !dbg !34
360 call void @llvm.dbg.declare(metadata %struct.DerivedClass* %dc, metadata !35, metadata !19), !dbg !46
361 %call = call %struct.DerivedClass* @"\01??0DerivedClass@@QEAA@XZ"(%struct.DerivedClass* %dc, i32 1) #3, !dbg !46
362 call void @llvm.dbg.declare(metadata %"struct.Class::Nested"* %n, metadata !47, metadata !19), !dbg !51
363 ret void, !dbg !52
364 }
365
366 ; Function Attrs: nounwind readnone
367 declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
368
369 ; Function Attrs: inlinehint nounwind uwtable
370 define linkonce_odr %struct.DerivedClass* @"\01??0DerivedClass@@QEAA@XZ"(%struct.DerivedClass* returned %this, i32 %is_most_derived) unnamed_addr #2 comdat align 2 !dbg !53 {
371 entry:
372 %retval = alloca %struct.DerivedClass*, align 8
373 %is_most_derived.addr = alloca i32, align 4
374 %this.addr = alloca %struct.DerivedClass*, align 8
375 store i32 %is_most_derived, i32* %is_most_derived.addr, align 4
376 call void @llvm.dbg.declare(metadata i32* %is_most_derived.addr, metadata !58, metadata !19), !dbg !59
377 store %struct.DerivedClass* %this, %struct.DerivedClass** %this.addr, align 8
378 call void @llvm.dbg.declare(metadata %struct.DerivedClass** %this.addr, metadata !60, metadata !19), !dbg !59
379 %this1 = load %struct.DerivedClass*, %struct.DerivedClass** %this.addr, align 8
380 store %struct.DerivedClass* %this1, %struct.DerivedClass** %retval, align 8
381 %is_most_derived2 = load i32, i32* %is_most_derived.addr, align 4
382 %is_complete_object = icmp ne i32 %is_most_derived2, 0, !dbg !62
383 br i1 %is_complete_object, label %ctor.init_vbases, label %ctor.skip_vbases, !dbg !62
384
385 ctor.init_vbases: ; preds = %entry
386 %this.int8 = bitcast %struct.DerivedClass* %this1 to i8*, !dbg !62
387 %0 = getelementptr inbounds i8, i8* %this.int8, i64 16, !dbg !62
388 %vbptr.DerivedClass = bitcast i8* %0 to i32**, !dbg !62
389 store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8DerivedClass@@7B@", i32 0, i32 0), i32** %vbptr.DerivedClass, align 8, !dbg !62
390 %1 = bitcast %struct.DerivedClass* %this1 to i8*, !dbg !62
391 %2 = getelementptr inbounds i8, i8* %1, i64 32, !dbg !62
392 %3 = bitcast i8* %2 to %class.Class*, !dbg !62
393 br label %ctor.skip_vbases, !dbg !62
394
395 ctor.skip_vbases: ; preds = %ctor.init_vbases, %entry
396 %4 = bitcast %struct.DerivedClass* %this1 to %struct.Struct*, !dbg !62
397 %5 = load %struct.DerivedClass*, %struct.DerivedClass** %retval, align 8, !dbg !62
398 ret %struct.DerivedClass* %5, !dbg !62
399 }
400
401 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" }
402 attributes #1 = { nounwind readnone }
403 attributes #2 = { inlinehint 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" }
404 attributes #3 = { nounwind }
405
406 !llvm.dbg.cu = !{!0}
407 !llvm.module.flags = !{!3, !4, !5}
408 !llvm.ident = !{!6}
409
410 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 271336) (llvm/trunk 271339)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
411 !1 = !DIFile(filename: "record-types.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
412 !2 = !{}
413 !3 = !{i32 2, !"CodeView", i32 1}
414 !4 = !{i32 2, !"Debug Info Version", i32 3}
415 !5 = !{i32 1, !"PIC Level", i32 2}
416 !6 = !{!"clang version 3.9.0 (trunk 271336) (llvm/trunk 271339)"}
417 !7 = distinct !DISubprogram(name: "UseTypes", linkageName: "\01?UseTypes@@YAXXZ", scope: !1, file: !1, line: 31, type: !8, isLocal: false, isDefinition: true, scopeLine: 31, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
418 !8 = !DISubroutineType(types: !9)
419 !9 = !{null}
420 !10 = !DILocalVariable(name: "s", scope: !7, file: !1, line: 32, type: !11)
421 !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Struct", file: !1, line: 1, size: 96, align: 32, elements: !12)
422 !12 = !{!13, !15, !16, !17}
423 !13 = !DIDerivedType(tag: DW_TAG_member, name: "s1", scope: !11, file: !1, line: 2, baseType: !14, size: 32, align: 32)
424 !14 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
425 !15 = !DIDerivedType(tag: DW_TAG_member, name: "s2", scope: !11, file: !1, line: 3, baseType: !14, size: 32, align: 32, offset: 32)
426 !16 = !DIDerivedType(tag: DW_TAG_member, name: "s3", scope: !11, file: !1, line: 4, baseType: !14, size: 32, align: 32, offset: 64)
427 !17 = !DIDerivedType(tag: DW_TAG_member, name: "sdm", scope: !11, file: !1, line: 5, baseType: !18, flags: DIFlagStaticMember, extraData: i32 3)
428 !18 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !14)
429 !19 = !DIExpression()
430 !20 = !DILocation(line: 32, column: 10, scope: !7)
431 !21 = !DILocalVariable(name: "u", scope: !7, file: !1, line: 33, type: !22)
432 !22 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "Union", file: !1, line: 8, size: 32, align: 32, elements: !23)
433 !23 = !{!24, !25}
434 !24 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !22, file: !1, line: 9, baseType: !14, size: 32, align: 32)
435 !25 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !22, file: !1, line: 10, baseType: !26, size: 32, align: 32)
436 !26 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float)
437 !27 = !DILocation(line: 33, column: 9, scope: !7)
438 !28 = !DILocalVariable(name: "c", scope: !7, file: !1, line: 34, type: !29)
439 !29 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "Class", file: !1, line: 13, size: 96, align: 32, elements: !30)
440 !30 = !{!31, !32, !33}
441 !31 = !DIDerivedType(tag: DW_TAG_member, name: "pub", scope: !29, file: !1, line: 15, baseType: !14, size: 32, align: 32, flags: DIFlagPublic)
442 !32 = !DIDerivedType(tag: DW_TAG_member, name: "priv", scope: !29, file: !1, line: 18, baseType: !14, size: 32, align: 32, offset: 32)
443 !33 = !DIDerivedType(tag: DW_TAG_member, name: "prot", scope: !29, file: !1, line: 20, baseType: !14, size: 32, align: 32, offset: 64, flags: DIFlagProtected)
444 !34 = !DILocation(line: 34, column: 9, scope: !7)
445 !35 = !DILocalVariable(name: "dc", scope: !7, file: !1, line: 35, type: !36)
446 !36 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "DerivedClass", file: !1, line: 23, size: 384, align: 64, elements: !37, vtableHolder: !36)
447 !37 = !{!38, !39, !40, !45}
448 !38 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !36, baseType: !11)
449 !39 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !36, baseType: !29, offset: 4, flags: DIFlagVirtual)
450 !40 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$DerivedClass", scope: !1, file: !1, baseType: !41, size: 64, flags: DIFlagArtificial)
451 !41 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !42, size: 64)
452 !42 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: !43, size: 64)
453 !43 = !DISubroutineType(types: !44)
454 !44 = !{!14}
455 !45 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !36, file: !1, line: 24, baseType: !14, size: 32, align: 32, offset: 192)
456 !46 = !DILocation(line: 35, column: 16, scope: !7)
457 !47 = !DILocalVariable(name: "n", scope: !7, file: !1, line: 36, type: !48)
458 !48 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", scope: !29, file: !1, line: 27, size: 32, align: 32, elements: !49)
459 !49 = !{!50}
460 !50 = !DIDerivedType(tag: DW_TAG_member, name: "n", scope: !48, file: !1, line: 28, baseType: !14, size: 32, align: 32)
461 !51 = !DILocation(line: 36, column: 17, scope: !7)
462 !52 = !DILocation(line: 37, column: 1, scope: !7)
463 !53 = distinct !DISubprogram(name: "DerivedClass::DerivedClass", linkageName: "\01??0DerivedClass@@QEAA@XZ", scope: !36, file: !1, line: 23, type: !54, isLocal: false, isDefinition: true, scopeLine: 23, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !57, variables: !2)
464 !54 = !DISubroutineType(types: !55)
465 !55 = !{null, !56}
466 !56 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !36, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
467 !57 = !DISubprogram(name: "DerivedClass::DerivedClass", scope: !36, type: !54, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
468 !58 = !DILocalVariable(name: "is_most_derived", arg: 2, scope: !53, type: !14, flags: DIFlagArtificial)
469 !59 = !DILocation(line: 0, scope: !53)
470 !60 = !DILocalVariable(name: "this", arg: 1, scope: !53, type: !61, flags: DIFlagArtificial | DIFlagObjectPointer)
471 !61 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !36, size: 64, align: 64)
472 !62 = !DILocation(line: 23, column: 8, scope: !53)
0 ; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s
1
2 ; This test ensures that circular type references through pointer types don't
3 ; cause infinite recursion. It also tests that we always refer to the forward
4 ; declaration type index in field lists and pointer types, which is consistent
5 ; with what MSVC does. It ensures that these records get merged when merging
6 ; streams even if the complete record types differ slightly due to ODR
7 ; violations, i.e. methods that only exist ifndef NDEBUG.
8
9 ; C++ source to regenerate:
10 ; $ cat t.cpp
11 ; struct B;
12 ; struct A { B *b; };
13 ; struct B { A a; };
14 ; void f() {
15 ; A a;
16 ; B b;
17 ; }
18 ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
19
20 ; CHECK: CodeViewTypes [
21 ; CHECK: Section: .debug$T (6)
22 ; CHECK: Magic: 0x4
23 ; CHECK: ArgList (0x1000) {
24 ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
25 ; CHECK: NumArgs: 0
26 ; CHECK: Arguments [
27 ; CHECK: ]
28 ; CHECK: }
29 ; CHECK: Procedure (0x1001) {
30 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
31 ; CHECK: ReturnType: void (0x3)
32 ; CHECK: CallingConvention: NearC (0x0)
33 ; CHECK: FunctionOptions [ (0x0)
34 ; CHECK: ]
35 ; CHECK: NumParameters: 0
36 ; CHECK: ArgListType: () (0x1000)
37 ; CHECK: }
38 ; CHECK: FuncId (0x1002) {
39 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
40 ; CHECK: ParentScope: 0x0
41 ; CHECK: FunctionType: void () (0x1001)
42 ; CHECK: Name: f
43 ; CHECK: }
44 ; CHECK: Struct (0x1003) {
45 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
46 ; CHECK: MemberCount: 0
47 ; CHECK: Properties [ (0x80)
48 ; CHECK: ForwardReference (0x80)
49 ; CHECK: ]
50 ; CHECK: FieldList: 0x0
51 ; CHECK: DerivedFrom: 0x0
52 ; CHECK: VShape: 0x0
53 ; CHECK: SizeOf: 0
54 ; CHECK: Name: A
55 ; CHECK: }
56 ; CHECK: Struct (0x1004) {
57 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
58 ; CHECK: MemberCount: 0
59 ; CHECK: Properties [ (0x80)
60 ; CHECK: ForwardReference (0x80)
61 ; CHECK: ]
62 ; CHECK: FieldList: 0x0
63 ; CHECK: DerivedFrom: 0x0
64 ; CHECK: VShape: 0x0
65 ; CHECK: SizeOf: 0
66 ; CHECK: Name: B
67 ; CHECK: }
68 ; CHECK: Pointer (0x1005) {
69 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
70 ; CHECK: PointeeType: B (0x1004)
71 ; CHECK: PointerAttributes: 0x1000C
72 ; CHECK: PtrType: Near64 (0xC)
73 ; CHECK: PtrMode: Pointer (0x0)
74 ; CHECK: IsFlat: 0
75 ; CHECK: IsConst: 0
76 ; CHECK: IsVolatile: 0
77 ; CHECK: IsUnaligned: 0
78 ; CHECK: }
79 ; CHECK: UnknownLeaf (0x1006) {
80 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
81 ; CHECK: DataMember {
82 ; CHECK: AccessSpecifier: Public (0x3)
83 ; CHECK: Type: B* (0x1005)
84 ; CHECK: FieldOffset: 0x0
85 ; CHECK: Name: b
86 ; CHECK: }
87 ; CHECK: }
88 ; CHECK: Struct (0x1007) {
89 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
90 ; CHECK: MemberCount: 1
91 ; CHECK: Properties [ (0x0)
92 ; CHECK: ]
93 ; CHECK: FieldList: b (0x1006)
94 ; CHECK: DerivedFrom: 0x0
95 ; CHECK: VShape: 0x0
96 ; CHECK: SizeOf: 8
97 ; CHECK: Name: A
98 ; CHECK: }
99 ; CHECK: UnknownLeaf (0x1008) {
100 ; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203)
101 ; CHECK: DataMember {
102 ; CHECK: AccessSpecifier: Public (0x3)
103 ; CHECK: Type: A (0x1003)
104 ; CHECK: FieldOffset: 0x0
105 ; CHECK: Name: a
106 ; CHECK: }
107 ; CHECK: }
108 ; CHECK: Struct (0x1009) {
109 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
110 ; CHECK: MemberCount: 1
111 ; CHECK: Properties [ (0x0)
112 ; CHECK: ]
113 ; CHECK: FieldList: a (0x1008)
114 ; CHECK: DerivedFrom: 0x0
115 ; CHECK: VShape: 0x0
116 ; CHECK: SizeOf: 8
117 ; CHECK: Name: B
118 ; CHECK: }
119 ; CHECK: ]
120
121 ; ModuleID = 't.cpp'
122 source_filename = "t.cpp"
123 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
124 target triple = "x86_64-pc-windows-msvc19.0.23918"
125
126 %struct.A = type { %struct.B* }
127 %struct.B = type { %struct.A }
128
129 ; Function Attrs: nounwind uwtable
130 define void @"\01?f@@YAXXZ"() #0 !dbg !7 {
131 entry:
132 %a = alloca %struct.A, align 8
133 %b = alloca %struct.B, align 8
134 call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !10, metadata !18), !dbg !19
135 call void @llvm.dbg.declare(metadata %struct.B* %b, metadata !20, metadata !18), !dbg !21
136 ret void, !dbg !22
137 }
138
139 ; Function Attrs: nounwind readnone
140 declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
141
142 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" }
143 attributes #1 = { nounwind readnone }
144
145 !llvm.dbg.cu = !{!0}
146 !llvm.module.flags = !{!3, !4, !5}
147 !llvm.ident = !{!6}
148
149 !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)
150 !1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
151 !2 = !{}
152 !3 = !{i32 2, !"CodeView", i32 1}
153 !4 = !{i32 2, !"Debug Info Version", i32 3}
154 !5 = !{i32 1, !"PIC Level", i32 2}
155 !6 = !{!"clang version 3.9.0 "}
156 !7 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAXXZ", scope: !1, file: !1, line: 4, type: !8, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
157 !8 = !DISubroutineType(types: !9)
158 !9 = !{null}
159 !10 = !DILocalVariable(name: "a", scope: !7, file: !1, line: 5, type: !11)
160 !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 2, size: 64, align: 64, elements: !12)
161 !12 = !{!13}
162 !13 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !11, file: !1, line: 2, baseType: !14, size: 64, align: 64)
163 !14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64, align: 64)
164 !15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !1, line: 3, size: 64, align: 64, elements: !16)
165 !16 = !{!17}
166 !17 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !15, file: !1, line: 3, baseType: !11, size: 64, align: 64)
167 !18 = !DIExpression()
168 !19 = !DILocation(line: 5, column: 5, scope: !7)
169 !20 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 6, type: !15)
170 !21 = !DILocation(line: 6, column: 5, scope: !7)
171 !22 = !DILocation(line: 7, column: 1, scope: !7)