[llvm] r272197 - [DebugInfo] Add calling convention support for DWARF and CodeView

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 8 13:34:29 PDT 2016


Author: rnk
Date: Wed Jun  8 15:34:29 2016
New Revision: 272197

URL: http://llvm.org/viewvc/llvm-project?rev=272197&view=rev
Log:
[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

Added:
    llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll
    llvm/trunk/test/DebugInfo/X86/DW_AT_calling-convention.ll
Modified:
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/include/llvm/IR/DIBuilder.h
    llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
    llvm/trunk/include/llvm/Support/Dwarf.def
    llvm/trunk/include/llvm/Support/Dwarf.h
    llvm/trunk/lib/AsmParser/LLLexer.cpp
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLToken.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/trunk/lib/IR/AsmWriter.cpp
    llvm/trunk/lib/IR/DIBuilder.cpp
    llvm/trunk/lib/IR/DebugInfoMetadata.cpp
    llvm/trunk/lib/IR/LLVMContextImpl.h
    llvm/trunk/lib/Support/Dwarf.cpp
    llvm/trunk/test/Assembler/disubroutinetype.ll
    llvm/trunk/unittests/IR/MetadataTest.cpp

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Wed Jun  8 15:34:29 2016
@@ -243,7 +243,7 @@ enum MetadataCodes {
   METADATA_FILE = 16,            // [distinct, filename, directory]
   METADATA_DERIVED_TYPE = 17,    // [distinct, ...]
   METADATA_COMPOSITE_TYPE = 18,  // [distinct, ...]
-  METADATA_SUBROUTINE_TYPE = 19, // [distinct, flags, types]
+  METADATA_SUBROUTINE_TYPE = 19, // [distinct, flags, types, cc]
   METADATA_COMPILE_UNIT = 20,    // [distinct, ...]
   METADATA_SUBPROGRAM = 21,      // [distinct, ...]
   METADATA_LEXICAL_BLOCK = 22,   // [distinct, scope, file, line, column]

Modified: llvm/trunk/include/llvm/IR/DIBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DIBuilder.h?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DIBuilder.h (original)
+++ llvm/trunk/include/llvm/IR/DIBuilder.h Wed Jun  8 15:34:29 2016
@@ -374,8 +374,9 @@ namespace llvm {
     ///                        includes return type at 0th index.
     /// \param Flags           E.g.: LValueReference.
     ///                        These flags are used to emit dwarf attributes.
+    /// \param CC              Calling convention, e.g. dwarf::DW_CC_normal
     DISubroutineType *createSubroutineType(DITypeRefArray ParameterTypes,
-                                           unsigned Flags = 0);
+                                           unsigned Flags = 0, unsigned CC = 0);
 
     /// Create an external type reference.
     /// \param Tag              Dwarf TAG.

Modified: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoMetadata.h?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h (original)
+++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h Wed Jun  8 15:34:29 2016
@@ -920,35 +920,44 @@ class DISubroutineType : public DIType {
   friend class LLVMContextImpl;
   friend class MDNode;
 
+  /// The calling convention used with DW_AT_calling_convention. Actually of
+  /// type dwarf::CallingConvention.
+  uint8_t CC;
+
   DISubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags,
-                   ArrayRef<Metadata *> Ops)
+                   uint8_t CC, ArrayRef<Metadata *> Ops)
       : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type,
-               0, 0, 0, 0, Flags, Ops) {}
+               0, 0, 0, 0, Flags, Ops),
+        CC(CC) {}
   ~DISubroutineType() = default;
 
   static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
-                                   DITypeRefArray TypeArray,
+                                   uint8_t CC, DITypeRefArray TypeArray,
                                    StorageType Storage,
                                    bool ShouldCreate = true) {
-    return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate);
+    return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate);
   }
   static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
-                                   Metadata *TypeArray, StorageType Storage,
+                                   uint8_t CC, Metadata *TypeArray,
+                                   StorageType Storage,
                                    bool ShouldCreate = true);
 
   TempDISubroutineType cloneImpl() const {
-    return getTemporary(getContext(), getFlags(), getTypeArray());
+    return getTemporary(getContext(), getFlags(), getCC(), getTypeArray());
   }
 
 public:
   DEFINE_MDNODE_GET(DISubroutineType,
-                    (unsigned Flags, DITypeRefArray TypeArray),
-                    (Flags, TypeArray))
-  DEFINE_MDNODE_GET(DISubroutineType, (unsigned Flags, Metadata *TypeArray),
-                    (Flags, TypeArray))
+                    (unsigned Flags, uint8_t CC, DITypeRefArray TypeArray),
+                    (Flags, CC, TypeArray))
+  DEFINE_MDNODE_GET(DISubroutineType,
+                    (unsigned Flags, uint8_t CC, Metadata *TypeArray),
+                    (Flags, CC, TypeArray))
 
   TempDISubroutineType clone() const { return cloneImpl(); }
 
