Skip to content

Commit bf2de4a

Browse files
Merge pull request #5481 from adrian-prantl/28748323
Push the debug info for the artificial error inout argument up to SIL.
2 parents 296d81d + dddd998 commit bf2de4a

11 files changed

+86
-89
lines changed

lib/IRGen/IRGenSIL.cpp

+25-59
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ class IRGenSILFunction :
313313

314314
/// All alloc_ref instructions which allocate the object on the stack.
315315
llvm::SmallPtrSet<SILInstruction *, 8> StackAllocs;
316+
316317
/// With closure captures it is actually possible to have two function
317318
/// arguments that both have the same name. Until this is fixed, we need to
318319
/// also hash the ArgNo here.
@@ -759,8 +760,7 @@ class IRGenSILFunction :
759760

760761
void visitSILBasicBlock(SILBasicBlock *BB);
761762

762-
void emitFunctionArgDebugInfo(SILBasicBlock *BB);
763-
763+
void emitErrorResultVar(SILResultInfo ErrorInfo, DebugValueInst *DbgValue);
764764
void emitDebugInfoForAllocStack(AllocStackInst *i, const TypeInfo &type,
765765
llvm::Value *addr);
766766
void visitAllocStackInst(AllocStackInst *i);
@@ -1470,52 +1470,12 @@ void IRGenSILFunction::estimateStackSize() {
14701470
}
14711471
}
14721472

1473-
/// Determine the number of source-level Swift of a function or closure.
1474-
static unsigned countArgs(DeclContext *DC) {
1475-
unsigned N = 0;
1476-
if (auto *Fn = dyn_cast<AbstractFunctionDecl>(DC)) {
1477-
for (auto *PL : Fn->getParameterLists())
1478-
N += PL->size();
1479-
1480-
} else if (auto *Closure = dyn_cast<AbstractClosureExpr>(DC))
1481-
N += Closure->getParameters()->size();
1482-
else
1483-
llvm_unreachable("unhandled declcontext type");
1484-
return N;
1485-
}
1486-
1487-
void IRGenSILFunction::emitFunctionArgDebugInfo(SILBasicBlock *BB) {
1488-
// Emit the artificial error result argument.
1489-
auto FnTy = CurSILFn->getLoweredFunctionType();
1490-
if (FnTy->hasErrorResult() && CurSILFn->getDeclContext()) {
1491-
auto ErrorInfo = FnTy->getErrorResult();
1492-
auto ErrorResultSlot = getErrorResultSlot(ErrorInfo.getSILType());
1493-
DebugTypeInfo DTI(ErrorInfo.getType(),
1494-
ErrorResultSlot->getType(),
1495-
IGM.getPointerSize(),
1496-
IGM.getPointerAlignment(),
1497-
nullptr);
1498-
StringRef Name("$error");
1499-
// We just need any number that is guaranteed to be larger than every
1500-
// other argument. It is only used for sorting.
1501-
unsigned ArgNo =
1502-
countArgs(CurSILFn->getDeclContext()) + 1 + BB->getBBArgs().size();
1503-
auto Storage = emitShadowCopy(ErrorResultSlot.getAddress(), getDebugScope(),
1504-
Name, ArgNo);
1505-
IGM.DebugInfo->emitVariableDeclaration(
1506-
Builder, Storage, DTI, getDebugScope(), nullptr, Name, ArgNo,
1507-
IndirectValue, ArtificialValue);
1508-
}
1509-
}
1510-
1511-
15121473
void IRGenSILFunction::visitSILBasicBlock(SILBasicBlock *BB) {
15131474
// Insert into the lowered basic block.
15141475
llvm::BasicBlock *llBB = getLoweredBB(BB).bb;
15151476
Builder.SetInsertPoint(llBB);
15161477

15171478
bool InEntryBlock = BB->pred_empty();
1518-
bool ArgsEmitted = false;
15191479

15201480
// Set this block as the dominance point. This implicitly communicates
15211481
// with the dominance resolver configured in emitSILFunction.
@@ -1585,22 +1545,6 @@ void IRGenSILFunction::visitSILBasicBlock(SILBasicBlock *BB) {
15851545
// Use an artificial (line 0) location.
15861546
IGM.DebugInfo->setCurrentLoc(Builder, DS);
15871547

1588-
// Function argument handling.
1589-
if (InEntryBlock && !ArgsEmitted) {
1590-
if (!I.getLoc().isInPrologue() && I.getLoc().getSourceLoc().isValid()) {
1591-
// This is the first non-prologue instruction in the entry
1592-
// block. The function prologue is where the stack frame is
1593-
// set up and storage for local variables and function
1594-
// arguments is initialized. We need to emit the debug info
1595-
// for the function arguments after the function prologue,
1596-
// after the initialization.
1597-
if (!DS)
1598-
DS = CurSILFn->getDebugScope();
1599-
PrologueLocation AutoRestore(IGM.DebugInfo, Builder);
1600-
emitFunctionArgDebugInfo(BB);
1601-
ArgsEmitted = true;
1602-
}
1603-
}
16041548
if (isa<TermInst>(&I))
16051549
emitDebugVariableRangeExtension(BB);
16061550
}
@@ -3188,13 +3132,35 @@ void IRGenSILFunction::visitStoreInst(swift::StoreInst *i) {
31883132
}
31893133
}
31903134

3135+
/// Emit the artificial error result argument.
3136+
void IRGenSILFunction::emitErrorResultVar(SILResultInfo ErrorInfo,
3137+
DebugValueInst *DbgValue) {
3138+
auto ErrorResultSlot = getErrorResultSlot(ErrorInfo.getSILType());
3139+
SILDebugVariable Var = DbgValue->getVarInfo();
3140+
auto Storage = emitShadowCopy(ErrorResultSlot.getAddress(), getDebugScope(),
3141+
Var.Name, Var.ArgNo);
3142+
DebugTypeInfo DTI(ErrorInfo.getType(), ErrorResultSlot->getType(),
3143+
IGM.getPointerSize(), IGM.getPointerAlignment(), nullptr);
3144+
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DTI, getDebugScope(),
3145+
nullptr, Var.Name, Var.ArgNo,
3146+
IndirectValue, ArtificialValue);
3147+
}
3148+
31913149
void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
31923150
if (!IGM.DebugInfo)
31933151
return;
31943152

31953153
auto SILVal = i->getOperand();
3196-
if (isa<SILUndef>(SILVal))
3154+
if (isa<SILUndef>(SILVal)) {
3155+
// We cannot track the location of inlined error arguments because it has no
3156+
// representation in SIL.
3157+
if (!i->getDebugScope()->InlinedCallSite &&
3158+
i->getVarInfo().Name == "$error") {
3159+
auto funcTy = CurSILFn->getLoweredFunctionType();
3160+
emitErrorResultVar(funcTy->getErrorResult(), i);
3161+
}
31973162
return;
3163+
}
31983164

31993165
StringRef Name = getVarName(i);
32003166
DebugTypeInfo DbgTy;

lib/SILGen/SILGenConstructor.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,8 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
187187
assert(!selfTy.getClassOrBoundGenericClass()
188188
&& "can't emit a class ctor here");
189189

190-
// Self is a curried argument and thus comes last.
191-
unsigned N = ctor->getParameterList(1)->size() + 1;
192190
// Allocate the local variable for 'self'.
193-
emitLocalVariableWithCleanup(selfDecl, false, N)->finishInitialization(*this);
191+
emitLocalVariableWithCleanup(selfDecl, false)->finishInitialization(*this);
194192

195193
// Mark self as being uninitialized so that DI knows where it is and how to
196194
// check for it.
@@ -204,7 +202,8 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
204202
}
205203

206204
// Emit the prolog.
207-
emitProlog(ctor->getParameterList(1), ctor->getResultType(), ctor);
205+
emitProlog(ctor->getParameterList(1), ctor->getResultType(), ctor,
206+
ctor->hasThrows());
208207
emitConstructorMetatypeArg(*this, ctor);
209208

210209
// Create a basic block to jump to for the implicit 'self' return.
@@ -565,7 +564,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
565564
// Emit the prolog for the non-self arguments.
566565
// FIXME: Handle self along with the other body patterns.
567566
emitProlog(ctor->getParameterList(1),
568-
TupleType::getEmpty(F.getASTContext()), ctor);
567+
TupleType::getEmpty(F.getASTContext()), ctor, ctor->hasThrows());
569568

570569
SILType selfTy = getLoweredLoadableType(selfDecl->getType());
571570
SILValue selfArg = new (SGM.M) SILArgument(F.begin(), selfTy, selfDecl);

lib/SILGen/SILGenFunction.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
468468
MagicFunctionName = SILGenModule::getMagicFunctionName(fd);
469469

470470
Type resultTy = fd->getResultType();
471-
emitProlog(fd, fd->getParameterLists(), resultTy);
471+
emitProlog(fd, fd->getParameterLists(), resultTy, fd->hasThrows());
472472
prepareEpilog(resultTy, fd->hasThrows(), CleanupLocation(fd));
473473

