From ed2b16dc5a086bcdb0b9a58cd39b5784b20abadd Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 2 Dec 2015 18:32:59 -0800 Subject: [PATCH] Add an argument-number field to DebugValueInst and friends. This commit adds a DebugVariable field that is shared by - AllocBoxInst - AllocStackInst - DebugValueInst - DebugValueAddrInst Currently DebugVariable only holds the Swift argument number. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to retire several expensive heuristics in IRGen that attempted to identify which local variables actually where arguments and recover their relative order. Memory footprint notes: This commit adds a 4-byte field to 4 SILInstructin subclasses. This was offset by 8ab1e2dd502fc7f37a67572699165e03f268c377 which removed 20 bytes from *every* SILInstruction. Caveats: This commit surfaces a known bug in FunctionSigantureOpts, tracked in rdar://problem/23727705 — debug info for exploded function arguments cannot be expressed until this is fixed. --- include/swift/SIL/SILBuilder.h | 23 +- include/swift/SIL/SILCloner.h | 12 +- include/swift/SIL/SILInstruction.h | 42 +++- lib/IRGen/DebugTypeInfo.h | 5 + lib/IRGen/IRGenSIL.cpp | 209 +++++------------- lib/SIL/SILInstructions.cpp | 9 +- lib/SIL/SILPrinter.cpp | 24 +- lib/SILGen/SILGenConstructor.cpp | 12 +- lib/SILGen/SILGenDecl.cpp | 15 +- lib/SILGen/SILGenFunction.h | 10 +- lib/SILGen/SILGenProlog.cpp | 37 +++- lib/SILPasses/EarlySIL/InOutDeshadowing.cpp | 5 +- lib/SILPasses/IPO/CapturePromotion.cpp | 22 +- .../SILCombiner/SILCombinerApplyVisitors.cpp | 2 +- .../SILCombiner/SILCombinerMiscVisitors.cpp | 5 +- lib/SILPasses/Scalar/AllocBoxToStack.cpp | 3 +- lib/SILPasses/Scalar/SILMem2Reg.cpp | 2 +- test/DebugInfo/Errors.swift | 2 +- test/DebugInfo/autoclosure.swift | 5 +- test/DebugInfo/byref-capture.swift | 10 +- test/DebugInfo/capturelist.swift | 10 +- test/DebugInfo/closure-args.swift | 3 - test/DebugInfo/closure-multivalue.swift | 4 +- test/DebugInfo/inout.swift | 32 +-- test/DebugInfo/linetable.swift | 6 +- test/DebugInfo/shadowcopy-linetable.swift | 14 +- test/DebugInfo/unowned-capture.swift | 7 +- test/SILGen/builtins.swift | 3 + test/SILGen/closures.swift | 5 +- test/SILGen/properties.swift | 15 +- test/SILGen/unmanaged.swift | 1 + test/SILGen/unowned.swift | 1 + test/SILGen/weak.swift | 7 +- test/SILPasses/inout_deshadow.sil | 4 +- 34 files changed, 295 insertions(+), 271 deletions(-) diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index 45ef2400ef5d0..737a1c2ce8f63 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -219,10 +219,11 @@ class SILBuilder { // SILInstruction Creation Methods //===--------------------------------------------------------------------===// - AllocStackInst *createAllocStack(SILLocation Loc, SILType elementType) { + AllocStackInst *createAllocStack(SILLocation Loc, SILType elementType, + unsigned ArgNo = 0) { Loc.markAsPrologue(); return insert(new (F.getModule()) AllocStackInst( - createSILDebugLocation(Loc), elementType, F)); + createSILDebugLocation(Loc), elementType, F, ArgNo)); } AllocRefInst *createAllocRef(SILLocation Loc, SILType elementType, bool objc, @@ -249,10 +250,11 @@ class SILBuilder { createSILDebugLocation(Loc), valueType, operand)); } - AllocBoxInst *createAllocBox(SILLocation Loc, SILType ElementType) { + AllocBoxInst *createAllocBox(SILLocation Loc, SILType ElementType, + unsigned ArgNo = 0) { Loc.markAsPrologue(); return insert(new (F.getModule()) AllocBoxInst(createSILDebugLocation(Loc), - ElementType, F)); + ElementType, F, ArgNo)); } AllocExistentialBoxInst * @@ -431,13 +433,16 @@ class SILBuilder { return insert( MarkFunctionEscapeInst::create(createSILDebugLocation(Loc), vars, F)); } - DebugValueInst *createDebugValue(SILLocation Loc, SILValue src) { + + DebugValueInst *createDebugValue(SILLocation Loc, SILValue src, + unsigned ArgNo = 0) { return insert(new (F.getModule()) - DebugValueInst(createSILDebugLocation(Loc), src)); + DebugValueInst(createSILDebugLocation(Loc), src, ArgNo)); } - DebugValueAddrInst *createDebugValueAddr(SILLocation Loc, SILValue src) { - return insert(new (F.getModule()) - DebugValueAddrInst(createSILDebugLocation(Loc), src)); + DebugValueAddrInst *createDebugValueAddr(SILLocation Loc, SILValue src, + unsigned ArgNo = 0) { + return insert(new (F.getModule()) DebugValueAddrInst( + createSILDebugLocation(Loc), src, ArgNo)); } LoadWeakInst *createLoadWeak(SILLocation Loc, SILValue src, IsTake_t isTake) { diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 2c4b5ce84a3a4..c5301deabbd5e 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -670,9 +670,9 @@ SILCloner::visitDebugValueInst(DebugValueInst *Inst) { // Since we want the debug info to survive, we do not remap the location here. getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - doPostProcess(Inst, - getBuilder().createDebugValue(Inst->getLoc(), - getOpValue(Inst->getOperand()))); + doPostProcess(Inst, getBuilder().createDebugValue( + Inst->getLoc(), getOpValue(Inst->getOperand()), + Inst->getVarInfo().getArgNo())); } template void @@ -686,9 +686,9 @@ SILCloner::visitDebugValueAddrInst(DebugValueAddrInst *Inst) { // Do not remap the location for a debug Instruction. SILValue OpValue = getOpValue(Inst->getOperand()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - doPostProcess(Inst, - getBuilder().createDebugValueAddr(Inst->getLoc(), - OpValue)); + doPostProcess( + Inst, getBuilder().createDebugValueAddr(Inst->getLoc(), OpValue, + Inst->getVarInfo().getArgNo())); } diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 9b7d14ccc0b6a..b739e7b8d042b 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -316,7 +316,7 @@ class UnaryInstructionBase : public BASE { typename std::enable_if::value, SILType>::type getType(unsigned i = 0) const { return ValueBase::getType(i); } - ArrayRef getAllOperands() const { return Operands.asArray(); } + ArrayRef getAllOperands() const { return Operands.asArray(); }\ MutableArrayRef getAllOperands() { return Operands.asArray(); } static bool classof(const ValueBase *V) { @@ -324,6 +324,19 @@ class UnaryInstructionBase : public BASE { } }; + +/// Holds common debug information about local variables and function +/// arguments that are needed by DebugValueInst, DebugValueAddrInst, +/// AllocStackInst, and AllocBoxInst. +class DebugVariable { + /// The source function argument position from left to right + /// starting with 1 or 0 if this is a local variable. + unsigned char ArgNo; +public: + DebugVariable(unsigned ArgNo) : ArgNo(ArgNo) {}; + unsigned getArgNo() const { return ArgNo; } +}; + //===----------------------------------------------------------------------===// // Allocation Instructions //===----------------------------------------------------------------------===// @@ -368,8 +381,10 @@ class StackPromotable { /// reference count) stack memory. The memory is provided uninitialized. class AllocStackInst : public AllocationInst { friend class SILBuilder; + DebugVariable VarInfo; - AllocStackInst(SILDebugLocation *Loc, SILType elementType, SILFunction &F); + AllocStackInst(SILDebugLocation *Loc, SILType elementType, SILFunction &F, + unsigned ArgNo); public: @@ -377,6 +392,9 @@ class AllocStackInst : public AllocationInst { /// allocation, or null if this is a temporary allocation. VarDecl *getDecl() const; + DebugVariable getVarInfo() const { return VarInfo; }; + void setArgNo(unsigned N) { VarInfo = DebugVariable(N); } + /// getElementType - Get the type of the allocated memory (as opposed to the /// (second) type of the instruction itself, which will be an address type). SILType getElementType() const { @@ -463,7 +481,10 @@ class AllocValueBufferInst : class AllocBoxInst : public AllocationInst { friend class SILBuilder; - AllocBoxInst(SILDebugLocation *DebugLoc, SILType ElementType, SILFunction &F); + DebugVariable VarInfo; + + AllocBoxInst(SILDebugLocation *DebugLoc, SILType ElementType, SILFunction &F, + unsigned ArgNo); public: @@ -478,6 +499,8 @@ class AllocBoxInst : public AllocationInst { /// allocation, or null if this is a temporary allocation. VarDecl *getDecl() const; + DebugVariable getVarInfo() const { return VarInfo; }; + ArrayRef getAllOperands() const { return {}; } MutableArrayRef getAllOperands() { return {}; } @@ -1341,14 +1364,16 @@ class MarkFunctionEscapeInst : public SILInstruction { /// types). class DebugValueInst : public UnaryInstructionBase { friend class SILBuilder; + DebugVariable VarInfo; - DebugValueInst(SILDebugLocation *DebugLoc, SILValue Operand) - : UnaryInstructionBase(DebugLoc, Operand) {} + DebugValueInst(SILDebugLocation *DebugLoc, SILValue Operand, unsigned ArgNo) + : UnaryInstructionBase(DebugLoc, Operand), VarInfo(ArgNo) {} public: /// getDecl - Return the underlying variable declaration that this denotes, /// or null if we don't have one. VarDecl *getDecl() const; + DebugVariable getVarInfo() const { return VarInfo; } }; /// Define the start or update to a symbolic variable value (for address-only @@ -1356,14 +1381,17 @@ class DebugValueInst : public UnaryInstructionBase { class DebugValueAddrInst : public UnaryInstructionBase { friend class SILBuilder; + DebugVariable VarInfo; - DebugValueAddrInst(SILDebugLocation *DebugLoc, SILValue Operand) - : UnaryInstructionBase(DebugLoc, Operand) {} + DebugValueAddrInst(SILDebugLocation *DebugLoc, SILValue Operand, + unsigned ArgNo) + : UnaryInstructionBase(DebugLoc, Operand), VarInfo(ArgNo) {} public: /// getDecl - Return the underlying variable declaration that this denotes, /// or null if we don't have one. VarDecl *getDecl() const; + DebugVariable getVarInfo() const { return VarInfo; } }; diff --git a/lib/IRGen/DebugTypeInfo.h b/lib/IRGen/DebugTypeInfo.h index 820d11576bd26..75c12f9509620 100644 --- a/lib/IRGen/DebugTypeInfo.h +++ b/lib/IRGen/DebugTypeInfo.h @@ -71,6 +71,11 @@ namespace swift { if (ValueDecl *D = getDecl()) return D->getDeclContext(); else return DeclOrContext.get(); } + + void unwrapInOutType() { + Type = Type->castTo()->getObjectType().getPointer(); + } + bool isNull() const { return Type == nullptr; } bool operator==(DebugTypeInfo T) const; bool operator!=(DebugTypeInfo T) const; diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index b26b4093b8a7f..b222e06186f13 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -300,12 +300,6 @@ class IRGenSILFunction : int EstimatedStackSize = -1; llvm::MapVector LoweredBBs; - // These could also be cached for the entire module which could pay - // off in optimized code with lots of inlining of the same functions. - // Or, probably even better, stored in the AST. - llvm::SmallDenseMap ArgNo; - llvm::SmallDenseMap NumArgs; - llvm::SmallDenseMap ArgEmitted; // Destination basic blocks for condfail traps. llvm::SmallVector FailBBs; @@ -548,61 +542,24 @@ class IRGenSILFunction : copy.push_back(alloca.getAddress()); } - /// Determine the Swift argument ordering for a given parameter and - /// the total number of arguments per function. - // TODO: It would be more efficient to determine this earlier and - // store the number in the AST instead. - unsigned getArgNo(const VarDecl *D) { - unsigned N = 0; - if (auto *param = dyn_cast(D)) { - auto countArgs = [&](const DeclContext *DC, ArrayRef Patterns) { - if (!NumArgs.lookup(DC)) { - unsigned I = 0; - for (auto p : reversed(Patterns)) - p->forEachVariable([&](VarDecl *VD) { - ArgNo[VD] = ++I; - if (VD == D) - N = I; - }); - NumArgs[DC] = I; - } - }; - auto *dc = param->getDeclContext(); - if (auto *fn = dyn_cast(dc)) - countArgs(dc, fn->getBodyParamPatterns()); - else if (auto *closure = dyn_cast(dc)) - countArgs(dc, closure->getParamPatterns()); - if (!N) - N = ArgNo.lookup(D); - } - return N; - } - /// Emit debug info for a function argument or a local variable. template void emitDebugVariableDeclaration(StorageType Storage, DebugTypeInfo Ty, const SILDebugScope *DS, - StringRef Name) { + StringRef Name, + unsigned ArgNo = 0, + IndirectionKind Indirection = DirectValue) { assert(IGM.DebugInfo && "debug info not enabled"); - - auto VD = cast(Ty.getDecl()); - auto N = getArgNo(VD); - if (N) { - if (!ArgEmitted.lookup(VD)) { - PrologueLocation AutoRestore(IGM.DebugInfo, Builder); - IGM.DebugInfo-> - emitArgVariableDeclaration(Builder, Storage, - Ty, DS, Name, N, DirectValue); - ArgEmitted[VD] = true; - } + if (ArgNo) { + PrologueLocation AutoRestore(IGM.DebugInfo, Builder); + IGM.DebugInfo->emitArgVariableDeclaration(Builder, Storage, Ty, DS, Name, + ArgNo, Indirection); } else - IGM.DebugInfo-> - emitStackVariableDeclaration(Builder, Storage, - Ty, DS, Name, DirectValue); + IGM.DebugInfo->emitStackVariableDeclaration(Builder, Storage, Ty, DS, + Name, Indirection); } - void emitFailBB() { if (!FailBBs.empty()) { // Move the trap basic blocks to the end of the function. @@ -1416,6 +1373,23 @@ void IRGenSILFunction::estimateStackSize() { } } +/// Determine the number of source-level Swift of a function or closure. +static unsigned countArgs(DeclContext *DC) { + unsigned N = 0; + auto count = [&](ArrayRef Patterns) { + for (auto p : Patterns) + p->forEachVariable([&](VarDecl *VD) { ++N; }); + }; + + if (auto *Fn = dyn_cast(DC)) + count(Fn->getBodyParamPatterns()); + else if (auto *Closure = dyn_cast(DC)) + count(Closure->getParamPatterns()); + else + llvm_unreachable("unhandled declcontext type"); + return N; +} + /// Store the lowered IR representation of Arg in the array /// Vals. Returns true if Arg is a byref argument. IndirectionKind IRGenSILFunction:: @@ -1435,97 +1409,9 @@ getLoweredArgValue(llvm::SmallVectorImpl &Vals, } void IRGenSILFunction::emitFunctionArgDebugInfo(SILBasicBlock *BB) { - assert(BB->pred_empty()); - if (!IGM.DebugInfo) - return; - - // We cannot deduce the correct argument ordering without a DeclContent. - if (!CurSILFn->getDeclContext()) - return; - - // This is the prologue of a function. Emit debug info for all - // trivial arguments and any captured and promoted [inout] - // variables. - unsigned NMax = NumArgs.lookup(CurSILFn->getDeclContext()); - const VarDecl* LastVD = nullptr; - for (auto I = BB->getBBArgs().begin(), E=BB->getBBArgs().end(); - I != E; ++I) { - SILArgument *Arg = *I; - unsigned N = 0; - - // Reconstruct the Swift argument numbering. - if (auto *VD = dyn_cast_or_null(Arg->getDecl())) - if (VD != LastVD) { - N = getArgNo(VD); - if (!NMax) - NMax = NumArgs.lookup(CurSILFn->getDeclContext()); - LastVD = VD; - } - - if (!Arg->getDecl()) - continue; - - // Generic and existential types were already handled in - // visitAllocStackInst. - if (Arg->getType().isExistentialType() || - Arg->getType().getSwiftRValueType()->isTypeParameter() || - Arg->getType().is()) - continue; - - if (ArgEmitted.lookup(LastVD)) - continue; - - auto Name = Arg->getDecl()->getNameStr(); - DebugTypeInfo DTI(const_cast(Arg->getDecl()), - getTypeInfo(Arg->getType())); - - llvm::SmallVector Vals, Copy; - bool Deref = getLoweredArgValue(Vals, Arg, Name); - // Don't bother emitting swift.refcounted* for now. - if (Vals.size() && Vals.back()->getType() == IGM.RefCountedPtrTy) - Vals.pop_back(); - - // Consolidate all pieces of an exploded multi-argument into one list. - for (auto Next = I+1; Next != E; ++Next, ++I) { - if ((*Next)->getDecl() != Arg->getDecl()) - break; - - Deref |= getLoweredArgValue(Vals, *Next, Name); - } - if (DTI.getType()->getKind() == TypeKind::InOut) { - if (!Deref) { - // If the value was promoted, unwrap the type. - DTI = DebugTypeInfo(DTI.getType()->castTo()->getObjectType(), - DTI.StorageType, DTI.size, DTI.align, - DTI.getDeclContext()); - } - - // In contrast to by-value captures, inout arguments are encoded - // as reference types, so there is no need to emit a deref - // operation. - Deref = DirectValue; - } - - // Emit -O0 shadow copies for by-value parameters to ensure they - // are visible until the end of the function. - emitShadowCopy(Vals, Name, Copy); - // Captures are pointing to the decl of the captured variable. - if (LastVD->getDeclContext() != CurSILFn->getDeclContext()) { - IGM.DebugInfo->emitArgVariableDeclaration - (Builder, Copy, DTI, getDebugScope(), Name, ++NMax, - IndirectionKind(Deref), ArtificialValue); - ArgEmitted[LastVD] = true; - } else if (N) { - IGM.DebugInfo->emitArgVariableDeclaration - (Builder, Copy, DTI, getDebugScope(), Name, N, - IndirectionKind(Deref), RealValue); - ArgEmitted[LastVD] = true; - } - } - // Emit the artificial error result argument. auto FnTy = CurSILFn->getLoweredFunctionType(); - if (FnTy->hasErrorResult()) { + if (FnTy->hasErrorResult() && CurSILFn->getDeclContext()) { auto ErrorInfo = FnTy->getErrorResult(); auto ErrorResultSlot = getErrorResultSlot(ErrorInfo.getSILType()); DebugTypeInfo DTI(ErrorInfo.getType(), @@ -1534,12 +1420,15 @@ void IRGenSILFunction::emitFunctionArgDebugInfo(SILBasicBlock *BB) { IGM.getPointerAlignment(), nullptr); StringRef Name("$error"); + // We just need any number that is guranteed to be larger than every + // other argument. It is only used for sorting. + unsigned ArgNo = + countArgs(CurSILFn->getDeclContext()) + 1 + BB->getBBArgs().size(); IGM.DebugInfo->emitArgVariableDeclaration( - Builder, emitShadowCopy(ErrorResultSlot.getAddress(), Name), DTI, - getDebugScope(), Name, ++NMax, - IndirectValue, ArtificialValue); + Builder, emitShadowCopy(ErrorResultSlot.getAddress(), Name), DTI, + getDebugScope(), Name, ArgNo, + IndirectValue, ArtificialValue); } - } @@ -3070,7 +2959,7 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) { return; VarDecl *Decl = i->getDecl(); - if (!Decl || ArgEmitted.lookup(Decl)) + if (!Decl) return; auto SILVal = i->getOperand(); @@ -3080,18 +2969,23 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) { StringRef Name = Decl->getNameStr(); Explosion e = getLoweredExplosion(SILVal); DebugTypeInfo DbgTy(Decl, Decl->getType(), getTypeInfo(SILVal.getType())); + if (DbgTy.getType()->getKind() == TypeKind::InOut) + // An inout type that is described by a debug *value* is a + // promoted capture. Unwrap the type. + DbgTy.unwrapInOutType(); // Put the value into a stack slot at -Onone. llvm::SmallVector Copy; emitShadowCopy(e.claimAll(), Name, Copy); - emitDebugVariableDeclaration(Copy, DbgTy, i->getDebugScope(), Name); + emitDebugVariableDeclaration(Copy, DbgTy, i->getDebugScope(), Name, + i->getVarInfo().getArgNo()); } void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) { if (!IGM.DebugInfo) return; VarDecl *Decl = i->getDecl(); - if (!Decl || ArgEmitted.lookup(Decl)) + if (!Decl) return; auto SILVal = i->getOperand(); @@ -3102,8 +2996,11 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) { auto Addr = getLoweredAddress(SILVal).getAddress(); DebugTypeInfo DbgTy(Decl, Decl->getType(), getTypeInfo(SILVal.getType())); // Put the value into a stack slot at -Onone and emit a debug intrinsic. - emitDebugVariableDeclaration(emitShadowCopy(Addr, Name), DbgTy, - i->getDebugScope(), Name); + emitDebugVariableDeclaration( + emitShadowCopy(Addr, Name), DbgTy, i->getDebugScope(), Name, + i->getVarInfo().getArgNo(), + (DbgTy.getType()->getKind() == TypeKind::InOut) ? DirectValue + : IndirectValue); } void IRGenSILFunction::visitLoadWeakInst(swift::LoadWeakInst *i) { @@ -3362,7 +3259,8 @@ static void emitDebugDeclarationForAllocStack(IRGenSILFunction &IGF, auto DS = i->getDebugScope(); if (DS) { assert(DS->SILFn == IGF.CurSILFn || DS->InlinedCallSite); - IGF.emitDebugVariableDeclaration(addr, DbgTy, DS, Name); + IGF.emitDebugVariableDeclaration(addr, DbgTy, DS, Name, + i->getVarInfo().getArgNo()); } } } @@ -3518,12 +3416,11 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) { if (Name == IGM.Context.Id_self.str()) return; auto Indirection = IndirectValue; - // LValues are implicitly indirect because of their type. - if (Decl->getType()->getKind() == TypeKind::LValue) + // LValues and inout args are implicitly indirect because of their type. + if (Decl->getType()->getKind() == TypeKind::LValue || + Decl->getType()->getKind() == TypeKind::InOut) Indirection = DirectValue; - // FIXME: inout arguments that are not promoted are emitted as - // arguments and also boxed and thus may show up twice. This may - // or may not be bad. + IGM.DebugInfo->emitStackVariableDeclaration (Builder, emitShadowCopy(addr.getAddress(), Name), diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp index bcf7aa93e4bc7..6bc4003e20d48 100644 --- a/lib/SIL/SILInstructions.cpp +++ b/lib/SIL/SILInstructions.cpp @@ -46,9 +46,9 @@ static SILTypeList *getAllocStackType(SILType eltTy, SILFunction &F) { } AllocStackInst::AllocStackInst(SILDebugLocation *Loc, SILType elementType, - SILFunction &F) + SILFunction &F, unsigned ArgNo) : AllocationInst(ValueKind::AllocStackInst, Loc, - getAllocStackType(elementType, F)) {} + getAllocStackType(elementType, F)), VarInfo(ArgNo) {} /// getDecl - Return the underlying variable declaration associated with this /// allocation, or null if this is a temporary allocation. @@ -75,9 +75,10 @@ static SILTypeList *getAllocBoxType(SILType EltTy, SILFunction &F) { } AllocBoxInst::AllocBoxInst(SILDebugLocation *Loc, SILType ElementType, - SILFunction &F) + SILFunction &F, unsigned ArgNo) : AllocationInst(ValueKind::AllocBoxInst, Loc, - getAllocBoxType(ElementType, F)) {} + getAllocBoxType(ElementType, F)), + VarInfo(ArgNo) {} /// getDecl - Return the underlying variable declaration associated with this /// allocation, or null if this is a temporary allocation. diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index 0bab6831fda84..1ac94cd1fe9b6 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -686,11 +686,18 @@ class SILPrinter : public SILVisitor { *this << "undef<" << A->getType() << ">"; } + template + void printVarDeclComment(VarDeclaringInst *VDI) { + if (VarDecl *VD = VDI->getDecl()) { + *this << " // " << (VD->isLet() ? "let " : "var ") << VD->getName(); + if (unsigned N = VDI->getVarInfo().getArgNo()) + *this << ", argno: " << N; + } + } void visitAllocStackInst(AllocStackInst *AVI) { *this << "alloc_stack " << AVI->getElementType(); - if (VarDecl *vd = AVI->getDecl()) - *this << " // " << (vd->isLet() ? "let " : "var ") << vd->getName(); + printVarDeclComment(AVI); } void visitAllocRefInst(AllocRefInst *ARI) { @@ -714,11 +721,10 @@ class SILPrinter : public SILVisitor { *this << "alloc_value_buffer " << AVBI->getValueType() << " in " << getIDAndType(AVBI->getOperand()); } - + void visitAllocBoxInst(AllocBoxInst *ABI) { *this << "alloc_box " << ABI->getElementType(); - if (VarDecl *vd = ABI->getDecl()) - *this << " // " << (vd->isLet() ? "let " : "var ") << vd->getName(); + printVarDeclComment(ABI); } void printSubstitutions(ArrayRef Subs) { @@ -860,16 +866,12 @@ class SILPrinter : public SILVisitor { void visitDebugValueInst(DebugValueInst *DVI) { *this << "debug_value " << getIDAndType(DVI->getOperand()); - - if (VarDecl *vd = DVI->getDecl()) - *this << " // " << (vd->isLet() ? "let " : "var ") << vd->getName(); + printVarDeclComment(DVI); } void visitDebugValueAddrInst(DebugValueAddrInst *DVAI) { *this << "debug_value_addr " << getIDAndType(DVAI->getOperand()); - - if (VarDecl *vd = DVAI->getDecl()) - *this << " // " << (vd->isLet() ? "let " : "var ") << vd->getName(); + printVarDeclComment(DVAI); } void visitLoadWeakInst(LoadWeakInst *LI) { diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index 3f38dca4be91b..4afca5feac6d4 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -164,6 +164,13 @@ static void emitImplicitValueConstructor(SILGenFunction &gen, return; } +static unsigned countSwiftArgs(ArrayRef Patterns) { + unsigned N = 0; + for (auto p : Patterns) + p->forEachVariable([&](VarDecl *) { ++N; }); + return N; +} + void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) { MagicFunctionName = SILGenModule::getMagicFunctionName(ctor); @@ -182,9 +189,10 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) { assert(!selfTy.getClassOrBoundGenericClass() && "can't emit a class ctor here"); - + // Self is a curried argument and thus comes last. + unsigned N = countSwiftArgs(ctor->getBodyParamPatterns()[1]) + 1; // Allocate the local variable for 'self'. - emitLocalVariableWithCleanup(selfDecl, false)->finishInitialization(*this); + emitLocalVariableWithCleanup(selfDecl, false, N)->finishInitialization(*this); // Mark self as being uninitialized so that DI knows where it is and how to // check for it. diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index 22fe8fa6f4cef..075d89397cc8b 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -239,8 +239,8 @@ class LocalVariableInitialization : public SingleBufferInitialization { /// CleanupUninitializedBox cleanup that will be replaced when /// initialization is completed. LocalVariableInitialization(VarDecl *decl, bool NeedsMarkUninit, - SILGenFunction &SGF) - : decl(decl), SGF(SGF) { + unsigned ArgNo, SILGenFunction &SGF) + : decl(decl), SGF(SGF) { assert(decl->getDeclContext()->isLocalContext() && "can't emit a local var for a non-local var decl"); assert(decl->hasStorage() && "can't emit storage for a computed variable"); @@ -250,7 +250,7 @@ class LocalVariableInitialization : public SingleBufferInitialization { // The variable may have its lifetime extended by a closure, heap-allocate // it using a box. - AllocBoxInst *allocBox = SGF.B.createAllocBox(decl, lType); + AllocBoxInst *allocBox = SGF.B.createAllocBox(decl, lType, ArgNo); auto box = SILValue(allocBox, 0); auto addr = SILValue(allocBox, 1); @@ -1215,10 +1215,11 @@ void SILGenModule::emitExternalDefinition(Decl *d) { } /// Create a LocalVariableInitialization for the uninitialized var. -InitializationPtr SILGenFunction:: -emitLocalVariableWithCleanup(VarDecl *vd, bool NeedsMarkUninit) { - return InitializationPtr(new LocalVariableInitialization(vd, NeedsMarkUninit, - *this)); +InitializationPtr +SILGenFunction::emitLocalVariableWithCleanup(VarDecl *vd, bool NeedsMarkUninit, + unsigned ArgNo) { + return InitializationPtr( + new LocalVariableInitialization(vd, NeedsMarkUninit, ArgNo, *this)); } /// Create an Initialization for an uninitialized temporary. diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index 596d4283b7966..24335a9445ffe 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -679,8 +679,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction /// storage for closure captures and local arguments. void emitProlog(AnyFunctionRef TheClosure, ArrayRef paramPatterns, Type resultType); - void emitProlog(ArrayRef paramPatterns, - Type resultType, DeclContext *DeclCtx); + /// returns the number of variables in paramPatterns. + unsigned emitProlog(ArrayRef paramPatterns, + Type resultType, DeclContext *DeclCtx); /// Create SILArguments in the entry block that bind all the values /// of the given pattern suitably for being forwarded. @@ -1458,8 +1459,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction /// Emit the allocation for a local variable, provides an Initialization /// that can be used to initialize it, and registers cleanups in the active /// scope. + /// \param ArgNo optionally describes this function argument's + /// position for debug info. std::unique_ptr - emitLocalVariableWithCleanup(VarDecl *D, bool NeedsMarkUninit); + emitLocalVariableWithCleanup(VarDecl *D, bool NeedsMarkUninit, + unsigned ArgNo = 0); /// Emit the allocation for a local temporary, provides an /// Initialization that can be used to initialize it, and registers diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index c1d566e1549f4..bb857af1beb6a 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -27,7 +27,8 @@ SILValue SILGenFunction::emitSelfDecl(VarDecl *selfDecl) { VarLocs[selfDecl] = VarLoc::get(selfValue); SILLocation PrologueLoc(selfDecl); PrologueLoc.markAsPrologue(); - B.createDebugValue(PrologueLoc, selfValue); + unsigned ArgNo = 1; // Hardcoded for destructors. + B.createDebugValue(PrologueLoc, selfValue, ArgNo); return selfValue; } @@ -210,6 +211,7 @@ struct ArgumentInitVisitor : /// An ArrayRef that we use in our SILParameterList queue. Parameters are /// sliced off of the front as they're emitted. ArrayRef parameters; + unsigned ArgNo = 0; ArgumentInitVisitor(SILGenFunction &gen, SILFunction &f) : gen(gen), f(f), initB(gen.B), @@ -219,6 +221,8 @@ struct ArgumentInitVisitor : parameters = parameters.slice(1); } + unsigned getNumArgs() const { return ArgNo; } + ManagedValue makeArgument(Type ty, SILBasicBlock *parent, SILLocation l) { assert(ty && "no type?!"); @@ -251,11 +255,12 @@ struct ArgumentInitVisitor : if (isa(objectType)) { // FIXME: mark a debug location? gen.VarLocs[vd] = SILGenFunction::VarLoc::get(address); + gen.B.createDebugValueAddr(loc, address, ArgNo); return; } // Allocate the local variable for the inout. - auto initVar = gen.emitLocalVariableWithCleanup(vd, false); + auto initVar = gen.emitLocalVariableWithCleanup(vd, false, ArgNo); // Initialize with the value from the inout with an "autogenerated" // copyaddr. @@ -272,14 +277,14 @@ struct ArgumentInitVisitor : // argument if we're responsible for it. gen.VarLocs[vd] = SILGenFunction::VarLoc::get(argrv.getValue()); if (argrv.getType().isAddress()) - gen.B.createDebugValueAddr(loc, argrv.getValue()); + gen.B.createDebugValueAddr(loc, argrv.getValue(), ArgNo); else - gen.B.createDebugValue(loc, argrv.getValue()); + gen.B.createDebugValue(loc, argrv.getValue(), ArgNo); } else { // If the variable is mutable, we need to copy or move the argument // value to local mutable memory. - auto initVar = gen.emitLocalVariableWithCleanup(vd, false); + auto initVar = gen.emitLocalVariableWithCleanup(vd, false, ArgNo); // If we have a cleanup on the value, we can move it into the variable. if (argrv.hasCleanup()) @@ -315,6 +320,7 @@ struct ArgumentInitVisitor : } void visitNamedPattern(NamedPattern *P) { + ++ArgNo; auto PD = P->getDecl(); if (!PD->hasName()) { // A value bound to _ is unused and can be immediately released. @@ -426,9 +432,12 @@ emitReconstitutedConstantCaptureArguments(SILType ty, return gen.B.createTuple(capture, ty, Elts); } -static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture) { +static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture, + unsigned ArgNo) { auto *VD = capture.getDecl(); auto type = VD->getType(); + SILLocation Loc(VD); + Loc.markAsPrologue(); switch (gen.SGM.Types.getDeclCaptureKind(capture)) { case CaptureKind::None: break; @@ -451,6 +460,10 @@ static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture) { } gen.VarLocs[VD] = SILGenFunction::VarLoc::get(val); + if (auto *AllocStack = dyn_cast(val)) + AllocStack->setArgNo(ArgNo); + else + gen.B.createDebugValue(Loc, val, ArgNo); if (!lowering.isTrivial()) gen.enterDestroyCleanup(val); break; @@ -465,6 +478,7 @@ static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture) { SILValue box = new (gen.SGM.M) SILArgument(gen.F.begin(), boxTy, VD); SILValue addr = new (gen.SGM.M) SILArgument(gen.F.begin(), ty, VD); gen.VarLocs[VD] = SILGenFunction::VarLoc::get(addr, box); + gen.B.createDebugValueAddr(Loc, addr, ArgNo); gen.Cleanups.pushCleanup(box); break; } @@ -473,6 +487,7 @@ static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture) { SILType ty = gen.getLoweredType(type).getAddressType(); SILValue addr = new (gen.SGM.M) SILArgument(gen.F.begin(), ty, VD); gen.VarLocs[VD] = SILGenFunction::VarLoc::get(addr); + gen.B.createDebugValueAddr(Loc, addr, ArgNo); break; } } @@ -481,17 +496,18 @@ static void emitCaptureArguments(SILGenFunction &gen, CapturedValue capture) { void SILGenFunction::emitProlog(AnyFunctionRef TheClosure, ArrayRef paramPatterns, Type resultType) { - emitProlog(paramPatterns, resultType, TheClosure.getAsDeclContext()); + unsigned ArgNo = + emitProlog(paramPatterns, resultType, TheClosure.getAsDeclContext()); // Emit the capture argument variables. These are placed last because they // become the first curry level of the SIL function. auto captureInfo = SGM.Types.getLoweredLocalCaptures(TheClosure); for (auto capture : captureInfo.getCaptures()) - emitCaptureArguments(*this, capture); + emitCaptureArguments(*this, capture, ++ArgNo); } -void SILGenFunction::emitProlog(ArrayRef paramPatterns, - Type resultType, DeclContext *DeclCtx) { +unsigned SILGenFunction::emitProlog(ArrayRef paramPatterns, + Type resultType, DeclContext *DeclCtx) { // If the return type is address-only, emit the indirect return argument. const TypeLowering &returnTI = getTypeLowering(resultType); if (returnTI.isReturnedIndirectly()) { @@ -511,5 +527,6 @@ void SILGenFunction::emitProlog(ArrayRef paramPatterns, // values. argVisitor.visit(p); } + return argVisitor.getNumArgs(); } diff --git a/lib/SILPasses/EarlySIL/InOutDeshadowing.cpp b/lib/SILPasses/EarlySIL/InOutDeshadowing.cpp index 582355caf914d..8f34f4cb51066 100644 --- a/lib/SILPasses/EarlySIL/InOutDeshadowing.cpp +++ b/lib/SILPasses/EarlySIL/InOutDeshadowing.cpp @@ -70,7 +70,10 @@ static void promoteShadow(AllocStackInst *Alloc, SILArgument *InOutArg) { // to use the InOutArg directly instead of using the allocation. Use->set(InOutArg); } - + // Make the debug information stored in the AllocBox explicit. + SILBuilder B(Alloc); + B.createDebugValueAddr(Alloc->getLoc(), InOutArg, + Alloc->getVarInfo().getArgNo()); Alloc->eraseFromParent(); } diff --git a/lib/SILPasses/IPO/CapturePromotion.cpp b/lib/SILPasses/IPO/CapturePromotion.cpp index a3bb0741375fb..cdb534283db52 100644 --- a/lib/SILPasses/IPO/CapturePromotion.cpp +++ b/lib/SILPasses/IPO/CapturePromotion.cpp @@ -215,6 +215,7 @@ class ClosureCloner : public TypeSubstCloner { TypeSubstitutionMap &InterfaceSubs, IndicesSet &PromotableIndices); + void visitDebugValueAddrInst(DebugValueAddrInst *Inst); void visitStrongReleaseInst(StrongReleaseInst *Inst); void visitStructElementAddrInst(StructElementAddrInst *Inst); void visitLoadInst(LoadInst *Inst); @@ -509,6 +510,25 @@ ClosureCloner::populateCloned() { } } +/// Handle a debug_value_addr instruction during cloning of a closure; +/// if its operand is the promoted address argument then lower it to a +/// debug_value, otherwise it is handled normally. +void ClosureCloner::visitDebugValueAddrInst(DebugValueAddrInst *Inst) { + SILValue Operand = Inst->getOperand(); + if (SILArgument *A = dyn_cast(Operand)) { + assert(Operand.getResultNumber() == 0); + auto I = AddrArgumentMap.find(A); + if (I != AddrArgumentMap.end()) { + getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); + getBuilder().createDebugValue(Inst->getLoc(), I->second, + Inst->getVarInfo().getArgNo()); + return; + } + } + + SILCloner::visitDebugValueAddrInst(Inst); +} + /// \brief Handle a strong_release instruction during cloning of a closure; if /// it is a strong release of a promoted box argument, then it is replaced wit /// a ReleaseValue of the new object type argument, otherwise it is handled @@ -621,7 +641,7 @@ isNonmutatingCapture(SILArgument *BoxArg, SILArgument *AddrArg) { return false; continue; } - if (!isa(O->getUser())) + if (!isa(O->getUser()) && !isa(O->getUser())) return false; } diff --git a/lib/SILPasses/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILPasses/SILCombiner/SILCombinerApplyVisitors.cpp index 0c235beeb8eee..8aa3f2d35c19d 100644 --- a/lib/SILPasses/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILPasses/SILCombiner/SILCombinerApplyVisitors.cpp @@ -212,7 +212,7 @@ void PartialApplyCombiner::allocateTemporaries() { (Param.isConsumed() && Param.isIndirect())) { Builder.setInsertionPoint(PAI->getFunction()->begin()->begin()); // Create a new temporary at the beginning of a function. - auto *Tmp = Builder.createAllocStack(PAI->getLoc(), Arg.getType()); + auto *Tmp = Builder.createAllocStack(PAI->getLoc(), Arg.getType(), AI); Builder.setInsertionPoint(PAI); // Copy argument into this temporary. Builder.createCopyAddr(PAI->getLoc(), Arg, SILValue(Tmp, 1), diff --git a/lib/SILPasses/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILPasses/SILCombiner/SILCombinerMiscVisitors.cpp index 5e1c94896de89..3a833c9b477cf 100644 --- a/lib/SILPasses/SILCombiner/SILCombinerMiscVisitors.cpp +++ b/lib/SILPasses/SILCombiner/SILCombinerMiscVisitors.cpp @@ -297,8 +297,9 @@ SILInstruction *SILCombiner::visitAllocStackInst(AllocStackInst *AS) { // init_existential_addr then we can promote the allocation of the init // existential. if (IEI && !OEI) { - auto *ConcAlloc = Builder.createAllocStack(AS->getLoc(), - IEI->getLoweredConcreteType()); + auto *ConcAlloc = + Builder.createAllocStack(AS->getLoc(), IEI->getLoweredConcreteType(), + AS->getVarInfo().getArgNo()); SILValue(IEI, 0).replaceAllUsesWith(ConcAlloc->getAddressResult()); eraseInstFromFunction(*IEI); diff --git a/lib/SILPasses/Scalar/AllocBoxToStack.cpp b/lib/SILPasses/Scalar/AllocBoxToStack.cpp index 7cbb459633202..d060843d2e925 100644 --- a/lib/SILPasses/Scalar/AllocBoxToStack.cpp +++ b/lib/SILPasses/Scalar/AllocBoxToStack.cpp @@ -405,7 +405,8 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI, auto &Entry = ABI->getFunction()->front(); SILBuilder BuildAlloc(&Entry, Entry.begin()); BuildAlloc.setCurrentDebugScope(ABI->getDebugScope()); - auto *ASI = BuildAlloc.createAllocStack(ABI->getLoc(), ABI->getElementType()); + auto *ASI = BuildAlloc.createAllocStack(ABI->getLoc(), ABI->getElementType(), + ABI->getVarInfo().getArgNo()); // Replace all uses of the address of the box's contained value with // the address of the stack location. diff --git a/lib/SILPasses/Scalar/SILMem2Reg.cpp b/lib/SILPasses/Scalar/SILMem2Reg.cpp index 9bdf8a31f7bd7..39aa04ed51355 100644 --- a/lib/SILPasses/Scalar/SILMem2Reg.cpp +++ b/lib/SILPasses/Scalar/SILMem2Reg.cpp @@ -282,7 +282,7 @@ promoteDebugValueAddr(DebugValueAddrInst *DVAI, SILValue Value, SILBuilder &B) { assert(Value.isValid() && "Expected valid value"); B.setInsertionPoint(DVAI); B.setCurrentDebugScope(DVAI->getDebugScope()); - B.createDebugValue(DVAI->getLoc(), Value); + B.createDebugValue(DVAI->getLoc(), Value, DVAI->getVarInfo().getArgNo()); DVAI->eraseFromParent(); } diff --git a/test/DebugInfo/Errors.swift b/test/DebugInfo/Errors.swift index 4c930712627b0..3f50151c6cc37 100644 --- a/test/DebugInfo/Errors.swift +++ b/test/DebugInfo/Errors.swift @@ -10,7 +10,7 @@ func simple(placeholder: Int64) throws -> () { // CHECK: define {{.*}}void @_TF6Errors6simpleFzVs5Int64T_(i64, %swift.refcounted*, %swift.error**) // CHECK: call void @llvm.dbg.declare // CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[ERROR:[0-9]+]], metadata ![[DEREF:[0-9]+]]) - // CHECK: ![[ERROR]] = !DILocalVariable(name: "$error", arg: 2, {{.*}} type: !"_TtPs9ErrorType_", flags: DIFlagArtificial) + // CHECK: ![[ERROR]] = !DILocalVariable(name: "$error", arg: 3, {{.*}} type: !"_TtPs9ErrorType_", flags: DIFlagArtificial) // CHECK: ![[DEREF]] = !DIExpression(DW_OP_deref) throw MyError.Simple } diff --git a/test/DebugInfo/autoclosure.swift b/test/DebugInfo/autoclosure.swift index a337784f1c9ad..d9c3d2f7aa59b 100644 --- a/test/DebugInfo/autoclosure.swift +++ b/test/DebugInfo/autoclosure.swift @@ -1,8 +1,11 @@ // RUN: %target-swift-frontend %s -emit-ir -g -o - | FileCheck %s -// CHECK: define linkonce_odr hidden void @_TFF11autoclosure7call_meFVs5Int64T_u_KT_Ps11BooleanType_ +// CHECK: define{{.*}}@_TFF11autoclosure7call_meFVs5Int64T_u_KT_Ps11BooleanType_ +// CHECK-NOT: ret void // CHECK: call void @llvm.dbg.declare{{.*}}, !dbg +// CHECK-NOT: ret void // CHECK: , !dbg ![[DBG:.*]] +// CHECK: ret void func get_truth(input: Int64) -> Int64 { return input % 2 diff --git a/test/DebugInfo/byref-capture.swift b/test/DebugInfo/byref-capture.swift index f941ec6ec1821..b35f0471dee3f 100644 --- a/test/DebugInfo/byref-capture.swift +++ b/test/DebugInfo/byref-capture.swift @@ -5,9 +5,12 @@ func makeIncrementor(inc : Int64) -> () -> Int64 var sum : Int64 = 0 // CHECK: define {{.*}}5inner func inner() -> Int64 { - // CHECK: call void @llvm.dbg.declare(metadata %Vs5Int64** %{{.*}}, metadata ![[SUM_CAPTURE:[0-9]+]], metadata ![[DEREF:[0-9]+]]) - // CHECK-DAG: ![[SUM_CAPTURE]] = !DILocalVariable(name: "sum",{{.*}} line: [[@LINE-4]] - // CHECK-DAG: ![[DEREF]] = !DIExpression(DW_OP_deref + // CHECK: call void @llvm.dbg.declare(metadata %Vs5Int64** + // CHECK-SAME: metadata ![[SUM_CAPTURE:[0-9]+]], + // CHECK-SAME: metadata ![[DEREF:[0-9]+]]) + // CHECK: ![[DEREF]] = !DIExpression(DW_OP_deref) + // CHECK: ![[SUM_CAPTURE]] = !DILocalVariable(name: "sum", + // CHECK-SAME: line: [[@LINE-8]] sum += inc return sum } @@ -15,3 +18,4 @@ func makeIncrementor(inc : Int64) -> () -> Int64 } var incrementor = makeIncrementor(5) +incrementor() diff --git a/test/DebugInfo/capturelist.swift b/test/DebugInfo/capturelist.swift index 64b4153a74f5c..cac7e8b4414e3 100644 --- a/test/DebugInfo/capturelist.swift +++ b/test/DebugInfo/capturelist.swift @@ -3,10 +3,16 @@ class C { func withClosure(_ : () -> ()) -> () {} func f() { + // CHECK: define{{.*}}_TFFC11capturelist1C1fFT_T_U_FT_T_ // There should not be a local weak variable "self" shadowing the // implicit self argument. - // CHECK: DILocalVariable(name: "self", arg: 1 - // CHECK-NOT: DILocalVariable(name: "self", scope + // let self + // CHECK: call void @llvm.dbg + // let s + // CHECK: call void @llvm.dbg + // var weak self + // CHECK-NOT: call void @llvm.dbg + // CHECK: ret void withClosure { [weak self] in guard let s = self else { return } } diff --git a/test/DebugInfo/closure-args.swift b/test/DebugInfo/closure-args.swift index fa6f6495867b4..ca30f0099e3ea 100644 --- a/test/DebugInfo/closure-args.swift +++ b/test/DebugInfo/closure-args.swift @@ -13,9 +13,6 @@ func main() -> Void // CHECK: define linkonce_odr hidden i1 @_TFF4main4mainFT_T_U_FTSSSS_Sb( // CHECK: %[[RANDOM_STR_ADDR:.*]] = alloca %SS*, align {{(4|8)}} // CHECK: store %SS* %{{.*}}, %SS** %[[RANDOM_STR_ADDR]], align {{(4|8)}} - // The shadow copying should happen in the prologue, because the - // stack pointer will be decremented after it. - // CHECK-NOT: !dbg // CHECK-NEXT: call void @llvm.dbg.declare(metadata %SS** %[[RANDOM_STR_ADDR]], metadata !{{.*}}, metadata !{{[0-9]+}}), !dbg // CHECK-DAG: !DILocalVariable(name: "lhs",{{.*}} line: [[@LINE+5]], // CHECK-DAG: !DILocalVariable(name: "rhs",{{.*}} line: [[@LINE+4]], diff --git a/test/DebugInfo/closure-multivalue.swift b/test/DebugInfo/closure-multivalue.swift index fccdc91a5004a..d7440393b2bb0 100644 --- a/test/DebugInfo/closure-multivalue.swift +++ b/test/DebugInfo/closure-multivalue.swift @@ -1,5 +1,5 @@ -// RUN: %target-swift-frontend -O %s -disable-llvm-optzns -emit-ir -g -o - | FileCheck %s - +// rdar://problem/23727705: +// RUN-DISABLED: %target-swift-frontend -O %s -disable-llvm-optzns -emit-ir -g -o - | FileCheck %s import StdlibUnittest // CHECK: define {{.*}}i1 {{.*}}4main4sort diff --git a/test/DebugInfo/inout.swift b/test/DebugInfo/inout.swift index b5680dcaaa3ba..c301d8f0345b7 100644 --- a/test/DebugInfo/inout.swift +++ b/test/DebugInfo/inout.swift @@ -9,23 +9,28 @@ func Close(fn: () -> Int64) { fn() } typealias MyFloat = Float // CHECK: define hidden void @_TF5inout13modifyFooHeap -// CHECK: %[[ALLOCB:.*]] = alloca %Sf // CHECK: %[[ALLOCA:.*]] = alloca %Vs5Int64* -// CHECK-DAG: call void @llvm.dbg.declare(metadata {{.*}} %[[ALLOCA]], metadata ![[A:[0-9]+]] -// CHECK-DAG: call void @llvm.dbg.declare(metadata {{.*}} %[[ALLOCB]], metadata ![[B:[0-9]+]], metadata !{{[0-9]+}}) +// CHECK: %[[ALLOCB:.*]] = alloca %Sf +// CHECK: call void @llvm.dbg.declare(metadata +// CHECK-SAME: %[[ALLOCA]], metadata ![[A:[0-9]+]] +// CHECK: call void @llvm.dbg.declare(metadata +// CHECK-SAME: %[[ALLOCB]], metadata ![[B:[0-9]+]], metadata !{{[0-9]+}}) // Closure with promoted capture. // PROMO-CHECK: define {{.*}}@_TTSf2d_i___TFF5inout13modifyFooHeapFTRVs5Int64Sf_T_U_FT_S0_ -// PROMO-CHECK: call void @llvm.dbg.declare(metadata {{(i32|i64)}}* %{{.*}}, metadata ![[A1:[0-9]+]], metadata ![[EMPTY_EXPR:[0-9]+]]) +// PROMO-CHECK: call void @llvm.dbg.declare(metadata {{(i32|i64)}}* % +// PROMO-CHECK-SAME: metadata ![[A1:[0-9]+]], metadata ![[EMPTY_EXPR:[0-9]+]]) -// PROMO-CHECK-DAG: ![[EMPTY_EXPR]] = !DIExpression() -// PROMO-CHECK-DAG: ![[REFINT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "_TtRVs5Int64" -// PROMO-CHECK-DAG: ![[A1]] = !DILocalVariable(name: "a", arg: 1{{.*}} type: !"_TtVs5Int64" -// PROMO-CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "_TtRVs5Int64" +// PROMO-CHECK: ![[EMPTY_EXPR]] = !DIExpression() +// PROMO-CHECK: ![[A1]] = !DILocalVariable(name: "a", arg: 1 +// PROMO-CHECK-SAME: type: !"_TtVs5Int64" func modifyFooHeap(inout a: Int64, -// CHECK-DAG: ![[A]] = !DILocalVariable(name: "a", arg: 1{{.*}} line: [[@LINE-1]],{{.*}} type: !"_TtRVs5Int64" -// CHECK-DAG: ![[B]] = !DILocalVariable(name: "b", scope:{{.*}} line: [[@LINE+4]],{{.*}} type: ![[MYFLOAT:[0-9]+]] -// CHECK-DAG: ![[MYFLOAT]] = !DIDerivedType(tag: DW_TAG_typedef, name: "_Tta5inout7MyFloat",{{.*}} baseType: !"_TtSf" + // CHECK: ![[A]] = !DILocalVariable(name: "a", arg: 1 + // CHECK-SAME: line: [[@LINE-2]],{{.*}} type: !"_TtRVs5Int64" + // CHECK: ![[B]] = !DILocalVariable(name: "b", scope: + // CHECK-SAME: line: [[@LINE+5]],{{.*}} type: ![[MYFLOAT:[0-9]+]] + // CHECK: ![[MYFLOAT]] = !DIDerivedType(tag: DW_TAG_typedef, + // CHECK-SAME: name: "_Tta5inout7MyFloat",{{.*}} baseType: !"_TtSf" _ b: MyFloat) { var b = b @@ -39,8 +44,9 @@ func modifyFooHeap(inout a: Int64, // Inout reference type. // FOO-CHECK: define {{.*}}@_TF5inout9modifyFooFTRVs5Int64Sf_T_ -// FOO-CHECK: call void @llvm.dbg.declare(metadata %Vs5Int64** %{{.*}}, metadata ![[U:[0-9]+]], metadata ![[EMPTY_EXPR:.*]]) -// FOO-CHECK-DAG: ![[EMPTY_EXPR]] = !DIExpression() +// FOO-CHECK: call void @llvm.dbg.declare(metadata %Vs5Int64** % +// FOO-CHECK-SAME: metadata ![[U:[0-9]+]], metadata ![[EMPTY_EXPR:.*]]) +// FOO-CHECK: ![[EMPTY_EXPR]] = !DIExpression() func modifyFoo(inout u: Int64, // FOO-CHECK-DAG: !DILocalVariable(name: "v", scope:{{.*}} line: [[@LINE+5]],{{.*}} type: ![[MYFLOAT:[0-9]+]] // FOO-CHECK-DAG: [[U]] = !DILocalVariable(name: "u", arg: 1{{.*}} line: [[@LINE-2]],{{.*}} type: !"_TtRVs5Int64" diff --git a/test/DebugInfo/linetable.swift b/test/DebugInfo/linetable.swift index 0ad52c6c296a3..846e98881c067 100644 --- a/test/DebugInfo/linetable.swift +++ b/test/DebugInfo/linetable.swift @@ -59,8 +59,8 @@ func main(x: Int64) -> Void // ASM-CHECK:_TTSf2d_i_n___TFF9linetable4mainFVs5Int64T_U_FT_T_: // ASM-CHECK-NOT: retq -// The end-of-prologue should have a valid location. -// ASM-CHECK: .loc [[FILEID]] 37 {{[0-9]+}} prologue_end - +// The end-of-prologue should have a valid location (0 is ok, too). +// ASM-CHECK: .loc [[FILEID]] 0 {{[0-9]+}} prologue_end +// ASM-CHECK: .loc [[FILEID]] 37 {{[0-9]+}} main(30) diff --git a/test/DebugInfo/shadowcopy-linetable.swift b/test/DebugInfo/shadowcopy-linetable.swift index 547650800aa83..2e1bcd863c46f 100644 --- a/test/DebugInfo/shadowcopy-linetable.swift +++ b/test/DebugInfo/shadowcopy-linetable.swift @@ -3,14 +3,18 @@ func markUsed(t: T) {} func foo(inout x : Int64) { - // Make sure the shadow copy is being made in the prologue, but the - // code to load the value from the inout storage is not. - x = x + 2 + // Make sure the shadow copy is being made in the prologue or (at + // line 0), but the code to load the value from the inout storage is + // not. // CHECK: %[[X:.*]] = alloca %Vs5Int64*, align {{(4|8)}} // CHECK: store %Vs5Int64* %0, %Vs5Int64** %[[X]], align {{(4|8)}} - // CHECK-NOT: !dbg + // CHECK-SAME: !dbg ![[LOC0:.*]] // CHECK-NEXT: call void @llvm.dbg.declare - // CHECK-NEXT: getelementptr inbounds %Vs5Int64, %Vs5Int64* %0, i32 0, i32 0, !dbg + // CHECK-NEXT: getelementptr inbounds %Vs5Int64, %Vs5Int64* %0, i32 0, i32 0, + // CHECK-SAME: !dbg ![[LOC1:.*]] + // CHECK: ![[LOC0]] = !DILocation(line: 0, + // CHECK: ![[LOC1]] = !DILocation(line: [[@LINE+1]], + x = x + 2 } func main() { diff --git a/test/DebugInfo/unowned-capture.swift b/test/DebugInfo/unowned-capture.swift index 16970ca34f93e..9a3474defce24 100644 --- a/test/DebugInfo/unowned-capture.swift +++ b/test/DebugInfo/unowned-capture.swift @@ -7,9 +7,10 @@ class Foo // Verify that we only emit the implicit argument, // and not the unowned local copy of self. // - // CHECK-NOT: !DILocalVariable(name: "self", scope - // CHECK: !DILocalVariable(name: "self", arg: 2 - // CHECK-NOT: !DILocalVariable(name: "self", scope + // CHECK: ![[SCOPE:.*]] = distinct !DISubprogram(name: "DefinesClosure", + // CHECK-NOT: !DILocalVariable(name: "self", scope: ![[SCOPE]] + // CHECK: !DILocalVariable(name: "self", arg: 2, scope: ![[SCOPE]] + // CHECK-NOT: !DILocalVariable(name: "self", scope: ![[SCOPE]] return { [unowned self] in var tmp_string = a_string return tmp_string diff --git a/test/SILGen/builtins.swift b/test/SILGen/builtins.swift index 9da064fb01235..ffc4331560b72 100644 --- a/test/SILGen/builtins.swift +++ b/test/SILGen/builtins.swift @@ -547,6 +547,7 @@ func pinUnpin(object : Builtin.NativeObject) { // CHECK-LABEL: sil hidden @_TF8builtins19allocateValueBuffer // CHECK: bb0([[BUFFER:%.*]] : $*Builtin.UnsafeValueBuffer): +// CHECK-NEXT: debug_value_addr %0 : $*Builtin.UnsafeValueBuffer // var buffer, argno: 1 // CHECK-NEXT: metatype $@thin Int.Type // CHECK-NEXT: [[T0:%.*]] = alloc_value_buffer $Int in [[BUFFER]] : $*Builtin.UnsafeValueBuffer // CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[T0]] : $*Int to $Builtin.RawPointer @@ -557,6 +558,7 @@ func allocateValueBuffer(inout buffer: Builtin.UnsafeValueBuffer) -> Builtin.Raw // CHECK-LABEL: sil hidden @_TF8builtins18projectValueBuffer // CHECK: bb0([[BUFFER:%.*]] : $*Builtin.UnsafeValueBuffer): +// CHECK-NEXT: debug_value_addr %0 : $*Builtin.UnsafeValueBuffer // var buffer, argno: 1 // CHECK-NEXT: metatype $@thin Int.Type // CHECK-NEXT: [[T0:%.*]] = project_value_buffer $Int in [[BUFFER]] : $*Builtin.UnsafeValueBuffer // CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[T0]] : $*Int to $Builtin.RawPointer @@ -567,6 +569,7 @@ func projectValueBuffer(inout buffer: Builtin.UnsafeValueBuffer) -> Builtin.RawP // CHECK-LABEL: sil hidden @_TF8builtins18deallocValueBuffer // CHECK: bb0([[BUFFER:%.*]] : $*Builtin.UnsafeValueBuffer): +//CHECK-NEXT: debug_value_addr %0 : $*Builtin.UnsafeValueBuffer // var buffer, argno: 1 // CHECK-NEXT: metatype $@thin Int.Type // CHECK-NEXT: dealloc_value_buffer $Int in [[BUFFER]] : $*Builtin.UnsafeValueBuffer // CHECK-NEXT: tuple () diff --git a/test/SILGen/closures.swift b/test/SILGen/closures.swift index a01b1a3db0a93..606ab4605f92d 100644 --- a/test/SILGen/closures.swift +++ b/test/SILGen/closures.swift @@ -236,6 +236,7 @@ func generateWithConstant(x : SomeSpecificClass) { } // CHECK-LABEL: sil shared @_TFF8closures20generateWithConstant // CHECK: bb0([[T0:%.*]] : $SomeSpecificClass): +// CHECK-NEXT: debug_value %0 : $SomeSpecificClass // let x, argno: 1 // CHECK-NEXT: [[T1:%.*]] = upcast [[T0]] : $SomeSpecificClass to $SomeClass // CHECK-NEXT: return [[T1]] @@ -299,7 +300,7 @@ func closeOverLetLValue() { // is loadable even though we capture the value. // CHECK-LABEL: sil shared @_TFF8closures18closeOverLetLValueFT_T_U_FT_Si // CHECK: bb0(%0 : $ClassWithIntProperty): -// CHECK-NEXT: [[TMP:%.*]] = alloc_stack $ClassWithIntProperty // let a +// CHECK-NEXT: [[TMP:%.*]] = alloc_stack $ClassWithIntProperty // let a, argno: 1 // CHECK-NEXT: store %0 to [[TMP]]#1 : $*ClassWithIntProperty // CHECK-NEXT: {{.*}} = load [[TMP]]#1 : $*ClassWithIntProperty // CHECK-NEXT: {{.*}} = ref_element_addr {{.*}} : $ClassWithIntProperty, #ClassWithIntProperty.x @@ -327,7 +328,7 @@ struct StructWithMutatingMethod { // CHECK-LABEL: sil hidden @_TFV8closures24StructWithMutatingMethod14mutatingMethod // CHECK: bb0(%0 : $*StructWithMutatingMethod): -// CHECK-NEXT: %1 = alloc_box $StructWithMutatingMethod // var self // users: %2, %5, %7, %8 +// CHECK-NEXT: %1 = alloc_box $StructWithMutatingMethod // var self, argno: 1 // users: %2, %5, %7, %8 // CHECK-NEXT: copy_addr %0 to [initialization] %1#1 : $*StructWithMutatingMethod // id: %2 // CHECK: [[CLOSURE:%[0-9]+]] = function_ref @_TFFV8closures24StructWithMutatingMethod14mutatingMethod{{.*}} : $@convention(thin) (@inout StructWithMutatingMethod) -> Int // CHECK: partial_apply [[CLOSURE]](%1#1) : $@convention(thin) (@inout StructWithMutatingMethod) -> Int diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift index 2d1790e12f6b3..cf553df07ceee 100644 --- a/test/SILGen/properties.swift +++ b/test/SILGen/properties.swift @@ -668,17 +668,18 @@ func propertyWithDidSetTakingOldValue() { // CHECK: // properties.(propertyWithDidSetTakingOldValue () -> ()).(p #1).setter : Swift.Int // CHECK-NEXT: sil {{.*}} @_TFF10properties32propertyWithDidSetTakingOldValue // CHECK: bb0(%0 : $Int, %1 : $@box Int, %2 : $*Int): -// CHECK-NEXT: debug_value %0 : $Int -// CHECK-NEXT: %4 = load %2 : $*Int -// CHECK-NEXT: debug_value %4 : $Int +// CHECK-NEXT: debug_value %0 : $Int // let newValue, argno: 1 +// CHECK-NEXT: debug_value_addr %2 : $*Int // var p, argno: 2 +// CHECK-NEXT: %5 = load %2 : $*Int +// CHECK-NEXT: debug_value %5 : $Int // CHECK-NEXT: assign %0 to %2 : $*Int // CHECK-NEXT: strong_retain %1 : $@box Int // CHECK-NEXT: // function_ref -// CHECK-NEXT: %8 = function_ref @_TFF10properties32propertyWithDidSetTakingOldValueFT_T_WL_1pSi : $@convention(thin) (Int, @owned @box Int, @inout Int) -> () -// CHECK-NEXT: %9 = apply %8(%4, %1, %2) : $@convention(thin) (Int, @owned @box Int, @inout Int) -> () +// CHECK-NEXT: %9 = function_ref @_TFF10properties32propertyWithDidSetTakingOldValueFT_T_WL_1pSi : $@convention(thin) (Int, @owned @box Int, @inout Int) -> () +// CHECK-NEXT: %10 = apply %9(%5, %1, %2) : $@convention(thin) (Int, @owned @box Int, @inout Int) -> () // CHECK-NEXT: strong_release %1 : $@box Int -// CHECK-NEXT: %11 = tuple () -// CHECK-NEXT: return %11 : $() +// CHECK-NEXT: %12 = tuple () +// CHECK-NEXT: return %12 : $() // CHECK-NEXT:} diff --git a/test/SILGen/unmanaged.swift b/test/SILGen/unmanaged.swift index b4d8b1ca99c27..55ccdf6290414 100644 --- a/test/SILGen/unmanaged.swift +++ b/test/SILGen/unmanaged.swift @@ -32,6 +32,7 @@ func get(inout holder holder: Holder) -> C { } // CHECK-LABEL:sil hidden @_TF9unmanaged3getFT6holderRVS_6Holder_CS_1C : $@convention(thin) (@inout Holder) -> @owned C // CHECK: bb0([[ADDR:%.*]] : $*Holder): +// CHECK-NEXT: debug_value_addr %0 : $*Holder // var holder, argno: 1 // CHECK-NEXT: [[T0:%.*]] = struct_element_addr [[ADDR]] : $*Holder, #Holder.value // CHECK-NEXT: [[T1:%.*]] = load [[T0]] : $*@sil_unmanaged C // CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]] diff --git a/test/SILGen/unowned.swift b/test/SILGen/unowned.swift index 7afa39e5c305d..f25c369024c26 100644 --- a/test/SILGen/unowned.swift +++ b/test/SILGen/unowned.swift @@ -96,6 +96,7 @@ func test_unowned_let_capture(aC : C) { // CHECK-LABEL: sil shared @_TFF7unowned24test_unowned_let_captureFCS_1CT_U_FT_Si : $@convention(thin) (@owned @sil_unowned C) -> Int { // CHECK: bb0([[ARG:%.*]] : $@sil_unowned C): +// CHECK-NEXT: debug_value %0 : $@sil_unowned C // let bC, argno: 1 // CHECK-NEXT: strong_retain_unowned [[ARG]] : $@sil_unowned C // CHECK-NEXT: [[UNOWNED_ARG:%.*]] = unowned_to_ref [[ARG]] : $@sil_unowned C to $C // CHECK-NEXT: [[FUN:%.*]] = class_method [[UNOWNED_ARG]] : $C, #C.f!1 : C -> () -> Int , $@convention(method) (@guaranteed C) -> Int diff --git a/test/SILGen/weak.swift b/test/SILGen/weak.swift index 18666fddd67b9..2777e25a9545c 100644 --- a/test/SILGen/weak.swift +++ b/test/SILGen/weak.swift @@ -47,9 +47,10 @@ func test0(c c: C) { // CHECK: weak.(testClosureOverWeak () -> ()).(closure #1) // CHECK-LABEL: sil shared @_TFF4weak19testClosureOverWeakFT_T_U_FT_Si : $@convention(thin) (@owned @box @sil_weak Optional, @inout @sil_weak Optional) -> Int { // CHECK: bb0(%0 : $@box @sil_weak Optional, %1 : $*@sil_weak Optional): -// CHECK-NEXT: %2 = alloc_stack $Optional -// CHECK-NEXT: %3 = load_weak %1 : $*@sil_weak Optional -// CHECK-NEXT: store %3 to %2#1 : $*Optional +// CHECK-NEXT: debug_value_addr %1 : $*@sil_weak Optional // var bC, argno: 1 +// CHECK-NEXT: %3 = alloc_stack $Optional +// CHECK-NEXT: %4 = load_weak %1 : $*@sil_weak Optional +// CHECK-NEXT: store %4 to %3#1 : $*Optional func testClosureOverWeak() { weak var bC = C() takeClosure { bC!.f() } diff --git a/test/SILPasses/inout_deshadow.sil b/test/SILPasses/inout_deshadow.sil index 839f6e3e5f651..a70da77e374bd 100644 --- a/test/SILPasses/inout_deshadow.sil +++ b/test/SILPasses/inout_deshadow.sil @@ -29,7 +29,8 @@ sil @AddressOnlyTest : $@convention(thin) (@inout P) -> () { bb0(%0 : $*P): // CHECK: bb0(%0 : $*P): %1 = alloc_stack $P copy_addr %0 to [initialization] %1#1 : $*P - + + // CHECK-NEXT: debug_value_addr %0 // CHECK-NEXT: open_existential_addr %0 : $*P %3 = open_existential_addr %1#1 : $*P to $*@opened("01234567-89ab-cdef-0123-000000000000") P %4 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000") P, #P.foo!1, %3 : $*@opened("01234567-89ab-cdef-0123-000000000000") P : $@convention(witness_method) @callee_owned (@inout T) -> () @@ -66,6 +67,7 @@ bb0(%0 : $*NontrivialStruct): %1 = alloc_stack $NontrivialStruct copy_addr %0 to [initialization] %1#1 : $*NontrivialStruct + // CHECK-NEXT: debug_value_addr %0 // CHECK-NEXT: // function_ref takeNontrivial // CHECK-NEXT: function_ref @takeNontrivial %3 = function_ref @takeNontrivial : $@convention(method) (@inout NontrivialStruct) -> () // user: %4