+  uint8_t getCC() const { return CC; }
+
   DITypeRefArray getTypeArray() const {
     return cast_or_null<MDTuple>(getRawTypeArray());
   }

Modified: llvm/trunk/include/llvm/Support/Dwarf.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Dwarf.def?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Dwarf.def (original)
+++ llvm/trunk/include/llvm/Support/Dwarf.def Wed Jun  8 15:34:29 2016
@@ -14,7 +14,7 @@
 // TODO: Add other DW-based macros.
 #if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP ||                         \
       defined HANDLE_DW_LANG || defined HANDLE_DW_ATE ||                       \
-      defined HANDLE_DW_VIRTUALITY)
+      defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_CC)
 #error "Missing macro definition of HANDLE_DW*"
 #endif
 
@@ -38,6 +38,11 @@
 #define HANDLE_DW_VIRTUALITY(ID, NAME)
 #endif
 
+#ifndef HANDLE_DW_CC
+#define HANDLE_DW_CC(ID, NAME)
+#endif
+
+
 HANDLE_DW_TAG(0x0001, array_type)
 HANDLE_DW_TAG(0x0002, class_type)
 HANDLE_DW_TAG(0x0003, entry_point)
@@ -346,8 +351,23 @@ HANDLE_DW_VIRTUALITY(0x00, none)
 HANDLE_DW_VIRTUALITY(0x01, virtual)
 HANDLE_DW_VIRTUALITY(0x02, pure_virtual)
 
+// DWARF calling convention codes.
+HANDLE_DW_CC(0x01, normal)
+HANDLE_DW_CC(0x02, program)
+HANDLE_DW_CC(0x03, nocall)
+HANDLE_DW_CC(0x41, GNU_borland_fastcall_i386)
+HANDLE_DW_CC(0xb0, BORLAND_safecall)
+HANDLE_DW_CC(0xb1, BORLAND_stdcall)
+HANDLE_DW_CC(0xb2, BORLAND_pascal)
+HANDLE_DW_CC(0xb3, BORLAND_msfastcall)
+HANDLE_DW_CC(0xb4, BORLAND_msreturn)
+HANDLE_DW_CC(0xb5, BORLAND_thiscall)
+HANDLE_DW_CC(0xb6, BORLAND_fastcall)
+HANDLE_DW_CC(0xc0, LLVM_vectorcall)
+
 #undef HANDLE_DW_TAG
 #undef HANDLE_DW_OP
 #undef HANDLE_DW_LANG
 #undef HANDLE_DW_ATE
 #undef HANDLE_DW_VIRTUALITY
+#undef HANDLE_DW_CC

Modified: llvm/trunk/include/llvm/Support/Dwarf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Dwarf.h?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Dwarf.h (original)
+++ llvm/trunk/include/llvm/Support/Dwarf.h Wed Jun  8 15:34:29 2016
@@ -389,18 +389,9 @@ enum CaseSensitivity {
 
 enum CallingConvention {
   // Calling convention codes
-  DW_CC_normal = 0x01,
-  DW_CC_program = 0x02,
-  DW_CC_nocall = 0x03,
+#define HANDLE_DW_CC(ID, NAME) DW_CC_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
   DW_CC_lo_user = 0x40,
-  DW_CC_GNU_borland_fastcall_i386 = 0x41,
-  DW_CC_BORLAND_safecall = 0xb0,
-  DW_CC_BORLAND_stdcall = 0xb1,
-  DW_CC_BORLAND_pascal = 0xb2,
-  DW_CC_BORLAND_msfastcall = 0xb3,
-  DW_CC_BORLAND_msreturn = 0xb4,
-  DW_CC_BORLAND_thiscall = 0xb5,
-  DW_CC_BORLAND_fastcall = 0xb6,
   DW_CC_hi_user = 0xff
 };
 
@@ -652,6 +643,7 @@ unsigned getTag(StringRef TagString);
 unsigned getOperationEncoding(StringRef OperationEncodingString);
 unsigned getVirtuality(StringRef VirtualityString);
 unsigned getLanguage(StringRef LanguageString);
+unsigned getCallingConvention(StringRef LanguageString);
 unsigned getAttributeEncoding(StringRef EncodingString);
 unsigned getMacinfo(StringRef MacinfoString);
 /// @}

Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Wed Jun  8 15:34:29 2016
@@ -793,6 +793,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   DWKEYWORD(ATE, DwarfAttEncoding);
   DWKEYWORD(VIRTUALITY, DwarfVirtuality);
   DWKEYWORD(LANG, DwarfLang);
+  DWKEYWORD(CC, DwarfCC);
   DWKEYWORD(OP, DwarfOp);
   DWKEYWORD(MACINFO, DwarfMacinfo);
 #undef DWKEYWORD

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Wed Jun  8 15:34:29 2016
@@ -3341,6 +3341,9 @@ struct DwarfVirtualityField : public MDU
 struct DwarfLangField : public MDUnsignedField {
   DwarfLangField() : MDUnsignedField(0, dwarf::DW_LANG_hi_user) {}
 };
+struct DwarfCCField : public MDUnsignedField {
+  DwarfCCField() : MDUnsignedField(0, dwarf::DW_CC_hi_user) {}
+};
 struct EmissionKindField : public MDUnsignedField {
   EmissionKindField() : MDUnsignedField(0, DICompileUnit::LastEmissionKind) {}
 };
@@ -3484,6 +3487,24 @@ bool LLParser::ParseMDField(LocTy Loc, S
 }
 
 template <>
+bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfCCField &Result) {
+  if (Lex.getKind() == lltok::APSInt)
+    return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result));
+
+  if (Lex.getKind() != lltok::DwarfCC)
+    return TokError("expected DWARF calling convention");
+
+  unsigned CC = dwarf::getCallingConvention(Lex.getStrVal());
+  if (!CC)
+    return TokError("invalid DWARF calling convention" + Twine(" '") + Lex.getStrVal() +
+                    "'");
+  assert(CC <= Result.Max && "Expected valid DWARF calling convention");
+  Result.assign(CC);
+  Lex.Lex();
+  return false;
+}
+
+template <>
 bool LLParser::ParseMDField(LocTy Loc, StringRef Name, EmissionKindField &Result) {
   if (Lex.getKind() == lltok::APSInt)
     return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result));
