Skip to content

Commit 1e4f55d

Browse files
Merge pull request swiftlang#15046 from aschwaighofer/without_actually_escaping_verification
Implement withoutActuallyEscaping verification
2 parents fce138f + b960275 commit 1e4f55d

33 files changed

+351
-57
lines changed

docs/SIL.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2855,6 +2855,19 @@ memory object or a reference to a pinned object. Returns 1 if the
28552855
strong reference count is 1 or the object has been marked pinned by
28562856
strong_pin.
28572857

2858+
is_escaping_closure
2859+
```````````````````
2860+
2861+
::
2862+
sil-instruction ::= 'is_escaping_closure' sil-operand
2863+
2864+
%1 = is_escaping_closure %0 : $@callee_guaranteed () -> ()
2865+
// %0 must be an escaping swift closure.
2866+
// %1 will be of type Builtin.Int1
2867+
2868+
Checks whether the context reference is not nil and bigger than one and returns
2869+
true if it is.
2870+
28582871
copy_block
28592872
``````````
28602873
::

include/swift/Runtime/Debug.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#define _SWIFT_RUNTIME_DEBUG_HELPERS_
1919

2020
#include <llvm/Support/Compiler.h>
21+
#include <cstdarg>
22+
#include <cstdio>
2123
#include <stdint.h>
2224
#include "swift/Runtime/Config.h"
2325
#include "swift/Runtime/Unreachable.h"
@@ -222,6 +224,39 @@ void _swift_reportToDebugger(uintptr_t flags, const char *message,
222224
SWIFT_RUNTIME_STDLIB_SPI
223225
bool _swift_reportFatalErrorsToDebugger;
224226

227+
LLVM_ATTRIBUTE_ALWAYS_INLINE
228+
inline static int swift_asprintf(char **strp, const char *fmt, ...) {
229+
va_list args;
230+
va_start(args, fmt);
231+
#if defined(_WIN32)
232+
#pragma GCC diagnostic push
233+
#pragma GCC diagnostic ignored "-Wuninitialized"
234+
int len = _vscprintf(fmt, args);
235+
#pragma GCC diagnostic pop
236+
if (len < 0) {
237+
va_end(args);
238+
return -1;
239+
}
240+
char *buffer = static_cast<char *>(malloc(len + 1));
241+
if (!buffer) {
242+
va_end(args);
243+
return -1;
244+
}
245+
int result = vsprintf(buffer, fmt, args);
246+
if (result < 0) {
247+
va_end(args);
248+
free(buffer);
249+
return -1;
250+
}
251+
*strp = buffer;
252+
#else
253+
int result = vasprintf(strp, fmt, args);
254+
#endif
255+
va_end(args);
256+
return result;
257+
}
258+
259+
225260
// namespace swift
226261
}
227262

include/swift/Runtime/HeapObject.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,16 @@ SWIFT_RUNTIME_EXPORT
280280
bool swift_isUniquelyReferencedOrPinned_nonNull_native(
281281
const struct HeapObject *);
282282

283+
/// Is this native Swift pointer non-null and has a reference count greater than
284+
/// one.
285+
/// This runtime call will print an error message with file name and location if
286+
/// the closure is escaping but it will not abort.
287+
SWIFT_RUNTIME_EXPORT
288+
bool swift_isEscapingClosureAtFileLocation(const struct HeapObject *object,
289+
const unsigned char *filename,
290+
int32_t filenameLength,
291+
int32_t line);
292+
283293
/// Deallocate the given memory.
284294
///
285295
/// It must have been returned by swift_allocObject and the strong reference

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,16 @@ FUNCTION(IsUniquelyReferencedOrPinned_nonNull_native,
677677
ARGS(RefCountedPtrTy),
678678
ATTRS(NoUnwind, ZExt))
679679

680+
// bool swift_isEscapingClosureAtFileLocation(const struct HeapObject *object,
681+
// const unsigned char *filename,
682+
// int32_t filenameLength,
683+
// int32_t line);
684+
FUNCTION(IsEscapingClosureAtFileLocation, swift_isEscapingClosureAtFileLocation,
685+
C_CC,
686+
RETURNS(Int1Ty),
687+
ARGS(RefCountedPtrTy, Int8PtrTy, Int32Ty, Int32Ty),
688+
ATTRS(NoUnwind, ZExt))
689+
680690
// void swift_arrayInitWithCopy(opaque*, opaque*, size_t, type*);
681691
FUNCTION(ArrayInitWithCopy, swift_arrayInitWithCopy, C_CC,
682692
RETURNS(VoidTy),

include/swift/SIL/SILBuilder.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,12 @@ class SILBuilder {
15381538
return insert(new (getModule()) IsUniqueOrPinnedInst(
15391539
getSILDebugLocation(Loc), value, Int1Ty));
15401540
}
1541+
IsEscapingClosureInst *createIsEscapingClosure(SILLocation Loc,
1542+
SILValue operand) {
1543+
auto Int1Ty = SILType::getBuiltinIntegerType(1, getASTContext());
1544+
return insert(new (getModule()) IsEscapingClosureInst(
1545+
getSILDebugLocation(Loc), operand, Int1Ty));
1546+
}
15411547

15421548
DeallocStackInst *createDeallocStack(SILLocation Loc, SILValue operand) {
15431549
return insert(new (getModule())
@@ -1615,7 +1621,14 @@ class SILBuilder {
16151621
// Runtime failure
16161622
//===--------------------------------------------------------------------===//
16171623

1618-
CondFailInst *createCondFail(SILLocation Loc, SILValue Operand) {
1624+
CondFailInst *createCondFail(SILLocation Loc, SILValue Operand,
1625+
bool Inverted = false) {
1626+
if (Inverted) {
1627+
SILType Ty = Operand->getType();
1628+
SILValue True(createIntegerLiteral(Loc, Ty, 1));
1629+
Operand =
1630+
createBuiltinBinaryFunction(Loc, "xor", Ty, Ty, {Operand, True});
1631+
}
16191632
return insert(new (getModule())
16201633
CondFailInst(getSILDebugLocation(Loc), Operand));
16211634
}

include/swift/SIL/SILCloner.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,14 @@ visitIsUniqueOrPinnedInst(IsUniqueOrPinnedInst *Inst) {
20132013
getBuilder().createIsUniqueOrPinned(getOpLocation(Inst->getLoc()),
20142014
getOpValue(Inst->getOperand())));
20152015
}
2016+
template <typename ImplClass>
2017+
void SILCloner<ImplClass>::visitIsEscapingClosureInst(
2018+
IsEscapingClosureInst *Inst) {
2019+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2020+
doPostProcess(
2021+
Inst, getBuilder().createIsEscapingClosure(
2022+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
2023+
}
20162024

20172025
template<typename ImplClass>
20182026
void

include/swift/SIL/SILInstruction.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6194,6 +6194,18 @@ class IsUniqueOrPinnedInst
61946194
: UnaryInstructionBase(DebugLoc, Operand, BoolTy) {}
61956195
};
61966196

6197+
/// Given an escaping closure return true iff it has a non-nil context and the
6198+
/// context has a strong reference count greater than 1.
6199+
class IsEscapingClosureInst
6200+
: public UnaryInstructionBase<SILInstructionKind::IsEscapingClosureInst,
6201+
SingleValueInstruction> {
6202+
friend SILBuilder;
6203+
6204+
IsEscapingClosureInst(SILDebugLocation DebugLoc, SILValue Operand,
6205+
SILType BoolTy)
6206+
: UnaryInstructionBase(DebugLoc, Operand, BoolTy) {}
6207+
};
6208+
61976209
//===----------------------------------------------------------------------===//
61986210
// DeallocationInsts
61996211
//===----------------------------------------------------------------------===//

include/swift/SIL/SILNodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
379379
SINGLE_VALUE_INST(IsUniqueOrPinnedInst, is_unique_or_pinned,
380380
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
381381

382+
SINGLE_VALUE_INST(IsEscapingClosureInst, is_escaping_closure,
383+
SingleValueInstruction, MayRead, DoesNotRelease)
384+
382385
// Accessing memory
383386
SINGLE_VALUE_INST(LoadInst, load,
384387
SingleValueInstruction, MayRead, DoesNotRelease)

lib/IRGen/GenHeap.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "swift/Basic/SourceLoc.h"
2626
#include "swift/ABI/MetadataValues.h"
27+
#include "swift/AST/ASTContext.h"
2728
#include "swift/AST/GenericEnvironment.h"
2829
#include "swift/AST/IRGenOptions.h"
2930

@@ -1430,6 +1431,20 @@ emitIsUniqueCall(llvm::Value *value, SourceLoc loc, bool isNonNull,
14301431
return call;
14311432
}
14321433

1434+
llvm::Value *IRGenFunction::emitIsEscapingClosureCall(llvm::Value *value,
1435+
SourceLoc sourceLoc) {
1436+
auto loc = SILLocation::decode(sourceLoc, IGM.Context.SourceMgr);
1437+
auto line = llvm::ConstantInt::get(IGM.Int32Ty, loc.Line);
1438+
auto filename = IGM.getAddrOfGlobalString(loc.Filename);
1439+
auto filenameLength =
1440+
llvm::ConstantInt::get(IGM.Int32Ty, loc.Filename.size());
1441+
llvm::CallInst *call =
1442+
Builder.CreateCall(IGM.getIsEscapingClosureAtFileLocationFn(),
1443+
{value, filename, filenameLength, line});
1444+
call->setDoesNotThrow();
1445+
return call;
1446+
}
1447+
14331448
namespace {
14341449
/// Basic layout and common operations for box types.
14351450
class BoxTypeInfo : public HeapTypeInfo<BoxTypeInfo> {

lib/IRGen/IRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,8 @@ class IRGenFunction {
435435
llvm::Value *emitIsUniqueCall(llvm::Value *value, SourceLoc loc,
436436
bool isNonNull, bool checkPinned);
437437

438+
llvm::Value *emitIsEscapingClosureCall(llvm::Value *value, SourceLoc loc);
439+
438440
//--- Expression emission ------------------------------------------------------
439441
public:
440442
void emitFakeExplosion(const TypeInfo &type, Explosion &explosion);

0 commit comments

Comments
 (0)