Skip to content

Commit 91186d4

Browse files
author
Joe Shajrawi
authored
Merge pull request #8127 from shajrawi/address_enum
Opaque values mode: address-only enum support
2 parents f328581 + 444b59c commit 91186d4

File tree

6 files changed

+98
-5
lines changed

6 files changed

+98
-5
lines changed

include/swift/SIL/TypeLowering.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,9 @@ class TypeConverter {
603603

604604
SILType getLoweredLoadableType(Type t) {
605605
const TypeLowering &ti = getTypeLowering(t);
606-
assert(ti.isLoadable() && "unexpected address-only type");
606+
assert(
607+
(ti.isLoadable() || !SILModuleConventions(M).useLoweredAddresses()) &&
608+
"unexpected address-only type");
607609
return ti.getLoweredType();
608610
}
609611

lib/SILGen/RValue.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ static SILValue implodeTupleValues(ArrayRef<ManagedValue> values,
257257

258258
// To implode an address-only tuple, we need to create a buffer to hold the
259259
// result tuple.
260-
if (loweredType.isAddressOnly(SGF.F.getModule())) {
260+
if (loweredType.isAddressOnly(SGF.F.getModule()) &&
261+
SGF.silConv.useLoweredAddresses()) {
261262
assert(KIND != ImplodeKind::Unmanaged &&
262263
"address-only values are always managed!");
263264
SILValue buffer = SGF.emitTemporaryAllocation(l, loweredType);

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3307,7 +3307,7 @@ ManagedValue SILGenFunction::emitInjectEnum(SILLocation loc,
33073307

33083308
// Easy case -- no payload
33093309
if (!payload) {
3310-
if (enumTy.isLoadable(SGM.M)) {
3310+
if (enumTy.isLoadable(SGM.M) || !silConv.useLoweredAddresses()) {
33113311
return emitManagedRValueWithCleanup(
33123312
B.createEnum(loc, SILValue(), element,
33133313
enumTy.getObjectType()));

lib/SILGen/SILGenConstructor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) {
376376

377377
// Emit the indirect return slot.
378378
std::unique_ptr<Initialization> dest;
379-
if (enumTI.isAddressOnly()) {
379+
if (enumTI.isAddressOnly() && silConv.useLoweredAddresses()) {
380380
auto &AC = getASTContext();
381381
auto VD = new (AC) ParamDecl(/*IsLet*/ false, SourceLoc(), SourceLoc(),
382382
AC.getIdentifier("$return_value"),
@@ -418,7 +418,7 @@ void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) {
418418
scope.pop();
419419
B.createReturn(ReturnLoc, emitEmptyTuple(Loc));
420420
} else {
421-
assert(enumTI.isLoadable());
421+
assert(enumTI.isLoadable() || !silConv.useLoweredAddresses());
422422
SILValue result = mv.forward(*this);
423423
scope.pop();
424424
B.createReturn(ReturnLoc, result);

test/SILGen/opaque_values_silgen.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,29 @@ struct Box<T> {
1414
let t: T
1515
}
1616

17+
protocol EmptyP {}
18+
19+
struct AddressOnlyStruct : EmptyP {}
20+
1721
func s010_hasVarArg(_ args: Any...) {}
1822

23+
// Tests Address only enums's construction
24+
// CHECK-LABEL: sil shared [transparent] @_T020opaque_values_silgen15AddressOnlyEnumO4mereAcA6EmptyP_pcACmF : $@convention(method) (@in EmptyP, @thin AddressOnlyEnum.Type) -> @out AddressOnlyEnum {
25+
// CHECK: bb0([[ARG0:%.*]] : $EmptyP, [[ARG1:%.*]] : $@thin AddressOnlyEnum.Type):
26+
// CHECK: [[RETVAL:%.*]] = enum $AddressOnlyEnum, #AddressOnlyEnum.mere!enumelt.1, [[ARG0]] : $EmptyP
27+
// CHECK: return [[RETVAL]] : $AddressOnlyEnum
28+
// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen15AddressOnlyEnumO4mereAcA6EmptyP_pcACmF'
29+
// CHECK-LABEL: sil shared [transparent] [thunk] @_T020opaque_values_silgen15AddressOnlyEnumO4mereAcA6EmptyP_pcACmFTc : $@convention(thin) (@thin AddressOnlyEnum.Type) -> @owned @callee_owned (@in EmptyP) -> @out AddressOnlyEnum {
30+
// CHECK: bb0([[ARG:%.*]] : $@thin AddressOnlyEnum.Type):
31+
// CHECK: [[RETVAL:%.*]] = partial_apply {{.*}}([[ARG]]) : $@convention(method) (@in EmptyP, @thin AddressOnlyEnum.Type) -> @out AddressOnlyEnum
32+
// CHECK: return [[RETVAL]] : $@callee_owned (@in EmptyP) -> @out AddressOnlyEnum
33+
// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen15AddressOnlyEnumO4mereAcA6EmptyP_pcACmFTc'
34+
enum AddressOnlyEnum {
35+
case nought
36+
case mere(EmptyP)
37+
case phantom(AddressOnlyStruct)
38+
}
39+
1940
// Test that we still use addresses when dealing with array initialization
2041
// ---
2142
// CHECK-LABEL: sil @_T020opaque_values_silgen21s020_______callVarArgyyF : $@convention(thin) () -> () {
@@ -411,6 +432,34 @@ func s250_________testBoxT() {
411432
let _ = Box(t: 42)
412433
}
413434

435+
// Tests Address only enums
436+
// ---
437+
// CHECK-LABEL: sil hidden @_T020opaque_values_silgen21s260_______AOnly_enumyAA17AddressOnlyStructVF : $@convention(thin) (AddressOnlyStruct) -> () {
438+
// CHECK: bb0([[ARG:%.*]] : $AddressOnlyStruct):
439+
// CHECK: [[MTYPE1:%.*]] = metatype $@thin AddressOnlyEnum.Type
440+
// CHECK: [[APPLY1:%.*]] = apply {{.*}}([[MTYPE1]]) : $@convention(thin) (@thin AddressOnlyEnum.Type) -> @owned @callee_owned (@in EmptyP) -> @out AddressOnlyEnum
441+
// CHECK: destroy_value [[APPLY1]]
442+
// CHECK: [[MTYPE2:%.*]] = metatype $@thin AddressOnlyEnum.Type
443+
// CHECK: [[ENUM1:%.*]] = enum $AddressOnlyEnum, #AddressOnlyEnum.nought!enumelt
444+
// CHECK: [[MTYPE3:%.*]] = metatype $@thin AddressOnlyEnum.Type
445+
// CHECK: [[INIT_OPAQUE:%.*]] = init_existential_opaque [[ARG]] : $AddressOnlyStruct, $AddressOnlyStruct, $EmptyP
446+
// CHECK: [[ENUM2:%.*]] = enum $AddressOnlyEnum, #AddressOnlyEnum.mere!enumelt.1, [[INIT_OPAQUE]] : $EmptyP
447+
// CHECK: destroy_value [[ENUM2]]
448+
// CHECK: [[MTYPE4:%.*]] = metatype $@thin AddressOnlyEnum.Type
449+
// CHECK: [[ENUM3:%.*]] = enum $AddressOnlyEnum, #AddressOnlyEnum.phantom!enumelt.1, [[ARG]] : $AddressOnlyStruct
450+
// CHECK: return %{{.*}} : $()
451+
// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen21s260_______AOnly_enumyAA17AddressOnlyStructVF'
452+
func s260_______AOnly_enum(_ s: AddressOnlyStruct) {
453+
_ = AddressOnlyEnum.mere
454+
455+
_ = AddressOnlyEnum.nought
456+
457+
_ = AddressOnlyEnum.mere(s)
458+
459+
_ = AddressOnlyEnum.phantom(s)
460+
}
461+
462+
414463
// Tests conditional value casts and correspondingly generated reabstraction thunk, with <T> types
415464
// ---
416465
// CHECK-LABEL: sil hidden @_T020opaque_values_silgen21s999_____condTFromAnyyyp_xtlF : $@convention(thin) <T> (@in Any, @in T) -> () {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %target-swift-frontend -enable-sil-opaque-values -emit-sorted-sil -Xllvm -new-mangling-for-tests -Xllvm -sil-full-demangle -parse-stdlib -parse-as-library -emit-silgen -module-name Swift %s | %FileCheck %s
2+
// UNSUPPORTED: resilient_stdlib
3+
4+
precedencegroup AssignmentPrecedence { assignment: true }
5+
6+
enum Optional<Wrapped> {
7+
case none
8+
case some(Wrapped)
9+
}
10+
11+
protocol EmptyP {}
12+
13+
struct String { var ptr: Builtin.NativeObject }
14+
15+
// Init of Empty protocol + Builtin.NativeObject enum (including opaque tuples as a return value)
16+
// ---
17+
// CHECK-LABEL: sil shared [transparent] [thunk] @_TFOs9PAndSEnum1AFMS_FTPs6EmptyP_SS_S_ : $@convention(thin) (@thin PAndSEnum.Type) -> @owned @callee_owned (@in EmptyP, @owned String) -> @out PAndSEnum {
18+
// CHECK: bb0([[ARG:%.*]] : $@thin PAndSEnum.Type):
19+
// CHECK: [[RETVAL:%.*]] = partial_apply {{.*}}([[ARG]]) : $@convention(method) (@in EmptyP, @owned String, @thin PAndSEnum.Type) -> @out PAndSEnum
20+
// CHECK: return [[RETVAL]] : $@callee_owned (@in EmptyP, @owned String) -> @out PAndSEnum
21+
// CHECK-LABEL: } // end sil function '_TFOs9PAndSEnum1AFMS_FTPs6EmptyP_SS_S_'
22+
// CHECK-LABEL: sil shared [transparent] @_TFOs9PAndSEnum1AfMS_FTPs6EmptyP_SS_S_ : $@convention(method) (@in EmptyP, @owned String, @thin PAndSEnum.Type) -> @out PAndSEnum {
23+
// CHECK: bb0([[ARG0:%.*]] : $EmptyP, [[ARG1:%.*]] : $String, [[ARG2:%.*]] : $@thin PAndSEnum.Type):
24+
// CHECK: [[RTUPLE:%.*]] = tuple ([[ARG0]] : $EmptyP, [[ARG1]] : $String)
25+
// CHECK: [[RETVAL:%.*]] = enum $PAndSEnum, #PAndSEnum.A!enumelt.1, [[RTUPLE]] : $(EmptyP, String)
26+
// CHECK: return [[RETVAL]] : $PAndSEnum
27+
// CHECK-LABEL: } // end sil function '_TFOs9PAndSEnum1AfMS_FTPs6EmptyP_SS_S_'
28+
enum PAndSEnum { case A(EmptyP, String) }
29+
30+
// Tests Empty protocol + Builtin.NativeObject enum (including opaque tuples as a return value)
31+
// ---
32+
// CHECK-LABEL: sil hidden @_TFs21s010______PAndS_casesFT_T_ : $@convention(thin) () -> () {
33+
// CHECK: bb0:
34+
// CHECK: [[MTYPE:%.*]] = metatype $@thin PAndSEnum.Type
35+
// CHECK: [[EAPPLY:%.*]] = apply {{.*}}([[MTYPE]]) : $@convention(thin) (@thin PAndSEnum.Type) -> @owned @callee_owned (@in EmptyP, @owned String) -> @out PAndSEnum
36+
// CHECK: destroy_value [[EAPPLY]]
37+
// CHECK: return %{{.*}} : $()
38+
// CHECK-LABEL: } // end sil function '_TFs21s010______PAndS_casesFT_T_'
39+
func s010______PAndS_cases() {
40+
_ = PAndSEnum.A
41+
}

0 commit comments

Comments
 (0)