@@ -3863,11 +3884,13 @@ bool LLParser::ParseDICompositeType(MDNo
 bool LLParser::ParseDISubroutineType(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   OPTIONAL(flags, DIFlagField, );                                              \
+  OPTIONAL(cc, DwarfCCField, );                                                \
   REQUIRED(types, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
-  Result = GET_OR_DISTINCT(DISubroutineType, (Context, flags.Val, types.Val));
+  Result = GET_OR_DISTINCT(DISubroutineType,
+                           (Context, flags.Val, cc.Val, types.Val));
   return false;
 }
 

Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Wed Jun  8 15:34:29 2016
@@ -344,6 +344,7 @@ enum Kind {
   DwarfAttEncoding, // DW_ATE_foo
   DwarfVirtuality,  // DW_VIRTUALITY_foo
   DwarfLang,        // DW_LANG_foo
+  DwarfCC,          // DW_CC_foo
   EmissionKind,     // lineTablesOnly
   DwarfOp,          // DW_OP_foo
   DIFlag,           // DIFlagFoo

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Wed Jun  8 15:34:29 2016
@@ -2409,17 +2409,18 @@ std::error_code BitcodeReader::parseMeta
       break;
     }
     case bitc::METADATA_SUBROUTINE_TYPE: {
-      if (Record.size() != 3)
+      if (Record.size() < 3 || Record.size() > 4)
         return error("Invalid record");
+      bool IsOldTypeRefArray = Record[0] < 2;
+      unsigned CC = (Record.size() > 3) ? Record[3] : 0;
 
       IsDistinct = Record[0] & 0x1;
-      bool IsOldTypeRefArray = Record[0] < 2;
       Metadata *Types = getMDOrNull(Record[2]);
       if (LLVM_UNLIKELY(IsOldTypeRefArray))
         Types = MetadataList.upgradeTypeRefArray(Types);
 
       MetadataList.assignValue(
-          GET_OR_DISTINCT(DISubroutineType, (Context, Record[1], Types)),
+          GET_OR_DISTINCT(DISubroutineType, (Context, Record[1], CC, Types)),
           NextMetadataNo++);
       break;
     }

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Wed Jun  8 15:34:29 2016
@@ -1467,6 +1467,7 @@ void ModuleBitcodeWriter::writeDISubrout
   Record.push_back(HasNoOldTypeRefs | (unsigned)N->isDistinct());
   Record.push_back(N->getFlags());
   Record.push_back(VE.getMetadataOrNullID(N->getTypeArray().get()));
+  Record.push_back(N->getCC());
 
   Stream.EmitRecord(bitc::METADATA_SUBROUTINE_TYPE, Record, Abbrev);
   Record.clear();

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Wed Jun  8 15:34:29 2016
@@ -926,6 +926,20 @@ TypeIndex CodeViewDebug::lowerTypeMember
   return TypeTable.writePointer(PR);
 }
 
+/// Given a DWARF calling convention, get the CodeView equivalent. If we don't
+/// have a translation, use the NearC convention.
+static CallingConvention dwarfCCToCodeView(unsigned DwarfCC) {
+  switch (DwarfCC) {
+  case dwarf::DW_CC_normal:             return CallingConvention::NearC;
+  case dwarf::DW_CC_BORLAND_msfastcall: return CallingConvention::NearFast;
+  case dwarf::DW_CC_BORLAND_thiscall:   return CallingConvention::ThisCall;
+  case dwarf::DW_CC_BORLAND_stdcall:    return CallingConvention::NearStdCall;
+  case dwarf::DW_CC_BORLAND_pascal:     return CallingConvention::NearPascal;
+  case dwarf::DW_CC_LLVM_vectorcall:    return CallingConvention::NearVector;
+  }
+  return CallingConvention::NearC;
+}
+
 TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
   ModifierOptions Mods = ModifierOptions::None;
   bool IsModifier = true;
@@ -967,13 +981,12 @@ TypeIndex CodeViewDebug::lowerTypeFuncti
   ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
   TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
 
-  // TODO: We should use DW_AT_calling_convention to determine what CC this
-  // procedure record should have.
+  CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
+
   // TODO: Some functions are member functions, we should use a more appropriate
   // record for those.
-  ProcedureRecord Procedure(ReturnTypeIndex, CallingConvention::NearC,
-                            FunctionOptions::None, ArgTypeIndices.size(),
-                            ArgListIndex);
+  ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None,
+                            ArgTypeIndices.size(), ArgListIndex);
   return TypeTable.writeProcedure(Procedure);
 }
 

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Wed Jun  8 15:34:29 2016
@@ -901,6 +901,11 @@ void DwarfUnit::constructTypeDIE(DIE &Bu
        Language == dwarf::DW_LANG_ObjC))
     addFlag(Buffer, dwarf::DW_AT_prototyped);
 
