diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3090,7 +3090,11 @@ bool IsSigned = ED->getIntegerType()->isSignedIntegerType(); for (const auto *Enum : ED->enumerators()) { const auto &InitVal = Enum->getInitVal(); - auto Value = IsSigned ? InitVal.getSExtValue() : InitVal.getZExtValue(); + uint64_t Value = + IsSigned + ? (InitVal.getNumWords() <= 1U ? InitVal.getSExtValue() : INT64_MIN) + : (InitVal.getNumWords() <= 1U ? InitVal.getZExtValue() + : UINT64_MAX); Enumerators.push_back( DBuilder.createEnumerator(Enum->getName(), Value, !IsSigned)); } diff --git a/clang/test/CodeGenCXX/debug-info-codeview-int128.cpp b/clang/test/CodeGenCXX/debug-info-codeview-int128.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-codeview-int128.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -triple x86_64-windows-gnu -debug-info-kind=limited -gcodeview -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LL +// RUN: %clang_cc1 -triple x86_64-windows-gnu -debug-info-kind=limited -gcodeview -S %s -o - | FileCheck %s --check-prefix=ASM + +enum class uns : __uint128_t { unsval = __uint128_t(1) << 64 }; +uns t1() { return uns::unsval; } + +// LL-LABEL: !DICompositeType(tag: DW_TAG_enumeration_type, name: "uns", {{.*}}) +// LL: !DIEnumerator(name: "unsval", value: 18446744073709551615, isUnsigned: true) + +// ASM-LABEL: .short 0x1203 # Record kind: LF_FIELDLIST +// ASM-NEXT: .short 0x1502 # Member kind: Enumerator ( LF_ENUMERATE ) +// ASM-NEXT: .short 0x3 # Attrs: Public +// ASM-NEXT: .short 0x800a +// ASM-NEXT: .quad 0xffffffffffffffff # EnumValue +// ASM-NEXT: .asciz "unsval" # Name + + +enum class sig : __int128 { sigval = -(__int128(1) << 64) }; +sig t2() { return sig::sigval; } + +// LL-LABEL: !DICompositeType(tag: DW_TAG_enumeration_type, name: "sig", {{.*}}) +// LL: !DIEnumerator(name: "sigval", value: -9223372036854775808) + +// ASM-LABEL: .short 0x1203 # Record kind: LF_FIELDLIST +// ASM-NEXT: .short 0x1502 # Member kind: Enumerator ( LF_ENUMERATE ) +// ASM-NEXT: .short 0x3 # Attrs: Public +// ASM-NEXT: .short 0x800a +// ASM-NEXT: .quad 0x8000000000000000 # EnumValue +// ASM-NEXT: .asciz "sigval" # Name + + +struct test { + static const __uint128_t u128 = __uint128_t(1) << 64; + static const __int128 s128 = -(__int128(1) << 64); +}; +test t3() { return test(); } + +// LL-LABEL: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "test", {{.*}}) +// LL: !DIDerivedType(tag: DW_TAG_member, name: "u128", {{.*}}, flags: DIFlagStaticMember, extraData: i128 18446744073709551616) +// LL: !DIDerivedType(tag: DW_TAG_member, name: "s128", {{.*}}, flags: DIFlagStaticMember, extraData: i128 -18446744073709551616) + +// ASM-LABEL: .short 0x1203 # Record kind: LF_FIELDLIST + +// ASM-LABEL: .short 0x150e # Member kind: StaticDataMember ( LF_STMEMBER ) +// ASM-NEXT: .short 0x3 # Attrs: Public +// ASM-NEXT: .long 0x100e # Type: const +// ASM-NEXT: .asciz "u128" # Name + +// ASM-LABEL: .short 0x150e # Member kind: StaticDataMember ( LF_STMEMBER ) +// ASM-NEXT: .short 0x3 # Attrs: Public +// ASM-NEXT: .long 0x100f # Type: const +// ASM-NEXT: .asciz "s128" # Name diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -181,7 +181,8 @@ DIFile *File); /// Create a single enumerator value. - DIEnumerator *createEnumerator(StringRef Name, int64_t Val, bool IsUnsigned = false); + DIEnumerator *createEnumerator(StringRef Name, uint64_t Val, + bool IsUnsigned = false); /// Create a DWARF unspecified type. DIBasicType *createUnspecifiedType(StringRef Name); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -315,6 +315,8 @@ void collectDebugInfoForGlobals(); void emitDebugInfoForGlobals(); void emitGlobalVariableList(ArrayRef Globals); + void emitConstantSymbolRecord(const DIType *DTy, APSInt &Value, + const std::string &QualifiedName); void emitDebugInfoForGlobal(const CVGlobalVariable &CVGV); void emitStaticConstMemberList(); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -3157,6 +3157,28 @@ } } +void CodeViewDebug::emitConstantSymbolRecord(const DIType *DTy, APSInt &Value, + const std::string &QualifiedName) { + MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT); + OS.AddComment("Type"); + OS.emitInt32(getTypeIndex(DTy).getIndex()); + + // TODO: Need to support bigger ints like __int128. + OS.AddComment("Value"); + + // Encoded integers shouldn't need more than 10 bytes. + uint8_t Data[10]; + BinaryStreamWriter Writer(Data, llvm::support::endianness::little); + CodeViewRecordIO IO(Writer); + cantFail(IO.mapEncodedInteger(Value)); + StringRef SRef((char *)Data, Writer.getOffset()); + OS.emitBinaryData(SRef); + + OS.AddComment("Name"); + emitNullTerminatedSymbolName(OS, QualifiedName); + endSymbolRecord(SConstantEnd); +} + void CodeViewDebug::emitStaticConstMemberList() { for (const DIDerivedType *DTy : StaticConstMembers) { const DIScope *Scope = DTy->getScope(); @@ -3172,24 +3194,8 @@ else llvm_unreachable("cannot emit a constant without a value"); - std::string QualifiedName = getFullyQualifiedName(Scope, DTy->getName()); - - MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT); - OS.AddComment("Type"); - OS.emitInt32(getTypeIndex(DTy->getBaseType()).getIndex()); - OS.AddComment("Value"); - - // Encoded integers shouldn't need more than 10 bytes. - uint8_t Data[10]; - BinaryStreamWriter Writer(Data, llvm::support::endianness::little); - CodeViewRecordIO IO(Writer); - cantFail(IO.mapEncodedInteger(Value)); - StringRef SRef((char *)Data, Writer.getOffset()); - OS.emitBinaryData(SRef); - - OS.AddComment("Name"); - emitNullTerminatedSymbolName(OS, QualifiedName); - endSymbolRecord(SConstantEnd); + emitConstantSymbolRecord(DTy->getBaseType(), Value, + getFullyQualifiedName(Scope, DTy->getName())); } } @@ -3253,22 +3259,6 @@ ? true : DebugHandlerBase::isUnsignedDIType(DIGV->getType()); APSInt Value(APInt(/*BitWidth=*/64, DIE->getElement(1)), isUnsigned); - - MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT); - OS.AddComment("Type"); - OS.emitInt32(getTypeIndex(DIGV->getType()).getIndex()); - OS.AddComment("Value"); - - // Encoded integers shouldn't need more than 10 bytes. - uint8_t data[10]; - BinaryStreamWriter Writer(data, llvm::support::endianness::little); - CodeViewRecordIO IO(Writer); - cantFail(IO.mapEncodedInteger(Value)); - StringRef SRef((char *)data, Writer.getOffset()); - OS.emitBinaryData(SRef); - - OS.AddComment("Name"); - emitNullTerminatedSymbolName(OS, QualifiedName); - endSymbolRecord(SConstantEnd); + emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName); } } diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp --- a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -188,14 +188,21 @@ Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value, const Twine &Comment) { if (isStreaming()) { + // FIXME: We also need to handle big values here, but it's + // not clear how we can excercise this code path yet. if (Value.isSigned()) emitEncodedSignedInteger(Value.getSExtValue(), Comment); else emitEncodedUnsignedInteger(Value.getZExtValue(), Comment); } else if (isWriting()) { - if (Value.isSigned()) - return writeEncodedSignedInteger(Value.getSExtValue()); - return writeEncodedUnsignedInteger(Value.getZExtValue()); + if (Value.isSigned()) { + int64_t Val = + Value.getNumWords() <= 1U ? Value.getSExtValue() : INT64_MIN; + return writeEncodedSignedInteger(Val); + } + uint64_t Val = + Value.getNumWords() <= 1U ? Value.getZExtValue() : UINT64_MAX; + return writeEncodedUnsignedInteger(Val); } else return consume(*Reader, Value); return Error::success(); @@ -273,6 +280,7 @@ void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value, const Twine &Comment) { + // FIXME: There are no test cases covering this function. if (Value >= std::numeric_limits::min()) { Streamer->emitIntValue(LF_CHAR, 2); emitComment(Comment); @@ -291,8 +299,8 @@ } else { Streamer->emitIntValue(LF_QUADWORD, 2); emitComment(Comment); - Streamer->emitIntValue(Value, 4); - incrStreamedLen(6); + Streamer->emitIntValue(Value, 4); // FIXME: Why not 8 (size of quadword)? + incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)? } } @@ -313,10 +321,11 @@ Streamer->emitIntValue(Value, 4); incrStreamedLen(6); } else { + // FIXME: There are no test cases covering this block. Streamer->emitIntValue(LF_UQUADWORD, 2); emitComment(Comment); Streamer->emitIntValue(Value, 8); - incrStreamedLen(6); + incrStreamedLen(6); // FIXME: Why not 10 (8 + 2)? } } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -243,7 +243,7 @@ return MF; } -DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val, +DIEnumerator *DIBuilder::createEnumerator(StringRef Name, uint64_t Val, bool IsUnsigned) { assert(!Name.empty() && "Unable to create enumerator without name"); return DIEnumerator::get(VMContext, APInt(64, Val, !IsUnsigned), IsUnsigned,