Skip to content

Commit af565e7

Browse files
committed
[sil-parser] Fix harmless bug when parsing ossa.
Specifically, we were preferring the always correct ownership kind specified by the FunctionType and ignoring what we parsed from the argument. This PR changes ossa to give a nice error when this is detected and fixes the places where this tests were written incorrectly.
1 parent 40c9e26 commit af565e7

18 files changed

+74
-26
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
//===--- DiagnosticsParse.def - Diagnostics Text ----------------*- C++ -*-===//
32
//
43
// This source file is part of the Swift.org open source project
@@ -485,6 +484,10 @@ ERROR(referenced_value_no_accessor,none,
485484
"referenced declaration has no %select{getter|setter}0", (unsigned))
486485
ERROR(expected_sil_value_ownership_kind,none,
487486
"expected value ownership kind in SIL code", ())
487+
ERROR(silfunc_and_silarg_have_incompatible_sil_value_ownership,none,
488+
"SILFunction and SILArgument have mismatching ValueOwnershipKinds. "
489+
"Function type specifies: '@%0'. SIL argument specifies: '@%1'.",
490+
(StringRef, StringRef))
488491
ERROR(expected_sil_colon,none,
489492
"expected ':' before %0", (StringRef))
490493
ERROR(expected_sil_tuple_index,none,

include/swift/SIL/SILValue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ struct ValueOwnershipKind {
197197
return acc.getValue().merge(x);
198198
});
199199
}
200+
201+
StringRef asString() const;
200202
};
201203

202204
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, ValueOwnershipKind Kind);