+  // Add a DW_AT_calling_convention if this has an explicit convention.
+  if (CTy->getCC() && CTy->getCC() != dwarf::DW_CC_normal)
+    addUInt(Buffer, dwarf::DW_AT_calling_convention, dwarf::DW_FORM_data1,
+            CTy->getCC());
+
   if (CTy->isLValueReference())
     addFlag(Buffer, dwarf::DW_AT_reference);
 
@@ -1207,9 +1212,16 @@ void DwarfUnit::applySubprogramAttribute
        Language == dwarf::DW_LANG_ObjC))
     addFlag(SPDie, dwarf::DW_AT_prototyped);
 
+  unsigned CC = 0;
   DITypeRefArray Args;
-  if (const DISubroutineType *SPTy = SP->getType())
+  if (const DISubroutineType *SPTy = SP->getType()) {
     Args = SPTy->getTypeArray();
+    CC = SPTy->getCC();
+  }
+
+  // Add a DW_AT_calling_convention if this has an explicit convention.
+  if (CC && CC != dwarf::DW_CC_normal)
+    addUInt(SPDie, dwarf::DW_AT_calling_convention, dwarf::DW_FORM_data1, CC);
 
   // Add a return type. If this is a type like a C/C++ void type we don't add a
   // return type.

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Wed Jun  8 15:34:29 2016
@@ -1659,6 +1659,7 @@ static void writeDISubroutineType(raw_os
   Out << "!DISubroutineType(";
   MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
   Printer.printDIFlags("flags", N->getFlags());
+  Printer.printDwarfEnum("cc", N->getCC(), dwarf::ConventionString);
   Printer.printMetadata("types", N->getRawTypeArray(),
                         /* ShouldSkipNull */ false);
   Out << ")";

Modified: llvm/trunk/lib/IR/DIBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DIBuilder.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DIBuilder.cpp (original)
+++ llvm/trunk/lib/IR/DIBuilder.cpp Wed Jun  8 15:34:29 2016
@@ -420,8 +420,8 @@ DICompositeType *DIBuilder::createUnionT
 }
 
 DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
-                                                  unsigned Flags) {
-  return DISubroutineType::get(VMContext, Flags, ParameterTypes);
+                                                  unsigned Flags, unsigned CC) {
+  return DISubroutineType::get(VMContext, Flags, CC, ParameterTypes);
 }
 
 DICompositeType *DIBuilder::createExternalTypeRef(unsigned Tag, DIFile *File,

Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)
+++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Wed Jun  8 15:34:29 2016
@@ -327,12 +327,13 @@ DICompositeType *DICompositeType::getODR
 }
 
 DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context,
-                                            unsigned Flags, Metadata *TypeArray,
+                                            unsigned Flags, uint8_t CC,
+                                            Metadata *TypeArray,
                                             StorageType Storage,
                                             bool ShouldCreate) {
-  DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, TypeArray));
+  DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray));
   Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray};
-  DEFINE_GETIMPL_STORE(DISubroutineType, (Flags), Ops);
+  DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
 }
 
 DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,

Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.h Wed Jun  8 15:34:29 2016
@@ -484,17 +484,19 @@ template <> struct MDNodeKeyImpl<DICompo
 
 template <> struct MDNodeKeyImpl<DISubroutineType> {
   unsigned Flags;
+  uint8_t CC;
   Metadata *TypeArray;
 
-  MDNodeKeyImpl(int64_t Flags, Metadata *TypeArray)
-      : Flags(Flags), TypeArray(TypeArray) {}
+  MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)
+      : Flags(Flags), CC(CC), TypeArray(TypeArray) {}
   MDNodeKeyImpl(const DISubroutineType *N)