474474
emitProfilerIncrement(fd->getBody());
@@ -480,7 +480,8 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
480480
void SILGenFunction::emitClosure(AbstractClosureExpr *ace) {
481481
MagicFunctionName = SILGenModule::getMagicFunctionName(ace);
482482

483-
emitProlog(ace, ace->getParameters(), ace->getResultType());
483+
emitProlog(ace, ace->getParameters(), ace->getResultType(),
484+
ace->isBodyThrowing());
484485
prepareEpilog(ace->getResultType(), ace->isBodyThrowing(),
485486
CleanupLocation(ace));
486487
if (auto *ce = dyn_cast<ClosureExpr>(ace)) {
@@ -858,7 +859,7 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value) {
858859
// is not going to be ever used anyway.
859860
overrideLocationForMagicIdentifiers = SourceLoc();
860861

861-
emitProlog({ }, value->getType(), function.getDecl()->getDeclContext());
862+
emitProlog({}, value->getType(), function.getDecl()->getDeclContext(), false);
862863
prepareEpilog(value->getType(), false, CleanupLocation::get(Loc));
863864
emitReturnExpr(Loc, value);
864865
emitEpilog(Loc);

lib/SILGen/SILGenFunction.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -709,14 +709,18 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
709709
//===--------------------------------------------------------------------===//
710710
// Memory management
711711
//===--------------------------------------------------------------------===//
712-
712+
713+
/// Emit debug info for the artificial error inout argument.
714+
void emitErrorArgument(SILLocation Loc, unsigned ArgNo);
715+
713716
/// emitProlog - Generates prolog code to allocate and clean up mutable
714717
/// storage for closure captures and local arguments.
715718
void emitProlog(AnyFunctionRef TheClosure,
716-
ArrayRef<ParameterList*> paramPatterns, Type resultType);
719+
ArrayRef<ParameterList *> paramPatterns, Type resultType,
720+
bool throws);
717721
/// returns the number of variables in paramPatterns.
718-
unsigned emitProlog(ArrayRef<ParameterList*> paramPatterns,
719-
Type resultType, DeclContext *DeclCtx);
722+
unsigned emitProlog(ArrayRef<ParameterList *> paramPatterns, Type resultType,
723+
DeclContext *DeclCtx, bool throws);
720724

721725
/// Create SILArguments in the entry block that bind all the values
722726
/// of the given pattern suitably for being forwarded.

lib/SILGen/SILGenProlog.cpp

+24-6
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,9 @@ static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture,
410410

411411
void SILGenFunction::emitProlog(AnyFunctionRef TheClosure,
412412
ArrayRef<ParameterList*> paramPatterns,
413-
Type resultType) {
414-
unsigned ArgNo =
415-
emitProlog(paramPatterns, resultType, TheClosure.getAsDeclContext());
413+
Type resultType, bool throws) {
414+
unsigned ArgNo = emitProlog(paramPatterns, resultType,
415+
TheClosure.getAsDeclContext(), throws);
416416

417417
// Emit the capture argument variables. These are placed last because they
418418
// become the first curry level of the SIL function.
@@ -457,10 +457,13 @@ static void emitIndirectResultParameters(SILGenFunction &gen, Type resultType,
457457
auto arg =
458458
new (gen.SGM.M) SILArgument(gen.F.begin(), resultTI.getLoweredType(), var);
459459
(void) arg;
460+
461+
460462
}
461463

462-
unsigned SILGenFunction::emitProlog(ArrayRef<ParameterList*> paramLists,
463-
Type resultType, DeclContext *DC) {
464+
unsigned SILGenFunction::emitProlog(ArrayRef<ParameterList *> paramLists,
465+
Type resultType, DeclContext *DC,
466+
bool throws) {
464467
// Create the indirect result parameters.
465468
emitIndirectResultParameters(*this, resultType, DC);
466469

@@ -473,6 +476,21 @@ unsigned SILGenFunction::emitProlog(ArrayRef<ParameterList*> paramLists,
473476
for (auto &param : *paramList)
474477
emitter.emitParam(param);
475478
}
476-
return emitter.getNumArgs();
479+
480+
// Record the ArgNo of the artificial $error inout argument.
481+
unsigned ArgNo = emitter.getNumArgs();
482+
if (throws) {
483+
RegularLocation Loc{SourceLoc()};
484+
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC))
485+
Loc = AFD->getThrowsLoc();
486+
else if (auto *ACE = dyn_cast<AbstractClosureExpr>(DC))
487+
Loc = ACE->getLoc();
488+
auto NativeErrorTy = SILType::getExceptionType(getASTContext());
489+
ManagedValue Undef = emitUndef(Loc, NativeErrorTy);
490+
B.createDebugValue(Loc, Undef.getValue(),
491+
{"$error", /*Constant*/ false, ++ArgNo});
492+
}
493+
494+
return ArgNo;
477495
}
478496

test/DebugInfo/Errors.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ func simple(_ placeholder: Int64) throws -> () {
1010
// CHECK: define {{.*}}void @_TF6Errors6simpleFzVs5Int64T_(i64, %swift.refcounted*, %swift.error**)
1111
// CHECK: call void @llvm.dbg.declare
1212
// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[ERROR:[0-9]+]], metadata ![[DEREF:[0-9]+]])
13-
// CHECK: ![[ERROR]] = !DILocalVariable(name: "$error", arg: 3,
13+
// CHECK: ![[ERROR]] = !DILocalVariable(name: "$error", arg: 2,
1414
// CHECK-SAME: type: ![[ERRTY:.*]], flags: DIFlagArtificial)
1515
// CHECK: ![[ERRTY]] = !DICompositeType({{.*}}identifier: "_TtPs5Error_"
1616
// CHECK: ![[DEREF]] = !DIExpression(DW_OP_deref)

test/DebugInfo/generic_enum_closure.swift

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ struct CErrorOr<T>
99
// CHECK-NOT: define
1010
// This is a SIL-level debug_value_addr instruction.
1111
// CHECK: call void @llvm.dbg.value({{.*}}, metadata ![[SELF:.*]], metadata !{{[0-9]+}})
12-
// CHECK-DAG: ![[T1:.*]] = !DICompositeType({{.*}}identifier: "_TtGV20generic_enum_closure8CErrorOrQq_S0__"
13-
// CHECK-DAG: ![[SELF]] = !DILocalVariable(name: "self", arg:{{.*}} type: ![[T1]]
12+
// CHECK: ![[SELF]] = !DILocalVariable(name: "self", scope
13+
// CHECK-SAME: type: ![[T1:.*]])
14+
// CHECK: ![[T1]] = !DICompositeType(
15+
// CHECK-SAME: identifier: "_TtGV20generic_enum_closure8CErrorOrQq_S0__"
1416
value = .none
1517
}
1618
func isError() -> Bool {

test/DebugInfo/self.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ public func f() {
1616
// CHECK: define {{.*}} @_TFV4self11stuffStructCfT_S0_(
1717
// CHECK-NEXT: entry:
1818
// CHECK-NEXT: %[[ALLOCA:.*]] = alloca %V4self11stuffStruct, align {{(4|8)}}
19-
// CHECK: call void @llvm.dbg.declare(metadata %V4self11stuffStruct* %[[ALLOCA]], metadata ![[SELF:.*]], metadata !{{[0-9]+}}), !db
19+
// CHECK: call void @llvm.dbg.declare(metadata %V4self11stuffStruct* %[[ALLOCA]],
20+
// CHECK-SAME: metadata ![[SELF:.*]], metadata !{{[0-9]+}}), !dbg
2021
// CHECK: ![[STUFFSTRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "stuffStruct",{{.*}}identifier
21-
// CHECK: ![[SELF]] = !DILocalVariable(name: "self", arg: 1,
22+
// CHECK: ![[SELF]] = !DILocalVariable(name: "self", scope
2223
// CHECK-SAME: type: ![[STUFFSTRUCT]]
2324

test/SILGen/errors.swift

+5-2
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,9 @@ func feedCat() throws -> Int {
347347
}
348348
}
349349
// CHECK-LABEL: sil hidden @_TF6errors7feedCatFzT_Si : $@convention(thin) () -> (Int, @error Error)
350-
// CHECK: %0 = function_ref @_TF6errors13preferredFoodFzT_OS_7CatFood : $@convention(thin) () -> (CatFood, @error Error)
351-
// CHECK: try_apply %0() : $@convention(thin) () -> (CatFood, @error Error), normal bb1, error bb5
350+
// CHECK: debug_value undef : $Error, var, name "$error", argno 1
351+
// CHECK: %1 = function_ref @_TF6errors13preferredFoodFzT_OS_7CatFood : $@convention(thin) () -> (CatFood, @error Error)
352+
// CHECK: try_apply %1() : $@convention(thin) () -> (CatFood, @error Error), normal bb1, error bb5
352353
// CHECK: bb1([[VAL:%.*]] : $CatFood):
353354
// CHECK: switch_enum [[VAL]] : $CatFood, case #CatFood.Canned!enumelt: bb2, case #CatFood.Dry!enumelt: bb3
354355
// CHECK: bb5([[ERROR:%.*]] : $Error)
@@ -366,6 +367,7 @@ func getHungryCat(_ food: CatFood) throws -> Cat {
366367
// errors.getHungryCat throws (errors.CatFood) -> errors.Cat
367368
// CHECK-LABEL: sil hidden @_TF6errors12getHungryCatFzOS_7CatFoodCS_3Cat : $@convention(thin) (CatFood) -> (@owned Cat, @error Error)
368369
// CHECK: bb0(%0 : $CatFood):
370+
// CHECK: debug_value undef : $Error, var, name "$error", argno 2
369371
// CHECK: switch_enum %0 : $CatFood, case #CatFood.Canned!enumelt: bb1, case #CatFood.Dry!enumelt: bb3
370372
// CHECK: bb1:
371373
// CHECK: [[FN:%.*]] = function_ref @_TF6errors10make_a_catFzT_CS_3Cat : $@convention(thin) () -> (@owned Cat, @error Error)
@@ -385,6 +387,7 @@ func test_variadic(_ cat: Cat) throws {
385387
try take_many_cats(make_a_cat(), cat, make_a_cat(), make_a_cat())
386388
}
387389
// CHECK-LABEL: sil hidden @_TF6errors13test_variadicFzCS_3CatT_
390+
// CHECK: debug_value undef : $Error, var, name "$error", argno 2
388391
// CHECK: [[TAKE_FN:%.*]] = function_ref @_TF6errors14take_many_catsFztGSaCS_3Cat__T_ : $@convention(thin) (@owned Array<Cat>) -> @error Error
389392
// CHECK: [[N:%.*]] = integer_literal $Builtin.Word, 4
390393
// CHECK: [[T0:%.*]] = function_ref @_TFs27_allocateUninitializedArray

test/SILGen/foreign_errors.swift

+4-2
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,15 @@ func testArgs() throws {
152152
try ErrorProne.consume(nil)
153153
}
154154
// CHECK: sil hidden @_TF14foreign_errors8testArgsFzT_T_ : $@convention(thin) () -> @error Error
155-
// CHECK: class_method [volatile] %0 : $@thick ErrorProne.Type, #ErrorProne.consume!1.foreign : (ErrorProne.Type) -> (Any!) throws -> () , $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
155+
// CHECK: debug_value undef : $Error, var, name "$error", argno 1
156+
// CHECK: class_method [volatile] %1 : $@thick ErrorProne.Type, #ErrorProne.consume!1.foreign : (ErrorProne.Type) -> (Any!) throws -> () , $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
156157

157158
func testBridgedResult() throws {
158159
let array = try ErrorProne.collection(withCount: 0)
159160
}
160161
// CHECK: sil hidden @_TF14foreign_errors17testBridgedResultFzT_T_ : $@convention(thin) () -> @error Error {
161-
// CHECK: class_method [volatile] %0 : $@thick ErrorProne.Type, #ErrorProne.collection!1.foreign : (ErrorProne.Type) -> (Int) throws -> [Any] , $@convention(objc_method) (Int, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> @autoreleased Optional<NSArray>
162+
// CHECK: debug_value undef : $Error, var, name "$error", argno 1
163+
// CHECK: class_method [volatile] %1 : $@thick ErrorProne.Type, #ErrorProne.collection!1.foreign : (ErrorProne.Type) -> (Int) throws -> [Any] , $@convention(objc_method) (Int, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> @autoreleased Optional<NSArray>
162164

163165
// rdar://20861374
164166
// Clear out the self box before delegating.

test/SILOptimizer/throw_inline.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ public func foo() throws -> Int32 {
88
}
99

1010
// CHECK-LABEL: _TF12throw_inline3foo
11-
// CHECK: %0 = integer_literal $Builtin.Int32, 999
12-
// CHECK: %1 = struct $Int32 (%0 : $Builtin.Int32)
13-
// CHECK: return %1 : $Int32
11+
// CHECK: debug_value undef : $Error, var, name "$error", argno 1
12+
// CHECK: %1 = integer_literal $Builtin.Int32, 999
13+
// CHECK: %2 = struct $Int32 (%1 : $Builtin.Int32)
14+
// CHECK: return %2 : $Int32
1415
func bar() throws -> Int32 {
1516
return try foo()
1617
}

0 commit comments

Comments
 (0)