mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 05:30:49 +00:00
[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
This commit is contained in:
parent
2ae3d2cd86
commit
3d3aca2d97
@ -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]
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
/// @}
|
||||
|
@ -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
|
||||
|
@ -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) {}
|
||||
};
|
||||
@ -3483,6 +3486,24 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfLangField &Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 << ")";
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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> {
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
212
test/DebugInfo/COFF/types-calling-conv.ll
Normal file
212
test/DebugInfo/COFF/types-calling-conv.ll
Normal file
@ -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@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@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@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)
|
86
test/DebugInfo/X86/DW_AT_calling-convention.ll
Normal file
86
test/DebugInfo/X86/DW_AT_calling-convention.ll
Normal file
@ -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@ZA" = global i32 (i32, i32)* @"\01?f@@YIHHH@Z", align 4
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
define x86_fastcallcc i32 @"\01?f@@YIHHH@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@ZA", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, variable: i32 (i32, i32)** @"\01?fptr@@3P6IHHH@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@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)
|
@ -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)));
|
||||
|
Loading…
Reference in New Issue
Block a user