Debug info for lazy variables triggers SROA assertion

Hi!

I created a bug report (https://llvm.org/bugs/show_bug.cgi?id=23712) for this failure but then I realized that my approach may be wrong.

The following D source contains a lazy variable:

void bar(lazy bool val)
{
     val();
}

The lazy variable val is translated to a delegate. The signature and the first IR lines are:

define void @_D7opover23barFLbZv({ i8*, i1 (i8*)* } %val_arg) #0 {
   %val = alloca { i8*, i1 (i8*)* }, align 8
   store { i8*, i1 (i8*)* } %val_arg, { i8*, i1 (i8*)* }* %val, !dbg !18
   call void @llvm.dbg.declare(metadata { i8*, i1 (i8*)* }* %val, metadata !11, metadata !19), !dbg !18
    ...
}
!11 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "val", arg: 0, scope: !6, file: !4, line: 1, type: !12)
!12 = !DIBasicType(name: "bool", size: 1, align: 8, encoding: DW_ATE_boolean)

The attached debug info says that val is of type bool (that's the view of the user).
But it is represented by a structure containing a pointer to a frame and a pointer to a function.

Optimizing this code triggers an assertion:

piece is larger than or outside of variable
   call void @llvm.dbg.value(metadata i8* %val_arg.fca.0.extract, i64 0, metadata !11, metadata !19), !dbg !18
!11 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "val", arg: 0, scope: !6, file: !4, line: 1, type: !12)
!19 = !DIExpression(DW_OP_bit_piece, 0, 64)
piece is larger than or outside of variable
   call void @llvm.dbg.value(metadata i1 (i8*)* %val_arg.fca.1.extract, i64 0, metadata !11, metadata !20), !dbg !18
!11 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "val", arg: 0, scope: !6, file: !4, line: 1, type: !12)
!20 = !DIExpression(DW_OP_bit_piece, 64, 64)
LLVM ERROR: Broken module found, compilation aborted!

(SROA.cpp, line 4207)

As I understand it, the SROA pass splits the structure into 2 pieces and does the same for the debug info. This wont work because there is only one piece, resulting in the assertion failure.

Should I use another approach, or is this really a bug?

Regards,
Kai

+aprantl

There is an argument to be made that LLVM should accept debug info in the form

call void @llvm.dbg.value(%complex_wrapper, i64 0,
                          DIVariable(type: DIBasicType(name: "bool", size: 1, encoding: DW_ATE_boolean)),
                          DIExpression({complex expression that extracts the 1 bit from the wrapper}))

This would currently trigger the same assertion that you were seeing and I definitely consider that a bug in LLVM.

But lacking the DIExpression, the resulting DWARF would tell the debugger to expect a 1-bit value at offset 0 in the alloca. I assume that the D debugger knows about lazy variables and thus can do the right thing to unpack the value? Does it need to call the function to get to the value?

To better answer the question I think I need more information on how you lazy variables are represented and what your debugger is expecting.

-- adrian