Skip to content
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

SIL: support store_borrow and partial_apply in memory lifetime verification #36211

Merged
merged 4 commits into from
Mar 2, 2021

Conversation

eeckstein
Copy link
Member

... and document store_borrow in SIL.rst

@eeckstein eeckstein requested a review from gottesmm March 1, 2021 16:17
@eeckstein
Copy link
Member Author

@swift-ci test

@swift-ci
Copy link
Collaborator

swift-ci commented Mar 1, 2021

Build failed
Swift Test Linux Platform
Git Sha - 3e511f3c4d0f8a1b62e78b0aed8335708b15dcbe

@eeckstein
Copy link
Member Author

@swift-ci test

@swift-ci
Copy link
Collaborator

swift-ci commented Mar 1, 2021

Build failed
Swift Test OS X Platform
Git Sha - e342fba161f46bb2570679f808e5899458713101

// $T must be a loadable type
// %1 must be an alloc_stack $T

Stores the value ``%0`` to a stack location ``%1``, which must be an
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add here that this is just the current implementation and the design is not final.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some questions.

/// For details see the partial_apply documentation in SIL.rst.
SILArgumentConvention getArgumentOperandConvention(const Operand &oper) const {
SILArgumentConvention conv = getArgumentConvention(oper);
auto *PAI = dyn_cast<PartialApplyInst>(Inst);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PAI -> pai.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

SI->getSrc()->getType(),
"Store operand type and dest type mismatch");
require(isa<AllocStackInst>(SI->getDest()),
"store_borrow destination can only be an alloc_stack");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment here similar to the SIL.rst comment. I want to make sure it is clear for posterity that this is not the final design and that we want to iterate further on this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -1,4 +1,4 @@
// RUN: %target-sil-opt -enable-sil-verify-all -inline %s -verify-continue-on-failure=true -o /dev/null 2>&1 | %FileCheck %s
// RUN: %target-sil-opt -enable-sil-verify-all -inline %s -verify-continue-on-failure=true -dont-abort-on-memory-lifetime-errors -o /dev/null 2>&1 | %FileCheck %s
// REQUIRES: asserts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is broken in this test file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the existing error, the memory lifetime verifier also issues an error. The test would fail if the memory lifetime verifier aborts

Copy link
Member

@gottesmm gottesmm Mar 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment here explaining that and also saying which test fails? Something like:

NOTE: We disable the memory lifetime verifier on this file since along side a _____ error that is caught by the load borrow verifier, @mytestname also contains a memory lifetime error. This is expected.

…gn_by_wrapper

So far we left this cleanup to SILCombine.
But the unused partial_apply (i.e. the "set" in case it's an init or the "init" in case it's a set) violates memory lifetime rules in case "self" is an inout.
Once we verify that, it would result in a memory lifetime violation.
Verify that
* the destination address is an alloc_stack
* the stack location is not modified beside a store_borrow
* the stack location has been initialized when used
@eeckstein
Copy link
Member Author

@swift-ci test

Copy link
Member

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick thoughts. Following up about the store_borrow thing via DM.

@@ -177,6 +178,7 @@ static void lowerAssignByWrapperInstruction(SILBuilderWithScope &b,
SILValue dest = inst->getDest();
SILLocation loc = inst->getLoc();
SILBuilderWithScope forCleanup(std::next(inst->getIterator()));
SingleValueInstruction *closureToDelete = nullptr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this change made? Also can you add a test?

@@ -1,4 +1,4 @@
// RUN: %target-sil-opt -enable-sil-verify-all -inline %s -verify-continue-on-failure=true -o /dev/null 2>&1 | %FileCheck %s
// RUN: %target-sil-opt -enable-sil-verify-all -inline %s -verify-continue-on-failure=true -dont-abort-on-memory-lifetime-errors -o /dev/null 2>&1 | %FileCheck %s
// REQUIRES: asserts
Copy link
Member

@gottesmm gottesmm Mar 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment here explaining that and also saying which test fails? Something like:

NOTE: We disable the memory lifetime verifier on this file since along side a _____ error that is caught by the load borrow verifier, @mytestname also contains a memory lifetime error. This is expected.

@@ -238,3 +238,115 @@ bb0(%0 : @owned $T):
return %r : $()
}

sil [ossa] @closure : $@convention(thin) (@in_guaranteed T) -> ()

// CHECK: SIL memory lifetime failure in @test_non_escaping_closure: memory is initialized at function return but shouldn't
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make these CHECK-LABEL:. Then I think file check will emit errors for all of them individually rather than only the first error.

// CHECK-NEXT: Block: bb0
// CHECK: Error#: 0. End Error in Function: 'recursive_interior_pointer_error'
sil [ossa] @recursive_interior_pointer_error : $@convention(thin) (@owned KlassUser, @guaranteed Klass) -> @owned Klass {
bb0(%0 : @owned $KlassUser, %0a : @guaranteed $Klass):
%1 = begin_borrow %0 : $KlassUser
%2 = ref_tail_addr %1 : $KlassUser, $Klass
%result = store_borrow %0a to %2 : $*Klass
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was testing that we are able to flag errors on store_borrow. This makes me a bit nervous about restricting store_borrow only to alloc_stack. I think this test case IIRC was from real code that we are emitting today. Now that I think further, one could imagine eliminating a temporary rvalue causing a store_borrow to be moved off of an alloc_stack.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked with eeckstein offline. This test is making sure that the use of %result is treated as a liveness requirement of %0. So by removing the store_borrow the test isn't testing anything anymore. Can you delete it?

Also for anyone listening in, we actually do not need to test this anymore since this PR makes it so that store_borrow's destination is always an alloc_stack meaning it can never store to an interior pointer destination.

Copy link
Member

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make these changes and then LGTM!

@gottesmm
Copy link
Member

gottesmm commented Mar 2, 2021

I am also fine with a follow on commit to fix (seems testing is finished). All of the changes I asked for are comment sort of changes, no functionality change so I would do that instead.

@eeckstein eeckstein merged commit 2d01286 into apple:main Mar 2, 2021
@eeckstein eeckstein deleted the memory-lifetime branch March 2, 2021 19:30
eeckstein added a commit to eeckstein/swift that referenced this pull request Mar 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants