Skip to content

[OSLogOptimization] emitCodeForSymbolicValue should not attempt generating code for closures created by callers of os_log #30893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions lib/SILOptimizer/Mandatory/OSLogOptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -728,17 +728,22 @@ static SILValue emitCodeForSymbolicValue(SymbolicValue symVal,
SILModule &module = builder.getModule();
SymbolicClosure *closure = symVal.getClosure();
SILValue resultVal;
if (!closure->hasOnlyConstantCaptures()) {
// If the closure captures a value that is not a constant, it should only
// come from the caller of the log call. Therefore, assert this and reuse
// the closure value.
SingleValueInstruction *originalClosureInst = closure->getClosureInst();
SILFunction &fun = builder.getFunction();
assert(originalClosureInst->getFunction() == &fun &&
"closure with non-constant captures not defined in this function");
// Copy the closure, since the returned value must be owned.

// If the closure was created in the context of this function where the code
// is generated, reuse the original closure value (after extending its
// lifetime by copying).
SingleValueInstruction *originalClosureInst = closure->getClosureInst();
SILFunction &fun = builder.getFunction();
if (originalClosureInst->getFunction() == &fun) {
// Copy the closure, since the returned value must be owned and the
// closure's lifetime must be extended until this point.
resultVal = makeOwnedCopyOfSILValue(originalClosureInst, fun);
} else {
// If the closure captures a value that is not a constant, it should only
// come from the caller of the log call. It should be handled by the then
// case and we should never reach here. Assert this.
assert(closure->hasOnlyConstantCaptures() &&
"closure with non-constant captures not defined in this function");
SubstitutionMap callSubstMap = closure->getCallSubstitutionMap();
ArrayRef<SymbolicClosureArgument> captures = closure->getCaptures();
// Recursively emit code for all captured values which must be mapped to a
Expand Down
28 changes: 27 additions & 1 deletion test/SILOptimizer/OSLogMandatoryOptTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@ protocol Proto {
var property: String { get set }
}

// Test capturing of address-only types in autoclosures.
// Test capturing of address-only types in autoclosures. The following tests check that
// there are no crashes in these cases.

// CHECK-LABEL: @${{.*}}testInterpolationOfExistentials1pyAA5Proto_p_tF
func testInterpolationOfExistentials(p: Proto) {
Expand All @@ -609,3 +610,28 @@ func testInterpolationOfGenerics<T : Proto>(p: T) {
_osLogTestHelper("A generic argument's property \(p.property)")
}

class TestClassSelfTypeCapture {
// CHECK-LABEL: @${{.*}}TestClassSelfTypeCaptureC04testdeF0yyF
func testSelfTypeCapture() {
_osLogTestHelper("Self type of a class \(String(describing: Self.self))")
}
}

struct TestStructSelfTypeCapture {
// CHECK-LABEL: @${{.*}}TestStructSelfTypeCaptureV04testdeF0yyF
func testSelfTypeCapture() {
_osLogTestHelper("Self type of a struct \(String(describing: Self.self))")
}
}

protocol TestProtocolSelfTypeCapture {
func testSelfTypeCapture()
}

extension TestProtocolSelfTypeCapture {
// CHECK-LABEL: @${{.*}}TestProtocolSelfTypeCapturePAAE04testdeF0yyF
func testSelfTypeCapture() {
_osLogTestHelper("Self type of a protocol \(String(describing: Self.self))")
}
}