clasp icon indicating copy to clipboard operation
clasp copied to clipboard

Bad code generation with llvm.dbg.value and llvm.dbg.addr calls

Open drmeister opened this issue 4 years ago • 4 comments

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))

drmeister avatar Jun 26 '21 18:06 drmeister

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"))

drmeister avatar Jun 26 '21 22:06 drmeister

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

drmeister avatar Jun 27 '21 17:06 drmeister

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.

drmeister avatar Jun 27 '21 17:06 drmeister

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

drmeister avatar Jun 27 '21 19:06 drmeister