lib/ParseSIL/ParseSIL.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,8 @@ namespace {
395395
bool parseSILOwnership(ValueOwnershipKind &OwnershipKind) {
396396
// We parse here @ <identifier>.
397397
if (!P.consumeIf(tok::at_sign)) {
398-
// If we fail, we must have @any ownership.
398+
// If we fail, we must have @any ownership. We check elsewhere in the
399+
// parser that this matches what the function signature wants.
399400
OwnershipKind = ValueOwnershipKind::Any;
400401
return false;
401402
}
@@ -5339,6 +5340,18 @@ bool SILParser::parseSILBasicBlock(SILBuilder &B) {
53395340
SILArgument *Arg;
53405341
if (IsEntry) {
53415342
Arg = BB->createFunctionArgument(Ty);
5343+
// Today, we construct the ownership kind straight from the function
5344+
// type. Make sure they are in sync, otherwise bail. We want this to
5345+
// be an exact check rather than a compatibility check since we do not
5346+
// want incompatibilities in between @any and other types of ownership
5347+
// to be ignored.
5348+
if (F->hasOwnership() && Arg->getOwnershipKind() != OwnershipKind) {
5349+
auto diagID =
5350+
diag::silfunc_and_silarg_have_incompatible_sil_value_ownership;
5351+
P.diagnose(NameLoc, diagID, Arg->getOwnershipKind().asString(),
5352+
OwnershipKind.asString());
5353+
return true;
5354+
}
53425355
} else {
53435356
Arg = BB->createPhiArgument(Ty, OwnershipKind);
53445357
}

lib/SIL/SILValue.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,22 +188,25 @@ ValueOwnershipKind::ValueOwnershipKind(const SILFunction &F, SILType Type,
188188
}
189189
}
190190

191-
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
192-
ValueOwnershipKind Kind) {
193-
switch (Kind) {
191+
StringRef ValueOwnershipKind::asString() const {
192+
switch (Value) {
194193
case ValueOwnershipKind::Unowned:
195-
return os << "unowned";
194+
return "unowned";
196195
case ValueOwnershipKind::Owned:
197-
return os << "owned";
196+
return "owned";
198197
case ValueOwnershipKind::Guaranteed:
199-
return os << "guaranteed";
198+
return "guaranteed";
200199
case ValueOwnershipKind::Any:
201-
return os << "any";
200+
return "any";
202201
}
203-
204202
llvm_unreachable("Unhandled ValueOwnershipKind in switch.");
205203
}
206204

205+
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
206+
ValueOwnershipKind kind) {
207+
return os << kind.asString();
208+
}
209+
207210
Optional<ValueOwnershipKind>
208211
ValueOwnershipKind::merge(ValueOwnershipKind RHS) const {
209212
auto LHSVal = Value;

test/SIL/Parser/apply_with_conformance.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ sil @_TFV4test1S3foofS0_US_1P__FQ_T_ : $@convention(method) <T where T : P> (@in
2222
// CHECK: call
2323
// test.bar (test.S, test.X) -> ()
2424
sil [ossa] @_TF4test3barFTVS_1SVS_1X_T_ : $@convention(thin) (S, X) -> () {
25-
bb0(%0 : @unowned $S, %1 : @unowned $X):
25+
bb0(%0 : $S, %1 : $X):
2626
debug_value %0 : $S // let s // id: %2
2727
debug_value %1 : $X // let x // id: %3
2828
// function_ref test.S.foo (test.S)<A : test.P>(A) -> ()
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: not %sil-opt -verify %s
2+
3+
// Make sure that we error if ossa functions do not parse unless the argument
4+
// has the proper ownership specifier on it.
5+
6+
import Builtin
7+
8+
sil [ossa] @test1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
9+
bb0(%0 : $Builtin.NativeObject): // {{expected-error: SILFunction and SILArgument have mismatching ValueOwnershipKinds. Function type specifies: '@owned'. SIL argument specifies: '@any'.}}
10+
destroy_value %0 : $Builtin.NativeObject
11+
%9999 = tuple()
12+
return %9999 : $()
13+
}
14+
15+
sil [ossa] @test2 : $@convention(thin) (Builtin.Int32) -> () {
16+
bb0(%0 : @owned $Builtin.Int32): // {{expected-error: SILFunction and SILArgument have mismatching ValueOwnershipKinds. Function type specifies: '@any'. SIL argument specifies: '@owned'.}}
17+
%9999 = tuple()
18+
return %9999 : $()
19+
}

test/SIL/Parser/overloaded_member.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class B {
5252
}
5353

5454
sil [ossa] @test_overloaded_subscript : $@convention(thin) (@guaranteed B, B.Index) -> () {
55-
bb0(%0 : $B, %1 : $B.Index):
55+
bb0(%0 : @guaranteed $B, %1 : $B.Index):
5656
%reader = class_method %0 : $B, #B.subscript!read.1 : (B) -> (B.Index) -> (), $@convention(method) @yield_once (B.Index, @guaranteed B) -> @yields @guaranteed B.Element
5757
(%element, %token) = begin_apply %reader(%1, %0) : $@convention(method) @yield_once (B.Index, @guaranteed B) -> @yields @guaranteed B.Element
5858
end_apply %token

test/SIL/Parser/unmanaged.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ bb0(%0 : $*Optional<U>):
1616
}
1717

1818
sil [ossa] @retain_release : $@convention(thin) (@sil_unmanaged Optional<C>) -> () {
19-
bb0(%0 : @unowned $@sil_unmanaged Optional<C>):
19+
bb0(%0 : $@sil_unmanaged Optional<C>):
2020
%1 = unmanaged_to_ref %0 : $@sil_unmanaged Optional<C> to $Optional<C>
2121
unmanaged_retain_value %1 : $Optional<C>
2222
unmanaged_autorelease_value %1 : $Optional<C>
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11

2-
struct X {}
2+
sil_stage raw
3+
4+
import Builtin
5+
6+
struct X {
7+
let x: Builtin.NativeObject
8+
}
39

410
// Make sure that we can deserialize an apply with various parameter calling
511
// conventions.
612
sil [serialized] [ossa] @foo : $@convention(thin) (@in X, @inout X, @in_guaranteed X, @owned X, X, @guaranteed X) -> @out X {
713
bb0(%0 : $*X, %1 : $*X, %2 : $*X, %3 : $*X, %4 : @owned $X, %5 : @unowned $X, %6 : @guaranteed $X):
14+
copy_addr [take] %1 to [initialization] %0 : $*X
15+
destroy_value %4 : $X
816
%9999 = tuple()
917
return %9999 : $()
1018
}

test/SIL/Serialization/Recovery/function.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Types
1313
// CHECK-LABEL: sil @missingParam : $@convention(thin) (SoonToBeMissing) -> () {
1414
// CHECK-RECOVERY-NEGATIVE-NOT: sil [ossa] @missingParam
1515
sil [ossa] @missingParam : $@convention(thin) (SoonToBeMissing) -> () {
16-
entry(%arg : @unowned $SoonToBeMissing):
16+
entry(%arg : $SoonToBeMissing):
1717
%9999 = tuple()
1818
return %9999 : $()
1919
}

test/SIL/Serialization/unmanaged.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class C {}
1616
// CHECK: unmanaged_autorelease_value [[REF]]
1717
// CHECK: unmanaged_release_value [[REF]]
1818
sil [serialized] [ossa] @retain_release : $@convention(thin) (@sil_unmanaged Optional<C>) -> () {
19-
bb0(%0 : @unowned $@sil_unmanaged Optional<C>):
19+
bb0(%0 : $@sil_unmanaged Optional<C>):
2020
%1 = unmanaged_to_ref %0 : $@sil_unmanaged Optional<C> to $Optional<C>
2121
unmanaged_retain_value %1 : $Optional<C>
2222
unmanaged_autorelease_value %1 : $Optional<C>

test/SIL/memory_lifetime.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ bb6:
5656
}
5757

5858
sil [ossa] @test_struct2 : $@convention(thin) (@in Outer, @owned T) -> () {
59-
bb0(%0 : $*Outer, %1 : $T):
59+
bb0(%0 : $*Outer, %1 : @owned $T):
6060
%2 = struct_element_addr %0 : $*Outer, #Outer.x
6161
store %1 to [assign] %2 : $*T
6262
destroy_addr %0 : $*Outer
@@ -122,7 +122,7 @@ bb3:
122122
}
123123

124124
sil [ossa] @test_unreachable_block : $@convention(thin) (@owned T) -> () {
125-
bb0(%0 : $T):
125+
bb0(%0 : @owned $T):
126126
%2 = alloc_stack $T
127127
store %0 to [init] %2 : $*T
128128
br bb2

test/SIL/memory_lifetime_failures.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ bb2(%4 : @owned $Error):
122122

123123
// CHECK: SIL memory lifetime failure in @test_single_block: memory is initialized, but shouldn't
124124
sil [ossa] @test_single_block : $@convention(thin) (@owned T) -> () {
125-
bb0(%0 : $T):
125+
bb0(%0 : @owned $T):
126126
%2 = alloc_stack $T
127127
store %0 to [init] %2 : $*T
128128
dealloc_stack %2 : $*T

test/SILOptimizer/allocbox_to_stack_ownership.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,7 @@ bb3:
10371037
// CHECK: return %{{.*}} : $()
10381038
// CHECK-LABEL: } // end sil function 'deinit_access'
10391039
sil [ossa] @deinit_access : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
1040-
bb0(%0 : @owned $*T, %1 : @owned $*T, %2 : @owned $*T):
1040+
bb0(%0 : $*T, %1 : $*T, %2 : $*T):
10411041
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>, var, name "x"
10421042
%5 = project_box %4 : $<τ_0_0> { var τ_0_0 } <T>, 0
10431043
copy_addr %2 to [initialization] %5 : $*T
@@ -1076,7 +1076,7 @@ bb0(%0 : @owned $*T, %1 : @owned $*T, %2 : @owned $*T):
10761076
// CHECK: return %{{.*}} : $()
10771077
// CHECK-LABEL: } // end sil function 'nodeinit_access'
10781078
sil [ossa] @nodeinit_access : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
1079-
bb0(%0 : @owned $*T, %1 : @owned $*T, %2 : @owned $*T):
1079+
bb0(%0 : $*T, %1 : $*T, %2 : $*T):
10801080
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <T>, var, name "x"
10811081
%5 = project_box %4 : $<τ_0_0> { var τ_0_0 } <T>, 0
10821082
copy_addr %2 to [initialization] %5 : $*T

test/SILOptimizer/devirtualize_ownership.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ bb0(%0 : @guaranteed $Node):
9999

100100
// CHECK-LABEL: sil private [transparent] [noinline] [ossa] @transparent_target
101101
sil private [transparent] [noinline] [ossa] @transparent_target : $@convention(method) (@guaranteed Node) -> Int {
102-
bb0(%0 : @owned $Node):
102+
bb0(%0 : @guaranteed $Node):
103103
%2 = ref_element_addr %0 : $Node, #Node.index
104104
%3 = load [trivial] %2 : $*Int
105105
// CHECK: return

test/SILOptimizer/mandatory_inlining_ownership2.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ bb0(%0 : @owned $Builtin.NativeObject):
486486
// CHECK-NEXT: return
487487
// CHECK: } // end sil function 'test_recursive_nativeobject_baz'
488488
sil [transparent] [ossa] @test_recursive_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
489-
bb0(%0 : $Builtin.NativeObject):
489+
bb0(%0 : @owned $Builtin.NativeObject):
490490
return %0 : $Builtin.NativeObject
491491
}
492492

test/SILOptimizer/opaque_values_mandatory.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ typealias Int = Builtin.Int64
1313
// CHECK: return %0 : $T
1414
// CHECK-LABEL: } // end sil function 'f010_diagnose_identity'
1515
sil hidden [ossa] @f010_diagnose_identity : $@convention(thin) <T> (@in T) -> @out T {
16-
bb0(%0 : $T):
16+
bb0(%0 : @owned $T):
1717
%c = copy_value %0 : $T
1818
destroy_value %0 : $T
1919
return %c : $T
@@ -31,7 +31,7 @@ bb0(%0 : $T):
3131
// CHECK: return %{{.*}} : $()
3232
// CHECK-LABEL: } // end sil function 'f020_assign_inout'
3333
sil hidden [ossa] @f020_assign_inout : $@convention(thin) <T> (@inout T, @in T) -> () {
34-
bb0(%0 : $*T, %1 : $T):
34+
bb0(%0 : $*T, %1 : @owned $T):
3535
%2 = copy_value %1 : $T
3636
assign %2 to %0 : $*T
3737
destroy_value %1 : $T

test/SILOptimizer/silgen_cleanup.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ struct X3 {
158158
// CHECK: end_access [[ACCESS]] : $*X3
159159
// CHECK-LABEL: } // end sil function 'testStoreNontrivial'
160160
sil private [ossa] @testStoreNontrivial : $@convention(thin) (@inout X3, @guaranteed AnyObject) -> () {
161-
bb0(%0 : $*X3, %1 : $AnyObject):
161+
bb0(%0 : $*X3, %1 : @guaranteed $AnyObject):
162162
%4 = copy_value %1 : $AnyObject
163163
%5 = begin_access [modify] [unknown] %0 : $*X3
164164
%6 = struct_element_addr %5 : $*X3, #X3.x2

0 commit comments

Comments
 (0)