Skip to content

LLVM's DWARF associates instruction from caller with source from inlined callee #152576

@hubert-reinterpretcast

Description

@hubert-reinterpretcast

Consider the following program:

__attribute__((optnone)) void f1(int x) { }
__attribute__((always_inline)) inline void f2(int *p, int x) {
  *p = 42; // moved outside of loop
  f1(x);
}
__attribute__((optnone)) void f3(int *p) { }
int main(int argc, char **argv) {
  int q;
  for (int x = 0; x < argc; ++x) {
    f2(&q, x);
  }
  f3(&q);
  return q;
}

Compiled with -O3 -g, the store of 42 is moved outside of the loop to just before the call to f3: https://godbolt.org/z/oYx7YqMhj

.LBB2_3:
        mov     dword ptr [rsp + 4], 42
        lea     rdi, [rsp + 4]
        call    f3(int*)

However, the lea instruction, which corresponds to &q in the call to f3 is associated with line 3 (*p = 42) in the DWARF:

Address            Line   Column File   ISA Discriminator OpIndex Flags
------------------ ------ ------ ------ --- ------------- ------- -------------
0x0000000000000000      1      0      0   0             0       0  is_stmt
0x0000000000000004      1     43      0   0             0       0  is_stmt prologue_end
0x0000000000000010      6      0      0   0             0       0  is_stmt
0x0000000000000015      6     44      0   0             0       0  is_stmt prologue_end
0x0000000000000020      7      0      0   0             0       0  is_stmt
0x0000000000000023      9     21      0   0             0       0  is_stmt prologue_end
0x0000000000000025      9      3      0   0             0       0
0x0000000000000027      0      3      0   0             0       0
0x0000000000000030      4      3      0   0             0       0  is_stmt
0x0000000000000037      9     29      0   0             0       0  is_stmt
0x0000000000000039      9     21      0   0             0       0
0x000000000000003b      9      3      0   0             0       0
0x000000000000003d      3      6      0   0             0       0  is_stmt
0x000000000000004a     12      3      0   0             0       0  is_stmt
0x000000000000004f     13     10      0   0             0       0  is_stmt
0x0000000000000053     13      3      0   0             0       0  epilogue_begin
0x000000000000005a     13      3      0   0             0       0  end_sequence
ranges.o:       file format elf64-x86-64

Disassembly of section .text:

0000000000000020 <main>:
      3d: c7 44 24 04 2a 00 00 00       movl    $0x2a, 0x4(%rsp)
      45: 48 8d 7c 24 04                leaq    0x4(%rsp), %rdi

Similarly, the lea instruction is represented as being inlined from f2:

0x000000b0:       DW_TAG_inlined_subroutine
                    DW_AT_abstract_origin       (0x00000059 "f2")
                    DW_AT_ranges        (indexed (0x0) rangelist = 0x00000010
                       [0x000000000000002b, 0x0000000000000037)
                       [0x000000000000003d, 0x000000000000004a))

Clang version info:

clang version 22.0.0git (https://github.com/llvm/llvm-project.git 7694856fddbb3fed10076aefec75c9b512cc352e)

Partial IR:

for.cond.cleanup:                                 ; preds = %for.body, %entry
  store i32 42, ptr %q, align 4, !dbg !52, !DIAssignID !61
  call void @f3(ptr noundef nonnull %q), !dbg !62
;   ...
!52 = !DILocation(line: 3, column: 6, scope: !53, inlinedAt: !59)
!53 = distinct !DISubprogram(name: "f2", scope: !1, file: !1, line: 2, type: !54, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !56)
;   ...
!59 = distinct !DILocation(line: 10, column: 5, scope: !60)
;   ...
!62 = !DILocation(line: 12, column: 3, scope: !33)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions