[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-26 Thread Matheus Izvekov via Phabricator via cfe-commits
mizvekov added a comment.

In D105320#2905887 , @rnk wrote:

> Yes, I filed https://bugs.llvm.org/show_bug.cgi?id=51221 for it. I plan to 
> disable the test under asan for now.

:-(

Thanks for taking care of it though!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-26 Thread Reid Kleckner via Phabricator via cfe-commits
rnk added a comment.

Yes, I filed https://bugs.llvm.org/show_bug.cgi?id=51221 for it. I plan to 
disable the test under asan for now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-26 Thread Matheus Izvekov via Phabricator via cfe-commits
mizvekov added a comment.

I received this report from one of the bots: 
https://lab.llvm.org/buildbot/#/builders/5/builds/9633/steps/13/logs/stdio

  `
  FAIL: Clang :: CodeGenCXX/debug-info-enum-i128.cpp (5356 of 77963)
   TEST 'Clang :: CodeGenCXX/debug-info-enum-i128.cpp' 
FAILED 
  Script:
  --
  : 'RUN: at line 1';   
/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/clang -cc1 
-internal-isystem 
/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/lib/clang/13.0.0/include 
-nostdsysteminc 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/test/CodeGenCXX/debug-info-enum-i128.cpp
 -triple x86_64-windows-msvc -gcodeview -debug-info-kind=limited -emit-llvm -o 
- | /b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/FileCheck 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/test/CodeGenCXX/debug-info-enum-i128.cpp
  : 'RUN: at line 2';   
/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/clang -cc1 
-internal-isystem 
/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/lib/clang/13.0.0/include 
-nostdsysteminc 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/test/CodeGenCXX/debug-info-enum-i128.cpp
 -triple x86_64-linux-gnu -debug-info-kind=limited -emit-llvm -o - | 
/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/FileCheck 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/test/CodeGenCXX/debug-info-enum-i128.cpp
  --
  Exit Code: 1
  Command Output (stderr):
  --
  =
  ==22208==ERROR: LeakSanitizer: detected memory leaks
  Direct leak of 16 byte(s) in 1 object(s) allocated from:
  #0 0x72240dd in operator new[](unsigned long) 
/b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_new_delete.cpp:98:3
  #1 0xe21510a in getMemory 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Support/APInt.cpp:46:10
  #2 0xe21510a in llvm::APInt::initSlowCase(llvm::APInt const&) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/lib/Support/APInt.cpp:87:12
  #3 0x164a460b in APInt 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/include/llvm/ADT/APInt.h:321:7
  #4 0x164a460b in APSInt 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/include/llvm/ADT/APSInt.h:22:22
  #5 0x164a460b in EnumConstantDecl 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/include/clang/AST/Decl.h:3048:62
  #6 0x164a460b in clang::EnumConstantDecl::Create(clang::ASTContext&, 
clang::EnumDecl*, clang::SourceLocation, clang::IdentifierInfo*, 
clang::QualType, clang::Expr*, llvm::APSInt const&) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/AST/Decl.cpp:4916:22
  #7 0x14605da3 in clang::Sema::CheckEnumConstant(clang::EnumDecl*, 
clang::EnumConstantDecl*, clang::SourceLocation, clang::IdentifierInfo*, 
clang::Expr*) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Sema/SemaDecl.cpp:17905:10
  #8 0x14607d80 in clang::Sema::ActOnEnumConstant(clang::Scope*, 
clang::Decl*, clang::Decl*, clang::SourceLocation, clang::IdentifierInfo*, 
clang::ParsedAttributesView const&, clang::SourceLocation, clang::Expr*) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Sema/SemaDecl.cpp:17970:5
  #9 0x13ead361 in clang::Parser::ParseEnumBody(clang::SourceLocation, 
clang::Decl*) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Parse/ParseDecl.cpp:4855:35
  #10 0x13e9f97b in 
clang::Parser::ParseEnumSpecifier(clang::SourceLocation, clang::DeclSpec&, 
clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, 
clang::Parser::DeclSpecContext) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Parse/ParseDecl.cpp:4774:5
  #11 0x13e7e7e3 in 
clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, 
clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, 
clang::Parser::DeclSpecContext, clang::Parser::LateParsedAttrList*) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Parse/ParseDecl.cpp:3999:7
  #12 0x13d47ec6 in 
clang::Parser::ParseDeclOrFunctionDefInternal(clang::ParsedAttributesWithRange&,
 clang::ParsingDeclSpec&, clang::AccessSpecifier) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Parse/Parser.cpp:1045:3
  #13 0x13d47183 in 
clang::Parser::ParseDeclarationOrFunctionDefinition(clang::ParsedAttributesWithRange&,
 clang::ParsingDeclSpec*, clang::AccessSpecifier) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Parse/Parser.cpp:1153:12
  #14 0x13d4305f in 
clang::Parser::ParseExternalDeclaration(clang::ParsedAttributesWithRange&, 
clang::ParsingDeclSpec*) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Parse/Parser.cpp:975:12
  #15 0x13d3bcb8 in 
clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&, bool) 
/b/sanitizer-x86_64-linux-fast/build/llvm-project/clang/lib/Parse/Parser.cpp:720:12
  #16 0x13d22d2c in clang::ParseAST(clang::Sema&, bool, bool) 

[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-26 Thread Matheus Izvekov via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf84c70a37939: [CodeView] Saturate values bigger than 
supported by APInt. (authored by mizvekov).

Changed prior to commit:
  https://reviews.llvm.org/D105320?vs=361547=361771#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

Files:
  llvm/include/llvm/ADT/APInt.h
  llvm/include/llvm/IR/DIBuilder.h
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
  llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
  llvm/lib/IR/DIBuilder.cpp
  llvm/test/DebugInfo/COFF/integer-128.ll

Index: llvm/test/DebugInfo/COFF/integer-128.ll
===
--- /dev/null
+++ llvm/test/DebugInfo/COFF/integer-128.ll
@@ -0,0 +1,136 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+
+; // C++ source to regenerate:
+; enum class uns : __uint128_t { unsval = __uint128_t(1) << 64 };
+; uns t1() { return uns::unsval; }
+; enum class sig : __int128 { sigval = -(__int128(1) << 64) };
+; sig t2() { return sig::sigval; }
+; struct test {
+;   static const __uint128_t u128 = __uint128_t(1) << 64;
+;   static const __int128s128 = -(__int128(1) << 64);
+; };
+; test t3() { return test(); }
+; 
+; $ clang a.cpp -S -emit-llvm -g -gcodeview
+
+; --
+
+; ASM-LABEL: .long   241 # Symbol subsection for globals
+;
+; ASM-LABEL: .short	4359# Record kind: S_CONSTANT
+; ASM-NEXT:  .long	4110# Type
+; ASM-NEXT:  .byte	0x0a, 0x80, 0xff, 0xff  # Value
+; ASM-NEXT:  .byte	0xff, 0xff, 0xff, 0xff
+; ASM-NEXT:  .byte	0xff, 0xff
+; ASM-NEXT:  .asciz	"test::u128"# Name
+; ASM-NEXT:  .p2align	2
+;
+; ASM-LABEL: .short	4359# Record kind: S_CONSTANT
+; ASM-NEXT:  .long	4111# Type
+; ASM-NEXT:  .byte	0x09, 0x80, 0x00, 0x00  # Value
+; ASM-NEXT:  .byte	0x00, 0x00, 0x00, 0x00
+; ASM-NEXT:  .byte	0x00, 0x80
+; ASM-NEXT:  .asciz	"test::s128"# Name
+; ASM-NEXT:  .p2align	2
+;
+; 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	0x  # EnumValue
+; ASM-NEXT:  .asciz	"unsval"# Name
+;
+; 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	0x  # EnumValue
+; ASM-NEXT:  .asciz	"sigval"# Name
+
+; --
+
+; ModuleID = 'a.cpp'
+source_filename = "a.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+%struct.test = type { i8 }
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local <2 x i64> @_Z2t1v() #0 !dbg !23 {
+entry:
+  %retval = alloca i128, align 16
+  store i128 18446744073709551616, i128* %retval, align 16, !dbg !27
+  %0 = bitcast i128* %retval to <2 x i64>*, !dbg !27
+  %1 = load <2 x i64>, <2 x i64>* %0, align 16, !dbg !27
+  ret <2 x i64> %1, !dbg !27
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local <2 x i64> @_Z2t2v() #0 !dbg !28 {
+entry:
+  %retval = alloca i128, align 16
+  store i128 -18446744073709551616, i128* %retval, align 16, !dbg !31
+  %0 = bitcast i128* %retval to <2 x i64>*, !dbg !31
+  %1 = load <2 x i64>, <2 x i64>* %0, align 16, !dbg !31
+  ret <2 x i64> %1, !dbg !31
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local i8 @_Z2t3v() #1 !dbg !32 {
+entry:
+  %retval = alloca %struct.test, align 1
+  %coerce.dive = getelementptr inbounds %struct.test, %struct.test* %retval, i32 0, i32 0, !dbg !41
+  %0 = load i8, i8* %coerce.dive, align 1, !dbg !41
+  ret i8 %0, !dbg !41
+}
+
+attributes #0 = { mustprogress noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="128" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+attributes #1 = { mustprogress noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+
+!llvm.dbg.cu = 

[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-26 Thread Matheus Izvekov via Phabricator via cfe-commits
mizvekov added inline comments.



Comment at: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp:3167
+
+  // TODO: Need to support bigger ints like __int128.
+  OS.AddComment("Value");

rnk wrote:
> I don't think we need a TODO here. If Microsoft ever adds an encoding for 
> large integers, the code change will be elsewhere, and in the process of 
> testing, this size 10 array is bounds checked during the writing process, so 
> we don't need this comment to remind us to change this code.
I agree the comment does not belong here, but I think we have encodings 
already, both for the value and the type.

`CodeViewTypes.def`:
```
CV_TYPE(LF_OCTWORD, 0x8017)
CV_TYPE(LF_UOCTWORD, 0x8018)
```

`CodeViewDebug.cpp`:
```
  case dwarf::DW_ATE_signed:
switch (ByteSize) {
case 1:  STK = SimpleTypeKind::SignedCharacter; break;
case 2:  STK = SimpleTypeKind::Int16Short;  break;
case 4:  STK = SimpleTypeKind::Int32;   break;
case 8:  STK = SimpleTypeKind::Int64Quad;   break;
case 16: STK = SimpleTypeKind::Int128Oct;   break; // <---
}
```

Unless it would be risky to try to use them, if for example the Microsoft 
tooling would have trouble digesting it?

FWIW I would have considered adding this support, but then I found all those 
other problems, and time is a bit short until release branching.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-26 Thread Reid Kleckner via Phabricator via cfe-commits
rnk accepted this revision.
rnk added a comment.
This revision is now accepted and ready to land.

lgtm with minor comment adjustments




Comment at: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp:3167
+
+  // TODO: Need to support bigger ints like __int128.
+  OS.AddComment("Value");

I don't think we need a TODO here. If Microsoft ever adds an encoding for large 
integers, the code change will be elsewhere, and in the process of testing, 
this size 10 array is bounds checked during the writing process, so we don't 
need this comment to remind us to change this code.



Comment at: llvm/test/DebugInfo/COFF/integer-128.ll:22
+; ASM-NEXT:  .long 4110# Type
+; ASM-NEXT:  .byte 0x0a, 0x80, 0xff, 0xff  # Value
+; ASM-NEXT:  .byte 0xff, 0xff, 0xff, 0xff

(no AI) I see, in the future we should make this use the "streaming" output 
style so this comes out as `.short .quad` directives.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-25 Thread Matheus Izvekov via Phabricator via cfe-commits
mizvekov updated this revision to Diff 361547.
mizvekov added a comment.

.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

Files:
  llvm/include/llvm/ADT/APInt.h
  llvm/include/llvm/IR/DIBuilder.h
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
  llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
  llvm/lib/IR/DIBuilder.cpp
  llvm/test/DebugInfo/COFF/integer-128.ll

Index: llvm/test/DebugInfo/COFF/integer-128.ll
===
--- /dev/null
+++ llvm/test/DebugInfo/COFF/integer-128.ll
@@ -0,0 +1,136 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+
+; // C++ source to regenerate:
+; enum class uns : __uint128_t { unsval = __uint128_t(1) << 64 };
+; uns t1() { return uns::unsval; }
+; enum class sig : __int128 { sigval = -(__int128(1) << 64) };
+; sig t2() { return sig::sigval; }
+; struct test {
+;   static const __uint128_t u128 = __uint128_t(1) << 64;
+;   static const __int128s128 = -(__int128(1) << 64);
+; };
+; test t3() { return test(); }
+; 
+; $ clang a.cpp -S -emit-llvm -g -gcodeview
+
+; --
+
+; ASM-LABEL: .long   241 # Symbol subsection for globals
+;
+; ASM-LABEL: .short	4359# Record kind: S_CONSTANT
+; ASM-NEXT:  .long	4110# Type
+; ASM-NEXT:  .byte	0x0a, 0x80, 0xff, 0xff  # Value
+; ASM-NEXT:  .byte	0xff, 0xff, 0xff, 0xff
+; ASM-NEXT:  .byte	0xff, 0xff
+; ASM-NEXT:  .asciz	"test::u128"# Name
+; ASM-NEXT:  .p2align	2
+;
+; ASM-LABEL: .short	4359# Record kind: S_CONSTANT
+; ASM-NEXT:  .long	4111# Type
+; ASM-NEXT:  .byte	0x09, 0x80, 0x00, 0x00  # Value
+; ASM-NEXT:  .byte	0x00, 0x00, 0x00, 0x00
+; ASM-NEXT:  .byte	0x00, 0x80
+; ASM-NEXT:  .asciz	"test::s128"# Name
+; ASM-NEXT:  .p2align	2
+;
+; 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	0x  # EnumValue
+; ASM-NEXT:  .asciz	"unsval"# Name
+;
+; 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	0x  # EnumValue
+; ASM-NEXT:  .asciz	"sigval"# Name
+
+; --
+
+; ModuleID = 'a.cpp'
+source_filename = "a.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+%struct.test = type { i8 }
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local <2 x i64> @_Z2t1v() #0 !dbg !23 {
+entry:
+  %retval = alloca i128, align 16
+  store i128 18446744073709551616, i128* %retval, align 16, !dbg !27
+  %0 = bitcast i128* %retval to <2 x i64>*, !dbg !27
+  %1 = load <2 x i64>, <2 x i64>* %0, align 16, !dbg !27
+  ret <2 x i64> %1, !dbg !27
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local <2 x i64> @_Z2t2v() #0 !dbg !28 {
+entry:
+  %retval = alloca i128, align 16
+  store i128 -18446744073709551616, i128* %retval, align 16, !dbg !31
+  %0 = bitcast i128* %retval to <2 x i64>*, !dbg !31
+  %1 = load <2 x i64>, <2 x i64>* %0, align 16, !dbg !31
+  ret <2 x i64> %1, !dbg !31
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local i8 @_Z2t3v() #1 !dbg !32 {
+entry:
+  %retval = alloca %struct.test, align 1
+  %coerce.dive = getelementptr inbounds %struct.test, %struct.test* %retval, i32 0, i32 0, !dbg !41
+  %0 = load i8, i8* %coerce.dive, align 1, !dbg !41
+  ret i8 %0, !dbg !41
+}
+
+attributes #0 = { mustprogress noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="128" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+attributes #1 = { mustprogress noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!19, !20, !21}
+!llvm.ident = !{!22}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, 

[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-25 Thread Matheus Izvekov via Phabricator via cfe-commits
mizvekov updated this revision to Diff 361543.
mizvekov marked 4 inline comments as done.
mizvekov added a comment.

- Expose and use APInt::isSingleWord.
- Use ApInt::getLimitedValue.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

Files:
  llvm/include/llvm/ADT/APInt.h
  llvm/include/llvm/IR/DIBuilder.h
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
  llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
  llvm/lib/IR/DIBuilder.cpp
  llvm/test/DebugInfo/COFF/integer-128.ll

Index: llvm/test/DebugInfo/COFF/integer-128.ll
===
--- /dev/null
+++ llvm/test/DebugInfo/COFF/integer-128.ll
@@ -0,0 +1,136 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+
+; // C++ source to regenerate:
+; enum class uns : __uint128_t { unsval = __uint128_t(1) << 64 };
+; uns t1() { return uns::unsval; }
+; enum class sig : __int128 { sigval = -(__int128(1) << 64) };
+; sig t2() { return sig::sigval; }
+; struct test {
+;   static const __uint128_t u128 = __uint128_t(1) << 64;
+;   static const __int128s128 = -(__int128(1) << 64);
+; };
+; test t3() { return test(); }
+; 
+; $ clang a.cpp -S -emit-llvm -g -gcodeview
+
+; --
+
+; ASM-LABEL: .long   241 # Symbol subsection for globals
+;
+; ASM-LABEL: .short	4359# Record kind: S_CONSTANT
+; ASM-NEXT:  .long	4110# Type
+; ASM-NEXT:  .byte	0x0a, 0x80, 0xff, 0xff  # Value
+; ASM-NEXT:  .byte	0xff, 0xff, 0xff, 0xff
+; ASM-NEXT:  .byte	0xff, 0xff
+; ASM-NEXT:  .asciz	"test::u128"# Name
+; ASM-NEXT:  .p2align	2
+;
+; ASM-LABEL: .short	4359# Record kind: S_CONSTANT
+; ASM-NEXT:  .long	4111# Type
+; ASM-NEXT:  .byte	0x09, 0x80, 0x00, 0x00  # Value
+; ASM-NEXT:  .byte	0x00, 0x00, 0x00, 0x00
+; ASM-NEXT:  .byte	0x00, 0x80
+; ASM-NEXT:  .asciz	"test::s128"# Name
+; ASM-NEXT:  .p2align	2
+;
+; 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	0x  # EnumValue
+; ASM-NEXT:  .asciz	"unsval"# Name
+;
+; 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	0x  # EnumValue
+; ASM-NEXT:  .asciz	"sigval"# Name
+
+; --
+
+; ModuleID = 'a.cpp'
+source_filename = "a.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+%struct.test = type { i8 }
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local <2 x i64> @_Z2t1v() #0 !dbg !23 {
+entry:
+  %retval = alloca i128, align 16
+  store i128 18446744073709551616, i128* %retval, align 16, !dbg !27
+  %0 = bitcast i128* %retval to <2 x i64>*, !dbg !27
+  %1 = load <2 x i64>, <2 x i64>* %0, align 16, !dbg !27
+  ret <2 x i64> %1, !dbg !27
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local <2 x i64> @_Z2t2v() #0 !dbg !28 {
+entry:
+  %retval = alloca i128, align 16
+  store i128 -18446744073709551616, i128* %retval, align 16, !dbg !31
+  %0 = bitcast i128* %retval to <2 x i64>*, !dbg !31
+  %1 = load <2 x i64>, <2 x i64>* %0, align 16, !dbg !31
+  ret <2 x i64> %1, !dbg !31
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local i8 @_Z2t3v() #1 !dbg !32 {
+entry:
+  %retval = alloca %struct.test, align 1
+  %coerce.dive = getelementptr inbounds %struct.test, %struct.test* %retval, i32 0, i32 0, !dbg !41
+  %0 = load i8, i8* %coerce.dive, align 1, !dbg !41
+  ret i8 %0, !dbg !41
+}
+
+attributes #0 = { mustprogress noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="128" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+attributes #1 = { mustprogress noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!19, !20, !21}
+!llvm.ident = !{!22}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, 

[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-25 Thread Matheus Izvekov via Phabricator via cfe-commits
mizvekov updated this revision to Diff 361527.
mizvekov marked an inline comment as done.
mizvekov added a comment.

- rebase on top of D106585 
- Reimplement test based on IR


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

Files:
  llvm/include/llvm/IR/DIBuilder.h
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
  llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
  llvm/lib/IR/DIBuilder.cpp
  llvm/test/DebugInfo/COFF/integer-128.ll

Index: llvm/test/DebugInfo/COFF/integer-128.ll
===
--- /dev/null
+++ llvm/test/DebugInfo/COFF/integer-128.ll
@@ -0,0 +1,136 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+
+; // C++ source to regenerate:
+; enum class uns : __uint128_t { unsval = __uint128_t(1) << 64 };
+; uns t1() { return uns::unsval; }
+; enum class sig : __int128 { sigval = -(__int128(1) << 64) };
+; sig t2() { return sig::sigval; }
+; struct test {
+;   static const __uint128_t u128 = __uint128_t(1) << 64;
+;   static const __int128s128 = -(__int128(1) << 64);
+; };
+; test t3() { return test(); }
+; 
+; $ clang a.cpp -S -emit-llvm -g -gcodeview
+
+; --
+
+; ASM-LABEL: .long   241 # Symbol subsection for globals
+;
+; ASM-LABEL: .short	4359# Record kind: S_CONSTANT
+; ASM-NEXT:  .long	4110# Type
+; ASM-NEXT:  .byte	0x0a, 0x80, 0xff, 0xff  # Value
+; ASM-NEXT:  .byte	0xff, 0xff, 0xff, 0xff
+; ASM-NEXT:  .byte	0xff, 0xff
+; ASM-NEXT:  .asciz	"test::u128"# Name
+; ASM-NEXT:  .p2align	2
+;
+; ASM-LABEL: .short	4359# Record kind: S_CONSTANT
+; ASM-NEXT:  .long	4111# Type
+; ASM-NEXT:  .byte	0x09, 0x80, 0x00, 0x00  # Value
+; ASM-NEXT:  .byte	0x00, 0x00, 0x00, 0x00
+; ASM-NEXT:  .byte	0x00, 0x80
+; ASM-NEXT:  .asciz	"test::s128"# Name
+; ASM-NEXT:  .p2align	2
+;
+; 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	0x  # EnumValue
+; ASM-NEXT:  .asciz	"unsval"# Name
+;
+; 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	0x  # EnumValue
+; ASM-NEXT:  .asciz	"sigval"# Name
+
+; --
+
+; ModuleID = 'a.cpp'
+source_filename = "a.cpp"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-gnu"
+
+%struct.test = type { i8 }
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local <2 x i64> @_Z2t1v() #0 !dbg !23 {
+entry:
+  %retval = alloca i128, align 16
+  store i128 18446744073709551616, i128* %retval, align 16, !dbg !27
+  %0 = bitcast i128* %retval to <2 x i64>*, !dbg !27
+  %1 = load <2 x i64>, <2 x i64>* %0, align 16, !dbg !27
+  ret <2 x i64> %1, !dbg !27
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local <2 x i64> @_Z2t2v() #0 !dbg !28 {
+entry:
+  %retval = alloca i128, align 16
+  store i128 -18446744073709551616, i128* %retval, align 16, !dbg !31
+  %0 = bitcast i128* %retval to <2 x i64>*, !dbg !31
+  %1 = load <2 x i64>, <2 x i64>* %0, align 16, !dbg !31
+  ret <2 x i64> %1, !dbg !31
+}
+
+; Function Attrs: mustprogress noinline nounwind optnone
+define dso_local i8 @_Z2t3v() #1 !dbg !32 {
+entry:
+  %retval = alloca %struct.test, align 1
+  %coerce.dive = getelementptr inbounds %struct.test, %struct.test* %retval, i32 0, i32 0, !dbg !41
+  %0 = load i8, i8* %coerce.dive, align 1, !dbg !41
+  ret i8 %0, !dbg !41
+}
+
+attributes #0 = { mustprogress noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="128" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+attributes #1 = { mustprogress noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!19, !20, !21}
+!llvm.ident = !{!22}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: 

[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-22 Thread Reid Kleckner via Phabricator via cfe-commits
rnk added subscribers: dblaikie, MaskRay, LemonBoy.
rnk added a comment.

I decided it would be faster and more convenient to respond in the form of a 
code review for clang, so here it is: D106585 

Assuming that goes through, go ahead and rebase onto that after it lands.




Comment at: clang/test/CodeGenCXX/debug-info-codeview-int128.cpp:1
+// 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

FWIW this actually isn't codeview specific. The existing code crashes if you 
compile for DWARF too:
https://gcc.godbolt.org/z/3ox8c87Y4

To channel @dblaikie , this test should be split up: ensure that clang produces 
the right LLVM IR, then add a codeview specific LLVM IR test case. We prefer to 
test the smallest testable unit.



Comment at: llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp:200
+  int64_t Val =
+  Value.getNumWords() <= 1U ? Value.getSExtValue() : INT64_MIN;
+  return writeEncodedSignedInteger(Val);

You can use `Value.isSingleWord()` for a simpler condition.



Comment at: llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp:204
+uint64_t Val =
+Value.getNumWords() <= 1U ? Value.getZExtValue() : UINT64_MAX;
+return writeEncodedUnsignedInteger(Val);

This can be `Value.getLimitedValue()`.



Comment at: llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp:283
 const Twine ) {
+  // FIXME: There are no test cases covering this function.
   if (Value >= std::numeric_limits::min()) {

I think this particular method is uncovered because of a separate bug. We 
always consider enumerators to be unsigned:
https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp#L2120

I'm not sure if that's a bug or if it is intended, but that's why this is 
relatively uncovered.



Comment at: llvm/lib/IR/DIBuilder.cpp:249
   assert(!Name.empty() && "Unable to create enumerator without name");
   return DIEnumerator::get(VMContext, APInt(64, Val, !IsUnsigned), IsUnsigned,
Name);

Since DIEnumerator actually stores an APInt, can you add an overload that 
accepts an APSInt and call that from clang instead? The implementation will 
have to decompose the sign bit and slice out the APInt portion, but that seems 
like a better way of handling this.

I noticed the APInt change to DIEnumerator is new as of D62475, so April 2020. 
+@maskray @LemonBoy 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-21 Thread Matheus Izvekov via Phabricator via cfe-commits
mizvekov updated this revision to Diff 360648.
mizvekov added a comment.

.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

Files:
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/test/CodeGenCXX/debug-info-codeview-int128.cpp
  llvm/include/llvm/IR/DIBuilder.h
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
  llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
  llvm/lib/IR/DIBuilder.cpp

Index: llvm/lib/IR/DIBuilder.cpp
===
--- llvm/lib/IR/DIBuilder.cpp
+++ 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,
Index: llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
===
--- llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
+++ llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -188,14 +188,21 @@
 
 Error CodeViewRecordIO::mapEncodedInteger(APSInt , const Twine ) {
   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 ,
 const Twine ) {
+  // 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)?
   }
 }
 
Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
===
--- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -315,6 +315,8 @@
   void collectDebugInfoForGlobals();
   void emitDebugInfoForGlobals();
   void emitGlobalVariableList(ArrayRef Globals);
+  void emitConstantSymbolRecord(const DIType *DTy, APSInt ,
+const std::string );
   void emitDebugInfoForGlobal(const CVGlobalVariable );
   void emitStaticConstMemberList();
 
Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
===
--- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -3157,6 +3157,28 @@
   }
 }
 
+void CodeViewDebug::emitConstantSymbolRecord(const DIType *DTy, APSInt ,
+ const std::string ) {
+  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 

[PATCH] D105320: [CodeView] Saturate values bigger than supported by APInt.

2021-07-21 Thread Matheus Izvekov via Phabricator via cfe-commits
mizvekov updated this revision to Diff 360645.
mizvekov added a comment.

- Really `git add` the test case this time.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105320/new/

https://reviews.llvm.org/D105320

Files:
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/test/CodeGenCXX/debug-info-codeview-int128.cpp
  llvm/include/llvm/IR/DIBuilder.h
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
  llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
  llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
  llvm/lib/IR/DIBuilder.cpp

Index: llvm/lib/IR/DIBuilder.cpp
===
--- llvm/lib/IR/DIBuilder.cpp
+++ 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,
Index: llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
===
--- llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
+++ llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -188,14 +188,21 @@
 
 Error CodeViewRecordIO::mapEncodedInteger(APSInt , const Twine ) {
   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 ,
 const Twine ) {
+  // 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)?
   }
 }
 
Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
===
--- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -315,6 +315,8 @@
   void collectDebugInfoForGlobals();
   void emitDebugInfoForGlobals();
   void emitGlobalVariableList(ArrayRef Globals);
+  void emitConstantSymbolRecord(const DIType *DTy, APSInt ,
+const std::string );
   void emitDebugInfoForGlobal(const CVGlobalVariable );
   void emitStaticConstMemberList();
 
Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
===
--- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -3157,6 +3157,28 @@
   }
 }
 
+void CodeViewDebug::emitConstantSymbolRecord(const DIType *DTy, APSInt ,
+ const std::string ) {
+  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