Skip to content

[DebugInfo] Merge fragments from SIL with fragments created in IRGen #66448

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
merged 6 commits into from
Jun 20, 2023

Conversation

asavonic
Copy link
Contributor

@asavonic asavonic commented Jun 8, 2023

SIL variables can be split by SILSROA into separate allocations, each having op_fragment expressions in debug_value (VarInfo.DIExpr). These allocations can be further split by IRGen (multiple values in Storage argument).

These "nested" fragments refer to the same DI variable, so it is important to merge them for the LLVM IR DI expression. The compiler used to ignore fragment expressions from SIL when IRGen fragments were also present. This led to incorrect DI info generation, and for some cases even triggered assertions in LLVM X86 CodeGen:

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

The patch resolves #64642. The LIT test is a reduced reproducer from that issue.

SIL variables can be split by SILSROA into separate allocations, each having
op_fragment expressions in debug_value (VarInfo.DIExpr). These allocations can
be further split by IRGen (multiple values in Storage argument).

These "nested" fragments refer to the same DI variable, so it is important to
merge them for the LLVM IR DI expression. The compiler used to ignore fragment
expressions from SIL when IRGen fragments were also present. This led to
incorrect DI info generation, and for some cases even triggered assertions in
LLVM X86 CodeGen:

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

The patch fixes issue swiftlang#64642. The LIT test is a reduced reproducer from that
issue.
@asavonic asavonic requested a review from adrian-prantl as a code owner June 8, 2023 13:28
@asl
Copy link
Contributor

asl commented Jun 8, 2023

@swift-ci please test

@asl
Copy link
Contributor

asl commented Jun 8, 2023

Tagging @BradLarson

@asl
Copy link
Contributor

asl commented Jun 14, 2023

@swift-ci please test

@asl
Copy link
Contributor

asl commented Jun 14, 2023

@swift-ci please test

@asl
Copy link
Contributor

asl commented Jun 14, 2023

@adrian-prantl ping :)

Copy link
Contributor

@adrian-prantl adrian-prantl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This great! I have a few minor suggestions inside.

@@ -215,10 +215,11 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {

/// Return false if we fail to create the right DW_OP_LLVM_fragment operand.
bool handleFragmentDIExpr(const SILDIExprOperand &CurDIExprOp,
SmallVectorImpl<uint64_t> &Operands);
std::pair<unsigned, unsigned> &Fragment);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about using an llvm::DIExpression::FragmentInfo here, so it's more clear which is which?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Done.

@@ -0,0 +1,40 @@
// RUN: %target-swift-frontend -disable-availability-checking -primary-file %s -emit-sil -O -g | %FileCheck %s --check-prefix CHECK-SIL
// RUN: %target-swift-frontend -disable-availability-checking -primary-file %s -emit-ir -disable-llvm-optzns -O -g | %FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be wonderful if we could have a test that uses textual SIL as input here, so it isn't depending on specific optimization decisions in the compiler pipeline.

SIL serialization for debug info isn't perfect, so let me know if this isn't an option!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reduced the reproducer into a somewhat shorter SIL. It shows the same issue in LLVM IR after IRGen, but it does not cause LLVM CG crash as the original.

// When the fragment of the SIL variable is further split into other
// fragments (PieceFragment), merge them into one DW_OP_LLVM_Fragment
// expression.
if (PieceFragmentSize)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we assert that PieceFragmentSize < VarFragmentSize here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is checked by createFragmentExpression:

        assert((OffsetInBits + SizeInBits <= FragmentSizeInBits) &&
               "new fragment outside of original fragment");

where FragmentSizeInBits is the fragment expression we're appending to.

@asl
Copy link
Contributor

asl commented Jun 19, 2023

@swift-ci please test

@asl asl requested a review from adrian-prantl June 19, 2023 17:38
@asl asl merged commit 31e4465 into swiftlang:main Jun 20, 2023
felipepiovezan added a commit to felipepiovezan/swift that referenced this pull request Jun 23, 2023
Two new tests were added in swiftlang#66448, and they both fail for watchOS:

1. debug_fragment_merge.sil fails on 32 bit architectures because the offset
calculation is different for those (fragments of 32 bits, instead of 64).
2. debug_fragment_merge.swift is failing for unknown reasons at this point,
there is simply no SIL debug information generated for the variable "data".
Since the original patch didn't change SILGen, this is not a regression.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants