From aad3d578da0ddf6d0d3d95e5e09a32e47f6dfeb8 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 18 Apr 2020 11:31:38 -0700 Subject: [PATCH] [DebugInfo] Change DIEnumerator payload type from int64_t to APInt This allows the representation of arbitrarily large enumeration values. See https://lists.llvm.org/pipermail/llvm-dev/2017-December/119475.html for context. Reviewed By: andrewrk, aprantl, MaskRay Differential Revision: https://reviews.llvm.org/D62475 --- llvm/include/llvm/Bitcode/BitcodeReader.h | 2 + llvm/include/llvm/IR/DebugInfoMetadata.h | 26 +++++++--- llvm/lib/AsmParser/LLParser.cpp | 48 ++++++++---------- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 2 +- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 16 ++++-- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 41 ++++++++------- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 2 +- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 3 +- llvm/lib/IR/AsmWriter.cpp | 20 +++++--- llvm/lib/IR/DIBuilder.cpp | 3 +- llvm/lib/IR/DebugInfoMetadata.cpp | 2 +- llvm/lib/IR/LLVMContextImpl.h | 11 ++-- llvm/lib/Target/BPF/BTFDebug.cpp | 7 ++- llvm/test/Assembler/DIEnumeratorBig.ll | 13 +++++ llvm/test/Bitcode/DIEnumerator-10.0.ll | 10 ++++ llvm/test/Bitcode/DIEnumerator-10.0.ll.bc | Bin 0 -> 1056 bytes llvm/unittests/IR/MetadataTest.cpp | 11 +++- 17 files changed, 145 insertions(+), 72 deletions(-) create mode 100644 llvm/test/Assembler/DIEnumeratorBig.ll create mode 100644 llvm/test/Bitcode/DIEnumerator-10.0.ll create mode 100644 llvm/test/Bitcode/DIEnumerator-10.0.ll.bc diff --git a/llvm/include/llvm/Bitcode/BitcodeReader.h b/llvm/include/llvm/Bitcode/BitcodeReader.h index ba61da733bea..c6f2378ec131 100644 --- a/llvm/include/llvm/Bitcode/BitcodeReader.h +++ b/llvm/include/llvm/Bitcode/BitcodeReader.h @@ -255,6 +255,8 @@ class Module; return false; } + APInt readWideAPInt(ArrayRef Vals, unsigned TypeBits); + const std::error_category &BitcodeErrorCategory(); enum class BitcodeError { CorruptedBitcode = 1 }; inline std::error_code make_error_code(BitcodeError E) { diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 3eaed3270602..718ecea5afeb 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -348,22 +348,26 @@ class DIEnumerator : public DINode { friend class LLVMContextImpl; friend class MDNode; - int64_t Value; - DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + APInt Value; + DIEnumerator(LLVMContext &C, StorageType Storage, APInt Value, bool IsUnsigned, ArrayRef Ops) : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), Value(Value) { SubclassData32 = IsUnsigned; } + DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + bool IsUnsigned, ArrayRef Ops) + : DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned, + Ops) {} ~DIEnumerator() = default; - static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, + static DIEnumerator *getImpl(LLVMContext &Context, APInt Value, 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, + static DIEnumerator *getImpl(LLVMContext &Context, APInt Value, bool IsUnsigned, MDString *Name, StorageType Storage, bool ShouldCreate = true); @@ -372,14 +376,22 @@ class DIEnumerator : public DINode { } public: - DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, StringRef Name), + DEFINE_MDNODE_GET(DIEnumerator, + (int64_t Value, bool IsUnsigned, StringRef Name), + (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) + DEFINE_MDNODE_GET(DIEnumerator, + (int64_t Value, bool IsUnsigned, MDString *Name), + (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) + DEFINE_MDNODE_GET(DIEnumerator, + (APInt Value, bool IsUnsigned, StringRef Name), (Value, IsUnsigned, Name)) - DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, MDString *Name), + DEFINE_MDNODE_GET(DIEnumerator, + (APInt Value, bool IsUnsigned, MDString *Name), (Value, IsUnsigned, Name)) TempDIEnumerator clone() const { return cloneImpl(); } - int64_t getValue() const { return Value; } + const APInt &getValue() const { return Value; } bool isUnsigned() const { return SubclassData32; } StringRef getName() const { return getStringOperand(0); } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 2e446abec1dc..e2d0180eb3c6 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -3872,6 +3872,10 @@ struct DISPFlagField : public MDFieldImpl { DISPFlagField() : MDFieldImpl(DISubprogram::SPFlagZero) {} }; +struct MDAPSIntField : public MDFieldImpl { + MDAPSIntField() : ImplTy(APSInt()) {} +}; + struct MDSignedField : public MDFieldImpl { int64_t Min; int64_t Max; @@ -3950,6 +3954,16 @@ struct MDSignedOrUnsignedField namespace llvm { +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDAPSIntField &Result) { + if (Lex.getKind() != lltok::APSInt) + return TokError("expected integer"); + + Result.assign(Lex.getAPSIntVal()); + Lex.Lex(); + return false; +} + template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDUnsignedField &Result) { @@ -4281,27 +4295,6 @@ 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(); @@ -4475,17 +4468,20 @@ bool LLParser::ParseDISubrange(MDNode *&Result, bool IsDistinct) { bool LLParser::ParseDIEnumerator(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(name, MDStringField, ); \ - REQUIRED(value, MDSignedOrUnsignedField, ); \ + REQUIRED(value, MDAPSIntField, ); \ OPTIONAL(isUnsigned, MDBoolField, (false)); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - if (isUnsigned.Val && value.isMDSignedField()) + if (isUnsigned.Val && value.Val.isNegative()) return TokError("unsigned enumerator with negative value"); - int64_t Value = value.isMDSignedField() - ? value.getMDSignedValue() - : static_cast(value.getMDUnsignedValue()); + APSInt Value(value.Val); + // Add a leading zero so that unsigned values with the msb set are not + // mistaken for negative values when used for signed enumerators. + if (!isUnsigned.Val && value.Val.isUnsigned() && value.Val.isSignBitSet()) + Value = Value.zext(Value.getBitWidth() + 1); + Result = GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val)); diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 8f7f980c517c..4b8b0ec8a24d 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2317,7 +2317,7 @@ Error BitcodeReader::resolveGlobalAndIndirectSymbolInits() { return Error::success(); } -static APInt readWideAPInt(ArrayRef Vals, unsigned TypeBits) { +APInt llvm::readWideAPInt(ArrayRef Vals, unsigned TypeBits) { SmallVector Words(Vals.size()); transform(Vals, Words.begin(), BitcodeReader::decodeSignRotatedValue); diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index c1fa91d0672d..6ec4416f4b43 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1277,14 +1277,24 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_ENUMERATOR: { - if (Record.size() != 3) + if (Record.size() < 3) return error("Invalid record"); IsDistinct = Record[0] & 1; bool IsUnsigned = Record[0] & 2; + bool IsBigInt = Record[0] & 4; + APInt Value; + + if (IsBigInt) { + const uint64_t BitWidth = Record[1]; + const size_t NumWords = Record.size() - 3; + Value = readWideAPInt(makeArrayRef(&Record[3], NumWords), BitWidth); + } else + Value = APInt(64, unrotateSign(Record[1]), !IsUnsigned); + MetadataList.assignValue( - GET_OR_DISTINCT(DIEnumerator, (Context, unrotateSign(Record[1]), - IsUnsigned, getMDString(Record[2]))), + GET_OR_DISTINCT(DIEnumerator, + (Context, Value, IsUnsigned, getMDString(Record[2]))), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 1de3ea898e53..f6d0e40aa639 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1529,12 +1529,32 @@ void ModuleBitcodeWriter::writeDISubrange(const DISubrange *N, Record.clear(); } +static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V) { + if ((int64_t)V >= 0) + Vals.push_back(V << 1); + else + Vals.push_back((-V << 1) | 1); +} + +static void emitWideAPInt(SmallVectorImpl &Vals, const APInt &A) { + // We have an arbitrary precision integer value to write whose + // bit width is > 64. However, in canonical unsigned integer + // format it is likely that the high bits are going to be zero. + // So, we only write the number of active words. + unsigned NumWords = A.getActiveWords(); + const uint64_t *RawData = A.getRawData(); + for (unsigned i = 0; i < NumWords; i++) + emitSignedInt64(Vals, RawData[i]); +} + void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N, SmallVectorImpl &Record, unsigned Abbrev) { - Record.push_back((N->isUnsigned() << 1) | N->isDistinct()); - Record.push_back(rotateSign(N->getValue())); + const uint64_t IsBigInt = 1 << 2; + Record.push_back(IsBigInt | (N->isUnsigned() << 1) | N->isDistinct()); + Record.push_back(N->getValue().getBitWidth()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); + emitWideAPInt(Record, N->getValue()); Stream.EmitRecord(bitc::METADATA_ENUMERATOR, Record, Abbrev); Record.clear(); @@ -2269,13 +2289,6 @@ void ModuleBitcodeWriter::writeSyncScopeNames() { Stream.ExitBlock(); } -static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V) { - if ((int64_t)V >= 0) - Vals.push_back(V << 1); - else - Vals.push_back((-V << 1) | 1); -} - void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, bool isGlobal) { if (FirstVal == LastVal) return; @@ -2362,15 +2375,7 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, Code = bitc::CST_CODE_INTEGER; AbbrevToUse = CONSTANTS_INTEGER_ABBREV; } else { // Wide integers, > 64 bits in size. - // We have an arbitrary precision integer value to write whose - // bit width is > 64. However, in canonical unsigned integer - // format it is likely that the high bits are going to be zero. - // So, we only write the number of active words. - unsigned NWords = IV->getValue().getActiveWords(); - const uint64_t *RawWords = IV->getValue().getRawData(); - for (unsigned i = 0; i != NWords; ++i) { - emitSignedInt64(Record, RawWords[i]); - } + emitWideAPInt(Record, IV->getValue()); Code = bitc::CST_CODE_WIDE_INTEGER; } } else if (const ConstantFP *CFP = dyn_cast(C)) { diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 7c2673a2d99a..cd182c77f41e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -2080,7 +2080,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) { // order, which is what MSVC does. if (auto *Enumerator = dyn_cast_or_null(Element)) { EnumeratorRecord ER(MemberAccess::Public, - APSInt::getUnsigned(Enumerator->getValue()), + APSInt(Enumerator->getValue(), true), Enumerator->getName()); ContinuationBuilder.writeMemberType(ER); EnumeratorCount++; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 91362644da21..ecf4a78f3be6 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1449,8 +1449,7 @@ 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); - auto Value = static_cast(Enum->getValue()); - addConstantValue(Enumerator, IsUnsigned, Value); + addConstantValue(Enumerator, Enum->getValue(), IsUnsigned); if (IndexEnumerators) addGlobalName(Name, Enumerator, Context); } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index ca01fe446283..5c04881d1af7 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1647,6 +1647,8 @@ struct MDFieldPrinter { bool ShouldSkipNull = true); template void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true); + void printAPInt(StringRef Name, APInt Int, bool IsUnsigned, + bool ShouldSkipZero); void printBool(StringRef Name, bool Value, Optional Default = None); void printDIFlags(StringRef Name, DINode::DIFlags Flags); void printDISPFlags(StringRef Name, DISubprogram::DISPFlags Flags); @@ -1722,6 +1724,15 @@ void MDFieldPrinter::printInt(StringRef Name, IntTy Int, bool ShouldSkipZero) { Out << FS << Name << ": " << Int; } +void MDFieldPrinter::printAPInt(StringRef Name, APInt Int, bool IsUnsigned, + bool ShouldSkipZero) { + if (ShouldSkipZero && Int.isNullValue()) + return; + + Out << FS << Name << ": "; + Int.print(Out, !IsUnsigned); +} + void MDFieldPrinter::printBool(StringRef Name, bool Value, Optional Default) { if (Default && Value == *Default) @@ -1851,13 +1862,10 @@ 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(N->getValue()); - Printer.printInt("value", Value, /* ShouldSkipZero */ false); + Printer.printAPInt("value", N->getValue(), N->isUnsigned(), + /*ShouldSkipZero=*/false); + if (N->isUnsigned()) 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 b6446f47e03e..6ed621c407ec 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -246,7 +246,8 @@ DIMacroFile *DIBuilder::createTempMacroFile(DIMacroFile *Parent, DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val, bool IsUnsigned) { assert(!Name.empty() && "Unable to create enumerator without name"); - return DIEnumerator::get(VMContext, Val, IsUnsigned, Name); + return DIEnumerator::get(VMContext, APInt(64, Val, !IsUnsigned), IsUnsigned, + Name); } DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) { diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index cb4fab0088fb..db92c126ad74 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -347,7 +347,7 @@ DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode, DEFINE_GETIMPL_STORE(DISubrange, (CountNode, Lo), Ops); } -DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value, +DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, APInt Value, bool IsUnsigned, MDString *Name, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index e136bd54dd90..26e08d265605 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -355,19 +355,22 @@ template <> struct MDNodeKeyImpl { }; template <> struct MDNodeKeyImpl { - int64_t Value; + APInt Value; MDString *Name; bool IsUnsigned; - MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name) + MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name) : Value(Value), Name(Name), IsUnsigned(IsUnsigned) {} + MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name) + : Value(APInt(64, Value, !IsUnsigned)), Name(Name), + IsUnsigned(IsUnsigned) {} MDNodeKeyImpl(const DIEnumerator *N) : Value(N->getValue()), Name(N->getRawName()), IsUnsigned(N->isUnsigned()) {} bool isKeyOf(const DIEnumerator *RHS) const { - return Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() && - Name == RHS->getRawName(); + return APInt::isSameValue(Value, RHS->getValue()) && + IsUnsigned == RHS->isUnsigned() && Name == RHS->getRawName(); } unsigned getHashValue() const { return hash_combine(Value, Name); } diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp index e9ca8dad6e24..8df2273b5995 100644 --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -171,7 +171,12 @@ void BTFTypeEnum::completeType(BTFDebug &BDebug) { struct BTF::BTFEnum BTFEnum; BTFEnum.NameOff = BDebug.addString(Enum->getName()); // BTF enum value is 32bit, enforce it. - BTFEnum.Val = static_cast(Enum->getValue()); + uint32_t Value; + if (Enum->isUnsigned()) + Value = static_cast(Enum->getValue().getZExtValue()); + else + Value = static_cast(Enum->getValue().getSExtValue()); + BTFEnum.Val = Value; EnumValues.push_back(BTFEnum); } } diff --git a/llvm/test/Assembler/DIEnumeratorBig.ll b/llvm/test/Assembler/DIEnumeratorBig.ll new file mode 100644 index 000000000000..0e4742fd6735 --- /dev/null +++ b/llvm/test/Assembler/DIEnumeratorBig.ll @@ -0,0 +1,13 @@ +;; Round-trip test for enumeration members using more than 64 bits. + +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s + +!named = !{!0, !1, !2} + +; CHECK: !DIEnumerator(name: "D0", value: -170141183460469231731687303715884105728) +; CHECK: !DIEnumerator(name: "D1", value: 170141183460469231731687303715884105727) +!0 = !DIEnumerator(name: "D0", value: -170141183460469231731687303715884105728) +!1 = !DIEnumerator(name: "D1", value: 170141183460469231731687303715884105727) + +; CHECK: !DIEnumerator(name: "D1", value: 2722258935367507707706996859454145691648, isUnsigned: true) +!2 = !DIEnumerator(name: "D1", value: 2722258935367507707706996859454145691648, isUnsigned: true) diff --git a/llvm/test/Bitcode/DIEnumerator-10.0.ll b/llvm/test/Bitcode/DIEnumerator-10.0.ll new file mode 100644 index 000000000000..b0372d078453 --- /dev/null +++ b/llvm/test/Bitcode/DIEnumerator-10.0.ll @@ -0,0 +1,10 @@ +;; DIEnumerator-10.0.ll.bc was generated by llvm-as 10.0.0 +; RUN: llvm-dis < %s.bc | FileCheck %s +; RUN: verify-uselistorder < %s.bc + +!named = !{!0, !1} + +; CHECK: !DIEnumerator(name: "A0", value: 9223372036854775807) +!0 = !DIEnumerator(name: "A0", value: 9223372036854775807) +; CHECK: !DIEnumerator(name: "B0", value: -9223372036854775808) +!1 = !DIEnumerator(name: "B0", value: -9223372036854775808) diff --git a/llvm/test/Bitcode/DIEnumerator-10.0.ll.bc b/llvm/test/Bitcode/DIEnumerator-10.0.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..93b77a5d60855abb8867526dafcdc279dcb5fa97 GIT binary patch literal 1056 zcmXw2acCP=7=P)dxwOgN-C~%Dy*uvK3Sp?briw`~874PJbakfa9~CAhrG!qTT(Z!n zol4SVT&6+Ou7Bi@{?Xw65fn1$9|MOpxj17vMmL63Eg>OkHzg~<)iH1|Uo!WO_kHhs z_ult@-}n7Kueect%?v;<0ASL{554`tkD+(|U4Pdw9v{=7JE*CRj^yO|T;iquHr%hle>Px?$0jRzs+p(M zuG|Syn;cb6(3?TsuUXMq5uLfNyrwu-L`NDER+QuD(Z`Fz9ZV=F#-Gp0(u5q5lF?~A z7LcPBIl3lWZ@x$D1LAK#Y-VBO4WiD%7K(zk(K|(^6ooW0mCR55C{lS2;nCv@HawC`oNbV>wE=hi@Bu$qyzOC{_2;+ibQJ;cS%pH< zy`CIMDUOWjR2A2?qO+o)7+tDwJ*>wOsxV66glzre25be0`!!vgC3bmYmn9zh;S32I zJVfS$n(ogUZ2I9NUabGl(R+ESt?42Up1Sj!;y}eJD95+OQB@pGi=!y&E%5}HXP^^odky%>0b#jfgO}U2c-mkLUH#Sla77_P6yq9kn<4>NA=Q1PU+4{-X z=w{z$>E-Xf&wOI`SkQ6sEs}?kHuOhqhzt0_gp?EAsH6qaxuq=bQ8)63?s+;?-Q(z| zIX?1gBLMIEQR#?gr+~y=KRoF8x| gwaD&_4^e-2?wGKZL&N+l=yRQqPMw=M(ftd+e;vVirT_o{ literal 0 HcmV?d00001 diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index e886c77ebb6f..b60bcac55013 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -1186,7 +1186,7 @@ typedef MetadataTest DIEnumeratorTest; TEST_F(DIEnumeratorTest, get) { auto *N = DIEnumerator::get(Context, 7, false, "name"); EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag()); - EXPECT_EQ(7, N->getValue()); + EXPECT_EQ(7, N->getValue().getSExtValue()); EXPECT_FALSE(N->isUnsigned()); EXPECT_EQ("name", N->getName()); EXPECT_EQ(N, DIEnumerator::get(Context, 7, false, "name")); @@ -1199,6 +1199,15 @@ TEST_F(DIEnumeratorTest, get) { EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); } +TEST_F(DIEnumeratorTest, getWithLargeValues) { + auto *N = DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val"); + EXPECT_EQ(128U, N->getValue().countPopulation()); + EXPECT_EQ(N, + DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val")); + EXPECT_NE(N, + DIEnumerator::get(Context, APInt::getMinValue(128), false, "val")); +} + typedef MetadataTest DIBasicTypeTest; TEST_F(DIBasicTypeTest, get) {