@@ -215,10 +215,11 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
215
215
216
216
// / Return false if we fail to create the right DW_OP_LLVM_fragment operand.
217
217
bool handleFragmentDIExpr (const SILDIExprOperand &CurDIExprOp,
218
- SmallVectorImpl< uint64_t > &Operands );
218
+ llvm::DIExpression::FragmentInfo &Fragment );
219
219
// / Return false if we fail to create the desired !DIExpression.
220
220
bool buildDebugInfoExpression (const SILDebugVariable &VarInfo,
221
- SmallVectorImpl<uint64_t > &Operands);
221
+ SmallVectorImpl<uint64_t > &Operands,
222
+ llvm::DIExpression::FragmentInfo &Fragment);
222
223
223
224
// / Emit a dbg.declare at the current insertion point in Builder.
224
225
void emitVariableDeclaration (IRBuilder &Builder,
@@ -2516,7 +2517,8 @@ void IRGenDebugInfoImpl::emitOutlinedFunction(IRBuilder &Builder,
2516
2517
}
2517
2518
2518
2519
bool IRGenDebugInfoImpl::handleFragmentDIExpr (
2519
- const SILDIExprOperand &CurDIExprOp, SmallVectorImpl<uint64_t > &Operands) {
2520
+ const SILDIExprOperand &CurDIExprOp,
2521
+ llvm::DIExpression::FragmentInfo &Fragment) {
2520
2522
assert (CurDIExprOp.getOperator () == SILDIExprOperator::Fragment);
2521
2523
// Expecting a VarDecl that points to a field in an struct
2522
2524
auto DIExprArgs = CurDIExprOp.args ();
@@ -2548,23 +2550,31 @@ bool IRGenDebugInfoImpl::handleFragmentDIExpr(
2548
2550
uint64_t OffsetInBits =
2549
2551
Offset->getUniqueInteger ().getLimitedValue () * SizeOfByte;
2550
2552
2551
- // Translate to LLVM dbg intrinsic operands
2552
- Operands.push_back (llvm::dwarf::DW_OP_LLVM_fragment);
2553
- Operands.push_back (OffsetInBits);
2554
- Operands.push_back (SizeInBits);
2553
+ // Translate to DW_OP_LLVM_fragment operands
2554
+ Fragment = {SizeInBits, OffsetInBits};
2555
2555
2556
2556
return true ;
2557
2557
}
2558
2558
2559
2559
bool IRGenDebugInfoImpl::buildDebugInfoExpression (
2560
- const SILDebugVariable &VarInfo, SmallVectorImpl<uint64_t > &Operands) {
2560
+ const SILDebugVariable &VarInfo, SmallVectorImpl<uint64_t > &Operands,
2561
+ llvm::DIExpression::FragmentInfo &Fragment) {
2561
2562
assert (VarInfo.DIExpr && " SIL debug info expression not found" );
2562
2563
2564
+ #ifndef NDEBUG
2565
+ bool HasFragment = VarInfo.DIExpr .hasFragment ();
2566
+ #endif
2567
+
2563
2568
const auto &DIExpr = VarInfo.DIExpr ;
2564
2569
for (const SILDIExprOperand &ExprOperand : DIExpr.operands ()) {
2565
2570
switch (ExprOperand.getOperator ()) {
2566
2571
case SILDIExprOperator::Fragment:
2567
- if (!handleFragmentDIExpr (ExprOperand, Operands))
2572
+ assert (HasFragment && " Fragment must be the last part of a DIExpr" );
2573
+ #ifndef NDEBUG
2574
+ // Trigger the assert above if we have more than one fragment expression.
2575
+ HasFragment = false ;
2576
+ #endif
2577
+ if (!handleFragmentDIExpr (ExprOperand, Fragment))
2568
2578
return false ;
2569
2579
break ;
2570
2580
case SILDIExprOperator::Dereference:
@@ -2671,24 +2681,54 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2671
2681
LocalVarCache.insert ({Key, llvm::TrackingMDNodeRef (Var)});
2672
2682
}
2673
2683
2674
- auto appendDIExpression =
2675
- [&VarInfo, this ](llvm::DIExpression *DIExpr) -> llvm::DIExpression * {
2676
- if (VarInfo.DIExpr ) {
2677
- llvm::SmallVector<uint64_t , 2 > Operands;
2678
- if (!buildDebugInfoExpression (VarInfo, Operands))
2679
- return nullptr ;
2680
- if (Operands.size ())
2681
- return llvm::DIExpression::append (DIExpr, Operands);
2682
- }
2683
- return DIExpr;
2684
- };
2685
-
2686
2684
// Running variables for the current/previous piece.
2687
2685
bool IsPiece = Storage.size () > 1 ;
2688
2686
uint64_t SizeOfByte = CI.getTargetInfo ().getCharWidth ();
2689
2687
unsigned AlignInBits = SizeOfByte;
2690
2688
unsigned OffsetInBits = 0 ;
2691
2689
unsigned SizeInBits = 0 ;
2690
+ llvm::DIExpression::FragmentInfo Fragment = {0 , 0 };
2691
+
2692
+ auto appendDIExpression =
2693
+ [&VarInfo, this ](llvm::DIExpression *DIExpr,
2694
+ llvm::DIExpression::FragmentInfo PieceFragment)
2695
+ -> llvm::DIExpression * {
2696
+ if (!VarInfo.DIExpr ) {
2697
+ if (!PieceFragment.SizeInBits )
2698
+ return DIExpr;
2699
+
2700
+ return llvm::DIExpression::createFragmentExpression (
2701
+ DIExpr, PieceFragment.OffsetInBits , PieceFragment.SizeInBits )
2702
+ .getValueOr (nullptr );
2703
+ }
2704
+
2705
+ llvm::SmallVector<uint64_t , 2 > Operands;
2706
+ llvm::DIExpression::FragmentInfo VarFragment = {0 , 0 };
2707
+ if (!buildDebugInfoExpression (VarInfo, Operands, VarFragment))
2708
+ return nullptr ;
2709
+
2710
+ if (!Operands.empty ())
2711
+ DIExpr = llvm::DIExpression::append (DIExpr, Operands);
2712
+
2713
+ // Add the fragment of the SIL variable.
2714
+ if (VarFragment.SizeInBits )
2715
+ DIExpr = llvm::DIExpression::createFragmentExpression (
2716
+ DIExpr, VarFragment.OffsetInBits , VarFragment.SizeInBits )
2717
+ .getValueOr (nullptr );
2718
+
2719
+ if (!DIExpr)
2720
+ return nullptr ;
2721
+
2722
+ // When the fragment of the SIL variable is further split into other
2723
+ // fragments (PieceFragment), merge them into one DW_OP_LLVM_Fragment
2724
+ // expression.
2725
+ if (PieceFragment.SizeInBits )
2726
+ return llvm::DIExpression::createFragmentExpression (
2727
+ DIExpr, PieceFragment.OffsetInBits , PieceFragment.SizeInBits )
2728
+ .getValueOr (nullptr );
2729
+
2730
+ return DIExpr;
2731
+ };
2692
2732
2693
2733
for (llvm::Value *Piece : Storage) {
2694
2734
SmallVector<uint64_t , 3 > Operands;
@@ -2717,16 +2757,12 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2717
2757
}
2718
2758
#endif
2719
2759
2720
- // Add the piece DWARF expression.
2721
- Operands.push_back (llvm::dwarf::DW_OP_LLVM_fragment);
2722
- Operands.push_back (OffsetInBits);
2723
- Operands.push_back (SizeInBits);
2760
+ // Add the piece DW_OP_LLVM_fragment operands
2761
+ Fragment.OffsetInBits = OffsetInBits;
2762
+ Fragment.SizeInBits = SizeInBits;
2724
2763
}
2725
2764
llvm::DIExpression *DIExpr = DBuilder.createExpression (Operands);
2726
- // DW_OP_LLVM_fragment must be the last part of an DIExpr
2727
- // so we can't append more if IsPiece is true.
2728
- if (!IsPiece)
2729
- DIExpr = appendDIExpression (DIExpr);
2765
+ DIExpr = appendDIExpression (DIExpr, Fragment);
2730
2766
if (DIExpr)
2731
2767
emitDbgIntrinsic (
2732
2768
Builder, Piece, Var, DIExpr, DInstLine, DInstLoc.column , Scope, DS,
@@ -2736,7 +2772,9 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2736
2772
2737
2773
// Emit locationless intrinsic for variables that were optimized away.
2738
2774
if (Storage.empty ()) {
2739
- if (auto *DIExpr = appendDIExpression (DBuilder.createExpression ()))
2775
+ llvm::DIExpression::FragmentInfo NoFragment = {0 , 0 };
2776
+ if (auto *DIExpr =
2777
+ appendDIExpression (DBuilder.createExpression (), NoFragment))
2740
2778
emitDbgIntrinsic (Builder, llvm::ConstantInt::get (IGM.Int64Ty , 0 ), Var,
2741
2779
DIExpr, DInstLine, DInstLoc.column , Scope, DS,
2742
2780
Indirection == CoroDirectValue ||
0 commit comments