Re-commit r324489: [DebugInfo] Improvements to representation of enumeration types (PR36168)
Differential Revision: https://reviews.llvm.org/D42734
llvm-svn: 324899
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 2833ef4..209a834 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -3636,6 +3636,22 @@
}
};
+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 {
@@ -3913,6 +3929,27 @@
}
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();
std::string S;
@@ -4077,15 +4114,24 @@
}
/// 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;
}
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index c0ec80e..374e315 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1200,10 +1200,11 @@
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;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index fd9cde1..8c65e95 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1457,7 +1457,7 @@
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()));
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 0e6ed1c..939d13f 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1427,6 +1427,15 @@
}
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 @@
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() {
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index d641a63..444a341 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1629,7 +1629,13 @@
Out << "!DIEnumerator(";
MDFieldPrinter Printer(Out);
Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false);
- Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ 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 << ")";
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index ed3e281..f9aca8a 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -233,9 +233,10 @@
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 @@
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;
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index c44bc75..a777198 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -263,12 +263,12 @@
}
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,
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index db7f368..c4cd785 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -354,13 +354,17 @@
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); }