-      : Flags(N->getFlags()), TypeArray(N->getRawTypeArray()) {}
+      : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {}
 
   bool isKeyOf(const DISubroutineType *RHS) const {
-    return Flags == RHS->getFlags() && TypeArray == RHS->getRawTypeArray();
+    return Flags == RHS->getFlags() && CC == RHS->getCC() &&
+           TypeArray == RHS->getRawTypeArray();
   }
-  unsigned getHashValue() const { return hash_combine(Flags, TypeArray); }
+  unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); }
 };
 
 template <> struct MDNodeKeyImpl<DIFile> {

Modified: llvm/trunk/lib/Support/Dwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Dwarf.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Dwarf.cpp (original)
+++ llvm/trunk/lib/Support/Dwarf.cpp Wed Jun  8 15:34:29 2016
@@ -384,23 +384,22 @@ const char *llvm::dwarf::CaseString(unsi
   return nullptr;
 }
 
-const char *llvm::dwarf::ConventionString(unsigned Convention) {
-   switch (Convention) {
-   case DW_CC_normal:                     return "DW_CC_normal";
-   case DW_CC_program:                    return "DW_CC_program";
-   case DW_CC_nocall:                     return "DW_CC_nocall";
-   case DW_CC_lo_user:                    return "DW_CC_lo_user";
-   case DW_CC_hi_user:                    return "DW_CC_hi_user";
-   case DW_CC_GNU_borland_fastcall_i386:  return "DW_CC_GNU_borland_fastcall_i386";
-   case DW_CC_BORLAND_safecall:           return "DW_CC_BORLAND_safecall";
-   case DW_CC_BORLAND_stdcall:            return "DW_CC_BORLAND_stdcall";
-   case DW_CC_BORLAND_pascal:             return "DW_CC_BORLAND_pascal";
-   case DW_CC_BORLAND_msfastcall:         return "DW_CC_BORLAND_msfastcall";
-   case DW_CC_BORLAND_msreturn:           return "DW_CC_BORLAND_msreturn";
-   case DW_CC_BORLAND_thiscall:           return "DW_CC_BORLAND_thiscall";
-   case DW_CC_BORLAND_fastcall:           return "DW_CC_BORLAND_fastcall";
+const char *llvm::dwarf::ConventionString(unsigned CC) {
+  switch (CC) {
+  default:
+    return nullptr;
+#define HANDLE_DW_CC(ID, NAME)                                               \
+  case DW_CC_##NAME:                                                         \
+    return "DW_CC_" #NAME;
+#include "llvm/Support/Dwarf.def"
   }
-  return nullptr;
+}
+
+unsigned llvm::dwarf::getCallingConvention(StringRef CCString) {
+  return StringSwitch<unsigned>(CCString)
+#define HANDLE_DW_CC(ID, NAME) .Case("DW_CC_" #NAME, DW_CC_##NAME)
+#include "llvm/Support/Dwarf.def"
+      .Default(0);
 }
 
 const char *llvm::dwarf::InlineCodeString(unsigned Code) {

Modified: llvm/trunk/test/Assembler/disubroutinetype.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/disubroutinetype.ll?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/test/Assembler/disubroutinetype.ll (original)
+++ llvm/trunk/test/Assembler/disubroutinetype.ll Wed Jun  8 15:34:29 2016
@@ -1,8 +1,8 @@
 ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
 ; RUN: verify-uselistorder %s
 
-; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
-!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
+; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12}
+!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12}
 
 !0 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
 !1 = !{null}
@@ -21,3 +21,12 @@
 
 ; CHECK: !8 = !DISubroutineType(types: null)
 !8 = !DISubroutineType(types: null)
+
+; CHECK: !9 = !DISubroutineType(cc: DW_CC_normal, types: null)
+; CHECK: !10 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: null)
+; CHECK: !11 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: null)
+; CHECK: !12 = !DISubroutineType(cc: DW_CC_LLVM_vectorcall, types: null)
+!9 = !DISubroutineType(cc: DW_CC_normal, types: null)
+!10 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: null)
+!11 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: null)
+!12 = !DISubroutineType(cc: DW_CC_LLVM_vectorcall, types: null)

