@@ -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
+ std::pair< unsigned , unsigned > &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
+ std::pair<unsigned , unsigned > &Fragment);
222
223
223
224
// / Emit a dbg.declare at the current insertion point in Builder.
224
225
void emitVariableDeclaration (IRBuilder &Builder,
@@ -2522,7 +2523,8 @@ void IRGenDebugInfoImpl::emitOutlinedFunction(IRBuilder &Builder,
2522
2523
}
2523
2524
2524
2525
bool IRGenDebugInfoImpl::handleFragmentDIExpr (
2525
- const SILDIExprOperand &CurDIExprOp, SmallVectorImpl<uint64_t > &Operands) {
2526
+ const SILDIExprOperand &CurDIExprOp,
2527
+ std::pair<unsigned , unsigned > &Fragment) {
2526
2528
assert (CurDIExprOp.getOperator () == SILDIExprOperator::Fragment);
2527
2529
// Expecting a VarDecl that points to a field in an struct
2528
2530
auto DIExprArgs = CurDIExprOp.args ();
@@ -2554,23 +2556,31 @@ bool IRGenDebugInfoImpl::handleFragmentDIExpr(
2554
2556
uint64_t OffsetInBits =
2555
2557
Offset->getUniqueInteger ().getLimitedValue () * SizeOfByte;
2556
2558
2557
- // Translate to LLVM dbg intrinsic operands
2558
- Operands.push_back (llvm::dwarf::DW_OP_LLVM_fragment);
2559
- Operands.push_back (OffsetInBits);
2560
- Operands.push_back (SizeInBits);
2559
+ // Translate to DW_OP_LLVM_fragment operands
2560
+ Fragment = std::make_pair (OffsetInBits, SizeInBits);
2561
2561
2562
2562
return true ;
2563
2563
}
2564
2564
2565
2565
bool IRGenDebugInfoImpl::buildDebugInfoExpression (
2566
- const SILDebugVariable &VarInfo, SmallVectorImpl<uint64_t > &Operands) {
2566
+ const SILDebugVariable &VarInfo, SmallVectorImpl<uint64_t > &Operands,
2567
+ std::pair<unsigned , unsigned > &Fragment) {
2567
2568
assert (VarInfo.DIExpr && " SIL debug info expression not found" );
2568
2569
2570
+ #ifndef NDEBUG
2571
+ bool HasFragment = VarInfo.DIExpr .hasFragment ();
2572
+ #endif
2573
+
2569
2574
const auto &DIExpr = VarInfo.DIExpr ;
2570
2575
for (const SILDIExprOperand &ExprOperand : DIExpr.operands ()) {
2571
2576
switch (ExprOperand.getOperator ()) {
2572
2577
case SILDIExprOperator::Fragment:
2573
- if (!handleFragmentDIExpr (ExprOperand, Operands))
2578
+ assert (HasFragment && " Fragment must be the last part of a DIExpr" );
2579
+ #ifndef NDEBUG
2580
+ // Trigger the assert above if we have more than one fragment expression.
2581
+ HasFragment = false ;
2582
+ #endif
2583
+ if (!handleFragmentDIExpr (ExprOperand, Fragment))
2574
2584
return false ;
2575
2585
break ;
2576
2586
case SILDIExprOperator::Dereference:
@@ -2677,24 +2687,60 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2677
2687
LocalVarCache.insert ({Key, llvm::TrackingMDNodeRef (Var)});
2678
2688
}
2679
2689
2680
- auto appendDIExpression =
2681
- [&VarInfo, this ](llvm::DIExpression *DIExpr) -> llvm::DIExpression * {
2682
- if (VarInfo.DIExpr ) {
2683
- llvm::SmallVector<uint64_t , 2 > Operands;
2684
- if (!buildDebugInfoExpression (VarInfo, Operands))
2685
- return nullptr ;
2686
- if (Operands.size ())
2687
- return llvm::DIExpression::append (DIExpr, Operands);
2688
- }
2689
- return DIExpr;
2690
- };
2691
-
2692
2690
// Running variables for the current/previous piece.
2693
2691
bool IsPiece = Storage.size () > 1 ;
2694
2692
uint64_t SizeOfByte = CI.getTargetInfo ().getCharWidth ();
2695
2693
unsigned AlignInBits = SizeOfByte;
2696
2694
unsigned OffsetInBits = 0 ;
2697
2695
unsigned SizeInBits = 0 ;
2696
+ std::pair<unsigned , unsigned > Fragment (0 , 0 );
2697
+
2698
+ auto appendDIExpression =
2699
+ [&VarInfo, this ](
2700
+ llvm::DIExpression *DIExpr,
2701
+ std::pair<unsigned , unsigned > PieceFragment) -> llvm::DIExpression * {
2702
+ unsigned PieceFragmentOffset = PieceFragment.first ;
2703
+ unsigned PieceFragmentSize = PieceFragment.second ;
2704
+
2705
+ if (!VarInfo.DIExpr ) {
2706
+ if (!PieceFragmentSize)
2707
+ return DIExpr;
2708
+
2709
+ return llvm::DIExpression::createFragmentExpression (
2710
+ DIExpr, PieceFragmentOffset, PieceFragmentSize)
2711
+ .getValueOr (nullptr );
2712
+ }
2713
+
2714
+ llvm::SmallVector<uint64_t , 2 > Operands;
2715
+ std::pair<unsigned , unsigned > VarFragment (0 , 0 );
2716
+ if (!buildDebugInfoExpression (VarInfo, Operands, VarFragment))
2717
+ return nullptr ;
2718
+
2719
+ if (!Operands.empty ())
2720
+ DIExpr = llvm::DIExpression::append (DIExpr, Operands);
2721
+
2722
+ unsigned VarFragmentOffset = VarFragment.first ;
2723
+ unsigned VarFragmentSize = VarFragment.second ;
2724
+
2725
+ // Add the fragment of the SIL variable.
2726
+ if (VarFragmentSize)
2727
+ DIExpr = llvm::DIExpression::createFragmentExpression (
2728
+ DIExpr, VarFragmentOffset, VarFragmentSize)
2729
+ .getValueOr (nullptr );
2730
+
2731
+ if (!DIExpr)
2732
+ return nullptr ;
2733
+
2734
+ // When the fragment of the SIL variable is further split into other
2735
+ // fragments (PieceFragment), merge them into one DW_OP_LLVM_Fragment
2736
+ // expression.
2737
+ if (PieceFragmentSize)
2738
+ return llvm::DIExpression::createFragmentExpression (
2739
+ DIExpr, PieceFragmentOffset, PieceFragmentSize)
2740
+ .getValueOr (nullptr );
2741
+
2742
+ return DIExpr;
2743
+ };
2698
2744
2699
2745
for (llvm::Value *Piece : Storage) {
2700
2746
SmallVector<uint64_t , 3 > Operands;
@@ -2723,16 +2769,12 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2723
2769
}
2724
2770
#endif
2725
2771
2726
- // Add the piece DWARF expression.
2727
- Operands.push_back (llvm::dwarf::DW_OP_LLVM_fragment);
2728
- Operands.push_back (OffsetInBits);
2729
- Operands.push_back (SizeInBits);
2772
+ // Add the piece DW_OP_LLVM_fragment operands
2773
+ Fragment.first = OffsetInBits;
2774
+ Fragment.second = SizeInBits;
2730
2775
}
2731
2776
llvm::DIExpression *DIExpr = DBuilder.createExpression (Operands);
2732
- // DW_OP_LLVM_fragment must be the last part of an DIExpr
2733
- // so we can't append more if IsPiece is true.
2734
- if (!IsPiece)
2735
- DIExpr = appendDIExpression (DIExpr);
2777
+ DIExpr = appendDIExpression (DIExpr, Fragment);
2736
2778
if (DIExpr)
2737
2779
emitDbgIntrinsic (
2738
2780
Builder, Piece, Var, DIExpr, DInstLine, DInstLoc.column , Scope, DS,
@@ -2742,7 +2784,9 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2742
2784
2743
2785
// Emit locationless intrinsic for variables that were optimized away.
2744
2786
if (Storage.empty ()) {
2745
- if (auto *DIExpr = appendDIExpression (DBuilder.createExpression ()))
2787
+ std::pair<unsigned , unsigned > NoFragment (0 , 0 );
2788
+ if (auto *DIExpr =
2789
+ appendDIExpression (DBuilder.createExpression (), NoFragment))
2746
2790
emitDbgIntrinsic (Builder, llvm::ConstantInt::get (IGM.Int64Ty , 0 ), Var,
2747
2791
DIExpr, DInstLine, DInstLoc.column , Scope, DS,
2748
2792
Indirection == CoroDirectValue ||
0 commit comments