Bad code generation with llvm.dbg.value and llvm.dbg.addr calls
When compiling alexandria using quicklisp some variables are being exposed with inconsistent scope.
Module error: mismatched subprogram between llvm.dbg.value variable and !dbg attachment
call void @llvm.dbg.value(metadata i8* %0, metadata !29, metadata !DIExpression()), !dbg !36
label %entry
{ i8*, i64 } (i8*, i64, i8*, i8*, i8*, i8*, ...)* @"PROGV-LAMBDA^CORE^FN^^.1"
!29 = !DILocalVariable(name: "closure", arg: 1, scope: !27, file: !2, line: 31, type: !30)
!27 = distinct !DISubprogram(name: "PROGV-LAMBDA^CORE^FN^^", linkageName: "PROGV-LAMBDA^CORE^FN^^", scope: !2, file: !2, line: 31, type: !7, scopeLine: 31, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !28)
!36 = !DILocation(line: 31, column: 16, scope: !18, inlinedAt: !37)
!18 = distinct !DISubprogram(name: "FORMAT-SYMBOL^ALEXANDRIA.0.DEV^FN^^", linkageName: "FORMAT-SYMBOL^ALEXANDRIA.0.DEV^FN^^", scope: !19, file: !19, line: 23, type: !7, scopeLine: 23, spFlags: DISPFlagDefinition, unit:$
I've disabled DILocalVariable generation under control of a dynamic variable. To reproduce this problem do the following...
COMMON-LISP-USER> (load "~/quicklisp/setup.lisp")
; caught STYLE-WARNING:
; STYLE-WARNING during compiler-macro-expansion:
; Undefined type COMPILER-NOTE
; at /home/meister/quicklisp/quicklisp/impl-util.lisp 20:18
;
;;; Warning: Lisp compilation had style-warnings while
compiling #<CL-SOURCE-FILE "quicklisp" "impl-util">
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
T
COMMON-LISP-USER> (let ((cmp::*%dbg-variable* t)) (ql:quickload :alexandria))
Here is a small reproducer...
(declaim (inline foo))
(defun foo ()
(LAMBDA ()
(declare (core:lambda-name foolambda))
42 ))
(macrolet
((fizbo ()
(foo)))
(fizbo))
It fails with:
(setf cmp:*compile-file-parallel* nil)
(let ((cmp::*%dbg-variable* t)) (compile-file "/tmp/vvv.lisp"))
I think this is a problem with inlining and !dbg information. If you compile-file the code above the inlined functions FOOLAMBDA (both XEP and internal functions) instructions will have !dbg !xxx where the !xxx DILocation will have the wrong scope - the scope will be for FOO
define internal { i8*, i64 } @"FOOLAMBDA^COMMON-LISP-USER^FN^^.6"() #2 personality i32 (...)* @__gxx_personality_v0 !dbg !54 {
entry:
%exn.slot = alloca i8*, align 8, !dbg !55
%ehselector.slot = alloca i32, align 8, !dbg !55
%go-index.slot = alloca i64, align 8, !dbg !55
!55 = !DILocation(line: 3, column: 2, scope: !46, inlinedAt: !56)
!46 = distinct !DISubprogram(name: "FOO^COMMON-LISP-USER^FN^^", linkageName: "FOO^COMMON-LISP-USER^FN^^", scope: !2, file: !2, line: 2, type: !7, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !3)
I think it should have the scope for FOOLAMBDA
I can get this simpler reproducer to fail if I (setf cmp:*compile-file-parallel* nil) first...
(declaim (inline foo))
(defun foo ()
(LAMBDA ()
(declare (core:lambda-name foolambda))
42 ))
(foo)
But if I forget to switch off compile-file-parallel the code above compiles without complaint. The code with the MACROLET always fails.
Is the problem that function scopes are not being defined properly for nested functions when inlining? compile-file the following...
(declaim (inline foo))
(defun foo ()
(LAMBDA ()
(declare (core:lambda-name bar))
(dotimes (i 10) (print i))))
When I look at the .ll file I see the BAR function and the instruction !dbg info looks like this:
%nargs1 = getelementptr inbounds [6 x i8*], [6 x i8*]* %register-save-area, i64 0, i64 1, !dbg !45
...
!42 = distinct !DISubprogram(name: "BAR^COMMON-LISP-USER^FN^^", linkageName: "BAR^COMMON-LISP-USER^FN^^", scope: !2, file: !2, line: 3, type: !7, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !43)
...
!45 = !DILocation(line: 3, column: 2, scope: !42)
That looks correct
But if load the fasp file that I compile-file'd and I inspect the (clasp-cleavir::inline-ast 'foo) - every AST node has FOO as the function scope.
Then I compile-file
(foo)
and I look at the !dbg info for BAR I see...
define internal { i8*, i64 } @"BAR^COMMON-LISP-USER^FN^^.2"(i8* %0, i64 %1, i8* %2, i8* %3, i8* %4, i8* %5, ...) #3 personality i32 (...)* @__gxx_personality_v0 !dbg !31 {
entry:
%register-save-area = alloca [6 x i8*], i64 1, align 8, !dbg !34
... (rest have !dbg !34)
!13 = distinct !DISubprogram(name: "FOO^COMMON-LISP-USER^FN^^", linkageName: "FOO^COMMON-LISP-USER^FN^^", scope: !14, file: !14, line: 2, type: !7, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !3)
...
!31 = distinct !DISubprogram(name: "BAR^COMMON-LISP-USER^FN^^", linkageName: "BAR^COMMON-LISP-USER^FN^^", scope: !2, file: !2, line: 3, type: !7, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !32)
!32 = !{!33}
!33 = !DILocalVariable(name: "closure533", arg: 1, scope: !31, file: !2, line: 3, type: !21)
!34 = !DILocation(line: 3, column: 2, scope: !13, inlinedAt: !35)
!35 = !DILocation(line: 2, column: 1, scope: !31)
Note how every instruction has the scope !13 - which is FOO
I think they should have the scope !31 - which is BAR