Re-commit r324489: [DebugInfo] Improvements to representation of enumeration types (PR36168)
Differential Revision: https://reviews.llvm.org/D42734 llvm-svn: 324899
This commit is contained in:
parent
b941f5dc5f
commit
08dc66eff0
|
@ -279,7 +279,7 @@ enum MetadataCodes {
|
|||
METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]]
|
||||
METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num]
|
||||
METADATA_SUBRANGE = 13, // [distinct, count, lo]
|
||||
METADATA_ENUMERATOR = 14, // [distinct, value, name]
|
||||
METADATA_ENUMERATOR = 14, // [isUnsigned|distinct, value, name]
|
||||
METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc]
|
||||
METADATA_FILE = 16, // [distinct, filename, directory, checksumkind, checksum]
|
||||
METADATA_DERIVED_TYPE = 17, // [distinct, ...]
|
||||
|
|
|
@ -166,7 +166,7 @@ namespace llvm {
|
|||
DIFile *File);
|
||||
|
||||
/// Create a single enumerator value.
|
||||
DIEnumerator *createEnumerator(StringRef Name, int64_t Val);
|
||||
DIEnumerator *createEnumerator(StringRef Name, int64_t Val, bool IsUnsigned = false);
|
||||
|
||||
/// Create a DWARF unspecified type.
|
||||
DIBasicType *createUnspecifiedType(StringRef Name);
|
||||
|
@ -487,10 +487,11 @@ namespace llvm {
|
|||
/// \param Elements Enumeration elements.
|
||||
/// \param UnderlyingType Underlying type of a C++11/ObjC fixed enum.
|
||||
/// \param UniqueIdentifier A unique identifier for the enum.
|
||||
/// \param IsFixed Boolean flag indicate if this is C++11/ObjC fixed enum.
|
||||
DICompositeType *createEnumerationType(
|
||||
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
|
||||
uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements,
|
||||
DIType *UnderlyingType, StringRef UniqueIdentifier = "");
|
||||
DIType *UnderlyingType, StringRef UniqueIdentifier = "", bool IsFixed = false);
|
||||
|
||||
/// Create subroutine type.
|
||||
/// \param ParameterTypes An array of subroutine parameter types. This
|
||||
|
|
|
@ -45,6 +45,7 @@ HANDLE_DI_FLAG((1 << 20), NoReturn)
|
|||
HANDLE_DI_FLAG((1 << 21), MainSubprogram)
|
||||
HANDLE_DI_FLAG((1 << 22), TypePassByValue)
|
||||
HANDLE_DI_FLAG((1 << 23), TypePassByReference)
|
||||
HANDLE_DI_FLAG((1 << 24), FixedEnum)
|
||||
|
||||
// To avoid needing a dedicated value for IndirectVirtualBase, we use
|
||||
// the bitwise or of Virtual and FwdDecl, which does not otherwise
|
||||
|
@ -54,7 +55,7 @@ HANDLE_DI_FLAG((1 << 2) | (1 << 5), IndirectVirtualBase)
|
|||
#ifdef DI_FLAG_LARGEST_NEEDED
|
||||
// intended to be used with ADT/BitmaskEnum.h
|
||||
// NOTE: always must be equal to largest flag, check this when adding new flag
|
||||
HANDLE_DI_FLAG((1 << 23), Largest)
|
||||
HANDLE_DI_FLAG((1 << 24), Largest)
|
||||
#undef DI_FLAG_LARGEST_NEEDED
|
||||
#endif
|
||||
|
||||
|
|
|
@ -396,36 +396,38 @@ class DIEnumerator : public DINode {
|
|||
friend class MDNode;
|
||||
|
||||
int64_t Value;
|
||||
|
||||
DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value,
|
||||
ArrayRef<Metadata *> Ops)
|
||||
bool IsUnsigned, ArrayRef<Metadata *> Ops)
|
||||
: DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
|
||||
Value(Value) {}
|
||||
Value(Value) {
|
||||
SubclassData32 = IsUnsigned;
|
||||
}
|
||||
~DIEnumerator() = default;
|
||||
|
||||
static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value,
|
||||
StringRef Name, StorageType Storage,
|
||||
bool ShouldCreate = true) {
|
||||
return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage,
|
||||
ShouldCreate);
|
||||
bool IsUnsigned, StringRef Name,
|
||||
StorageType Storage, bool ShouldCreate = true) {
|
||||
return getImpl(Context, Value, IsUnsigned,
|
||||
getCanonicalMDString(Context, Name), Storage, ShouldCreate);
|
||||
}
|
||||
static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value,
|
||||
MDString *Name, StorageType Storage,
|
||||
bool ShouldCreate = true);
|
||||
bool IsUnsigned, MDString *Name,
|
||||
StorageType Storage, bool ShouldCreate = true);
|
||||
|
||||
TempDIEnumerator cloneImpl() const {
|
||||
return getTemporary(getContext(), getValue(), getName());
|
||||
return getTemporary(getContext(), getValue(), isUnsigned(), getName());
|
||||
}
|
||||
|
||||
public:
|
||||
DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, StringRef Name),
|
||||
(Value, Name))
|
||||
DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, MDString *Name),
|
||||
(Value, Name))
|
||||
DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, StringRef Name),
|
||||
(Value, IsUnsigned, Name))
|
||||
DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, MDString *Name),
|
||||
(Value, IsUnsigned, Name))
|
||||
|
||||
TempDIEnumerator clone() const { return cloneImpl(); }
|
||||
|
||||
int64_t getValue() const { return Value; }
|
||||
bool isUnsigned() const { return SubclassData32; }
|
||||
StringRef getName() const { return getStringOperand(0); }
|
||||
|
||||
MDString *getRawName() const { return getOperandAs<MDString>(0); }
|
||||
|
|
|
@ -3636,6 +3636,22 @@ struct MDSignedOrMDField : MDEitherFieldImpl<MDSignedField, MDField> {
|
|||
}
|
||||
};
|
||||
|
||||
struct MDSignedOrUnsignedField
|
||||
: MDEitherFieldImpl<MDSignedField, MDUnsignedField> {
|
||||
MDSignedOrUnsignedField() : ImplTy(MDSignedField(0), MDUnsignedField(0)) {}
|
||||
|
||||
bool isMDSignedField() const { return WhatIs == IsTypeA; }
|
||||
bool isMDUnsignedField() const { return WhatIs == IsTypeB; }
|
||||
int64_t getMDSignedValue() const {
|
||||
assert(isMDSignedField() && "Wrong field type");
|
||||
return A.Val;
|
||||
}
|
||||
uint64_t getMDUnsignedValue() const {
|
||||
assert(isMDUnsignedField() && "Wrong field type");
|
||||
return B.Val;
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace llvm {
|
||||
|
@ -3912,6 +3928,27 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
|
|||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
|
||||
MDSignedOrUnsignedField &Result) {
|
||||
if (Lex.getKind() != lltok::APSInt)
|
||||
return false;
|
||||
|
||||
if (Lex.getAPSIntVal().isSigned()) {
|
||||
MDSignedField Res = Result.A;
|
||||
if (ParseMDField(Loc, Name, Res))
|
||||
return true;
|
||||
Result.assign(Res);
|
||||
return false;
|
||||
}
|
||||
|
||||
MDUnsignedField Res = Result.B;
|
||||
if (ParseMDField(Loc, Name, Res))
|
||||
return true;
|
||||
Result.assign(Res);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
|
||||
LocTy ValueLoc = Lex.getLoc();
|
||||
|
@ -4077,15 +4114,24 @@ bool LLParser::ParseDISubrange(MDNode *&Result, bool IsDistinct) {
|
|||
}
|
||||
|
||||
/// ParseDIEnumerator:
|
||||
/// ::= !DIEnumerator(value: 30, name: "SomeKind")
|
||||
/// ::= !DIEnumerator(value: 30, isUnsigned: true, name: "SomeKind")
|
||||
bool LLParser::ParseDIEnumerator(MDNode *&Result, bool IsDistinct) {
|
||||
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
|
||||
REQUIRED(name, MDStringField, ); \
|
||||
REQUIRED(value, MDSignedField, );
|
||||
REQUIRED(value, MDSignedOrUnsignedField, ); \
|
||||
OPTIONAL(isUnsigned, MDBoolField, (false));
|
||||
PARSE_MD_FIELDS();
|
||||
#undef VISIT_MD_FIELDS
|
||||
|
||||
Result = GET_OR_DISTINCT(DIEnumerator, (Context, value.Val, name.Val));
|
||||
if (isUnsigned.Val && value.isMDSignedField())
|
||||
return TokError("unsigned enumerator with negative value");
|
||||
|
||||
int64_t Value = value.isMDSignedField()
|
||||
? value.getMDSignedValue()
|
||||
: static_cast<int64_t>(value.getMDUnsignedValue());
|
||||
Result =
|
||||
GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1200,10 +1200,11 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
|
|||
if (Record.size() != 3)
|
||||
return error("Invalid record");
|
||||
|
||||
IsDistinct = Record[0];
|
||||
IsDistinct = Record[0] & 1;
|
||||
bool IsUnsigned = Record[0] & 2;
|
||||
MetadataList.assignValue(
|
||||
GET_OR_DISTINCT(DIEnumerator, (Context, unrotateSign(Record[1]),
|
||||
getMDString(Record[2]))),
|
||||
IsUnsigned, getMDString(Record[2]))),
|
||||
NextMetadataNo);
|
||||
NextMetadataNo++;
|
||||
break;
|
||||
|
|
|
@ -1457,7 +1457,7 @@ void ModuleBitcodeWriter::writeDISubrange(const DISubrange *N,
|
|||
void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N,
|
||||
SmallVectorImpl<uint64_t> &Record,
|
||||
unsigned Abbrev) {
|
||||
Record.push_back(N->isDistinct());
|
||||
Record.push_back((N->isUnsigned() << 1) | N->isDistinct());
|
||||
Record.push_back(rotateSign(N->getValue()));
|
||||
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
|
||||
|
||||
|
|
|
@ -1427,6 +1427,15 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
|
|||
}
|
||||
|
||||
void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
|
||||
const DIType *DTy = resolve(CTy->getBaseType());
|
||||
bool IsUnsigned = DTy && isUnsignedDIType(DD, DTy);
|
||||
if (DTy && DD->getDwarfVersion() >= 3)
|
||||
addType(Buffer, DTy);
|
||||
if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagFixedEnum)) {
|
||||
assert(DTy);
|
||||
addFlag(Buffer, dwarf::DW_AT_enum_class);
|
||||
}
|
||||
|
||||
DINodeArray Elements = CTy->getElements();
|
||||
|
||||
// Add enumerators to enumeration type.
|
||||
|
@ -1436,16 +1445,10 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
|
|||
DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);
|
||||
StringRef Name = Enum->getName();
|
||||
addString(Enumerator, dwarf::DW_AT_name, Name);
|
||||
int64_t Value = Enum->getValue();
|
||||
addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata,
|
||||
Value);
|
||||
auto Value = static_cast<uint64_t>(Enum->getValue());
|
||||
addConstantValue(Enumerator, IsUnsigned, Value);
|
||||
}
|
||||
}
|
||||
const DIType *DTy = resolve(CTy->getBaseType());
|
||||
if (DTy) {
|
||||
addType(Buffer, DTy);
|
||||
addFlag(Buffer, dwarf::DW_AT_enum_class);
|
||||
}
|
||||
}
|
||||
|
||||
void DwarfUnit::constructContainingTypeDIEs() {
|
||||
|
|
|
@ -1629,7 +1629,13 @@ static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
|
|||
Out << "!DIEnumerator(";
|
||||
MDFieldPrinter Printer(Out);
|
||||
Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false);
|
||||
if (N->isUnsigned()) {
|
||||
auto Value = static_cast<uint64_t>(N->getValue());
|
||||
Printer.printInt("value", Value, /* ShouldSkipZero */ false);
|
||||
Printer.printBool("isUnsigned", true);
|
||||
} else {
|
||||
Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false);
|
||||
}
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
|
|
|
@ -233,9 +233,10 @@ DIMacroFile *DIBuilder::createTempMacroFile(DIMacroFile *Parent,
|
|||
return MF;
|
||||
}
|
||||
|
||||
DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val) {
|
||||
DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val,
|
||||
bool IsUnsigned) {
|
||||
assert(!Name.empty() && "Unable to create enumerator without name");
|
||||
return DIEnumerator::get(VMContext, Val, Name);
|
||||
return DIEnumerator::get(VMContext, Val, IsUnsigned, Name);
|
||||
}
|
||||
|
||||
DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) {
|
||||
|
@ -492,11 +493,12 @@ DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
|
|||
DICompositeType *DIBuilder::createEnumerationType(
|
||||
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
|
||||
uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements,
|
||||
DIType *UnderlyingType, StringRef UniqueIdentifier) {
|
||||
DIType *UnderlyingType, StringRef UniqueIdentifier, bool IsFixed) {
|
||||
auto *CTy = DICompositeType::get(
|
||||
VMContext, dwarf::DW_TAG_enumeration_type, Name, File, LineNumber,
|
||||
getNonCompileUnitScope(Scope), UnderlyingType, SizeInBits, AlignInBits, 0,
|
||||
DINode::FlagZero, Elements, 0, nullptr, nullptr, UniqueIdentifier);
|
||||
IsFixed ? DINode::FlagFixedEnum : DINode::FlagZero, Elements, 0, nullptr,
|
||||
nullptr, UniqueIdentifier);
|
||||
AllEnumTypes.push_back(CTy);
|
||||
trackIfUnresolved(CTy);
|
||||
return CTy;
|
||||
|
|
|
@ -263,12 +263,12 @@ DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
|
|||
}
|
||||
|
||||
DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value,
|
||||
MDString *Name, StorageType Storage,
|
||||
bool ShouldCreate) {
|
||||
bool IsUnsigned, MDString *Name,
|
||||
StorageType Storage, bool ShouldCreate) {
|
||||
assert(isCanonical(Name) && "Expected canonical MDString");
|
||||
DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, Name));
|
||||
DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, IsUnsigned, Name));
|
||||
Metadata *Ops[] = {Name};
|
||||
DEFINE_GETIMPL_STORE(DIEnumerator, (Value), Ops);
|
||||
DEFINE_GETIMPL_STORE(DIEnumerator, (Value, IsUnsigned), Ops);
|
||||
}
|
||||
|
||||
DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,
|
||||
|
|
|
@ -354,13 +354,17 @@ template <> struct MDNodeKeyImpl<DISubrange> {
|
|||
template <> struct MDNodeKeyImpl<DIEnumerator> {
|
||||
int64_t Value;
|
||||
MDString *Name;
|
||||
bool IsUnsigned;
|
||||
|
||||
MDNodeKeyImpl(int64_t Value, MDString *Name) : Value(Value), Name(Name) {}
|
||||
MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
|
||||
: Value(Value), Name(Name), IsUnsigned(IsUnsigned) {}
|
||||
MDNodeKeyImpl(const DIEnumerator *N)
|
||||
: Value(N->getValue()), Name(N->getRawName()) {}
|
||||
: Value(N->getValue()), Name(N->getRawName()),
|
||||
IsUnsigned(N->isUnsigned()) {}
|
||||
|
||||
bool isKeyOf(const DIEnumerator *RHS) const {
|
||||
return Value == RHS->getValue() && Name == RHS->getRawName();
|
||||
return Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() &&
|
||||
Name == RHS->getRawName();
|
||||
}
|
||||
|
||||
unsigned getHashValue() const { return hash_combine(Value, Name); }
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
; Round-trip test for the following program:
|
||||
; ```
|
||||
; enum E0 { A0 = -2147483648, B0 = 2147483647 } x0;
|
||||
; enum E1 : signed int { A1 = -2147483648, B1 = 2147483647 } x1;
|
||||
; enum E2 : signed long long { A2 = -9223372036854775807LL - 1,
|
||||
; B2 = 9223372036854775807LL } x2;
|
||||
; enum E3 : unsigned long long { A3 = 0x8000000000000000ULL } x3;
|
||||
; ```
|
||||
; Test FixedEnum flag presence/absence, the underlying integer type and
|
||||
; enumerator values (signed and unsigned, and extreme cases) all survive through
|
||||
; the round-trip.
|
||||
|
||||
; RUN: llvm-as %s -o - | llvm-dis | llvm-as | llvm-dis | FileCheck %s
|
||||
|
||||
@x0 = global i32 0, align 4, !dbg !0
|
||||
@x1 = global i32 0, align 4, !dbg !24
|
||||
@x2 = global i64 0, align 8, !dbg !26
|
||||
@x3 = global i64 0, align 8, !dbg !28
|
||||
|
||||
!llvm.dbg.cu = !{!2}
|
||||
!llvm.module.flags = !{!30, !31, !32}
|
||||
!llvm.ident = !{!33}
|
||||
|
||||
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
||||
!1 = distinct !DIGlobalVariable(name: "x0", scope: !2, file: !3, line: 1, type: !5, isLocal: false, isDefinition: true)
|
||||
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (/data/src/llvm/tools/clang 697b0cb4c2e712a28767c2f7fe50c90bae7255f5) (/data/src/llvm 5ba8dcca7470b5da405bc92b9681b1f36e5d6772)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !23)
|
||||
!3 = !DIFile(filename: "e.cc", directory: "/work/build/clang-dev")
|
||||
!4 = !{!5, !10, !14, !19}
|
||||
|
||||
|
||||
!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E0", file: !3, line: 1, baseType: !6, size: 32, elements: !7, identifier: "_ZTS2E0")
|
||||
; CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E0"{{.*}}, baseType: ![[INT:[0-9]+]]
|
||||
; CHECK-NOT: FixedEnum
|
||||
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
; CHECK: ![[INT]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!7 = !{!8, !9}
|
||||
!8 = !DIEnumerator(name: "A0", value: -2147483648)
|
||||
!9 = !DIEnumerator(name: "B0", value: 2147483647)
|
||||
; CHECK: !DIEnumerator(name: "A0", value: -2147483648)
|
||||
; CHECK: !DIEnumerator(name: "B0", value: 2147483647)
|
||||
|
||||
|
||||
!10 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E1", file: !3, line: 3, baseType: !6, size: 32, flags: DIFlagFixedEnum, elements: !11, identifier: "_ZTS2E1")
|
||||
; CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E1"{{.*}}, baseType: ![[INT]]
|
||||
; CHECK-SAME: DIFlagFixedEnum
|
||||
!11 = !{!12, !13}
|
||||
!12 = !DIEnumerator(name: "A1", value: -2147483648)
|
||||
!13 = !DIEnumerator(name: "B1", value: 2147483647)
|
||||
; CHECK: !DIEnumerator(name: "A1", value: -2147483648)
|
||||
; CHECK: !DIEnumerator(name: "B1", value: 2147483647)
|
||||
|
||||
|
||||
!14 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E2", file: !3, line: 5, baseType: !15, size: 64, flags: DIFlagFixedEnum, elements: !16, identifier: "_ZTS2E2")
|
||||
; CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E2"{{.*}}, baseType: ![[LONG:[0-9]+]]
|
||||
; CHECK-SAME: DIFlagFixedEnum
|
||||
!15 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
|
||||
; CHECK: ![[LONG]] = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
|
||||
!16 = !{!17, !18}
|
||||
!17 = !DIEnumerator(name: "A2", value: -9223372036854775808)
|
||||
!18 = !DIEnumerator(name: "B2", value: 9223372036854775807)
|
||||
; CHECK: !DIEnumerator(name: "A2", value: -9223372036854775808)
|
||||
; CHECK: !DIEnumerator(name: "B2", value: 9223372036854775807)
|
||||
|
||||
|
||||
!19 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E3", file: !3, line: 7, baseType: !20, size: 64, flags: DIFlagFixedEnum, elements: !21, identifier: "_ZTS2E3")
|
||||
; CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "E3"{{.*}}, baseType: ![[ULONG:[0-9]+]]
|
||||
; CHECK-SAME: DIFlagFixedEnum
|
||||
!20 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
|
||||
; CHECK: ![[ULONG]] = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
|
||||
!21 = !{!22}
|
||||
!22 = !DIEnumerator(name: "A3", value: 9223372036854775808, isUnsigned: true)
|
||||
; CHECK: !DIEnumerator(name: "A3", value: 9223372036854775808, isUnsigned: true)
|
||||
|
||||
|
||||
!23 = !{!0, !24, !26, !28}
|
||||
!24 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression())
|
||||
!25 = distinct !DIGlobalVariable(name: "x1", scope: !2, file: !3, line: 3, type: !10, isLocal: false, isDefinition: true)
|
||||
!26 = !DIGlobalVariableExpression(var: !27, expr: !DIExpression())
|
||||
!27 = distinct !DIGlobalVariable(name: "x2", scope: !2, file: !3, line: 5, type: !14, isLocal: false, isDefinition: true)
|
||||
!28 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression())
|
||||
!29 = distinct !DIGlobalVariable(name: "x3", scope: !2, file: !3, line: 7, type: !19, isLocal: false, isDefinition: true)
|
||||
!30 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!31 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!32 = !{i32 1, !"wchar_size", i32 4}
|
||||
!33 = !{!"clang version 7.0.0 (/data/src/llvm/tools/clang 697b0cb4c2e712a28767c2f7fe50c90bae7255f5) (/data/src/llvm 5ba8dcca7470b5da405bc92b9681b1f36e5d6772)"}
|
|
@ -0,0 +1,188 @@
|
|||
; Test enumeration representation in DWARF debug info:
|
||||
; * test value representation for each possible underlying integer type
|
||||
; * test the integer type is as expected
|
||||
; * test the DW_AT_enum_class attribute is present (resp. absent) as expected.
|
||||
|
||||
; RUN: llc -debugger-tune=gdb -dwarf-version=4 -filetype=obj -o %t.o < %s
|
||||
; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DW4
|
||||
; RUN: llc -debugger-tune=gdb -dwarf-version=2 -filetype=obj -o %t.o < %s
|
||||
; RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DW2
|
||||
|
||||
@x0 = global i8 0, align 1, !dbg !0
|
||||
@x1 = global i8 0, align 1, !dbg !46
|
||||
@x2 = global i16 0, align 2, !dbg !48
|
||||
@x3 = global i16 0, align 2, !dbg !50
|
||||
@x4 = global i32 0, align 4, !dbg !52
|
||||
@x5 = global i32 0, align 4, !dbg !54
|
||||
@x6 = global i64 0, align 8, !dbg !56
|
||||
@x7 = global i64 0, align 8, !dbg !58
|
||||
@x8 = global i32 0, align 4, !dbg !60
|
||||
|
||||
!llvm.dbg.cu = !{!2}
|
||||
!llvm.module.flags = !{!62}
|
||||
|
||||
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
||||
!1 = distinct !DIGlobalVariable(name: "x0", scope: !2, file: !3, line: 5, type: !5, isLocal: false, isDefinition: true)
|
||||
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (/data/src/llvm/tools/clang 0c08d9830124a75675348b4eeb47256f3da6693d) (/data/src/llvm cf29510f52faa77b98510cd53276f564d1f4f41f)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !45)
|
||||
!3 = !DIFile(filename: "/data/src/llvm-dev/tools/clang/test/CodeGen/debug-info-enum.cpp", directory: "/work/build/clang-dev")
|
||||
!4 = !{!5, !10, !14, !19, !23, !28, !32, !37, !41}
|
||||
|
||||
; Test enumeration with a fixed "signed char" underlying type.
|
||||
!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E0", file: !3, line: 2, baseType: !6, size: 8, flags: DIFlagFixedEnum, elements: !7, identifier: "_ZTS2E0")
|
||||
!6 = !DIBasicType(name: "signed char", size: 8, encoding: DW_ATE_signed_char)
|
||||
!7 = !{!8, !9}
|
||||
!8 = !DIEnumerator(name: "A0", value: -128)
|
||||
!9 = !DIEnumerator(name: "B0", value: 127)
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}}"signed char"
|
||||
; CHECK-DW4: DW_AT_enum_class (true)
|
||||
; CHECK: DW_AT_name ("E0")
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("A0")
|
||||
; CHECK-NEXT: DW_AT_const_value (-128)
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("B0")
|
||||
; CHECK-NEXT: DW_AT_const_value (127)
|
||||
|
||||
; Test enumeration with a fixed "unsigned char" underlying type.
|
||||
!10 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E1", file: !3, line: 12, baseType: !11, size: 8, flags: DIFlagFixedEnum, elements: !12, identifier: "_ZTS2E1")
|
||||
!11 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
|
||||
!12 = !{!13}
|
||||
!13 = !DIEnumerator(name: "A1", value: 255, isUnsigned: true)
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}}"unsigned char"
|
||||
; CHECK-DW4: DW_AT_enum_class (true)
|
||||
; CHECK: DW_AT_name ("E1")
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("A1")
|
||||
; CHECK-NEXT: DW_AT_const_value (255)
|
||||
|
||||
; Test enumeration with a fixed "short" underlying type.
|
||||
!14 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E2", file: !3, line: 18, baseType: !15, size: 16, flags: DIFlagFixedEnum, elements: !16, identifier: "_ZTS2E2")
|
||||
!15 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed)
|
||||
!16 = !{!17, !18}
|
||||
!17 = !DIEnumerator(name: "A2", value: -32768)
|
||||
!18 = !DIEnumerator(name: "B2", value: 32767)
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}} "short"
|
||||
; CHECK-DW4: DW_AT_enum_class (true)
|
||||
; CHECK: DW_AT_name ("E2")
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("A2")
|
||||
; CHECK-NEXT: DW_AT_const_value (-32768)
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("B2")
|
||||
; CHECK-NEXT: DW_AT_const_value (32767)
|
||||
|
||||
; Test enumeration with a fixed "unsigned short" underlying type.
|
||||
!19 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E3", file: !3, line: 28, baseType: !20, size: 16, flags: DIFlagFixedEnum, elements: !21, identifier: "_ZTS2E3")
|
||||
!20 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned)
|
||||
!21 = !{!22}
|
||||
!22 = !DIEnumerator(name: "A3", value: 65535, isUnsigned: true)
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}}"unsigned short"
|
||||
; CHECK-DW4: DW_AT_enum_class (true)
|
||||
; CHECK: DW_AT_name ("E3")
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("A3")
|
||||
; CHECK-NEXT: DW_AT_const_value (65535)
|
||||
|
||||
; Test enumeration with a fixed "int" underlying type.
|
||||
!23 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E4", file: !3, line: 34, baseType: !24, size: 32, flags: DIFlagFixedEnum, elements: !25, identifier: "_ZTS2E4")
|
||||
!24 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!25 = !{!26, !27}
|
||||
!26 = !DIEnumerator(name: "A4", value: -2147483648)
|
||||
!27 = !DIEnumerator(name: "B4", value: 2147483647)
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}}"int"
|
||||
; CHECK-DW4: DW_AT_enum_class (true)
|
||||
; CHECK: DW_AT_name ("E4")
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("A4")
|
||||
; CHECK-NEXT: DW_AT_const_value (-2147483648)
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("B4")
|
||||
; CHECK-NEXT: DW_AT_const_value (2147483647)
|
||||
|
||||
; Test enumeration with a fixed "unsigend int" underlying type.
|
||||
!28 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E5", file: !3, line: 41, baseType: !29, size: 32, flags: DIFlagFixedEnum, elements: !30, identifier: "_ZTS2E5")
|
||||
!29 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
|
||||
!30 = !{!31}
|
||||
!31 = !DIEnumerator(name: "A5", value: 4294967295, isUnsigned: true)
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}}"unsigned int"
|
||||
; CHECK-DW4: DW_AT_enum_class (true)
|
||||
; CHECK: DW_AT_name ("E5")
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("A5")
|
||||
; CHECK-NEXT: DW_AT_const_value (4294967295)
|
||||
|
||||
; Test enumeration with a fixed "long long" underlying type.
|
||||
!32 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E6", file: !3, line: 47, baseType: !33, size: 64, flags: DIFlagFixedEnum, elements: !34, identifier: "_ZTS2E6")
|
||||
!33 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
|
||||
!34 = !{!35, !36}
|
||||
!35 = !DIEnumerator(name: "A6", value: -9223372036854775808)
|
||||
!36 = !DIEnumerator(name: "B6", value: 9223372036854775807)
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}}"long long int"
|
||||
; CHECK-DW4: DW_AT_enum_class (true)
|
||||
; CHECK: DW_AT_name ("E6")
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("A6")
|
||||
; CHECK-NEXT: DW_AT_const_value (-9223372036854775808)
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("B6")
|
||||
; CHECK-NEXT: DW_AT_const_value (9223372036854775807)
|
||||
|
||||
; Test enumeration with a fixed "unsigned long long" underlying type.
|
||||
!37 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E7", file: !3, line: 57, baseType: !38, size: 64, flags: DIFlagFixedEnum, elements: !39, identifier: "_ZTS2E7")
|
||||
!38 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
|
||||
!39 = !{!40}
|
||||
!40 = !DIEnumerator(name: "A7", value: 18446744073709551615, isUnsigned: true)
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}}"long long unsigned int"
|
||||
; CHECK-DW4: DW_AT_enum_class (true)
|
||||
; CHECK: DW_AT_name ("E7")
|
||||
; CHECK: DW_TAG_enumerator
|
||||
; CHECK: DW_AT_name ("A7")
|
||||
; CHECK-NEXT: DW_AT_const_value (18446744073709551615)
|
||||
|
||||
; Test enumeration without a fixed underlying type. The underlying type should
|
||||
; still be present (for DWARF >= 3), but the DW_AT_enum_class attribute should
|
||||
; be absent.
|
||||
!41 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E8", file: !3, line: 63, baseType: !24, size: 32, elements: !42, identifier: "_ZTS2E8")
|
||||
!42 = !{!43, !44}
|
||||
!43 = !DIEnumerator(name: "A8", value: -128)
|
||||
!44 = !DIEnumerator(name: "B8", value: 127)
|
||||
!45 = !{!0, !46, !48, !50, !52, !54, !56, !58, !60}
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-DW2-NOT: DW_AT_type
|
||||
; CHECK-DW4: DW_AT_type{{.*}}"int"
|
||||
; CHECK-NOT: DW_AT_enum_class
|
||||
; CHECK: DW_AT_name ("E8")
|
||||
|
||||
!46 = !DIGlobalVariableExpression(var: !47, expr: !DIExpression())
|
||||
!47 = distinct !DIGlobalVariable(name: "x1", scope: !2, file: !3, line: 12, type: !10, isLocal: false, isDefinition: true)
|
||||
!48 = !DIGlobalVariableExpression(var: !49, expr: !DIExpression())
|
||||
!49 = distinct !DIGlobalVariable(name: "x2", scope: !2, file: !3, line: 21, type: !14, isLocal: false, isDefinition: true)
|
||||
!50 = !DIGlobalVariableExpression(var: !51, expr: !DIExpression())
|
||||
!51 = distinct !DIGlobalVariable(name: "x3", scope: !2, file: !3, line: 28, type: !19, isLocal: false, isDefinition: true)
|
||||
!52 = !DIGlobalVariableExpression(var: !53, expr: !DIExpression())
|
||||
!53 = distinct !DIGlobalVariable(name: "x4", scope: !2, file: !3, line: 34, type: !23, isLocal: false, isDefinition: true)
|
||||
!54 = !DIGlobalVariableExpression(var: !55, expr: !DIExpression())
|
||||
!55 = distinct !DIGlobalVariable(name: "x5", scope: !2, file: !3, line: 41, type: !28, isLocal: false, isDefinition: true)
|
||||
!56 = !DIGlobalVariableExpression(var: !57, expr: !DIExpression())
|
||||
!57 = distinct !DIGlobalVariable(name: "x6", scope: !2, file: !3, line: 50, type: !32, isLocal: false, isDefinition: true)
|
||||
!58 = !DIGlobalVariableExpression(var: !59, expr: !DIExpression())
|
||||
!59 = distinct !DIGlobalVariable(name: "x7", scope: !2, file: !3, line: 57, type: !37, isLocal: false, isDefinition: true)
|
||||
!60 = !DIGlobalVariableExpression(var: !61, expr: !DIExpression())
|
||||
!61 = distinct !DIGlobalVariable(name: "x8", scope: !2, file: !3, line: 63, type: !41, isLocal: false, isDefinition: true)
|
||||
!62 = !{i32 2, !"Debug Info Version", i32 3}
|
|
@ -13,13 +13,13 @@ source_filename = "test/DebugInfo/X86/enum-class.ll"
|
|||
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
||||
!1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 4, type: !3, isLocal: false, isDefinition: true)
|
||||
!2 = !DIFile(filename: "foo.cpp", directory: "/Users/echristo/tmp")
|
||||
!3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "A", file: !2, line: 1, baseType: !4, size: 32, align: 32, elements: !5)
|
||||
!3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "A", file: !2, line: 1, baseType: !4, size: 32, flags: DIFlagFixedEnum, align: 32, elements: !5)
|
||||
!4 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
|
||||
!5 = !{!6}
|
||||
!6 = !DIEnumerator(name: "A1", value: 1)
|
||||
!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression()) ; [ DW_TAG_enumerator ]
|
||||
!8 = !DIGlobalVariable(name: "b", scope: null, file: !2, line: 5, type: !9, isLocal: false, isDefinition: true)
|
||||
!9 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "B", file: !2, line: 2, baseType: !10, size: 64, align: 64, elements: !11)
|
||||
!9 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "B", file: !2, line: 2, baseType: !10, size: 64, flags: DIFlagFixedEnum, align: 64, elements: !11)
|
||||
!10 = !DIBasicType(name: "long unsigned int", size: 64, align: 64, encoding: DW_ATE_unsigned)
|
||||
!11 = !{!12}
|
||||
!12 = !DIEnumerator(name: "B1", value: 1) ; [ DW_TAG_enumerator ]
|
||||
|
@ -44,6 +44,6 @@ source_filename = "test/DebugInfo/X86/enum-class.ll"
|
|||
; CHECK: DW_AT_enum_class [DW_FORM_flag_present] (true)
|
||||
; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "B")
|
||||
|
||||
; CHECK: DW_TAG_enumeration_type [6]
|
||||
; CHECK: DW_TAG_enumeration_type
|
||||
; CHECK-NOT: DW_AT_enum_class
|
||||
; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "C")
|
||||
|
|
|
@ -978,14 +978,16 @@ TEST_F(DISubrangeTest, getVariableCount) {
|
|||
typedef MetadataTest DIEnumeratorTest;
|
||||
|
||||
TEST_F(DIEnumeratorTest, get) {
|
||||
auto *N = DIEnumerator::get(Context, 7, "name");
|
||||
auto *N = DIEnumerator::get(Context, 7, false, "name");
|
||||
EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag());
|
||||
EXPECT_EQ(7, N->getValue());
|
||||
EXPECT_EQ(false, N->isUnsigned());
|
||||
EXPECT_EQ("name", N->getName());
|
||||
EXPECT_EQ(N, DIEnumerator::get(Context, 7, "name"));
|
||||
EXPECT_EQ(N, DIEnumerator::get(Context, 7, false, "name"));
|
||||
|
||||
EXPECT_NE(N, DIEnumerator::get(Context, 8, "name"));
|
||||
EXPECT_NE(N, DIEnumerator::get(Context, 7, "nam"));
|
||||
EXPECT_NE(N, DIEnumerator::get(Context, 7, true, "name"));
|
||||
EXPECT_NE(N, DIEnumerator::get(Context, 8, false, "name"));
|
||||
EXPECT_NE(N, DIEnumerator::get(Context, 7, false, "nam"));
|
||||
|
||||
TempDIEnumerator Temp = N->clone();
|
||||
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
|
||||
|
|
Loading…
Reference in New Issue