Skip to content

[DebugInfo] Emit distinct DILocation for different inline instances #66744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

asavonic
Copy link
Contributor

LLVM seems to determine a variable instance as a combination of DILocalVariable
and DILocation. Therefore if multiple llvm.dbg.declare have the same
variable/location parameters, they are considered to be referencing the same
instance of variable.

Swift IRGen emits a set of llvm.dbg.declare calls for every variable
instance (with unique SILDebugScope), so it is important that these calls have
distinct variable/location parameters. Otherwise their DIExpression may be
incorrect when treated as referencing the same variable. For example, if they
have a DIExpression with fragments, we will see this as multiple declarations of
the same fragment. LLVM detects this and crashes with assertion failure:

DwarfExpression.cpp:679: void llvm::DwarfExpression::addFragmentOffset(const
llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits &&
"overlapping or duplicate fragments"' failed.

The patch resolves #55703. The LIT test (debug_scope_distinct.swift) is the
reproducer from that issue.

@asavonic asavonic requested a review from adrian-prantl as a code owner June 19, 2023 11:08
@asl
Copy link
Contributor

asl commented Jun 19, 2023

@swift-ci please test

@asavonic
Copy link
Contributor Author

The LIT test is a bit too minimal - it has some undefs in IR, which does not play nicely with optimizations. I cannot reproduce CI failures locally, but the issue is obvious. I'll change the test to avoid undefs, and we can try again.

@asavonic asavonic force-pushed the debuginfo-fragment-distinct-inline-loc branch from 2751d98 to 43d8b5d Compare June 22, 2023 09:55
@asl
Copy link
Contributor

asl commented Jun 22, 2023

@swift-ci please test

@asavonic asavonic force-pushed the debuginfo-fragment-distinct-inline-loc branch from 43d8b5d to 820ebe3 Compare June 28, 2023 15:35
@asl
Copy link
Contributor

asl commented Jun 28, 2023

@swift-ci please test

LLVM seems to determine a variable instance as a combination of DILocalVariable
and DILocation. Therefore if multiple llvm.dbg.declare have the same
variable/location parameters, they are considered to be referencing the same
instance of variable.

Swift IRGen emits a set of llvm.dbg.declare calls for every variable
instance (with unique SILDebugScope), so it is important that these calls have
distinct variable/location parameters. Otherwise their DIExpression may be
incorrect when treated as referencing the same variable. For example, if they
have a DIExpression with fragments, we will see this as multiple declarations of
the same fragment. LLVM detects this and crashes with assertion failure:

DwarfExpression.cpp:679: void llvm::DwarfExpression::addFragmentOffset(const
llvm::DIExpression *): Assertion `FragmentOffset >= OffsetInBits &&
"overlapping or duplicate fragments"' failed.

The patch resolves swiftlang#55703. The LIT test (debug_scope_distinct.swift) is the
reproducer from that issue.
@asavonic asavonic force-pushed the debuginfo-fragment-distinct-inline-loc branch from 820ebe3 to ca6e742 Compare June 29, 2023 08:06
@asl
Copy link
Contributor

asl commented Jun 29, 2023

@swift-ci please test

@asl
Copy link
Contributor

asl commented Jun 30, 2023

@adrian-prantl ping :)

@asavonic
Copy link
Contributor Author

asavonic commented Jul 7, 2023

@adrian-prantl, can you please check if the patch is OK?

@asl
Copy link
Contributor

asl commented Jul 24, 2023

@adrian-prantl Gentle ping

@adrian-prantl
Copy link
Contributor

(Sorry for the delayed response, I've been on vacation)

In the reproducer, the inlined-at locations are all at line 0 and it looks like that is the actual problem. I think it would be okay to emit line 0 inlined-at locations as distinct to avoid this problem, but a better solution would be to ensure the autodifferentiation transformation would assign meaningful line numbers. Inlined functions with no source location at the call site are not a great user experience.

Would you mind changing the patch to only apply the distinct locations to line-0 call sites?

@asavonic
Copy link
Contributor Author

Right, it seems that the compiler lost the actual line number somewhere, and it is better to fix this issue.
However, these locations are tied to the same local variable (multiple instances of it after inlining), so the correct line number would also be the same for both, and we're back to the same problem.

@adrian-prantl
Copy link
Contributor

Right, it seems that the compiler lost the actual line number somewhere, and it is better to fix this issue.

Correct. I'd still be fine with a variant of this patch to only make line 0 call site locations distinct, though I'd prefer we could assert that no function call is on line 0.

However, these locations are tied to the same local variable (multiple instances of it after inlining), so the correct line number would also be the same for both, and we're back to the same problem.

I don't think that's true. If the same function is inlined multiple times, and locations are tracked correctly, then the inlined call sites would differ and the locations would be distinct.

@asavonic
Copy link
Contributor Author

though I'd prefer we could assert that no function call is on line 0.

This is likely because these calls are artificial, and generated by the compiler to support differentiation.
I will check if this is the case.

However, these locations are tied to the same local variable (multiple instances of it after inlining), so the correct line number would also be the same for both, and we're back to the same problem.

I don't think that's true. If the same function is inlined multiple times, and locations are tracked correctly, then the inlined call sites would differ and the locations would be distinct.

Without the patch, all it takes to get a collision of inlinedAt locations is for them to have the same source line and scope.
Lines are not unique in general: we can have multiple inlined calls on the same source line.
Scopes (DISubprogram in this case) are not unique either, at least we don't have a unique scope for each inline instance.

I think this is the same problem that LLVM had back in the day:
llvm/llvm-project@df70628

@adrian-prantl
Copy link
Contributor

Okay, if LLVM also generates all inlinedAt locations as distinct, we should match that behavior. One thing I was worried about here was that we would generate distinct inlinedAt information for two instructions originating from the same inlined call, however, these should share the same SILDebugScope on so the caching mechanism should prevent this from happening.

LGTM! And thanks for pointing this out.

@adrian-prantl adrian-prantl merged commit 1f6091a into swiftlang:main Jul 28, 2023
@finagolfin
Copy link
Member

This is failing on Android armv7, similar to previous tests that were disabled for 32-bit in #66879:

Command Output (stderr):
--
/home/ubuntu/jenkins/workspace/oss-swift-RA-linux-ubuntu-16.04-android/swift/test/IRGen/debug_scope_distinct.swift:10:11: error: CHECK: expected string not found in input
// CHECK: call void @llvm.dbg.value(metadata {{.*}} %[[ARG0]], metadata ![[VAR1:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg ![[LOC1:[0-9]+]]
          ^
<stdin>:1030:42: note: scanning from here
 %.sroa.013.0.copyload = load ptr, ptr %0, align 4, !dbg !286
                                         ^
<stdin>:1030:42: note: with "ARG0" equal to "\\.sroa\\.013\\.0\\.copyload"
 %.sroa.013.0.copyload = load ptr, ptr %0, align 4, !dbg !286
                                         ^
<stdin>:1078:2: note: possible intended match here
 call void @llvm.dbg.value(metadata i64 %22, metadata !280, metadata !DIExpression(DW_OP_LLVM_fragment, 40, 64)), !dbg !309
 ^

Input file: <stdin>
Check file: /home/ubuntu/jenkins/workspace/oss-swift-RA-linux-ubuntu-16.04-android/swift/test/IRGen/debug_scope_distinct.swift

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            .
            .
            .
         1025:  call void @llvm.dbg.declare(metadata ptr %3, metadata !268, metadata !DIExpression()), !dbg !283 
         1026:  call void @llvm.lifetime.start.p0(i64 5, ptr nonnull %2), !dbg !286 
         1027:  call void @llvm.lifetime.start.p0(i64 5, ptr nonnull %3), !dbg !286 
         1028:  call void @llvm.dbg.value(metadata ptr %0, metadata !266, metadata !DIExpression(DW_OP_deref)), !dbg !286 
         1029:  call void @llvm.dbg.value(metadata ptr %1, metadata !267, metadata !DIExpression(DW_OP_deref)), !dbg !286 
         1030:  %.sroa.013.0.copyload = load ptr, ptr %0, align 4, !dbg !286 
check:10'0                                              X~~~~~~~~~~~~~~~~~~~~ error: no match found
check:10'1                                                                    with "ARG0" equal to "\\.sroa\\.013\\.0\\.copyload"
         1031:  call void @llvm.dbg.value(metadata ptr %.sroa.013.0.copyload, metadata !280, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32)), !dbg !287 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1032:  %.sroa.414.0..u1.sroa_idx = getelementptr inbounds i8, ptr %0, i32 4, !dbg !286 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1033:  %.sroa.414.0.copyload = load i8, ptr %.sroa.414.0..u1.sroa_idx, align 4, !dbg !286 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1034:  call void @llvm.dbg.value(metadata i8 %.sroa.414.0.copyload, metadata !280, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 8)), !dbg !287 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1035:  %.sroa.515.0..u1.sroa_idx = getelementptr inbounds i8, ptr %0, i32 5, !dbg !286 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            .
            .
            .
         1073:  %.sroa.4.0..u2.sroa_idx = getelementptr inbounds %T4main1TV13TangentVectorV, ptr %0, i32 0, i32 2, i32 0, i32 1, !dbg !286 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1074:  %.sroa.4.0.copyload = load i8, ptr %.sroa.4.0..u2.sroa_idx, align 4, !dbg !286 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1075:  call void @llvm.dbg.value(metadata i8 %.sroa.4.0.copyload, metadata !280, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 8)), !dbg !309 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1076:  %.sroa.5.0..u2.sroa_idx = getelementptr inbounds %T4main1TV13TangentVectorV, ptr %0, i32 0, i32 2, i32 1, !dbg !286 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1077:  %22 = load i64, ptr %.sroa.5.0..u2.sroa_idx, align 1, !dbg !286 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1078:  call void @llvm.dbg.value(metadata i64 %22, metadata !280, metadata !DIExpression(DW_OP_LLVM_fragment, 40, 64)), !dbg !309 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
check:10'2      ?                                                                                                                           possible intended match
         1079:  %.u26 = getelementptr inbounds %T4main1TV, ptr %1, i32 0, i32 2, !dbg !286 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1080:  call void @llvm.dbg.value(metadata ptr %.u26, metadata !281, metadata !DIExpression(DW_OP_deref)), !dbg !309 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1081:  %23 = load ptr, ptr %.u26, align 4, !dbg !310 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1082:  %.u26.s.b = getelementptr inbounds %T4main1TV, ptr %1, i32 0, i32 2, i32 0, i32 1, !dbg !310 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         1083:  %24 = load i8, ptr %.u26.s.b, align 4, !dbg !310 
check:10'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            .
            .
            .
>>>>>>

@felipepiovezan, can you check if this test is failing on watchos too?

@adrian-prantl
Copy link
Contributor

@asavonic This may just be too dependent on the architecture. Can you put a REQUIRES on the test that limits it to 64 bit architectures?

asavonic added a commit to asavonic/swift that referenced this pull request Aug 3, 2023
These tests depend on the target layout, and there were issues reported for
Android armv7 (see swiftlang#66744) and watchOS (swiftlang#66879) targets.
@asavonic
Copy link
Contributor Author

asavonic commented Aug 3, 2023

@finagolfin, @adrian-prantl, thank you for letting me know, I missed the follow-up patch that disabled these tests for watchOS. Can you please check the patch #67699?

asl pushed a commit that referenced this pull request Aug 10, 2023
…7699)

These tests depend on the target layout, and there were issues reported for Android armv7 (see #66744) and watchOS (#66879) targets.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[SR-13263] Invalid Debug Information Generation
4 participants