Added: llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll?rev=272197&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll (added)
+++ llvm/trunk/test/DebugInfo/COFF/types-calling-conv.ll Wed Jun  8 15:34:29 2016
@@ -0,0 +1,212 @@
+; RUN: llc < %s -filetype=obj -o - | llvm-readobj - -codeview | FileCheck %s
+
+; C++ source to regenerate:
+; $ cat t.cpp
+; struct A {
+;   void thiscallcc();
+; };
+; void A::thiscallcc() {}
+; void cdeclcc() {}
+; void __fastcall fastcallcc() {}
+; void __stdcall stdcallcc() {}
+; void __vectorcall vectorcallcc() {}
+; $ clang -g -gcodeview t.cpp -emit-llvm -S -o t.ll -O1
+
+; CHECK: CodeViewTypes [
+; CHECK:   Section: .debug$T (5)
+; CHECK:   Magic: 0x4
+; CHECK:   Struct (0x1000) {
+; 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: A
+; CHECK:   }
+; CHECK:   Pointer (0x1001) {
+; CHECK:     TypeLeafKind: LF_POINTER (0x1002)
+; CHECK:     PointeeType: A (0x1000)
+; CHECK:     PointerAttributes: 0x800A
+; CHECK:     PtrType: Near32 (0xA)
+; CHECK:     PtrMode: Pointer (0x0)
+; CHECK:     IsFlat: 0
+; CHECK:     IsConst: 0
+; CHECK:     IsVolatile: 0
+; CHECK:     IsUnaligned: 0
+; CHECK:   }
+; CHECK:   ArgList (0x1002) {
+; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
+; CHECK:     NumArgs: 1
+; CHECK:     Arguments [
+; CHECK:       ArgType: A* (0x1001)
+; CHECK:     ]
+; CHECK:   }
+; CHECK:   Procedure (0x1003) {
+; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     CallingConvention: ThisCall (0xB)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 1
+; CHECK:     ArgListType: (A*) (0x1002)
+; CHECK:   }
+; CHECK:   FuncId (0x1004) {
+; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
+; CHECK:     ParentScope: 0x0
+; CHECK:     FunctionType: void (A*) (0x1003)
+; CHECK:     Name: A::thiscallcc
+; CHECK:   }
+; CHECK:   ArgList (0x1005) {
+; CHECK:     TypeLeafKind: LF_ARGLIST (0x1201)
+; CHECK:     NumArgs: 0
+; CHECK:     Arguments [
+; CHECK:     ]
+; CHECK:   }
+; CHECK:   Procedure (0x1006) {
+; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     CallingConvention: NearC (0x0)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1005)
+; CHECK:   }
+; CHECK:   FuncId (0x1007) {
+; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
+; CHECK:     ParentScope: 0x0
+; CHECK:     FunctionType: void () (0x1006)
+; CHECK:     Name: cdeclcc
+; CHECK:   }
+; CHECK:   Procedure (0x1008) {
+; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     CallingConvention: NearFast (0x4)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1005)
+; CHECK:   }
+; CHECK:   FuncId (0x1009) {
+; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
+; CHECK:     ParentScope: 0x0
+; CHECK:     FunctionType: void () (0x1008)
+; CHECK:     Name: fastcallcc
+; CHECK:   }
+; CHECK:   Procedure (0x100A) {
+; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     CallingConvention: NearStdCall (0x7)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1005)
+; CHECK:   }
+; CHECK:   FuncId (0x100B) {
+; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
+; CHECK:     ParentScope: 0x0
+; CHECK:     FunctionType: void () (0x100A)
+; CHECK:     Name: stdcallcc
+; CHECK:   }
+; CHECK:   Procedure (0x100C) {
+; CHECK:     TypeLeafKind: LF_PROCEDURE (0x1008)
+; CHECK:     ReturnType: void (0x3)
+; CHECK:     CallingConvention: NearVector (0x18)
+; CHECK:     FunctionOptions [ (0x0)
+; CHECK:     ]
+; CHECK:     NumParameters: 0
+; CHECK:     ArgListType: () (0x1005)
+; CHECK:   }
+; CHECK:   FuncId (0x100D) {
+; CHECK:     TypeLeafKind: LF_FUNC_ID (0x1601)
+; CHECK:     ParentScope: 0x0
+; CHECK:     FunctionType: void () (0x100C)
+; CHECK:     Name: vectorcallcc
+; CHECK:   }
+; CHECK: ]
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.0.23918"
+
+%struct.A = type { i8 }
+
+; Function Attrs: nounwind readnone
+define x86_thiscallcc void @"\01?thiscallcc at A@@QAEXXZ"(%struct.A* nocapture %this) #0 align 2 !dbg !6 {
+entry:
+  tail call void @llvm.dbg.value(metadata %struct.A* %this, i64 0, metadata !14, metadata !16), !dbg !17
+  ret void, !dbg !18
+}
+
+; Function Attrs: norecurse nounwind readnone
+define void @"\01?cdeclcc@@YAXXZ"() #1 !dbg !19 {
+entry:
+  ret void, !dbg !22
+}
+
+; Function Attrs: norecurse nounwind readnone
+define x86_fastcallcc void @"\01?fastcallcc@@YIXXZ"() #1 !dbg !23 {
+entry:
+  ret void, !dbg !24
+}
+
+; Function Attrs: norecurse nounwind readnone
+define x86_stdcallcc void @"\01?stdcallcc@@YGXXZ"() #1 !dbg !25 {
+entry:
+  ret void, !dbg !26
+}
+
+; Function Attrs: norecurse nounwind readnone
+define x86_vectorcallcc void @"\01?vectorcallcc@@YQXXZ"() #1 !dbg !27 {
+entry:
+  ret void, !dbg !28
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
+
+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" }
+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" }
+attributes #2 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!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)
+!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
+!2 = !{}
+!3 = !{i32 2, !"CodeView", i32 1}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{!"clang version 3.9.0 (trunk 272067)"}
+!6 = distinct !DISubprogram(name: "A::thiscallcc", linkageName: "\01?thiscallcc at 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)
+!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 1, size: 8, align: 8, elements: !8)
+!8 = !{!9}
+!9 = !DISubprogram(name: "A::thiscallcc", linkageName: "\01?thiscallcc at A@@QAEXXZ", scope: !7, file: !1, line: 2, type: !10, isLocal: false, isDefinition: false, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true)
+!10 = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: !11)
+!11 = !{null, !12}
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
+!13 = !{!14}
+!14 = !DILocalVariable(name: "this", arg: 1, scope: !6, type: !15, flags: DIFlagArtificial | DIFlagObjectPointer)
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32)
+!16 = !DIExpression()
+!17 = !DILocation(line: 0, scope: !6)
+!18 = !DILocation(line: 4, column: 23, scope: !6)
+!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)
+!21 = !{null}
+!22 = !DILocation(line: 5, column: 17, scope: !19)
+!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)
+!24 = !DILocation(line: 6, column: 31, scope: !23)
+!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)
+!26 = !DILocation(line: 7, column: 29, scope: !25)
+!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)
+!28 = !DILocation(line: 8, column: 35, scope: !27)
+
+!20 = !DISubroutineType(cc: DW_CC_normal, types: !21)
+!29 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: !21)
+!30 = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: !21)
+!31 = !DISubroutineType(cc: DW_CC_LLVM_vectorcall, types: !21)

Added: llvm/trunk/test/DebugInfo/X86/DW_AT_calling-convention.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/DW_AT_calling-convention.ll?rev=272197&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/DW_AT_calling-convention.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/DW_AT_calling-convention.ll Wed Jun  8 15:34:29 2016
@@ -0,0 +1,86 @@
+; RUN: llc < %s -filetype=obj -o %t
+; RUN: llvm-dwarfdump %t | FileCheck %s
+
+; C++ source to regenerate:
+; $ cat t.cpp
+; struct A {
+;   void thiscallcc();
+; };
+; void A::thiscallcc() {}
+; void cdeclcc() {}
+; void __fastcall fastcallcc() {}
+; void __stdcall stdcallcc() {}
+; void __vectorcall vectorcallcc() {}
+; $ clang -g t.cpp -emit-llvm -S -o t.ll -O1
+
+; CHECK: .debug_abbrev contents:
+
+; CHECK: [[subroutine_abbrev:\[[0-9]+\]]] DW_TAG_subroutine_type      DW_CHILDREN_yes
+; CHECK-NEXT:         DW_AT_type      DW_FORM_ref4
+; CHECK-NEXT:         DW_AT_calling_convention        DW_FORM_data1
+
+; CHECK: .debug_info contents:
+
+; CHECK:  DW_TAG_subroutine_type [[subroutine_abbrev]] *
+; CHECK-NEXT:         DW_AT_type [DW_FORM_ref4]       {{.*}}
+; CHECK-NEXT:         DW_AT_calling_convention [DW_FORM_data1]        (DW_CC_BORLAND_msfastcall)
+
+; CHECK: DW_TAG_subprogram [{{.*}}] *
+; CHECK:                 DW_AT_low_pc
+; CHECK:                 DW_AT_high_pc
+; CHECK:                 DW_AT_frame_base
+; CHECK:                 DW_AT_linkage_name
+; CHECK:                 DW_AT_name
+; CHECK:                 DW_AT_decl_file
+; CHECK:                 DW_AT_decl_line
+; CHECK:                 DW_AT_calling_convention [DW_FORM_data1]        (DW_CC_BORLAND_msfastcall)
+; CHECK:                 DW_AT_type
+; CHECK:                 DW_AT_external
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.0.23918"
+
+@"\01?fptr@@3P6IHHH at ZA" = global i32 (i32, i32)* @"\01?f@@YIHHH at Z", align 4
+
+; Function Attrs: nounwind readnone
+define x86_fastcallcc i32 @"\01?f@@YIHHH at Z"(i32 inreg %a, i32 inreg %b) #0 !dbg !12 {
+entry:
+  tail call void @llvm.dbg.value(metadata i32 %b, i64 0, metadata !14, metadata !16), !dbg !17
+  tail call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata !15, metadata !16), !dbg !18
+  %add = add nsw i32 %b, %a, !dbg !19
+  ret i32 %add, !dbg !20
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
+
+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" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10}
+!llvm.ident = !{!11}
+
+!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)
+!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
+!2 = !{}
+!3 = !{!4}
+!4 = distinct !DIGlobalVariable(name: "fptr", linkageName: "\01?fptr@@3P6IHHH at ZA", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, variable: i32 (i32, i32)** @"\01?fptr@@3P6IHHH at ZA")
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 32, align: 32)
+!6 = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: !7)
+!7 = !{!8, !8, !8}
+!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!9 = !{i32 2, !"Dwarf Version", i32 4}
+!10 = !{i32 2, !"Debug Info Version", i32 3}
+!11 = !{!"clang version 3.9.0 (trunk 272067)"}
+!12 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YIHHH at Z", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !13)
+!13 = !{!14, !15}
+!14 = !DILocalVariable(name: "b", arg: 2, scope: !12, file: !1, line: 1, type: !8)
+!15 = !DILocalVariable(name: "a", arg: 1, scope: !12, file: !1, line: 1, type: !8)
+!16 = !DIExpression()
+!17 = !DILocation(line: 1, column: 29, scope: !12)
+!18 = !DILocation(line: 1, column: 22, scope: !12)
+!19 = !DILocation(line: 1, column: 43, scope: !12)
+!20 = !DILocation(line: 1, column: 34, scope: !12)

Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=272197&r1=272196&r2=272197&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Wed Jun  8 15:34:29 2016
@@ -80,7 +80,7 @@ protected:
 
   MDTuple *getTuple() { return MDTuple::getDistinct(Context, None); }
   DISubroutineType *getSubroutineType() {
-    return DISubroutineType::getDistinct(Context, 0, getNode(nullptr));
+    return DISubroutineType::getDistinct(Context, 0, 0, getNode(nullptr));
   }
   DISubprogram *getSubprogram() {
     return DISubprogram::getDistinct(Context, nullptr, "", "", nullptr, 0,
@@ -969,14 +969,14 @@ TEST_F(DITypeTest, setFlags) {
   Metadata *TypesOps[] = {nullptr};
   Metadata *Types = MDTuple::get(Context, TypesOps);
 
-  DIType *D = DISubroutineType::getDistinct(Context, 0u, Types);
+  DIType *D = DISubroutineType::getDistinct(Context, 0u, 0, Types);
   EXPECT_EQ(0u, D->getFlags());
   D->setFlags(DINode::FlagRValueReference);
   EXPECT_EQ(DINode::FlagRValueReference, D->getFlags());
   D->setFlags(0u);
   EXPECT_EQ(0u, D->getFlags());
 
-  TempDIType T = DISubroutineType::getTemporary(Context, 0u, Types);
+  TempDIType T = DISubroutineType::getTemporary(Context, 0u, 0, Types);
   EXPECT_EQ(0u, T->getFlags());
   T->setFlags(DINode::FlagRValueReference);
   EXPECT_EQ(DINode::FlagRValueReference, T->getFlags());
@@ -1254,14 +1254,29 @@ TEST_F(DISubroutineTypeTest, get) {
   unsigned Flags = 1;
   MDTuple *TypeArray = getTuple();
 
-  auto *N = DISubroutineType::get(Context, Flags, TypeArray);
+  auto *N = DISubroutineType::get(Context, Flags, 0, TypeArray);
   EXPECT_EQ(dwarf::DW_TAG_subroutine_type, N->getTag());
   EXPECT_EQ(Flags, N->getFlags());
   EXPECT_EQ(TypeArray, N->getTypeArray().get());
-  EXPECT_EQ(N, DISubroutineType::get(Context, Flags, TypeArray));
+  EXPECT_EQ(N, DISubroutineType::get(Context, Flags, 0, TypeArray));
 
-  EXPECT_NE(N, DISubroutineType::get(Context, Flags + 1, TypeArray));
-  EXPECT_NE(N, DISubroutineType::get(Context, Flags, getTuple()));
+  EXPECT_NE(N, DISubroutineType::get(Context, Flags + 1, 0, TypeArray));
+  EXPECT_NE(N, DISubroutineType::get(Context, Flags, 0, getTuple()));
+
+  // Test the hashing of calling conventions.
+  auto *Fast = DISubroutineType::get(
+      Context, Flags, dwarf::DW_CC_BORLAND_msfastcall, TypeArray);
+  auto *Std = DISubroutineType::get(Context, Flags,
+                                    dwarf::DW_CC_BORLAND_stdcall, TypeArray);
+  EXPECT_EQ(Fast,
+            DISubroutineType::get(Context, Flags,
+                                  dwarf::DW_CC_BORLAND_msfastcall, TypeArray));
+  EXPECT_EQ(Std, DISubroutineType::get(
+                     Context, Flags, dwarf::DW_CC_BORLAND_stdcall, TypeArray));
+
+  EXPECT_NE(N, Fast);
+  EXPECT_NE(N, Std);
+  EXPECT_NE(Fast, Std);
 
   TempDISubroutineType Temp = N->clone();
   EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));




More information about the llvm-commits mailing list