diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLToken.h | 1 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 12 | ||||
-rw-r--r-- | llvm/lib/Support/Dwarf.cpp | 31 |
12 files changed, 91 insertions, 36 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index bf457a95cd7..1ba698ebd61 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -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 diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 8081ef23297..cc7b98fa56d 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -3341,6 +3341,9 @@ struct DwarfVirtualityField : public MDUnsignedField { 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, StringRef Name, DwarfLangField &Result) { } 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(MDNode *&Result, bool IsDistinct) { 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; } diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index 9713cd67598..85881d6f11b 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -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 diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 79d358a3281..0c2895007b9 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2409,17 +2409,18 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) { 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; } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index d65e924507c..06a4ef1892d 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1467,6 +1467,7 @@ void ModuleBitcodeWriter::writeDISubroutineType( 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(); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 530b1febeae..828f89e9254 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -926,6 +926,20 @@ TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) { 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::lowerTypeFunction(const DISubroutineType *Ty) { 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); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index f1f8ecfd45c..6a5e29a4ff0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -901,6 +901,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy) { 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::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, 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. diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index c5002dc8c2f..24b92b8eb3c 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1659,6 +1659,7 @@ static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N, 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 << ")"; diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 9a61afb099d..0c1876a3e43 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -420,8 +420,8 @@ DICompositeType *DIBuilder::createUnionType( } 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, diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 81e20f4e1b9..4cbe838f87d 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -327,12 +327,13 @@ DICompositeType *DICompositeType::getODRTypeIfExists(LLVMContext &Context, } 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, diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 3e0ba4a59ed..b1c91c6bcdb 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -484,17 +484,19 @@ template <> struct MDNodeKeyImpl<DICompositeType> { 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> { diff --git a/llvm/lib/Support/Dwarf.cpp b/llvm/lib/Support/Dwarf.cpp index 7d722567173..230a3dafe62 100644 --- a/llvm/lib/Support/Dwarf.cpp +++ b/llvm/lib/Support/Dwarf.cpp @@ -384,23 +384,22 @@ const char *llvm::dwarf::CaseString(unsigned Case) { 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) { |