17
17
#define DEBUG_TYPE " debug-info"
18
18
#include " IRGenDebugInfo.h"
19
19
#include " GenOpaque.h"
20
+ #include " GenStruct.h"
20
21
#include " GenType.h"
21
22
#include " swift/AST/ASTMangler.h"
22
23
#include " swift/AST/Expr.h"
@@ -189,6 +190,12 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
189
190
llvm::DISubprogram *emitFunction (SILFunction &SILFn, llvm::Function *Fn);
190
191
void emitArtificialFunction (IRBuilder &Builder, llvm::Function *Fn,
191
192
SILType SILTy);
193
+
194
+ void handleFragmentDIExpr (const SILDIExprOperand &CurDIExprOp,
195
+ SmallVectorImpl<uint64_t > &Operands);
196
+ void buildDebugInfoExpression (const SILDebugVariable &VarInfo,
197
+ SmallVectorImpl<uint64_t > &Operands);
198
+
192
199
void emitVariableDeclaration (IRBuilder &Builder,
193
200
ArrayRef<llvm::Value *> Storage,
194
201
DebugTypeInfo Ty, const SILDebugScope *DS,
@@ -2330,10 +2337,59 @@ void IRGenDebugInfoImpl::emitArtificialFunction(IRBuilder &Builder,
2330
2337
setCurrentLoc (Builder, Scope, ALoc);
2331
2338
}
2332
2339
2340
+ void IRGenDebugInfoImpl::handleFragmentDIExpr (
2341
+ const SILDIExprOperand &CurDIExprOp,
2342
+ SmallVectorImpl<uint64_t > &Operands) {
2343
+ assert (CurDIExprOp.getOperator () == SILDIExprOperator::Fragment);
2344
+ // Expecting a VarDecl that points to a field in an struct
2345
+ auto DIExprArgs = CurDIExprOp.args ();
2346
+ auto *VD = dyn_cast_or_null<VarDecl>(DIExprArgs.size ()?
2347
+ DIExprArgs[0 ].getAsDecl () : nullptr );
2348
+ assert (VD && " Expecting a VarDecl as the operand for "
2349
+ " DIExprOperator::Fragment" );
2350
+ // Translate the based type
2351
+ DeclContext *ParentDecl = VD->getDeclContext ();
2352
+ SILType ParentSILType =
2353
+ IGM.getLoweredType (ParentDecl->getDeclaredTypeInContext ());
2354
+ // Retrieve the offset & size of the field
2355
+ llvm::Constant *Offset =
2356
+ emitPhysicalStructMemberFixedOffset (IGM, ParentSILType, VD);
2357
+ llvm::Type *FieldTy =
2358
+ getPhysicalStructFieldTypeInfo (IGM, ParentSILType, VD)->getStorageType ();
2359
+ assert (Offset && FieldTy && " Non-fixed type?" );
2360
+
2361
+ uint64_t SizeOfByte = CI.getTargetInfo ().getCharWidth ();
2362
+ uint64_t SizeInBits = IGM.DataLayout .getTypeSizeInBits (FieldTy);
2363
+ uint64_t OffsetInBits =
2364
+ Offset->getUniqueInteger ().getLimitedValue () * SizeOfByte;
2365
+
2366
+ // Translate to LLVM dbg intrinsic operands
2367
+ Operands.push_back (llvm::dwarf::DW_OP_LLVM_fragment);
2368
+ Operands.push_back (OffsetInBits);
2369
+ Operands.push_back (SizeInBits);
2370
+ }
2371
+
2372
+ void IRGenDebugInfoImpl::buildDebugInfoExpression (
2373
+ const SILDebugVariable &VarInfo, SmallVectorImpl<uint64_t > &Operands) {
2374
+ assert (VarInfo.DIExpr && " SIL debug info expression not found" );
2375
+
2376
+ const auto &DIExpr = VarInfo.DIExpr ;
2377
+ for (const SILDIExprOperand &ExprOperand : DIExpr.operands ()) {
2378
+ switch (ExprOperand.getOperator ()) {
2379
+ case SILDIExprOperator::Fragment:
2380
+ handleFragmentDIExpr (ExprOperand, Operands);
2381
+ break ;
2382
+ default :
2383
+ llvm_unreachable (" Unrecoginized operator" );
2384
+ }
2385
+ }
2386
+ }
2387
+
2333
2388
void IRGenDebugInfoImpl::emitVariableDeclaration (
2334
2389
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo DbgTy,
2335
- const SILDebugScope *DS, Optional<SILLocation> VarLoc, SILDebugVariable VarInfo,
2336
- IndirectionKind Indirection, ArtificialKind Artificial) {
2390
+ const SILDebugScope *DS, Optional<SILLocation> DbgInstLoc,
2391
+ SILDebugVariable VarInfo, IndirectionKind Indirection,
2392
+ ArtificialKind Artificial) {
2337
2393
assert (DS && " variable has no scope" );
2338
2394
2339
2395
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
@@ -2348,7 +2404,7 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2348
2404
2349
2405
auto *Scope = dyn_cast_or_null<llvm::DILocalScope>(getOrCreateScope (DS));
2350
2406
assert (Scope && " variable has no local scope" );
2351
- auto Loc = getStartLocation (VarLoc );
2407
+ auto DInstLoc = getStartLocation (DbgInstLoc );
2352
2408
2353
2409
// FIXME: this should be the scope of the type's declaration.
2354
2410
// If this is an argument, attach it to the current function scope.
@@ -2363,10 +2419,11 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2363
2419
if (VarInfo.Constant )
2364
2420
DITy = DBuilder.createQualifiedType (llvm::dwarf::DW_TAG_const_type, DITy);
2365
2421
2366
- unsigned Line = Loc .line ;
2422
+ unsigned DInstLine = DInstLoc .line ;
2367
2423
2368
2424
// Self is always an artificial argument, so are variables without location.
2369
- if (!Line || (VarInfo.ArgNo > 0 && VarInfo.Name == IGM.Context .Id_self .str ()))
2425
+ if (!DInstLine ||
2426
+ (VarInfo.ArgNo > 0 && VarInfo.Name == IGM.Context .Id_self .str ()))
2370
2427
Artificial = ArtificialValue;
2371
2428
2372
2429
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
@@ -2376,12 +2433,35 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2376
2433
// This could be Opts.Optimize if we would also unique DIVariables here.
2377
2434
bool Optimized = false ;
2378
2435
// Create the descriptor for the variable.
2436
+ unsigned DVarLine = DInstLine;
2437
+ if (VarInfo.Loc ) {
2438
+ auto DVarLoc = getStartLocation (VarInfo.Loc );
2439
+ DVarLine = DVarLoc.line ;
2440
+ }
2441
+ llvm::DIScope *VarScope = Scope;
2442
+ if (VarInfo.Scope ) {
2443
+ if (auto *VS = dyn_cast_or_null<llvm::DILocalScope>(
2444
+ getOrCreateScope (VarInfo.Scope )))
2445
+ VarScope = VS;
2446
+ }
2379
2447
llvm::DILocalVariable *Var =
2380
2448
(VarInfo.ArgNo > 0 )
2381
- ? DBuilder.createParameterVariable (Scope, VarInfo.Name , VarInfo.ArgNo ,
2382
- Unit, Line, DITy, Optimized, Flags)
2383
- : DBuilder.createAutoVariable (Scope, VarInfo.Name , Unit, Line, DITy,
2384
- Optimized, Flags);
2449
+ ? DBuilder.createParameterVariable (VarScope, VarInfo.Name ,
2450
+ VarInfo.ArgNo , Unit, DVarLine,
2451
+ DITy, Optimized, Flags)
2452
+ : DBuilder.createAutoVariable (VarScope, VarInfo.Name , Unit, DVarLine,
2453
+ DITy, Optimized, Flags);
2454
+
2455
+ auto appendDIExpression =
2456
+ [&VarInfo, this ](llvm::DIExpression *DIExpr) -> llvm::DIExpression * {
2457
+ if (VarInfo.DIExpr ) {
2458
+ llvm::SmallVector<uint64_t , 2 > Operands;
2459
+ buildDebugInfoExpression (VarInfo, Operands);
2460
+ if (Operands.size ())
2461
+ return llvm::DIExpression::append (DIExpr, Operands);
2462
+ }
2463
+ return DIExpr;
2464
+ };
2385
2465
2386
2466
// Running variables for the current/previous piece.
2387
2467
bool IsPiece = Storage.size () > 1 ;
@@ -2413,16 +2493,21 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
2413
2493
Operands.push_back (OffsetInBits);
2414
2494
Operands.push_back (SizeInBits);
2415
2495
}
2416
- emitDbgIntrinsic (Builder, Piece, Var, DBuilder.createExpression (Operands),
2417
- Line, Loc.column , Scope, DS,
2418
- Indirection == CoroDirectValue ||
2419
- Indirection == CoroIndirectValue);
2496
+ llvm::DIExpression *DIExpr = DBuilder.createExpression (Operands);
2497
+ emitDbgIntrinsic (
2498
+ Builder, Piece, Var,
2499
+ // DW_OP_LLVM_fragment must be the last part of an DIExpr
2500
+ // so we can't append more if IsPiece is true.
2501
+ Operands.empty () || IsPiece ? DIExpr : appendDIExpression (DIExpr),
2502
+ DInstLine, DInstLoc.column , Scope, DS,
2503
+ Indirection == CoroDirectValue || Indirection == CoroIndirectValue);
2420
2504
}
2421
2505
2422
2506
// Emit locationless intrinsic for variables that were optimized away.
2423
2507
if (Storage.empty ())
2424
2508
emitDbgIntrinsic (Builder, llvm::ConstantInt::get (IGM.Int64Ty , 0 ), Var,
2425
- DBuilder.createExpression (), Line, Loc.column , Scope, DS,
2509
+ appendDIExpression (DBuilder.createExpression ()), DInstLine,
2510
+ DInstLoc.column , Scope, DS,
2426
2511
Indirection == CoroDirectValue ||
2427
2512
Indirection == CoroIndirectValue);
2428
2513
}
@@ -2438,7 +2523,8 @@ void IRGenDebugInfoImpl::emitDbgIntrinsic(
2438
2523
auto *BB = Builder.GetInsertBlock ();
2439
2524
2440
2525
// An alloca may only be described by exactly one dbg.declare.
2441
- if (isa<llvm::AllocaInst>(Storage) && !llvm::FindDbgAddrUses (Storage).empty ())
2526
+ if (isa<llvm::AllocaInst>(Storage) &&
2527
+ !llvm::FindDbgDeclareUses (Storage).empty ())
2442
2528
return ;
2443
2529
2444
2530
// A dbg.declare is only meaningful if there is a single alloca for
0 commit comments