llvm.org GIT mirror llvm / 3d3aca2
[DebugInfo] Add calling convention support for DWARF and CodeView Summary: Now DISubroutineType has a 'cc' field which should be a DW_CC_ enum. If it is present and non-zero, the backend will emit it as a DW_AT_calling_convention attribute. On the CodeView side, we translate it to the appropriate enum for the LF_PROCEDURE record. I added a new LLVM vendor specific enum to the list of DWARF calling conventions. DWARF does not appear to attempt to standardize these, so I assume it's OK to do this until we coordinate with GCC on how to emit vectorcall convention functions. Reviewers: dexonsmith, majnemer, aaboud, amccarth Subscribers: mehdi_amini, llvm-commits Differential Revision: http://reviews.llvm.org/D21114 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272197 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
21 changed file(s) with 472 addition(s) and 73 deletion(s). Raw diff Collapse all Expand all
242242 METADATA_FILE = 16, // [distinct, filename, directory]
243243 METADATA_DERIVED_TYPE = 17, // [distinct, ...]
244244 METADATA_COMPOSITE_TYPE = 18, // [distinct, ...]
245 METADATA_SUBROUTINE_TYPE = 19, // [distinct, flags, types]
245 METADATA_SUBROUTINE_TYPE = 19, // [distinct, flags, types, cc]
246246 METADATA_COMPILE_UNIT = 20, // [distinct, ...]
247247 METADATA_SUBPROGRAM = 21, // [distinct, ...]
248248 METADATA_LEXICAL_BLOCK = 22, // [distinct, scope, file, line, column]
373373 /// includes return type at 0th index.
374374 /// \param Flags E.g.: LValueReference.
375375 /// These flags are used to emit dwarf attributes.
376 /// \param CC Calling convention, e.g. dwarf::DW_CC_normal
376377 DISubroutineType *createSubroutineType(DITypeRefArray ParameterTypes,
377 unsigned Flags = 0);
378 unsigned Flags = 0, unsigned CC = 0);
378379
379380 /// Create an external type reference.
380381 /// \param Tag Dwarf TAG.
919919 friend class LLVMContextImpl;
920920 friend class MDNode;
921921
922 /// The calling convention used with DW_AT_calling_convention. Actually of
923 /// type dwarf::CallingConvention.
924 uint8_t CC;
925
922926 DISubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags,
923 ArrayRef Ops)
927 uint8_t CC, ArrayRef Ops)
924928 : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type,
925 0, 0, 0, 0, Flags, Ops) {}
929 0, 0, 0, 0, Flags, Ops),
930 CC(CC) {}
926931 ~DISubroutineType() = default;
927932
928933 static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
929 DITypeRefArray TypeArray,
934 uint8_t CC, DITypeRefArray TypeArray,
930935 StorageType Storage,
931936 bool ShouldCreate = true) {
932 return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate);
937 return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate);
933938 }
934939 static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
935 Metadata *TypeArray, StorageType Storage,
940 uint8_t CC, Metadata *TypeArray,
941 StorageType Storage,
936942 bool ShouldCreate = true);
937943
938944 TempDISubroutineType cloneImpl() const {
939 return getTemporary(getContext(), getFlags(), getTypeArray());
945 return getTemporary(getContext(), getFlags(), getCC(), getTypeArray());
940946 }
941947
942948 public:
943949 DEFINE_MDNODE_GET(DISubroutineType,
944 (unsigned Flags, DITypeRefArray TypeArray),
945 (Flags, TypeArray))
946 DEFINE_MDNODE_GET(DISubroutineType, (unsigned Flags, Metadata *TypeArray),
947 (Flags, TypeArray))
950 (unsigned Flags, uint8_t CC, DITypeRefArray TypeArray),
951 (Flags, CC, TypeArray))
952 DEFINE_MDNODE_GET(DISubroutineType,
953 (unsigned Flags, uint8_t CC, Metadata *TypeArray),
954 (Flags, CC, TypeArray))
948955
949956 TempDISubroutineType clone() const { return cloneImpl(); }
957
958 uint8_t getCC() const { return CC; }
950959
951960 DITypeRefArray getTypeArray() const {
952961 return cast_or_null(getRawTypeArray());
1313 // TODO: Add other DW-based macros.
1414 #if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \
1515 defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \
16 defined HANDLE_DW_VIRTUALITY)
16 defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_CC)
1717 #error "Missing macro definition of HANDLE_DW*"
1818 #endif
1919
3636 #ifndef HANDLE_DW_VIRTUALITY
3737 #define HANDLE_DW_VIRTUALITY(ID, NAME)
3838 #endif
39
40 #ifndef HANDLE_DW_CC
41 #define HANDLE_DW_CC(ID, NAME)
42 #endif
43
3944
4045 HANDLE_DW_TAG(0x0001, array_type)
4146 HANDLE_DW_TAG(0x0002, class_type)
345350 HANDLE_DW_VIRTUALITY(0x01, virtual)
346351 HANDLE_DW_VIRTUALITY(0x02, pure_virtual)
347352
353 // DWARF calling convention codes.
354 HANDLE_DW_CC(0x01, normal)
355 HANDLE_DW_CC(0x02, program)
356 HANDLE_DW_CC(0x03, nocall)
357 HANDLE_DW_CC(0x41, GNU_borland_fastcall_i386)
358 HANDLE_DW_CC(0xb0, BORLAND_safecall)
359 HANDLE_DW_CC(0xb1, BORLAND_stdcall)
360 HANDLE_DW_CC(0xb2, BORLAND_pascal)
361 HANDLE_DW_CC(0xb3, BORLAND_msfastcall)
362 HANDLE_DW_CC(0xb4, BORLAND_msreturn)
363 HANDLE_DW_CC(0xb5, BORLAND_thiscall)
364 HANDLE_DW_CC(0xb6, BORLAND_fastcall)
365 HANDLE_DW_CC(0xc0, LLVM_vectorcall)
366
348367 #undef HANDLE_DW_TAG
349368 #undef HANDLE_DW_OP
350369 #undef HANDLE_DW_LANG
351370 #undef HANDLE_DW_ATE
352371 #undef HANDLE_DW_VIRTUALITY
372 #undef HANDLE_DW_CC
388388
389389 enum CallingConvention {
390390 // Calling convention codes
391 DW_CC_normal = 0x01,
392 DW_CC_program = 0x02,
393 DW_CC_nocall = 0x03,
391 #define HANDLE_DW_CC(ID, NAME) DW_CC_##NAME = ID,
392 #include "llvm/Support/Dwarf.def"
394393 DW_CC_lo_user = 0x40,
395 DW_CC_GNU_borland_fastcall_i386 = 0x41,
396 DW_CC_BORLAND_safecall = 0xb0,
397 DW_CC_BORLAND_stdcall = 0xb1,
398 DW_CC_BORLAND_pascal = 0xb2,
399 DW_CC_BORLAND_msfastcall = 0xb3,
400 DW_CC_BORLAND_msreturn = 0xb4,
401 DW_CC_BORLAND_thiscall = 0xb5,
402 DW_CC_BORLAND_fastcall = 0xb6,
403394 DW_CC_hi_user = 0xff
404395 };
405396
651642 unsigned getOperationEncoding(StringRef OperationEncodingString);
652643 unsigned getVirtuality(StringRef VirtualityString);
653644 unsigned getLanguage(StringRef LanguageString);
645 unsigned getCallingConvention(StringRef LanguageString);
654646 unsigned getAttributeEncoding(StringRef EncodingString);
655647 unsigned getMacinfo(StringRef MacinfoString);
656648 /// @}
792792 DWKEYWORD(ATE, DwarfAttEncoding);
793793 DWKEYWORD(VIRTUALITY, DwarfVirtuality);
794794 DWKEYWORD(LANG, DwarfLang);
795 DWKEYWORD(CC, DwarfCC);
795796 DWKEYWORD(OP, DwarfOp);
796797 DWKEYWORD(MACINFO, DwarfMacinfo);
797798 #undef DWKEYWORD
33403340 struct DwarfLangField : public MDUnsignedField {
33413341 DwarfLangField() : MDUnsignedField(0, dwarf::DW_LANG_hi_user) {}
33423342 };
3343 struct DwarfCCField : public MDUnsignedField {
3344 DwarfCCField() : MDUnsignedField(0, dwarf::DW_CC_hi_user) {}
3345 };
33433346 struct EmissionKindField : public MDUnsignedField {
33443347 EmissionKindField() : MDUnsignedField(0, DICompileUnit::LastEmissionKind) {}
33453348 };
34783481 "'");
34793482 assert(Lang <= Result.Max && "Expected valid DWARF language");
34803483 Result.assign(Lang);
3484 Lex.Lex();
3485 return false;
3486 }
3487
3488 template <>
3489 bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfCCField &Result) {
3490 if (Lex.getKind() == lltok::APSInt)
3491 return ParseMDField(Loc, Name, static_cast(Result));
3492
3493 if (Lex.getKind() != lltok::DwarfCC)
3494 return TokError("expected DWARF calling convention");
3495
3496 unsigned CC = dwarf::getCallingConvention(Lex.getStrVal());
3497 if (!CC)
3498 return TokError("invalid DWARF calling convention" + Twine(" '") + Lex.getStrVal() +
3499 "'");
3500 assert(CC <= Result.Max && "Expected valid DWARF calling convention");
3501 Result.assign(CC);
34813502 Lex.Lex();
34823503 return false;
34833504 }
38623883 bool LLParser::ParseDISubroutineType(MDNode *&Result, bool IsDistinct) {
38633884 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
38643885 OPTIONAL(flags, DIFlagField, ); \
3886 OPTIONAL(cc, DwarfCCField, ); \
38653887 REQUIRED(types, MDField, );
38663888 PARSE_MD_FIELDS();
38673889 #undef VISIT_MD_FIELDS
38683890
3869 Result = GET_OR_DISTINCT(DISubroutineType, (Context, flags.Val, types.Val));
3891 Result = GET_OR_DISTINCT(DISubroutineType,
3892 (Context, flags.Val, cc.Val, types.Val));
38703893 return false;
38713894 }
38723895
343343 DwarfAttEncoding, // DW_ATE_foo
344344 DwarfVirtuality, // DW_VIRTUALITY_foo
345345 DwarfLang, // DW_LANG_foo
346 DwarfCC, // DW_CC_foo
346347 EmissionKind, // lineTablesOnly
347348 DwarfOp, // DW_OP_foo
348349 DIFlag, // DIFlagFoo
24082408 break;
24092409 }
24102410 case bitc::METADATA_SUBROUTINE_TYPE: {
2411 if (Record.size() != 3)
2412 return error("Invalid record");
2411 if (Record.size() < 3 || Record.size() > 4)
2412 return error("Invalid record");
2413 bool IsOldTypeRefArray = Record[0] < 2;
2414 unsigned CC = (Record.size() > 3) ? Record[3] : 0;
24132415
24142416 IsDistinct = Record[0] & 0x1;
2415 bool IsOldTypeRefArray = Record[0] < 2;
24162417 Metadata *Types = getMDOrNull(Record[2]);
24172418 if (LLVM_UNLIKELY(IsOldTypeRefArray))
24182419 Types = MetadataList.upgradeTypeRefArray(Types);
24192420
24202421 MetadataList.assignValue(
2421 GET_OR_DISTINCT(DISubroutineType, (Context, Record[1], Types)),
2422 GET_OR_DISTINCT(DISubroutineType, (Context, Record[1], CC, Types)),
24222423 NextMetadataNo++);
24232424 break;
24242425 }
14661466 Record.push_back(HasNoOldTypeRefs | (unsigned)N->isDistinct());
14671467 Record.push_back(N->getFlags());
14681468 Record.push_back(VE.getMetadataOrNullID(N->getTypeArray().get()));
1469 Record.push_back(N->getCC());
14691470
14701471 Stream.EmitRecord(bitc::METADATA_SUBROUTINE_TYPE, Record, Abbrev);
14711472 Record.clear();
925925 return TypeTable.writePointer(PR);
926926 }
927927
928 /// Given a DWARF calling convention, get the CodeView equivalent. If we don't
929 /// have a translation, use the NearC convention.
930 static CallingConvention dwarfCCToCodeView(unsigned DwarfCC) {
931 switch (DwarfCC) {
932 case dwarf::DW_CC_normal: return CallingConvention::NearC;
933 case dwarf::DW_CC_BORLAND_msfastcall: return CallingConvention::NearFast;
934 case dwarf::DW_CC_BORLAND_thiscall: return CallingConvention::ThisCall;
935 case dwarf::DW_CC_BORLAND_stdcall: return CallingConvention::NearStdCall;
936 case dwarf::DW_CC_BORLAND_pascal: return CallingConvention::NearPascal;
937 case dwarf::DW_CC_LLVM_vectorcall: return CallingConvention::NearVector;
938 }
939 return CallingConvention::NearC;
940 }
941
928942 TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
929943 ModifierOptions Mods = ModifierOptions::None;
930944 bool IsModifier = true;
966980 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
967981 TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
968982
969 // TODO: We should use DW_AT_calling_convention to determine what CC this
970 // procedure record should have.
983 CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
984
971985 // TODO: Some functions are member functions, we should use a more appropriate
972986 // record for those.
973 ProcedureRecord Procedure(ReturnTypeIndex, CallingConvention::NearC,
974 FunctionOptions::None, ArgTypeIndices.size(),
975 ArgListIndex);
987 ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None,
988 ArgTypeIndices.size(), ArgListIndex);
976989 return TypeTable.writeProcedure(Procedure);
977990 }
978991
899899 (Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 ||
900900 Language == dwarf::DW_LANG_ObjC))
901901 addFlag(Buffer, dwarf::DW_AT_prototyped);
902
903 // Add a DW_AT_calling_convention if this has an explicit convention.
904 if (CTy->getCC() && CTy->getCC() != dwarf::DW_CC_normal)
905 addUInt(Buffer, dwarf::DW_AT_calling_convention, dwarf::DW_FORM_data1,
906 CTy->getCC());
902907
903908 if (CTy->isLValueReference())
904909 addFlag(Buffer, dwarf::DW_AT_reference);
12061211 Language == dwarf::DW_LANG_ObjC))
12071212 addFlag(SPDie, dwarf::DW_AT_prototyped);
12081213
1214 unsigned CC = 0;
12091215 DITypeRefArray Args;
1210 if (const DISubroutineType *SPTy = SP->getType())
1216 if (const DISubroutineType *SPTy = SP->getType()) {
12111217 Args = SPTy->getTypeArray();
1218 CC = SPTy->getCC();
1219 }
1220
1221 // Add a DW_AT_calling_convention if this has an explicit convention.
1222 if (CC && CC != dwarf::DW_CC_normal)
1223 addUInt(SPDie, dwarf::DW_AT_calling_convention, dwarf::DW_FORM_data1, CC);
12121224
12131225 // Add a return type. If this is a type like a C/C++ void type we don't add a
12141226 // return type.
16581658 Out << "!DISubroutineType(";
16591659 MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
16601660 Printer.printDIFlags("flags", N->getFlags());
1661 Printer.printDwarfEnum("cc", N->getCC(), dwarf::ConventionString);
16611662 Printer.printMetadata("types", N->getRawTypeArray(),
16621663 /* ShouldSkipNull */ false);
16631664 Out << ")";
419419 }
420420
421421 DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
422 unsigned Flags) {
423 return DISubroutineType::get(VMContext, Flags, ParameterTypes);
422 unsigned Flags, unsigned CC) {
423 return DISubroutineType::get(VMContext, Flags, CC, ParameterTypes);
424424 }
425425
426426 DICompositeType *DIBuilder::createExternalTypeRef(unsigned Tag, DIFile *File,
326326 }
327327
328328 DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context,
329 unsigned Flags, Metadata *TypeArray,
329 unsigned Flags, uint8_t CC,
330 Metadata *TypeArray,
330331 StorageType Storage,
331332 bool ShouldCreate) {
332 DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, TypeArray));
333 DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray));
333334 Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray};
334 DEFINE_GETIMPL_STORE(DISubroutineType, (Flags), Ops);
335 DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
335336 }
336337
337338 DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
483483
484484 template <> struct MDNodeKeyImpl {
485485 unsigned Flags;
486 uint8_t CC;
486487 Metadata *TypeArray;
487488
488 MDNodeKeyImpl(int64_t Flags, Metadata *TypeArray)
489 : Flags(Flags), TypeArray(TypeArray) {}
489 MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)
490 : Flags(Flags), CC(CC), TypeArray(TypeArray) {}
490491 MDNodeKeyImpl(const DISubroutineType *N)
491 : Flags(N->getFlags()), TypeArray(N->getRawTypeArray()) {}
492 : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {}
492493
493494 bool isKeyOf(const DISubroutineType *RHS) const {
494 return Flags == RHS->getFlags() && TypeArray == RHS->getRawTypeArray();
495 }
496 unsigned getHashValue() const { return hash_combine(Flags, TypeArray); }
495 return Flags == RHS->getFlags() && CC == RHS->getCC() &&
496 TypeArray == RHS->getRawTypeArray();
497 }
498 unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); }
497499 };
498500
499501 template <> struct MDNodeKeyImpl {
383383 return nullptr;
384384 }
385385
386 const char *llvm::dwarf::ConventionString(unsigned Convention) {
387 switch (Convention) {
388 case DW_CC_normal: return "DW_CC_normal";
389 case DW_CC_program: return "DW_CC_program";
390 case DW_CC_nocall: return "DW_CC_nocall";
391 case DW_CC_lo_user: return "DW_CC_lo_user";
392 case DW_CC_hi_user: return "DW_CC_hi_user";
393 case DW_CC_GNU_borland_fastcall_i386: return "DW_CC_GNU_borland_fastcall_i386";
394 case DW_CC_BORLAND_safecall: return "DW_CC_BORLAND_safecall";
395 case DW_CC_BORLAND_stdcall: return "DW_CC_BORLAND_stdcall";
396 case DW_CC_BORLAND_pascal: return "DW_CC_BORLAND_pascal";
397 case DW_CC_BORLAND_msfastcall: return "DW_CC_BORLAND_msfastcall";
398 case DW_CC_BORLAND_msreturn: return "DW_CC_BORLAND_msreturn";
399 case DW_CC_BORLAND_thiscall: return "DW_CC_BORLAND_thiscall";
400 case DW_CC_BORLAND_fastcall: return "DW_CC_BORLAND_fastcall";
401 }
402 return nullptr;
386 const char *llvm::dwarf::ConventionString(unsigned CC) {
387 switch (CC) {
388 default:
389 return nullptr;
390 #define HANDLE_DW_CC(ID, NAME) \
391 case DW_CC_##NAME: \
392 return "DW_CC_" #NAME;
393 #include "llvm/Support/Dwarf.def"
394 }
395 }
396
397 unsigned llvm::dwarf::getCallingConvention(StringRef CCString) {
398 return StringSwitch(CCString)
399 #define HANDLE_DW_CC(ID, NAME) .Case("DW_CC_" #NAME, DW_CC_##NAME)
400 #include "llvm/Support/Dwarf.def"
401 .Default(0);
403402 }
404403
405404 const char *llvm::dwarf::InlineCodeString(unsigned Code) {
0 ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
11 ; RUN: verify-uselistorder %s
22
3 ; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
4 !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
3 ; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12}
4 !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12}
55
66 !0 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
77 !1 = !{null}
2020
2121 ; CHECK: !8 = !DISubroutineType(types: null)
2222 !8 = !DISubroutineType(types: null)
23
24 ; CHECK: !9 = !DISubroutineType(cc: DW_CC_normal, types: null)
25 ; CHECK: !10 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: null)
26 ; CHECK: !11 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: null)
27 ; CHECK: !12 = !DISubroutineType(cc: DW_CC_LLVM_vectorcall, types: null)
28 !9 = !DISubroutineType(cc: DW_CC_normal, types: null)
29 !10 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: null)
30 !11 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: null)
31 !12 = !DISubroutineType(cc: DW_CC_LLVM_vectorcall, types: null)
0 ; RUN: llc < %s -filetype=obj -o - | llvm-readobj - -codeview | FileCheck %s
1
2 ; C++ source to regenerate:
3 ; $ cat t.cpp
4 ; struct A {
5 ; void thiscallcc();
6 ; };
7 ; void A::thiscallcc() {}
8 ; void cdeclcc() {}
9 ; void __fastcall fastcallcc() {}
10 ; void __stdcall stdcallcc() {}
11 ; void __vectorcall vectorcallcc() {}
12 ; $ clang -g -gcodeview t.cpp -emit-llvm -S -o t.ll -O1
13
14 ; CHECK: CodeViewTypes [
15 ; CHECK: Section: .debug$T (5)
16 ; CHECK: Magic: 0x4
17 ; CHECK: Struct (0x1000) {
18 ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
19 ; CHECK: MemberCount: 0
20 ; CHECK: Properties [ (0x80)
21 ; CHECK: ForwardReference (0x80)
22 ; CHECK: ]
23 ; CHECK: FieldList: 0x0
24 ; CHECK: DerivedFrom: 0x0
25 ; CHECK: VShape: 0x0
26 ; CHECK: SizeOf: 0
27 ; CHECK: Name: A
28 ; CHECK: }
29 ; CHECK: Pointer (0x1001) {
30 ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
31 ; CHECK: PointeeType: A (0x1000)
32 ; CHECK: PointerAttributes: 0x800A
33 ; CHECK: PtrType: Near32 (0xA)
34 ; CHECK: PtrMode: Pointer (0x0)
35 ; CHECK: IsFlat: 0
36 ; CHECK: IsConst: 0
37 ; CHECK: IsVolatile: 0
38 ; CHECK: IsUnaligned: 0
39 ; CHECK: }
40 ; CHECK: ArgList (0x1002) {
41 ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
42 ; CHECK: NumArgs: 1
43 ; CHECK: Arguments [
44 ; CHECK: ArgType: A* (0x1001)
45 ; CHECK: ]
46 ; CHECK: }
47 ; CHECK: Procedure (0x1003) {
48 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
49 ; CHECK: ReturnType: void (0x3)
50 ; CHECK: CallingConvention: ThisCall (0xB)
51 ; CHECK: FunctionOptions [ (0x0)
52 ; CHECK: ]
53 ; CHECK: NumParameters: 1
54 ; CHECK: ArgListType: (A*) (0x1002)
55 ; CHECK: }
56 ; CHECK: FuncId (0x1004) {
57 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
58 ; CHECK: ParentScope: 0x0
59 ; CHECK: FunctionType: void (A*) (0x1003)
60 ; CHECK: Name: A::thiscallcc
61 ; CHECK: }
62 ; CHECK: ArgList (0x1005) {
63 ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
64 ; CHECK: NumArgs: 0
65 ; CHECK: Arguments [
66 ; CHECK: ]
67 ; CHECK: }
68 ; CHECK: Procedure (0x1006) {
69 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
70 ; CHECK: ReturnType: void (0x3)
71 ; CHECK: CallingConvention: NearC (0x0)
72 ; CHECK: FunctionOptions [ (0x0)
73 ; CHECK: ]
74 ; CHECK: NumParameters: 0
75 ; CHECK: ArgListType: () (0x1005)
76 ; CHECK: }
77 ; CHECK: FuncId (0x1007) {
78 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
79 ; CHECK: ParentScope: 0x0
80 ; CHECK: FunctionType: void () (0x1006)
81 ; CHECK: Name: cdeclcc
82 ; CHECK: }
83 ; CHECK: Procedure (0x1008) {
84 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
85 ; CHECK: ReturnType: void (0x3)
86 ; CHECK: CallingConvention: NearFast (0x4)
87 ; CHECK: FunctionOptions [ (0x0)
88 ; CHECK: ]
89 ; CHECK: NumParameters: 0
90 ; CHECK: ArgListType: () (0x1005)
91 ; CHECK: }
92 ; CHECK: FuncId (0x1009) {
93 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
94 ; CHECK: ParentScope: 0x0
95 ; CHECK: FunctionType: void () (0x1008)
96 ; CHECK: Name: fastcallcc
97 ; CHECK: }
98 ; CHECK: Procedure (0x100A) {
99 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
100 ; CHECK: ReturnType: void (0x3)
101 ; CHECK: CallingConvention: NearStdCall (0x7)
102 ; CHECK: FunctionOptions [ (0x0)
103 ; CHECK: ]
104 ; CHECK: NumParameters: 0
105 ; CHECK: ArgListType: () (0x1005)
106 ; CHECK: }
107 ; CHECK: FuncId (0x100B) {
108 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
109 ; CHECK: ParentScope: 0x0
110 ; CHECK: FunctionType: void () (0x100A)
111 ; CHECK: Name: stdcallcc
112 ; CHECK: }
113 ; CHECK: Procedure (0x100C) {
114 ; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008)
115 ; CHECK: ReturnType: void (0x3)
116 ; CHECK: CallingConvention: NearVector (0x18)
117 ; CHECK: FunctionOptions [ (0x0)
118 ; CHECK: ]
119 ; CHECK: NumParameters: 0
120 ; CHECK: ArgListType: () (0x1005)
121 ; CHECK: }
122 ; CHECK: FuncId (0x100D) {
123 ; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601)
124 ; CHECK: ParentScope: 0x0
125 ; CHECK: FunctionType: void () (0x100C)
126 ; CHECK: Name: vectorcallcc
127 ; CHECK: }
128 ; CHECK: ]
129
130 ; ModuleID = 't.cpp'
131 source_filename = "t.cpp"
132 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
133 target triple = "i386-pc-windows-msvc19.0.23918"
134
135 %struct.A = type { i8 }
136
137 ; Function Attrs: nounwind readnone
138 define x86_thiscallcc void @"\01?thiscallcc@A@@QAEXXZ"(%struct.A* nocapture %this) #0 align 2 !dbg !6 {
139 entry:
140 tail call void @llvm.dbg.value(metadata %struct.A* %this, i64 0, metadata !14, metadata !16), !dbg !17
141 ret void, !dbg !18
142 }
143
144 ; Function Attrs: norecurse nounwind readnone
145 define void @"\01?cdeclcc@@YAXXZ"() #1 !dbg !19 {
146 entry:
147 ret void, !dbg !22
148 }
149
150 ; Function Attrs: norecurse nounwind readnone
151 define x86_fastcallcc void @"\01?fastcallcc@@YIXXZ"() #1 !dbg !23 {
152 entry:
153 ret void, !dbg !24
154 }
155
156 ; Function Attrs: norecurse nounwind readnone
157 define x86_stdcallcc void @"\01?stdcallcc@@YGXXZ"() #1 !dbg !25 {
158 entry:
159 ret void, !dbg !26
160 }
161
162 ; Function Attrs: norecurse nounwind readnone
163 define x86_vectorcallcc void @"\01?vectorcallcc@@YQXXZ"() #1 !dbg !27 {
164 entry:
165 ret void, !dbg !28
166 }
167
168 ; Function Attrs: nounwind readnone
169 declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
170
171 attributes #0 = { nounwind readnone "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"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
172 attributes #1 = { norecurse nounwind readnone "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"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
173 attributes #2 = { nounwind readnone }
174
175 !llvm.dbg.cu = !{!0}
176 !llvm.module.flags = !{!3, !4}
177 !llvm.ident = !{!5}
178
179 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 272067)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
180 !1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
181 !2 = !{}
182 !3 = !{i32 2, !"CodeView", i32 1}
183 !4 = !{i32 2, !"Debug Info Version", i32 3}
184 !5 = !{!"clang version 3.9.0 (trunk 272067)"}
185 !6 = distinct !DISubprogram(name: "A::thiscallcc", linkageName: "\01?thiscallcc@A@@QAEXXZ", scope: !7, file: !1, line: 4, type: !10, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: true, unit: !0, declaration: !9, variables: !13)
186 !7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 1, size: 8, align: 8, elements: !8)
187 !8 = !{!9}
188 !9 = !DISubprogram(name: "A::thiscallcc", linkageName: "\01?thiscallcc@A@@QAEXXZ", scope: !7, file: !1, line: 2, type: !10, isLocal: false, isDefinition: false, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true)
189 !10 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !11)
190 !11 = !{null, !12}
191 !12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
192 !13 = !{!14}
193 !14 = !DILocalVariable(name: "this", arg: 1, scope: !6, type: !15, flags: DIFlagArtificial | DIFlagObjectPointer)
194 !15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32)
195 !16 = !DIExpression()
196 !17 = !DILocation(line: 0, scope: !6)
197 !18 = !DILocation(line: 4, column: 23, scope: !6)
198 !19 = distinct !DISubprogram(name: "cdeclcc", linkageName: "\01?cdeclcc@@YAXXZ", scope: !1, file: !1, line: 5, type: !20, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
199 !21 = !{null}
200 !22 = !DILocation(line: 5, column: 17, scope: !19)
201 !23 = distinct !DISubprogram(name: "fastcallcc", linkageName: "\01?fastcallcc@@YIXXZ", scope: !1, file: !1, line: 6, type: !29, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
202 !24 = !DILocation(line: 6, column: 31, scope: !23)
203 !25 = distinct !DISubprogram(name: "stdcallcc", linkageName: "\01?stdcallcc@@YGXXZ", scope: !1, file: !1, line: 7, type: !30, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
204 !26 = !DILocation(line: 7, column: 29, scope: !25)
205 !27 = distinct !DISubprogram(name: "vectorcallcc", linkageName: "\01?vectorcallcc@@YQXXZ", scope: !1, file: !1, line: 8, type: !31, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
206 !28 = !DILocation(line: 8, column: 35, scope: !27)
207
208 !20 = !DISubroutineType(cc: DW_CC_normal, types: !21)
209 !29 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: !21)
210 !30 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: !21)
211 !31 = !DISubroutineType(cc: DW_CC_LLVM_vectorcall, types: !21)
0 ; RUN: llc < %s -filetype=obj -o %t
1 ; RUN: llvm-dwarfdump %t | FileCheck %s
2
3 ; C++ source to regenerate:
4 ; $ cat t.cpp
5 ; struct A {
6 ; void thiscallcc();
7 ; };
8 ; void A::thiscallcc() {}
9 ; void cdeclcc() {}
10 ; void __fastcall fastcallcc() {}
11 ; void __stdcall stdcallcc() {}
12 ; void __vectorcall vectorcallcc() {}
13 ; $ clang -g t.cpp -emit-llvm -S -o t.ll -O1
14
15 ; CHECK: .debug_abbrev contents:
16
17 ; CHECK: [[subroutine_abbrev:\[[0-9]+\]]] DW_TAG_subroutine_type DW_CHILDREN_yes
18 ; CHECK-NEXT: DW_AT_type DW_FORM_ref4
19 ; CHECK-NEXT: DW_AT_calling_convention DW_FORM_data1
20
21 ; CHECK: .debug_info contents:
22
23 ; CHECK: DW_TAG_subroutine_type [[subroutine_abbrev]] *
24 ; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] {{.*}}
25 ; CHECK-NEXT: DW_AT_calling_convention [DW_FORM_data1] (DW_CC_BORLAND_msfastcall)
26
27 ; CHECK: DW_TAG_subprogram [{{.*}}] *
28 ; CHECK: DW_AT_low_pc
29 ; CHECK: DW_AT_high_pc
30 ; CHECK: DW_AT_frame_base
31 ; CHECK: DW_AT_linkage_name
32 ; CHECK: DW_AT_name
33 ; CHECK: DW_AT_decl_file
34 ; CHECK: DW_AT_decl_line
35 ; CHECK: DW_AT_calling_convention [DW_FORM_data1] (DW_CC_BORLAND_msfastcall)
36 ; CHECK: DW_AT_type
37 ; CHECK: DW_AT_external
38
39 ; ModuleID = 't.cpp'
40 source_filename = "t.cpp"
41 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
42 target triple = "i386-pc-windows-msvc19.0.23918"
43
44 @"\01?fptr@@3P6IHHH@ZA" = global i32 (i32, i32)* @"\01?f@@YIHHH@Z", align 4
45
46 ; Function Attrs: nounwind readnone
47 define x86_fastcallcc i32 @"\01?f@@YIHHH@Z"(i32 inreg %a, i32 inreg %b) #0 !dbg !12 {
48 entry:
49 tail call void @llvm.dbg.value(metadata i32 %b, i64 0, metadata !14, metadata !16), !dbg !17
50 tail call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata !15, metadata !16), !dbg !18
51 %add = add nsw i32 %b, %a, !dbg !19
52 ret i32 %add, !dbg !20
53 }
54
55 ; Function Attrs: nounwind readnone
56 declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
57
58 attributes #0 = { nounwind readnone "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"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
59 attributes #1 = { nounwind readnone }
60
61 !llvm.dbg.cu = !{!0}
62 !llvm.module.flags = !{!9, !10}
63 !llvm.ident = !{!11}
64
65 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 272067)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
66 !1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
67 !2 = !{}
68 !3 = !{!4}
69 !4 = distinct !DIGlobalVariable(name: "fptr", linkageName: "\01?fptr@@3P6IHHH@ZA", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, variable: i32 (i32, i32)** @"\01?fptr@@3P6IHHH@ZA")
70 !5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 32, align: 32)
71 !6 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: !7)
72 !7 = !{!8, !8, !8}
73 !8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
74 !9 = !{i32 2, !"Dwarf Version", i32 4}
75 !10 = !{i32 2, !"Debug Info Version", i32 3}
76 !11 = !{!"clang version 3.9.0 (trunk 272067)"}
77 !12 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YIHHH@Z", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !13)
78 !13 = !{!14, !15}
79 !14 = !DILocalVariable(name: "b", arg: 2, scope: !12, file: !1, line: 1, type: !8)
80 !15 = !DILocalVariable(name: "a", arg: 1, scope: !12, file: !1, line: 1, type: !8)
81 !16 = !DIExpression()
82 !17 = !DILocation(line: 1, column: 29, scope: !12)
83 !18 = !DILocation(line: 1, column: 22, scope: !12)
84 !19 = !DILocation(line: 1, column: 43, scope: !12)
85 !20 = !DILocation(line: 1, column: 34, scope: !12)
7979
8080 MDTuple *getTuple() { return MDTuple::getDistinct(Context, None); }
8181 DISubroutineType *getSubroutineType() {
82 return DISubroutineType::getDistinct(Context, 0, getNode(nullptr));
82 return DISubroutineType::getDistinct(Context, 0, 0, getNode(nullptr));
8383 }
8484 DISubprogram *getSubprogram() {
8585 return DISubprogram::getDistinct(Context, nullptr, "", "", nullptr, 0,
968968 Metadata *TypesOps[] = {nullptr};
969969 Metadata *Types = MDTuple::get(Context, TypesOps);
970970
971 DIType *D = DISubroutineType::getDistinct(Context, 0u, Types);
971 DIType *D = DISubroutineType::getDistinct(Context, 0u, 0, Types);
972972 EXPECT_EQ(0u, D->getFlags());
973973 D->setFlags(DINode::FlagRValueReference);
974974 EXPECT_EQ(DINode::FlagRValueReference, D->getFlags());
975975 D->setFlags(0u);
976976 EXPECT_EQ(0u, D->getFlags());
977977
978 TempDIType T = DISubroutineType::getTemporary(Context, 0u, Types);
978 TempDIType T = DISubroutineType::getTemporary(Context, 0u, 0, Types);
979979 EXPECT_EQ(0u, T->getFlags());
980980 T->setFlags(DINode::FlagRValueReference);
981981 EXPECT_EQ(DINode::FlagRValueReference, T->getFlags());
12531253 unsigned Flags = 1;
12541254 MDTuple *TypeArray = getTuple();
12551255
1256 auto *N = DISubroutineType::get(Context, Flags, TypeArray);
1256 auto *N = DISubroutineType::get(Context, Flags, 0, TypeArray);
12571257 EXPECT_EQ(dwarf::DW_TAG_subroutine_type, N->getTag());
12581258 EXPECT_EQ(Flags, N->getFlags());
12591259 EXPECT_EQ(TypeArray, N->getTypeArray().get());
1260 EXPECT_EQ(N, DISubroutineType::get(Context, Flags, TypeArray));
1261
1262 EXPECT_NE(N, DISubroutineType::get(Context, Flags + 1, TypeArray));
1263 EXPECT_NE(N, DISubroutineType::get(Context, Flags, getTuple()));
1260 EXPECT_EQ(N, DISubroutineType::get(Context, Flags, 0, TypeArray));
1261
1262 EXPECT_NE(N, DISubroutineType::get(Context, Flags + 1, 0, TypeArray));
1263 EXPECT_NE(N, DISubroutineType::get(Context, Flags, 0, getTuple()));
1264
1265 // Test the hashing of calling conventions.
1266 auto *Fast = DISubroutineType::get(
1267 Context, Flags, dwarf::DW_CC_BORLAND_msfastcall, TypeArray);
1268 auto *Std = DISubroutineType::get(Context, Flags,
1269 dwarf::DW_CC_BORLAND_stdcall, TypeArray);
1270 EXPECT_EQ(Fast,
1271 DISubroutineType::get(Context, Flags,
1272 dwarf::DW_CC_BORLAND_msfastcall, TypeArray));
1273 EXPECT_EQ(Std, DISubroutineType::get(
1274 Context, Flags, dwarf::DW_CC_BORLAND_stdcall, TypeArray));
1275
1276 EXPECT_NE(N, Fast);
1277 EXPECT_NE(N, Std);
1278 EXPECT_NE(Fast, Std);
12641279
12651280 TempDISubroutineType Temp = N->clone();
12661281 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));