summaryrefslogtreecommitdiffstats
path: root/llvm/test/DebugInfo/COFF
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2018-10-01 21:59:45 +0000
committerReid Kleckner <rnk@google.com>2018-10-01 21:59:45 +0000
commit9ea2c01264eac590bf149cbb882a1f1bd1c2bc1b (patch)
treeb19c87e9c7ee5cb156a3d33e3632eabff4102235 /llvm/test/DebugInfo/COFF
parent8e57b07f668528fa4ed893093342ba8d899a1556 (diff)
downloadbcm5719-llvm-9ea2c01264eac590bf149cbb882a1f1bd1c2bc1b.tar.gz
bcm5719-llvm-9ea2c01264eac590bf149cbb882a1f1bd1c2bc1b.zip
[codeview] Emit S_FRAMEPROC and use S_DEFRANGE_FRAMEPOINTER_REL
Summary: Before this change, LLVM would always describe locals on the stack as being relative to some specific register, RSP, ESP, EBP, ESI, etc. Variables in stack memory are pretty common, so there is a special S_DEFRANGE_FRAMEPOINTER_REL symbol for them. This change uses it to reduce the size of our debug info. On top of the size savings, there are cases on 32-bit x86 where local variables are addressed from ESP, but ESP changes across the function. Unlike in DWARF, there is no FPO data to describe the stack adjustments made to push arguments onto the stack and pop them off after the call, which makes it hard for the debugger to find the local variables in frames further up the stack. To handle this, CodeView has a special VFRAME register, which corresponds to the $T0 variable set by our FPO data in 32-bit. Offsets to local variables are instead relative to this value. This is part of PR38857. Reviewers: hans, zturner, javed.absar Subscribers: aprantl, hiraditya, JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D52217 llvm-svn: 343543
Diffstat (limited to 'llvm/test/DebugInfo/COFF')
-rw-r--r--llvm/test/DebugInfo/COFF/asm.ll2
-rw-r--r--llvm/test/DebugInfo/COFF/frameproc-flags.ll379
-rw-r--r--llvm/test/DebugInfo/COFF/local-variables.ll45
-rw-r--r--llvm/test/DebugInfo/COFF/multifile.ll4
-rw-r--r--llvm/test/DebugInfo/COFF/multifunction.ll86
-rw-r--r--llvm/test/DebugInfo/COFF/pieces.ll10
-rw-r--r--llvm/test/DebugInfo/COFF/simple.ll34
-rw-r--r--llvm/test/DebugInfo/COFF/types-array.ll7
-rw-r--r--llvm/test/DebugInfo/COFF/vframe-fpo.ll264
9 files changed, 772 insertions, 59 deletions
diff --git a/llvm/test/DebugInfo/COFF/asm.ll b/llvm/test/DebugInfo/COFF/asm.ll
index fa2a25894f6..ed71b246f3c 100644
--- a/llvm/test/DebugInfo/COFF/asm.ll
+++ b/llvm/test/DebugInfo/COFF/asm.ll
@@ -99,7 +99,7 @@
; OBJ64: DisplayName: f
; OBJ64: LinkageName: f
; OBJ64: }
-; OBJ64-NEXT: ProcEnd {
+; OBJ64: ProcEnd {
; OBJ64: }
; OBJ64-NEXT: ]
; OBJ64: FunctionLineTable [
diff --git a/llvm/test/DebugInfo/COFF/frameproc-flags.ll b/llvm/test/DebugInfo/COFF/frameproc-flags.ll
new file mode 100644
index 00000000000..a9d0fe067da
--- /dev/null
+++ b/llvm/test/DebugInfo/COFF/frameproc-flags.ll
@@ -0,0 +1,379 @@
+; RUN: llc -filetype=obj %s -o %t.obj
+; RUN: llvm-pdbutil dump %t.obj -symbols | FileCheck %s
+
+; A fairly exhaustive test of S_FRAMEPROC flags. Use the source below to compare
+; the flags we set with MSVC.
+
+; extern "C" {
+;
+; void *_alloca(size_t);
+; struct __declspec(align(16)) _jmp_buf_str {
+; unsigned __int64 Part[2];
+; };
+; typedef struct _jmp_buf_str jmp_buf[16];
+; int __cdecl _setjmp(jmp_buf _Buf);
+;
+; void may_throw(void);
+; void use_intptr(int *);
+;
+; void use_alloca(int n) {
+; int *p = (int*)_alloca(n * sizeof(int));
+; use_intptr(p);
+; }
+;
+; jmp_buf g_jbuf;
+; void call_setjmp(int n) {
+; if (!_setjmp(g_jbuf))
+; use_intptr(nullptr);
+; }
+;
+; void use_inlineasm() {
+; __asm nop
+; }
+;
+; void cpp_eh() {
+; try {
+; may_throw();
+; } catch (...) {
+; }
+; }
+;
+; static inline int is_marked_inline(int x, int y) {
+; return x + y;
+; }
+; int (*use_inline())(int x, int y) {
+; return &is_marked_inline;
+; }
+;
+; void seh() {
+; __try {
+; may_throw();
+; } __except (1) {
+; }
+; }
+;
+; void __declspec(naked) use_naked() {
+; __asm ret
+; }
+;
+; void stack_guard() {
+; int arr[12] = {0};
+; use_intptr(&arr[0]);
+; }
+; }
+
+; CHECK-LABEL: S_GPROC32_ID [size = 50] `use_alloca`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = VFRAME, param fp reg = EBP
+; CHECK: flags = has alloca | secure checks | opt speed
+; CHECK-LABEL: S_GPROC32_ID [size = 51] `call_setjmp`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = NONE, param fp reg = NONE
+; CHECK: flags = has setjmp | opt speed
+; CHECK-LABEL: S_GPROC32_ID [size = 53] `use_inlineasm`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = NONE, param fp reg = NONE
+; CHECK: flags = has inline asm | opt speed
+; CHECK-LABEL: S_GPROC32_ID [size = 46] `cpp_eh`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = EBP, param fp reg = EBP
+; CHECK: flags = has eh | opt speed
+; CHECK-LABEL: S_GPROC32_ID [size = 50] `use_inline`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = NONE, param fp reg = NONE
+; CHECK: flags = opt speed
+; CHECK-LABEL: S_LPROC32_ID [size = 56] `is_marked_inline`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = NONE, param fp reg = NONE
+; CHECK: flags = marked inline | opt speed
+; CHECK-LABEL: S_GPROC32_ID [size = 43] `seh`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = EBP, param fp reg = EBP
+; CHECK: flags = has seh | opt speed
+; CHECK-LABEL: S_LPROC32_ID [size = 55] `?filt$0@0@seh@@`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = EBP, param fp reg = EBP
+; CHECK: flags = opt speed
+; CHECK-LABEL: S_GPROC32_ID [size = 49] `use_naked`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = NONE, param fp reg = NONE
+; CHECK: flags = has inline asm | naked | opt speed
+; CHECK-LABEL: S_GPROC32_ID [size = 51] `stack_guard`
+; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: local fp reg = VFRAME, param fp reg = EBP
+; CHECK: flags = secure checks | opt speed
+
+; ModuleID = 'frameproc-flags.cpp'
+source_filename = "frameproc-flags.cpp"
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.14.26433"
+
+%struct._jmp_buf_str = type { [2 x i64] }
+
+@g_jbuf = dso_local global [16 x %struct._jmp_buf_str] zeroinitializer, align 16, !dbg !0
+
+define dso_local void @use_alloca(i32 %n) local_unnamed_addr #0 !dbg !25 {
+entry:
+ call void @llvm.dbg.value(metadata i32 %n, metadata !29, metadata !DIExpression()), !dbg !31
+ %mul = shl i32 %n, 2, !dbg !32
+ %0 = alloca i8, i32 %mul, align 16, !dbg !32
+ %1 = bitcast i8* %0 to i32*, !dbg !32
+ call void @llvm.dbg.value(metadata i32* %1, metadata !30, metadata !DIExpression()), !dbg !32
+ call void @use_intptr(i32* nonnull %1), !dbg !33
+ ret void, !dbg !34
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #2
+
+declare dso_local void @use_intptr(i32*) local_unnamed_addr #3
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #2
+
+define dso_local void @call_setjmp(i32 %n) local_unnamed_addr #0 !dbg !35 {
+entry:
+ call void @llvm.dbg.value(metadata i32 %n, metadata !37, metadata !DIExpression()), !dbg !38
+ %0 = call i32 (i8*, i32, ...) @_setjmp3(i8* bitcast ([16 x %struct._jmp_buf_str]* @g_jbuf to i8*), i32 0) #4, !dbg !39
+ %tobool = icmp eq i32 %0, 0, !dbg !39
+ br i1 %tobool, label %if.then, label %if.end, !dbg !39
+
+if.then: ; preds = %entry
+ call void @use_intptr(i32* null), !dbg !40
+ br label %if.end, !dbg !40
+
+if.end: ; preds = %entry, %if.then
+ ret void, !dbg !42
+}
+
+; Function Attrs: returns_twice
+declare dso_local i32 @_setjmp3(i8*, i32, ...) local_unnamed_addr #4
+
+; Function Attrs: nounwind
+define dso_local void @use_inlineasm() local_unnamed_addr #5 !dbg !43 {
+entry:
+ tail call void asm sideeffect inteldialect "nop", "~{dirflag},~{fpsr},~{flags}"() #10, !dbg !46, !srcloc !47
+ ret void, !dbg !48
+}
+
+define dso_local void @cpp_eh() local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) !dbg !49 {
+entry:
+ invoke void @may_throw()
+ to label %try.cont unwind label %catch.dispatch, !dbg !50
+
+catch.dispatch: ; preds = %entry
+ %0 = catchswitch within none [label %catch] unwind to caller, !dbg !52
+
+catch: ; preds = %catch.dispatch
+ %1 = catchpad within %0 [i8* null, i32 64, i8* null], !dbg !52
+ catchret from %1 to label %try.cont, !dbg !53
+
+try.cont: ; preds = %entry, %catch
+ ret void, !dbg !55
+}
+
+declare dso_local void @may_throw() local_unnamed_addr #3
+
+declare dso_local i32 @__CxxFrameHandler3(...)
+
+; Function Attrs: norecurse nounwind readnone
+define dso_local nonnull i32 (i32, i32)* @use_inline() local_unnamed_addr #6 !dbg !56 {
+entry:
+ ret i32 (i32, i32)* @"?is_marked_inline@@YAHHH@Z", !dbg !62
+}
+
+; Function Attrs: inlinehint nounwind readnone
+define internal i32 @"?is_marked_inline@@YAHHH@Z"(i32 %x, i32 %y) #7 !dbg !63 {
+entry:
+ call void @llvm.dbg.value(metadata i32 %y, metadata !65, metadata !DIExpression()), !dbg !67
+ call void @llvm.dbg.value(metadata i32 %x, metadata !66, metadata !DIExpression()), !dbg !67
+ %add = add nsw i32 %y, %x, !dbg !68
+ ret i32 %add, !dbg !68
+}
+
+define dso_local void @seh() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) !dbg !69 {
+entry:
+ %__exception_code = alloca i32, align 4
+ call void (...) @llvm.localescape(i32* nonnull %__exception_code)
+ invoke void @may_throw() #12
+ to label %__try.cont unwind label %catch.dispatch, !dbg !70
+
+catch.dispatch: ; preds = %entry
+ %0 = catchswitch within none [label %__except.ret] unwind to caller, !dbg !72
+
+__except.ret: ; preds = %catch.dispatch
+ %1 = catchpad within %0 [i8* bitcast (i32 ()* @"?filt$0@0@seh@@" to i8*)], !dbg !72
+ catchret from %1 to label %__try.cont, !dbg !72
+
+__try.cont: ; preds = %entry, %__except.ret
+ ret void, !dbg !73
+}
+
+; Function Attrs: nounwind
+define internal i32 @"?filt$0@0@seh@@"() #8 !dbg !74 {
+entry:
+ %0 = tail call i8* @llvm.frameaddress(i32 1)
+ %1 = tail call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @seh to i8*), i8* %0)
+ %2 = tail call i8* @llvm.localrecover(i8* bitcast (void ()* @seh to i8*), i8* %1, i32 0)
+ %__exception_code = bitcast i8* %2 to i32*
+ %3 = getelementptr inbounds i8, i8* %0, i32 -20, !dbg !76
+ %4 = bitcast i8* %3 to { i32*, i8* }**, !dbg !76
+ %5 = load { i32*, i8* }*, { i32*, i8* }** %4, align 4, !dbg !76
+ %6 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %5, i32 0, i32 0, !dbg !76
+ %7 = load i32*, i32** %6, align 4, !dbg !76
+ %8 = load i32, i32* %7, align 4, !dbg !76
+ store i32 %8, i32* %__exception_code, align 4, !dbg !76
+ ret i32 1, !dbg !76
+}
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.frameaddress(i32) #9
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #9
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.localrecover(i8*, i8*, i32) #9
+
+declare dso_local i32 @_except_handler3(...)
+
+; Function Attrs: nounwind
+declare void @llvm.localescape(...) #10
+
+; Function Attrs: naked noinline nounwind
+define dso_local void @use_naked() #11 !dbg !77 {
+entry:
+ tail call void asm sideeffect inteldialect "ret", "~{dirflag},~{fpsr},~{flags}"() #10, !dbg !78, !srcloc !79
+ unreachable, !dbg !80
+}
+
+define dso_local void @stack_guard() local_unnamed_addr #0 !dbg !81 {
+entry:
+ %arr = alloca [12 x i32], align 4
+ %0 = bitcast [12 x i32]* %arr to i8*, !dbg !87
+ call void @llvm.lifetime.start.p0i8(i64 48, i8* nonnull %0) #10, !dbg !87
+ call void @llvm.dbg.declare(metadata [12 x i32]* %arr, metadata !83, metadata !DIExpression()), !dbg !87
+ call void @llvm.memset.p0i8.i32(i8* nonnull align 4 %0, i8 0, i32 48, i1 false), !dbg !87
+ %arrayidx = getelementptr inbounds [12 x i32], [12 x i32]* %arr, i32 0, i32 0, !dbg !88
+ call void @use_intptr(i32* nonnull %arrayidx), !dbg !88
+ call void @llvm.lifetime.end.p0i8(i64 48, i8* nonnull %0) #10, !dbg !89
+ ret void, !dbg !89
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1) #2
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { sspstrong "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone speculatable }
+attributes #2 = { argmemonly nounwind }
+attributes #3 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { returns_twice }
+attributes #5 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #6 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #7 = { inlinehint nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #8 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #9 = { nounwind readnone }
+attributes #10 = { nounwind }
+attributes #11 = { naked noinline nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #12 = { noinline }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!20, !21, !22, !23}
+!llvm.ident = !{!24}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g_jbuf", scope: !2, file: !3, line: 18, type: !9, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 8.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !8, nameTableKind: None)
+!3 = !DIFile(filename: "frameproc-flags.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "1dd66a71668512c95552767c3a35300a")
+!4 = !{}
+!5 = !{!6}
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32)
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !{!0}
+!9 = !DIDerivedType(tag: DW_TAG_typedef, name: "jmp_buf", file: !3, line: 7, baseType: !10)
+!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 2048, elements: !18)
+!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "_jmp_buf_str", file: !3, line: 4, size: 128, align: 128, flags: DIFlagTypePassByValue | DIFlagTrivial, elements: !12, identifier: ".?AU_jmp_buf_str@@")
+!12 = !{!13}
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "Part", scope: !11, file: !3, line: 5, baseType: !14, size: 128)
+!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 128, elements: !16)
+!15 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
+!16 = !{!17}
+!17 = !DISubrange(count: 2)
+!18 = !{!19}
+!19 = !DISubrange(count: 16)
+!20 = !{i32 1, !"NumRegisterParameters", i32 0}
+!21 = !{i32 2, !"CodeView", i32 1}
+!22 = !{i32 2, !"Debug Info Version", i32 3}
+!23 = !{i32 1, !"wchar_size", i32 2}
+!24 = !{!"clang version 8.0.0 "}
+!25 = distinct !DISubprogram(name: "use_alloca", scope: !3, file: !3, line: 13, type: !26, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !28)
+!26 = !DISubroutineType(types: !27)
+!27 = !{null, !7}
+!28 = !{!29, !30}
+!29 = !DILocalVariable(name: "n", arg: 1, scope: !25, file: !3, line: 13, type: !7)
+!30 = !DILocalVariable(name: "p", scope: !25, file: !3, line: 14, type: !6)
+!31 = !DILocation(line: 13, scope: !25)
+!32 = !DILocation(line: 14, scope: !25)
+!33 = !DILocation(line: 15, scope: !25)
+!34 = !DILocation(line: 16, scope: !25)
+!35 = distinct !DISubprogram(name: "call_setjmp", scope: !3, file: !3, line: 19, type: !26, isLocal: false, isDefinition: true, scopeLine: 19, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !36)
+!36 = !{!37}
+!37 = !DILocalVariable(name: "n", arg: 1, scope: !35, file: !3, line: 19, type: !7)
+!38 = !DILocation(line: 19, scope: !35)
+!39 = !DILocation(line: 20, scope: !35)
+!40 = !DILocation(line: 21, scope: !41)
+!41 = distinct !DILexicalBlock(scope: !35, file: !3, line: 20)
+!42 = !DILocation(line: 22, scope: !35)
+!43 = distinct !DISubprogram(name: "use_inlineasm", scope: !3, file: !3, line: 24, type: !44, isLocal: false, isDefinition: true, scopeLine: 24, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4)
+!44 = !DISubroutineType(types: !45)
+!45 = !{null}
+!46 = !DILocation(line: 25, scope: !43)
+!47 = !{i32 445}
+!48 = !DILocation(line: 26, scope: !43)
+!49 = distinct !DISubprogram(name: "cpp_eh", scope: !3, file: !3, line: 28, type: !44, isLocal: false, isDefinition: true, scopeLine: 28, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4)
+!50 = !DILocation(line: 30, scope: !51)
+!51 = distinct !DILexicalBlock(scope: !49, file: !3, line: 29)
+!52 = !DILocation(line: 31, scope: !51)
+!53 = !DILocation(line: 32, scope: !54)
+!54 = distinct !DILexicalBlock(scope: !49, file: !3, line: 31)
+!55 = !DILocation(line: 33, scope: !49)
+!56 = distinct !DISubprogram(name: "use_inline", scope: !3, file: !3, line: 38, type: !57, isLocal: false, isDefinition: true, scopeLine: 38, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4)
+!57 = !DISubroutineType(types: !58)
+!58 = !{!59}
+!59 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !60, size: 32)
+!60 = !DISubroutineType(types: !61)
+!61 = !{!7, !7, !7}
+!62 = !DILocation(line: 39, scope: !56)
+!63 = distinct !DISubprogram(name: "is_marked_inline", linkageName: "?is_marked_inline@@YAHHH@Z", scope: !3, file: !3, line: 35, type: !60, isLocal: true, isDefinition: true, scopeLine: 35, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !64)
+!64 = !{!65, !66}
+!65 = !DILocalVariable(name: "y", arg: 2, scope: !63, file: !3, line: 35, type: !7)
+!66 = !DILocalVariable(name: "x", arg: 1, scope: !63, file: !3, line: 35, type: !7)
+!67 = !DILocation(line: 35, scope: !63)
+!68 = !DILocation(line: 36, scope: !63)
+!69 = distinct !DISubprogram(name: "seh", scope: !3, file: !3, line: 42, type: !44, isLocal: false, isDefinition: true, scopeLine: 42, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4)
+!70 = !DILocation(line: 44, scope: !71)
+!71 = distinct !DILexicalBlock(scope: !69, file: !3, line: 43)
+!72 = !DILocation(line: 45, scope: !71)
+!73 = !DILocation(line: 47, scope: !69)
+!74 = distinct !DISubprogram(linkageName: "?filt$0@0@seh@@", scope: !3, file: !3, line: 45, type: !75, isLocal: true, isDefinition: true, scopeLine: 45, flags: DIFlagArtificial, isOptimized: true, unit: !2, retainedNodes: !4)
+!75 = !DISubroutineType(types: !4)
+!76 = !DILocation(line: 45, scope: !74)
+!77 = distinct !DISubprogram(name: "use_naked", scope: !3, file: !3, line: 49, type: !44, isLocal: false, isDefinition: true, scopeLine: 49, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !4)
+!78 = !DILocation(line: 50, scope: !77)
+!79 = !{i32 765}
+!80 = !DILocation(line: 51, scope: !77)
+!81 = distinct !DISubprogram(name: "stack_guard", scope: !3, file: !3, line: 53, type: !44, isLocal: false, isDefinition: true, scopeLine: 53, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !82)
+!82 = !{!83}
+!83 = !DILocalVariable(name: "arr", scope: !81, file: !3, line: 54, type: !84)
+!84 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 384, elements: !85)
+!85 = !{!86}
+!86 = !DISubrange(count: 12)
+!87 = !DILocation(line: 54, scope: !81)
+!88 = !DILocation(line: 55, scope: !81)
+!89 = !DILocation(line: 56, scope: !81)
diff --git a/llvm/test/DebugInfo/COFF/local-variables.ll b/llvm/test/DebugInfo/COFF/local-variables.ll
index 683b438d396..085ced17262 100644
--- a/llvm/test/DebugInfo/COFF/local-variables.ll
+++ b/llvm/test/DebugInfo/COFF/local-variables.ll
@@ -71,30 +71,30 @@
; ASM: .long 116 # TypeIndex
; ASM: .short 1 # Flags
; ASM: .asciz "param"
-; ASM: .cv_def_range [[prologue_end]] [[param_end]], "E\021O\001\000\0004\000\000\000"
+; ASM: .cv_def_range [[prologue_end]] [[param_end]], "B\0214\000\000\000"
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .long 116 # TypeIndex
; ASM: .short 0 # Flags
; ASM: .asciz "a"
-; ASM: .cv_def_range [[if_start]] [[else_start]], "E\021O\001\000\000(\000\000\000"
+; ASM: .cv_def_range [[if_start]] [[else_start]], "B\021(\000\000\000"
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .long 116 # TypeIndex
; ASM: .short 0 # Flags
; ASM: .asciz "b"
-; ASM: .cv_def_range [[else_start]] [[else_end]], "E\021O\001\000\000$\000\000\000"
+; ASM: .cv_def_range [[else_start]] [[else_end]], "B\021$\000\000\000"
; ASM: .short 4429 # Record kind: S_INLINESITE
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .long 116 # TypeIndex
; ASM: .short 0 # Flags
; ASM: .asciz "v"
-; ASM: .cv_def_range [[inline_site1]] [[else_start]], "E\021O\001\000\000,\000\000\000"
+; ASM: .cv_def_range [[inline_site1]] [[else_start]], "B\021,\000\000\000"
; ASM: .short 4430 # Record kind: S_INLINESITE_END
; ASM: .short 4429 # Record kind: S_INLINESITE
; ASM: .short 4414 # Record kind: S_LOCAL
; ASM: .long 116 # TypeIndex
; ASM: .short 0 # Flags
; ASM: .asciz "v"
-; ASM: .cv_def_range [[inline_site2]] [[else_end]], "E\021O\001\000\0000\000\000\000"
+; ASM: .cv_def_range [[inline_site2]] [[else_end]], "B\0210\000\000\000"
; ASM: .short 4430 # Record kind: S_INLINESITE_END
; OBJ: Subsection [
@@ -110,11 +110,8 @@
; OBJ: ]
; OBJ: VarName: param
; OBJ: }
-; OBJ: DefRangeRegisterRelSym {
-; OBJ: BaseRegister: RSP (0x14F)
-; OBJ: HasSpilledUDTMember: No
-; OBJ: OffsetInParent: 0
-; OBJ: BasePointerOffset: 52
+; OBJ: DefRangeFramePointerRelSym {
+; OBJ: Offset: 52
; OBJ: LocalVariableAddrRange {
; OBJ: OffsetStart: .text+0x8
; OBJ: ISectStart: 0x0
@@ -127,11 +124,8 @@
; OBJ: ]
; OBJ: VarName: a
; OBJ: }
-; OBJ: DefRangeRegisterRelSym {
-; OBJ: BaseRegister: RSP (0x14F)
-; OBJ: HasSpilledUDTMember: No
-; OBJ: OffsetInParent: 0
-; OBJ: BasePointerOffset: 40
+; OBJ: DefRangeFramePointerRelSym {
+; OBJ: Offset: 40
; OBJ: LocalVariableAddrRange {
; OBJ: OffsetStart: .text+0xC
; OBJ: ISectStart: 0x0
@@ -144,11 +138,8 @@
; OBJ: ]
; OBJ: VarName: b
; OBJ: }
-; OBJ: DefRangeRegisterRelSym {
-; OBJ: BaseRegister: RSP (0x14F)
-; OBJ: HasSpilledUDTMember: No
-; OBJ: OffsetInParent: 0
-; OBJ: BasePointerOffset: 36
+; OBJ: DefRangeFramePointerRelSym {
+; OBJ: Offset: 36
; OBJ: LocalVariableAddrRange {
; OBJ: OffsetStart: .text+0x2D
; OBJ: ISectStart: 0x0
@@ -172,11 +163,8 @@
; OBJ: ]
; OBJ: VarName: v
; OBJ: }
-; OBJ: DefRangeRegisterRelSym {
-; OBJ: BaseRegister: RSP (0x14F)
-; OBJ: HasSpilledUDTMember: No
-; OBJ: OffsetInParent: 0
-; OBJ: BasePointerOffset: 44
+; OBJ: DefRangeFramePointerRelSym {
+; OBJ: Offset: 44
; OBJ: LocalVariableAddrRange {
; OBJ: OffsetStart: .text+0x14
; OBJ: ISectStart: 0x0
@@ -202,11 +190,8 @@
; OBJ: ]
; OBJ: VarName: v
; OBJ: }
-; OBJ: DefRangeRegisterRelSym {
-; OBJ: BaseRegister: RSP (0x14F)
-; OBJ: HasSpilledUDTMember: No
-; OBJ: OffsetInParent: 0
-; OBJ: BasePointerOffset: 48
+; OBJ: DefRangeFramePointerRelSym {
+; OBJ: Offset: 48
; OBJ: LocalVariableAddrRange {
; OBJ: OffsetStart: .text+0x35
; OBJ: ISectStart: 0x0
diff --git a/llvm/test/DebugInfo/COFF/multifile.ll b/llvm/test/DebugInfo/COFF/multifile.ll
index ea6e758a243..cb281ea7a4d 100644
--- a/llvm/test/DebugInfo/COFF/multifile.ll
+++ b/llvm/test/DebugInfo/COFF/multifile.ll
@@ -48,7 +48,7 @@
; OBJ32: DisplayName: f
; OBJ32: LinkageName: _f
; OBJ32: }
-; OBJ32-NEXT: ProcEnd {
+; OBJ32: ProcEnd {
; OBJ32: }
; OBJ32-NEXT: ]
; OBJ32: Subsection [
@@ -136,7 +136,7 @@
; OBJ64: DisplayName: f
; OBJ64: LinkageName: f
; OBJ64: }
-; OBJ64-NEXT: ProcEnd {
+; OBJ64: ProcEnd {
; OBJ64: }
; OBJ64-NEXT: ]
; OBJ64: Subsection [
diff --git a/llvm/test/DebugInfo/COFF/multifunction.ll b/llvm/test/DebugInfo/COFF/multifunction.ll
index c675edab5aa..c74b332d8b8 100644
--- a/llvm/test/DebugInfo/COFF/multifunction.ll
+++ b/llvm/test/DebugInfo/COFF/multifunction.ll
@@ -81,6 +81,17 @@
; X86-NEXT: .byte 0
; X86-NEXT: .asciz "x"
; X86-NEXT: [[PROC_SEGMENT_END]]:
+; X86-NEXT: .short [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]] # Record length
+; X86-NEXT: [[FPROC_BEG]]:
+; X86-NEXT: .short 4114 # Record kind: S_FRAMEPROC
+; X86-NEXT: .long 0 # FrameSize
+; X86-NEXT: .long 0 # Padding
+; X86-NEXT: .long 0 # Offset of padding
+; X86-NEXT: .long 0 # Bytes of callee saved registers
+; X86-NEXT: .long 0 # Exception handler offset
+; X86-NEXT: .short 0 # Exception handler section
+; X86-NEXT: .long 0 # Flags (defines frame register)
+; X86-NEXT: [[FPROC_END]]:
; X86-NEXT: .short 2
; X86-NEXT: .short 4431
; X86-NEXT: [[F1_END]]:
@@ -107,6 +118,17 @@
; X86-NEXT: .byte 0
; X86-NEXT: .asciz "y"
; X86-NEXT: [[PROC_SEGMENT_END]]:
+; X86-NEXT: .short [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]] # Record length
+; X86-NEXT: [[FPROC_BEG]]:
+; X86-NEXT: .short 4114 # Record kind: S_FRAMEPROC
+; X86-NEXT: .long 0 # FrameSize
+; X86-NEXT: .long 0 # Padding
+; X86-NEXT: .long 0 # Offset of padding
+; X86-NEXT: .long 0 # Bytes of callee saved registers
+; X86-NEXT: .long 0 # Exception handler offset
+; X86-NEXT: .short 0 # Exception handler section
+; X86-NEXT: .long 0 # Flags (defines frame register)
+; X86-NEXT: [[FPROC_END]]:
; X86-NEXT: .short 2
; X86-NEXT: .short 4431
; X86-NEXT: [[COMPILE_END]]:
@@ -133,6 +155,17 @@
; X86-NEXT: .byte 0
; X86-NEXT: .asciz "f"
; X86-NEXT: [[PROC_SEGMENT_END]]:
+; X86-NEXT: .short [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]] # Record length
+; X86-NEXT: [[FPROC_BEG]]:
+; X86-NEXT: .short 4114 # Record kind: S_FRAMEPROC
+; X86-NEXT: .long 0 # FrameSize
+; X86-NEXT: .long 0 # Padding
+; X86-NEXT: .long 0 # Offset of padding
+; X86-NEXT: .long 0 # Bytes of callee saved registers
+; X86-NEXT: .long 0 # Exception handler offset
+; X86-NEXT: .short 0 # Exception handler section
+; X86-NEXT: .long 0 # Flags (defines frame register)
+; X86-NEXT: [[FPROC_END]]:
; X86-NEXT: .short 2
; X86-NEXT: .short 4431
; X86-NEXT: [[COMPILE_END]]:
@@ -354,6 +387,17 @@
; X64-NEXT: .byte 0
; X64-NEXT: .asciz "x"
; X64-NEXT: [[PROC_SEGMENT_END]]:
+; X64-NEXT: .short [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]] # Record length
+; X64-NEXT: [[FPROC_BEG]]:
+; X64-NEXT: .short 4114 # Record kind: S_FRAMEPROC
+; X64-NEXT: .long 40 # FrameSize
+; X64-NEXT: .long 0 # Padding
+; X64-NEXT: .long 0 # Offset of padding
+; X64-NEXT: .long 0 # Bytes of callee saved registers
+; X64-NEXT: .long 0 # Exception handler offset
+; X64-NEXT: .short 0 # Exception handler section
+; X64-NEXT: .long 81920 # Flags (defines frame register)
+; X64-NEXT: [[FPROC_END]]:
; X64-NEXT: .short 2
; X64-NEXT: .short 4431
; X64-NEXT: [[F1_END]]:
@@ -379,6 +423,17 @@
; X64-NEXT: .byte 0
; X64-NEXT: .asciz "y"
; X64-NEXT: [[PROC_SEGMENT_END]]:
+; X64-NEXT: .short [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]] # Record length
+; X64-NEXT: [[FPROC_BEG]]:
+; X64-NEXT: .short 4114 # Record kind: S_FRAMEPROC
+; X64-NEXT: .long 40 # FrameSize
+; X64-NEXT: .long 0 # Padding
+; X64-NEXT: .long 0 # Offset of padding
+; X64-NEXT: .long 0 # Bytes of callee saved registers
+; X64-NEXT: .long 0 # Exception handler offset
+; X64-NEXT: .short 0 # Exception handler section
+; X64-NEXT: .long 81920 # Flags (defines frame register)
+; X64-NEXT: [[FPROC_END]]:
; X64-NEXT: .short 2
; X64-NEXT: .short 4431
; X64-NEXT: [[COMPILE_END]]:
@@ -404,6 +459,17 @@
; X64-NEXT: .byte 0
; X64-NEXT: .asciz "f"
; X64-NEXT: [[PROC_SEGMENT_END]]:
+; X64-NEXT: .short [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]] # Record length
+; X64-NEXT: [[FPROC_BEG]]:
+; X64-NEXT: .short 4114 # Record kind: S_FRAMEPROC
+; X64-NEXT: .long 40 # FrameSize
+; X64-NEXT: .long 0 # Padding
+; X64-NEXT: .long 0 # Offset of padding
+; X64-NEXT: .long 0 # Bytes of callee saved registers
+; X64-NEXT: .long 0 # Exception handler offset
+; X64-NEXT: .short 0 # Exception handler section
+; X64-NEXT: .long 81920 # Flags (defines frame register)
+; X64-NEXT: [[FPROC_END]]:
; X64-NEXT: .short 2
; X64-NEXT: .short 4431
; X64-NEXT: [[COMPILE_END]]:
@@ -422,16 +488,16 @@
; OBJ64: Relocations [
; OBJ64-NEXT: 0x64 IMAGE_REL_AMD64_SECREL x
; OBJ64-NEXT: 0x68 IMAGE_REL_AMD64_SECTION x
-; OBJ64-NEXT: 0x7C IMAGE_REL_AMD64_SECREL x
-; OBJ64-NEXT: 0x80 IMAGE_REL_AMD64_SECTION x
-; OBJ64-NEXT: 0xE0 IMAGE_REL_AMD64_SECREL y
-; OBJ64-NEXT: 0xE4 IMAGE_REL_AMD64_SECTION y
-; OBJ64-NEXT: 0xF8 IMAGE_REL_AMD64_SECREL y
-; OBJ64-NEXT: 0xFC IMAGE_REL_AMD64_SECTION y
-; OBJ64-NEXT: 0x15C IMAGE_REL_AMD64_SECREL f
-; OBJ64-NEXT: 0x160 IMAGE_REL_AMD64_SECTION f
-; OBJ64-NEXT: 0x174 IMAGE_REL_AMD64_SECREL f
-; OBJ64-NEXT: 0x178 IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT: 0x98 IMAGE_REL_AMD64_SECREL x
+; OBJ64-NEXT: 0x9C IMAGE_REL_AMD64_SECTION x
+; OBJ64-NEXT: 0xFC IMAGE_REL_AMD64_SECREL y
+; OBJ64-NEXT: 0x100 IMAGE_REL_AMD64_SECTION y
+; OBJ64-NEXT: 0x130 IMAGE_REL_AMD64_SECREL y
+; OBJ64-NEXT: 0x134 IMAGE_REL_AMD64_SECTION y
+; OBJ64-NEXT: 0x194 IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT: 0x198 IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT: 0x1C8 IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT: 0x1CC IMAGE_REL_AMD64_SECTION f
; OBJ64-NEXT: ]
; OBJ64: Subsection [
; OBJ64-NEXT: SubSectionType: Symbols (0xF1)
diff --git a/llvm/test/DebugInfo/COFF/pieces.ll b/llvm/test/DebugInfo/COFF/pieces.ll
index ab3794dd0b7..10a81e17d92 100644
--- a/llvm/test/DebugInfo/COFF/pieces.ll
+++ b/llvm/test/DebugInfo/COFF/pieces.ll
@@ -108,7 +108,7 @@
; ASM: .cv_def_range [[oy_start]] [[oy_end]], "C\021\027\000\000\000\004\000\000\000"
-; OBJ-LABEL: {{.*}}Proc{{.*}}Sym {
+; OBJ-LABEL: GlobalProcIdSym {
; OBJ: Kind: S_GPROC32_ID (0x1147)
; OBJ: DisplayName: loop_csr
; OBJ: }
@@ -138,7 +138,7 @@
; ASM: .asciz "o"
; ASM: .cv_def_range .Lfunc_begin1 .Ltmp8, "C\021\021\000\000\000\004\000\000\000"
-; OBJ-LABEL: {{.*}}Proc{{.*}}Sym {
+; OBJ-LABEL: GlobalProcIdSym {
; OBJ: Kind: S_GPROC32_ID (0x1147)
; OBJ: DisplayName: pad_right
; OBJ: }
@@ -161,7 +161,7 @@
; ASM: .asciz "o"
; ASM: .cv_def_range .Lfunc_begin2 .Ltmp10, "C\021\021\000\000\000\000\000\000\000"
-; OBJ-LABEL: {{.*}}Proc{{.*}}Sym {
+; OBJ-LABEL: GlobalProcIdSym {
; OBJ: Kind: S_GPROC32_ID (0x1147)
; OBJ: DisplayName: pad_left
; OBJ: }
@@ -187,7 +187,7 @@
; ASM: .asciz "p"
; ASM: .cv_def_range [[p_start]] .Lfunc_end3, "C\021\021\000\000\000\004\000\000\000"
-; OBJ-LABEL: {{.*}}Proc{{.*}}Sym {
+; OBJ-LABEL: GlobalProcIdSym {
; OBJ: Kind: S_GPROC32_ID (0x1147)
; OBJ: DisplayName: nested
; OBJ: }
@@ -223,7 +223,7 @@
; ASM: .asciz "o"
; ASM: .cv_def_range [[spill_o_x_start]] [[spill_o_x_end]], "E\021O\001A\000$\000\000\000"
-; OBJ-LABEL: {{.*}}Proc{{.*}}Sym {
+; OBJ-LABEL: GlobalProcIdSym {
; OBJ: Kind: S_GPROC32_ID (0x1147)
; OBJ: DisplayName: bitpiece_spill
; OBJ: }
diff --git a/llvm/test/DebugInfo/COFF/simple.ll b/llvm/test/DebugInfo/COFF/simple.ll
index 175be1ab424..3c495a33b8a 100644
--- a/llvm/test/DebugInfo/COFF/simple.ll
+++ b/llvm/test/DebugInfo/COFF/simple.ll
@@ -59,6 +59,17 @@
; X86-NEXT: .byte 0
; X86-NEXT: .asciz "f"
; X86-NEXT: [[PROC_SEGMENT_END]]:
+; X86-NEXT: .short [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]] # Record length
+; X86-NEXT: [[FPROC_BEG]]:
+; X86-NEXT: .short 4114 # Record kind: S_FRAMEPROC
+; X86-NEXT: .long 0 # FrameSize
+; X86-NEXT: .long 0 # Padding
+; X86-NEXT: .long 0 # Offset of padding
+; X86-NEXT: .long 0 # Bytes of callee saved registers
+; X86-NEXT: .long 0 # Exception handler offset
+; X86-NEXT: .short 0 # Exception handler section
+; X86-NEXT: .long 0 # Flags (defines frame register)
+; X86-NEXT: [[FPROC_END]]:
; X86-NEXT: .short 2
; X86-NEXT: .short 4431
; X86-NEXT: [[F1_END]]:
@@ -78,8 +89,8 @@
; OBJ32-NEXT: 0x44 IMAGE_REL_I386_DIR32NB _f
; OBJ32-NEXT: 0x90 IMAGE_REL_I386_SECREL _f
; OBJ32-NEXT: 0x94 IMAGE_REL_I386_SECTION _f
-; OBJ32-NEXT: 0xA8 IMAGE_REL_I386_SECREL _f
-; OBJ32-NEXT: 0xAC IMAGE_REL_I386_SECTION _f
+; OBJ32-NEXT: 0xC4 IMAGE_REL_I386_SECREL _f
+; OBJ32-NEXT: 0xC8 IMAGE_REL_I386_SECTION _f
; OBJ32-NEXT: ]
; OBJ32: Subsection [
; OBJ32-NEXT: SubSectionType: Symbols (0xF1)
@@ -95,7 +106,7 @@
; OBJ32: DisplayName: f
; OBJ32: LinkageName: _f
; OBJ32: }
-; OBJ32-NEXT: ProcEnd {
+; OBJ32: ProcEnd {
; OBJ32: }
; OBJ32-NEXT: ]
; OBJ32: Subsection [
@@ -174,6 +185,17 @@
; X64-NEXT: .byte 0
; X64-NEXT: .asciz "f"
; X64-NEXT: [[PROC_SEGMENT_END]]:
+; X64-NEXT: .short [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]] # Record length
+; X64-NEXT: [[FPROC_BEG]]:
+; X64-NEXT: .short 4114 # Record kind: S_FRAMEPROC
+; X64-NEXT: .long 40 # FrameSize
+; X64-NEXT: .long 0 # Padding
+; X64-NEXT: .long 0 # Offset of padding
+; X64-NEXT: .long 0 # Bytes of callee saved registers
+; X64-NEXT: .long 0 # Exception handler offset
+; X64-NEXT: .short 0 # Exception handler section
+; X64-NEXT: .long 81920 # Flags (defines frame register)
+; X64-NEXT: [[FPROC_END]]:
; X64-NEXT: .short 2
; X64-NEXT: .short 4431
; X64-NEXT: [[F1_END]]:
@@ -192,8 +214,8 @@
; OBJ64: Relocations [
; OBJ64-NEXT: 0x64 IMAGE_REL_AMD64_SECREL f
; OBJ64-NEXT: 0x68 IMAGE_REL_AMD64_SECTION f
-; OBJ64-NEXT: 0x7C IMAGE_REL_AMD64_SECREL f
-; OBJ64-NEXT: 0x80 IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT: 0x98 IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT: 0x9C IMAGE_REL_AMD64_SECTION f
; OBJ64-NEXT: ]
; OBJ64: Subsection [
; OBJ64-NEXT: SubSectionType: Symbols (0xF1)
@@ -202,7 +224,7 @@
; OBJ64: DisplayName: f
; OBJ64: LinkageName: f
; OBJ64: }
-; OBJ64-NEXT: ProcEnd {
+; OBJ64: ProcEnd {
; OBJ64: }
; OBJ64-NEXT: ]
; OBJ64: Subsection [
diff --git a/llvm/test/DebugInfo/COFF/types-array.ll b/llvm/test/DebugInfo/COFF/types-array.ll
index 10ae42653fa..16298dafbd4 100644
--- a/llvm/test/DebugInfo/COFF/types-array.ll
+++ b/llvm/test/DebugInfo/COFF/types-array.ll
@@ -67,11 +67,8 @@
; CHECK: ]
; CHECK: VarName: a
; CHECK: }
-; CHECK: DefRangeRegisterRelSym {
-; CHECK: BaseRegister: EBP (0x16)
-; CHECK: HasSpilledUDTMember: No
-; CHECK: OffsetInParent: 0
-; CHECK: BasePointerOffset: -20
+; CHECK: DefRangeFramePointerRelSym {
+; CHECK: Offset: -20
; CHECK: LocalVariableAddrRange {
; CHECK: OffsetStart: .text+0x6
; CHECK: ISectStart: 0x0
diff --git a/llvm/test/DebugInfo/COFF/vframe-fpo.ll b/llvm/test/DebugInfo/COFF/vframe-fpo.ll
new file mode 100644
index 00000000000..b3b71530214
--- /dev/null
+++ b/llvm/test/DebugInfo/COFF/vframe-fpo.ll
@@ -0,0 +1,264 @@
+; RUN: llc < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc < %s -filetype=obj | llvm-readobj -codeview | FileCheck %s --check-prefix=CODEVIEW
+
+; This test checks that for 32-bit x86 we use VFRAME and
+; S_DEFRANGE_FRAMEPOINTER_REL with the right offsets. The test has two function
+; calls with different stack depths, which makes it impossible to correctly
+; describe locals in memory as being ESP-relative.
+
+; The following source can be used with a debugger to check that locals are
+; displayed correctly:
+; $ cat fpo.cpp
+; #if 0
+; void __attribute__((optnone)) __declspec(noinline) f(int &a, int &b) {
+; __debugbreak();
+; a += b;
+; }
+; void __attribute__((optnone)) __declspec(noinline) g(int &a, int &b, int &c) {
+; __debugbreak();
+; a += b;
+; a += c;
+; }
+; #endif
+; void f(int &a, int &b);
+; void g(int &a, int &b, int &c);
+; int main() {
+; int a = 1;
+; int b = 2;
+; int c = 3;
+; f(a, b);
+; g(a, b, c);
+; return a + b + c;
+; }
+; $ clang -S -g -gcodeview t.cpp -emit-llvm -o vframe-fpo.ll -Os
+
+; ASM-LABEL: _main:
+; ASM: # %bb.0: # %entry
+; ASM-NEXT: pushl %ebx
+; ASM-NEXT: .cv_fpo_pushreg %ebx
+; ASM-NEXT: pushl %edi
+; ASM-NEXT: .cv_fpo_pushreg %edi
+; ASM-NEXT: pushl %esi
+; ASM-NEXT: .cv_fpo_pushreg %esi
+; ASM-NEXT: subl $12, %esp
+; ASM-NEXT: .cv_fpo_stackalloc 12
+; ASM-NEXT: .cv_fpo_endprologue
+
+; Store locals.
+; ASM: movl $1, {{.*}}
+; ASM: movl $2, {{.*}}
+; ASM: movl $3, {{.*}}
+
+; ASM that store-to-push conversion fires.
+; ASM: pushl
+; ASM-NEXT: pushl
+; ASM-NEXT: calll "?f@@YAXAAH0@Z"
+; ASM-NEXT: addl $8, %esp
+; ASM: pushl
+; ASM-NEXT: pushl
+; ASM-NEXT: pushl
+; ASM-NEXT: calll "?g@@YAXAAH00@Z"
+
+; CODEVIEW: CodeViewDebugInfo [
+; CODEVIEW-NEXT: Section: .debug$S (4)
+; CODEVIEW-NEXT: Magic: 0x4
+; CODEVIEW-NEXT: Subsection [
+; CODEVIEW-NEXT: SubSectionType: Symbols (0xF1)
+; CODEVIEW-NEXT: SubSectionSize: 0x2F
+; CODEVIEW-NEXT: Compile3Sym {
+; CODEVIEW-NEXT: Kind: S_COMPILE3 (0x113C)
+; CODEVIEW: }
+; CODEVIEW: ]
+; CODEVIEW: Subsection [
+; CODEVIEW-NEXT: SubSectionType: FrameData (0xF5)
+; CODEVIEW-NEXT: SubSectionSize: 0xA4
+; CODEVIEW-NEXT: LinkageName: _main
+; CODEVIEW: FrameData {
+; CODEVIEW: }
+; CODEVIEW: FrameData {
+; CODEVIEW: }
+; CODEVIEW: FrameData {
+; CODEVIEW: }
+; CODEVIEW: FrameData {
+; CODEVIEW: }
+; CODEVIEW: FrameData {
+; CODEVIEW-NEXT: RvaStart:
+; CODEVIEW-NEXT: CodeSize:
+; CODEVIEW-NEXT: LocalSize: 0xC
+; CODEVIEW-NEXT: ParamsSize: 0x0
+; CODEVIEW-NEXT: MaxStackSize: 0x0
+; CODEVIEW-NEXT: PrologSize:
+; CODEVIEW-NEXT: SavedRegsSize: 0xC
+; CODEVIEW-NEXT: Flags [ (0x0)
+; CODEVIEW-NEXT: ]
+
+; $T0 is the CFA, the address of the return address, and our defranges are
+; relative to it.
+; CODEVIEW-NEXT: FrameFunc [
+; CODEVIEW-NEXT: $T0 .raSearch =
+; CODEVIEW-NEXT: $eip $T0 ^ =
+; CODEVIEW-NEXT: $esp $T0 4 + =
+; CODEVIEW-NEXT: $ebx $T0 4 - ^ =
+; CODEVIEW-NEXT: $edi $T0 8 - ^ =
+; CODEVIEW-NEXT: $esi $T0 12 - ^ =
+; CODEVIEW-NEXT: ]
+; CODEVIEW-NEXT: }
+
+; We push 16 bytes in the prologue, so our local variables are at offsets -16,
+; -20, and -24.
+
+; CODEVIEW: Subsection [
+; CODEVIEW-NEXT: SubSectionType: Symbols (0xF1)
+; CODEVIEW-NEXT: SubSectionSize: 0xA2
+; CODEVIEW-NEXT: GlobalProcIdSym {
+; CODEVIEW-NEXT: Kind: S_GPROC32_ID (0x1147)
+; CODEVIEW: DisplayName: main
+; CODEVIEW: LinkageName: _main
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: FrameProcSym {
+; CODEVIEW-NEXT: Kind: S_FRAMEPROC (0x1012)
+; CODEVIEW-NEXT: TotalFrameBytes: 0xC
+; CODEVIEW-NEXT: PaddingFrameBytes: 0x0
+; CODEVIEW-NEXT: OffsetToPadding: 0x0
+; CODEVIEW-NEXT: BytesOfCalleeSavedRegisters: 0xC
+; CODEVIEW-NEXT: OffsetOfExceptionHandler: 0x0
+; CODEVIEW-NEXT: SectionIdOfExceptionHandler: 0x0
+; CODEVIEW-NEXT: Flags [ (0x14000)
+; CODEVIEW-NEXT: ]
+; CODEVIEW-NEXT: LocalFramePtrReg: VFRAME (0x7536)
+; CODEVIEW-NEXT: ParamFramePtrReg: VFRAME (0x7536)
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: LocalSym {
+; CODEVIEW-NEXT: Kind: S_LOCAL (0x113E)
+; CODEVIEW: VarName: a
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: DefRangeFramePointerRelSym {
+; CODEVIEW-NEXT: Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
+; CODEVIEW-NEXT: Offset: -16
+; CODEVIEW-NEXT: LocalVariableAddrRange {
+; CODEVIEW-NEXT: OffsetStart:
+; CODEVIEW-NEXT: ISectStart:
+; CODEVIEW-NEXT: Range:
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: LocalSym {
+; CODEVIEW-NEXT: Kind: S_LOCAL (0x113E)
+; CODEVIEW: VarName: b
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: DefRangeFramePointerRelSym {
+; CODEVIEW-NEXT: Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
+; CODEVIEW-NEXT: Offset: -20
+; CODEVIEW-NEXT: LocalVariableAddrRange {
+; CODEVIEW-NEXT: OffsetStart:
+; CODEVIEW-NEXT: ISectStart:
+; CODEVIEW-NEXT: Range:
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: LocalSym {
+; CODEVIEW-NEXT: Kind: S_LOCAL (0x113E)
+; CODEVIEW: VarName: c
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: DefRangeFramePointerRelSym {
+; CODEVIEW-NEXT: Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
+; CODEVIEW-NEXT: Offset: -24
+; CODEVIEW-NEXT: LocalVariableAddrRange {
+; CODEVIEW-NEXT: OffsetStart:
+; CODEVIEW-NEXT: ISectStart:
+; CODEVIEW-NEXT: Range:
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: ProcEnd {
+; CODEVIEW-NEXT: Kind: S_PROC_ID_END (0x114F)
+; CODEVIEW-NEXT: }
+; CODEVIEW-NEXT: ]
+
+
+; ModuleID = 'fpo.cpp'
+source_filename = "fpo.cpp"
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.14.26433"
+
+; Function Attrs: norecurse optsize
+define dso_local i32 @main() local_unnamed_addr #0 !dbg !8 {
+entry:
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+ %c = alloca i32, align 4
+ %0 = bitcast i32* %a to i8*, !dbg !16
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #4, !dbg !16
+ call void @llvm.dbg.declare(metadata i32* %a, metadata !13, metadata !DIExpression()), !dbg !16
+ store i32 1, i32* %a, align 4, !dbg !16, !tbaa !17
+ %1 = bitcast i32* %b to i8*, !dbg !21
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %1) #4, !dbg !21
+ call void @llvm.dbg.declare(metadata i32* %b, metadata !14, metadata !DIExpression()), !dbg !21
+ store i32 2, i32* %b, align 4, !dbg !21, !tbaa !17
+ %2 = bitcast i32* %c to i8*, !dbg !22
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %2) #4, !dbg !22
+ call void @llvm.dbg.declare(metadata i32* %c, metadata !15, metadata !DIExpression()), !dbg !22
+ store i32 3, i32* %c, align 4, !dbg !22, !tbaa !17
+ call void @"?f@@YAXAAH0@Z"(i32* nonnull dereferenceable(4) %a, i32* nonnull dereferenceable(4) %b) #5, !dbg !23
+ call void @"?g@@YAXAAH00@Z"(i32* nonnull dereferenceable(4) %a, i32* nonnull dereferenceable(4) %b, i32* nonnull dereferenceable(4) %c) #5, !dbg !24
+ %3 = load i32, i32* %a, align 4, !dbg !25, !tbaa !17
+ %4 = load i32, i32* %b, align 4, !dbg !25, !tbaa !17
+ %add = add nsw i32 %4, %3, !dbg !25
+ %5 = load i32, i32* %c, align 4, !dbg !25, !tbaa !17
+ %add1 = add nsw i32 %add, %5, !dbg !25
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %2) #4, !dbg !26
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %1) #4, !dbg !26
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #4, !dbg !26
+ ret i32 %add1, !dbg !25
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
+
+; Function Attrs: optsize
+declare dso_local void @"?f@@YAXAAH0@Z"(i32* dereferenceable(4), i32* dereferenceable(4)) local_unnamed_addr #3
+
+; Function Attrs: optsize
+declare dso_local void @"?g@@YAXAAH00@Z"(i32* dereferenceable(4), i32* dereferenceable(4), i32* dereferenceable(4)) local_unnamed_addr #3
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
+
+attributes #0 = { norecurse optsize "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone speculatable }
+attributes #3 = { optsize "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind }
+attributes #5 = { optsize }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "fpo.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "d0bb7e43f4e54936a94da008319a7de3")
+!2 = !{}
+!3 = !{i32 1, !"NumRegisterParameters", i32 0}
+!4 = !{i32 2, !"CodeView", i32 1}
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = !{i32 1, !"wchar_size", i32 2}
+!7 = !{!"clang version 8.0.0 "}
+!8 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 14, type: !9, isLocal: false, isDefinition: true, scopeLine: 14, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !12)
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !{!13, !14, !15}
+!13 = !DILocalVariable(name: "a", scope: !8, file: !1, line: 15, type: !11)
+!14 = !DILocalVariable(name: "b", scope: !8, file: !1, line: 16, type: !11)
+!15 = !DILocalVariable(name: "c", scope: !8, file: !1, line: 17, type: !11)
+!16 = !DILocation(line: 15, scope: !8)
+!17 = !{!18, !18, i64 0}
+!18 = !{!"int", !19, i64 0}
+!19 = !{!"omnipotent char", !20, i64 0}
+!20 = !{!"Simple C++ TBAA"}
+!21 = !DILocation(line: 16, scope: !8)
+!22 = !DILocation(line: 17, scope: !8)
+!23 = !DILocation(line: 18, scope: !8)
+!24 = !DILocation(line: 19, scope: !8)
+!25 = !DILocation(line: 20, scope: !8)
+!26 = !DILocation(line: 21, scope: !8)
OpenPOWER on IntegriCloud