mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
OpaqueValues: add support for property wrappers
resolves rdar://163071245
This commit is contained in:
@@ -515,6 +515,9 @@ public:
|
||||
- getNumIndirectSILErrorResults()];
|
||||
}
|
||||
|
||||
/// WARNING: Do not use this from SILGen!
|
||||
/// Use methods such as `isSILIndirect` or query the ParameterInfo instead.
|
||||
///
|
||||
/// Return the SIL argument convention of apply/entry argument at
|
||||
/// the given argument index.
|
||||
SILArgumentConvention getSILArgumentConvention(unsigned index) const;
|
||||
|
||||
@@ -87,6 +87,8 @@ SILParameterInfo SILFunctionArgument::getKnownParameterInfo() const {
|
||||
return getFunction()->getConventions().getParamInfoForSILArg(getIndex());
|
||||
}
|
||||
|
||||
/// WARNING: Do not use this from SILGen!
|
||||
/// Use methods such as `isSILIndirect` or query the ParameterInfo instead.
|
||||
SILArgumentConvention
|
||||
SILFunctionConventions::getSILArgumentConvention(unsigned index) const {
|
||||
assert(index < getNumSILArguments());
|
||||
|
||||
@@ -3189,9 +3189,9 @@ public:
|
||||
CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
|
||||
SILFunctionConventions initConv(initTy, AI->getModule());
|
||||
|
||||
require(initConv.getNumIndirectSILResults() ==
|
||||
require(initConv.getResults().size() ==
|
||||
AI->getNumInitializedProperties(),
|
||||
"init function has invalid number of indirect results");
|
||||
"init function has invalid number of results");
|
||||
checkAssigOrInitInstAccessorArgs(Src->getType(), initConv);
|
||||
}
|
||||
|
||||
|
||||
@@ -1822,35 +1822,46 @@ void SILGenFunction::emitPropertyWrappedFieldInitAccessor(
|
||||
RegularLocation Loc(value);
|
||||
Loc.markAutoGenerated();
|
||||
|
||||
auto loweredFuncDeclTy = F.getLoweredFunctionType();
|
||||
bool isLocalContext = vd->getDeclContext()->isLocalContext();
|
||||
|
||||
auto createArgument = [&](VarDecl *property, SILType type,
|
||||
bool markUninitialized = false) {
|
||||
auto *arg = ParamDecl::createImplicit(
|
||||
getASTContext(), property->getBaseIdentifier(),
|
||||
property->getBaseIdentifier(), property->getInterfaceType(),
|
||||
declContext, ParamSpecifier::InOut);
|
||||
|
||||
RegularLocation loc(property);
|
||||
loc.markAutoGenerated();
|
||||
|
||||
SILValue argValue = F.begin()->createFunctionArgument(type, arg);
|
||||
if (markUninitialized) {
|
||||
argValue = B.createMarkUninitializedOut(loc, argValue);
|
||||
}
|
||||
|
||||
VarLocs[arg] = VarLoc(argValue, SILAccessEnforcement::Static);
|
||||
InitAccessorArgumentMappings[property] = arg;
|
||||
};
|
||||
|
||||
// Emit @out backing storage argument
|
||||
auto backingStorage = vd->getPropertyWrapperBackingProperty();
|
||||
auto backingStorageTy = getSILTypeInContext(
|
||||
loweredFuncDeclTy->getResults()[0], loweredFuncDeclTy);
|
||||
createArgument(backingStorage, backingStorageTy, /*markUninitialized=*/true);
|
||||
Type returnTy = vd->getPropertyWrapperBackingPropertyType();
|
||||
|
||||
// Emit `newValue` argument
|
||||
/// This thunk uses its own return convention, unlike a usual function,
|
||||
/// by always returning its result indirect, even if the type is trivial.
|
||||
///
|
||||
/// Because of that, much of the work that would normally be handled in SILGen
|
||||
/// using standard function conventions is done manually here, when
|
||||
/// -enable-sil-opaque-values is disabled. Part of the reason for this is
|
||||
/// that calls to this accessor are lowered after DefiniteInitialization.
|
||||
if (useLoweredAddresses()) {
|
||||
returnTy = TupleType::getEmpty(F.getASTContext());
|
||||
|
||||
auto loweredFuncDeclTy = F.getLoweredFunctionType();
|
||||
auto createArgument = [&](VarDecl *property, SILType type,
|
||||
bool markUninitialized = false) {
|
||||
auto *arg = ParamDecl::createImplicit(
|
||||
getASTContext(), property->getBaseIdentifier(),
|
||||
property->getBaseIdentifier(), property->getInterfaceType(),
|
||||
declContext, ParamSpecifier::InOut);
|
||||
|
||||
RegularLocation loc(property);
|
||||
loc.markAutoGenerated();
|
||||
|
||||
SILValue argValue = F.begin()->createFunctionArgument(type, arg);
|
||||
if (markUninitialized) {
|
||||
argValue = B.createMarkUninitializedOut(loc, argValue);
|
||||
}
|
||||
|
||||
VarLocs[arg] = VarLoc(argValue, SILAccessEnforcement::Static);
|
||||
InitAccessorArgumentMappings[property] = arg;
|
||||
};
|
||||
|
||||
// Emit @out backing storage argument
|
||||
auto backingStorageTy = getSILTypeInContext(
|
||||
loweredFuncDeclTy->getResults()[0], loweredFuncDeclTy);
|
||||
createArgument(backingStorage, backingStorageTy, /*markUninitialized=*/true);
|
||||
}
|
||||
|
||||
// Create the `newValue` argument
|
||||
ParameterList *params = nullptr;
|
||||
auto newValueParam = new (ctx)
|
||||
ParamDecl(SourceLoc(), SourceLoc(), ctx.getIdentifier("$input_value"),
|
||||
@@ -1864,9 +1875,10 @@ void SILGenFunction::emitPropertyWrappedFieldInitAccessor(
|
||||
|
||||
// Nominal contexts have an extra trailing metatype argument,
|
||||
// local contexts do not
|
||||
const bool isLocalContext = vd->getDeclContext()->isLocalContext();
|
||||
auto numIgnoredParams = isLocalContext ? 0 : 1;
|
||||
emitBasicProlog(declContext, params,
|
||||
/*selfParam=*/nullptr, TupleType::getEmpty(F.getASTContext()),
|
||||
/*selfParam=*/nullptr, returnTy,
|
||||
/*errorType=*/std::nullopt,
|
||||
/*throwsLoc=*/SourceLoc(),
|
||||
/*ignored parameters*/ numIgnoredParams);
|
||||
@@ -1875,9 +1887,14 @@ void SILGenFunction::emitPropertyWrappedFieldInitAccessor(
|
||||
if (!isLocalContext)
|
||||
emitConstructorMetatypeArg(*this, vd);
|
||||
|
||||
prepareEpilog(declContext, TupleType::getEmpty(F.getASTContext()),
|
||||
prepareEpilog(declContext, returnTy,
|
||||
std::nullopt, CleanupLocation(Loc));
|
||||
|
||||
if (EmitProfilerIncrement)
|
||||
emitProfilerIncrement(value);
|
||||
|
||||
FullExpr scope(Cleanups, CleanupLocation(value));
|
||||
|
||||
// Create an opaque value binding that maps 'newValue' to the wrapper's
|
||||
// wrappedValue AST placeholder. This makes the argument available when
|
||||
// init(wrappedValue:) is emitted
|
||||
@@ -1889,16 +1906,19 @@ void SILGenFunction::emitPropertyWrappedFieldInitAccessor(
|
||||
maybeEmitValueOfLocalVarDecl(newValueParam, AccessKind::Read));
|
||||
assert(value == initInfo.getInitFromWrappedValue());
|
||||
|
||||
// Prepare InitializationPtr for the @out return buffer
|
||||
FullExpr scope(Cleanups, CleanupLocation(value));
|
||||
auto backingStorageArg = InitAccessorArgumentMappings[backingStorage];
|
||||
auto backingStorageAddr = VarLocs[backingStorageArg].value;
|
||||
InitializationPtr init(new KnownAddressInitialization(backingStorageAddr));
|
||||
if (useLoweredAddresses()) {
|
||||
// Prepare InitializationPtr for the @out return buffer
|
||||
auto backingStorageArg = InitAccessorArgumentMappings[backingStorage];
|
||||
auto backingStorageAddr = VarLocs[backingStorageArg].value;
|
||||
InitializationPtr init(new KnownAddressInitialization(backingStorageAddr));
|
||||
|
||||
// Intialize the @out buffer with the given expression
|
||||
emitExprInto(value, init.get());
|
||||
// Intialize the @out buffer with the given expression
|
||||
emitExprInto(value, init.get());
|
||||
} else {
|
||||
emitReturnExpr(Loc, value);
|
||||
}
|
||||
|
||||
// Emit epilog/cleanups
|
||||
emitEpilog(Loc);
|
||||
mergeCleanupBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1883,9 +1883,10 @@ SILGenFunction::emitApplyOfSetterToBase(SILLocation loc, SILDeclRef setter,
|
||||
assert(base);
|
||||
|
||||
SILValue capturedBase;
|
||||
unsigned argIdx = setterConv.getNumSILArguments() - 1;
|
||||
unsigned argIdx = setterConv.getSILArgIndexOfSelf();
|
||||
auto paramInfo = setterConv.getParamInfoForSILArg(argIdx);
|
||||
|
||||
if (setterConv.getSILArgumentConvention(argIdx).isInoutConvention()) {
|
||||
if (paramInfo.isIndirectMutating()) {
|
||||
capturedBase = base.getValue();
|
||||
} else if (base.getType().isAddress() &&
|
||||
base.getType().getObjectType() ==
|
||||
@@ -1975,9 +1976,9 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue,
|
||||
SILFunctionConventions initConv(initTy, SGM.M);
|
||||
|
||||
auto newValueArgIdx = initConv.getSILArgIndexOfFirstParam();
|
||||
auto newValueParamInfo = initConv.getParamInfoForSILArg(newValueArgIdx);
|
||||
// If we need the argument in memory, materialize an address.
|
||||
if (initConv.getSILArgumentConvention(newValueArgIdx)
|
||||
.isIndirectConvention() &&
|
||||
if (initConv.isSILIndirect(newValueParamInfo) &&
|
||||
!newValue.getType().isAddress()) {
|
||||
newValue = newValue.materialize(*this, loc);
|
||||
}
|
||||
|
||||
@@ -1528,8 +1528,10 @@ namespace {
|
||||
return cast<AccessorDecl>(Accessor.getFuncDecl());
|
||||
}
|
||||
|
||||
ManagedValue emitValue(SILGenFunction &SGF, SILLocation loc, VarDecl *field,
|
||||
ArgumentSource &&value, AccessorKind accessorKind) {
|
||||
ManagedValue emitValueForAssignOrInit(SILGenFunction &SGF, SILLocation loc,
|
||||
VarDecl *field,
|
||||
ArgumentSource &&value,
|
||||
AccessorKind accessorKind) {
|
||||
auto accessorInfo = SGF.getConstantInfo(
|
||||
SGF.getTypeExpansionContext(),
|
||||
SILDeclRef(field->getOpaqueAccessor(accessorKind)));
|
||||
@@ -1553,7 +1555,8 @@ namespace {
|
||||
assert(value.isRValue());
|
||||
ManagedValue Mval =
|
||||
std::move(value).asKnownRValue(SGF).getAsSingleValue(SGF, loc);
|
||||
auto param = accessorTy->getParameters()[0];
|
||||
auto paramIdx = accessorConv.getSILArgIndexOfFirstParam();
|
||||
auto param = accessorConv.getParamInfoForSILArg(paramIdx);
|
||||
SILType loweredSubstArgType = Mval.getType();
|
||||
if (param.isIndirectInOut()) {
|
||||
loweredSubstArgType =
|
||||
@@ -1572,11 +1575,8 @@ namespace {
|
||||
fieldTy->getCanonicalType());
|
||||
}
|
||||
|
||||
auto newValueArgIdx = accessorConv.getNumIndirectSILResults();
|
||||
// If we need the argument in memory, materialize an address.
|
||||
if (accessorConv.getSILArgumentConvention(newValueArgIdx)
|
||||
.isIndirectConvention() &&
|
||||
!Mval.getType().isAddress()) {
|
||||
if (accessorConv.isSILIndirect(param) && !Mval.getType().isAddress()) {
|
||||
Mval = Mval.materialize(SGF, loc);
|
||||
}
|
||||
|
||||
@@ -1610,7 +1610,7 @@ namespace {
|
||||
override {
|
||||
VarDecl *field = cast<VarDecl>(Storage);
|
||||
auto Mval =
|
||||
emitValue(SGF, loc, field, std::move(value), AccessorKind::Init);
|
||||
emitValueForAssignOrInit(SGF, loc, field, std::move(value), AccessorKind::Init);
|
||||
SGF.emitAssignOrInit(loc, base, field, Mval, Substitutions);
|
||||
}
|
||||
|
||||
@@ -1875,7 +1875,7 @@ namespace {
|
||||
|
||||
// Create the assign_or_init SIL instruction
|
||||
auto Mval =
|
||||
emitValue(SGF, loc, field, std::move(value), AccessorKind::Set);
|
||||
emitValueForAssignOrInit(SGF, loc, field, std::move(value), AccessorKind::Set);
|
||||
auto selfOrLocal = selfMetatype ? base.getValue() : proj.forward(SGF);
|
||||
SGF.B.createAssignOrInit(loc, field, selfOrLocal, Mval.forward(SGF),
|
||||
initFn.getValue(), setterFn,
|
||||
|
||||
@@ -1331,11 +1331,9 @@ static void emitCaptureArguments(SILGenFunction &SGF,
|
||||
case CaptureKind::Immutable: {
|
||||
auto argIndex = SGF.F.begin()->getNumArguments();
|
||||
// Non-escaping stored decls are captured as the address of the value.
|
||||
auto argConv = SGF.F.getConventions().getSILArgumentConvention(argIndex);
|
||||
bool isInOut = (argConv == SILArgumentConvention::Indirect_Inout ||
|
||||
argConv == SILArgumentConvention::Indirect_InoutAliasable);
|
||||
auto param = SGF.F.getConventions().getParamInfoForSILArg(argIndex);
|
||||
if (SGF.F.getConventions().isSILIndirect(param)) {
|
||||
auto fnConv = SGF.F.getConventions();
|
||||
auto paramInfo = fnConv.getParamInfoForSILArg(argIndex);
|
||||
if (fnConv.isSILIndirect(paramInfo)) {
|
||||
ty = ty.getAddressType();
|
||||
}
|
||||
auto *fArg = SGF.F.begin()->createFunctionArgument(ty, VD);
|
||||
@@ -1343,7 +1341,8 @@ static void emitCaptureArguments(SILGenFunction &SGF,
|
||||
arg = SILValue(fArg);
|
||||
|
||||
if (isNoImplicitCopy && !arg->getType().isMoveOnly()) {
|
||||
switch (argConv) {
|
||||
// FIXME: this incompatible with -enable-sil-opaque-values
|
||||
switch (fnConv.getSILArgumentConvention(argIndex)) {
|
||||
case SILArgumentConvention::Indirect_Inout:
|
||||
case SILArgumentConvention::Indirect_InoutAliasable:
|
||||
case SILArgumentConvention::Indirect_In:
|
||||
@@ -1377,6 +1376,7 @@ static void emitCaptureArguments(SILGenFunction &SGF,
|
||||
// in SIL since it is illegal to capture an inout value in an escaping
|
||||
// closure. The later code knows how to handle that we have the
|
||||
// mark_unresolved_non_copyable_value here.
|
||||
bool isInOut = paramInfo.isIndirectMutating();
|
||||
if (isInOut && arg->getType().isMoveOnly()) {
|
||||
arg = SGF.B.createMarkUnresolvedNonCopyableValueInst(
|
||||
Loc, arg,
|
||||
|
||||
@@ -206,8 +206,8 @@ lowerAssignOrInitInstruction(SILBuilderWithScope &b,
|
||||
|
||||
auto inLocalContext =
|
||||
inst->getProperty()->getDeclContext()->isLocalContext();
|
||||
auto selfOrLocalValue = inst->getSelfOrLocalOperand();
|
||||
bool isRefSelf =
|
||||
const auto selfOrLocalValue = inst->getSelfOrLocalOperand();
|
||||
const bool isRefSelf =
|
||||
selfOrLocalValue->getType().getASTType()->mayHaveSuperclass();
|
||||
|
||||
auto emitFieldReference = [&](SILValue selfRef, VarDecl *field,
|
||||
@@ -225,40 +225,58 @@ lowerAssignOrInitInstruction(SILBuilderWithScope &b,
|
||||
return fieldRef;
|
||||
};
|
||||
|
||||
SmallVector<SILValue> arguments;
|
||||
/// Returns the reference of self ready for modification, and a flag
|
||||
/// indicating whether a begin_access was emitted that must be ended.
|
||||
auto emitBeginModifyOfSelf = [&]() -> std::pair<SILValue, bool> {
|
||||
if (isRefSelf)
|
||||
return {b.emitBeginBorrowOperation(loc, selfOrLocalValue), false};
|
||||
|
||||
// First, emit all of the properties listed in `initializes`. They
|
||||
// are passed as indirect results.
|
||||
SILValue selfRef = nullptr;
|
||||
bool needInsertEndAccess = false;
|
||||
if (inLocalContext) {
|
||||
// add the local projection which is for the _x backing local storage
|
||||
arguments.push_back(selfOrLocalValue);
|
||||
} else {
|
||||
if (isRefSelf) {
|
||||
selfRef = b.emitBeginBorrowOperation(loc, selfOrLocalValue);
|
||||
} else if (isa<BeginAccessInst>(selfOrLocalValue)) {
|
||||
// Don't insert an access scope if there is already one. This avoids
|
||||
// inserting a dynamic access check when the parent is static (and therefore
|
||||
// can be statically enforced).
|
||||
selfRef = selfOrLocalValue;
|
||||
}
|
||||
else {
|
||||
selfRef =
|
||||
b.createBeginAccess(loc, selfOrLocalValue, SILAccessKind::Modify,
|
||||
SILAccessEnforcement::Dynamic,
|
||||
/*noNestedConflict=*/false,
|
||||
/*fromBuiltin=*/false);
|
||||
needInsertEndAccess = true;
|
||||
// Don't insert an access scope if there is already one. This avoids
|
||||
// inserting a dynamic access check when the parent is static (and
|
||||
// therefore can be statically enforced).
|
||||
if (auto *bai = dyn_cast<BeginAccessInst>(selfOrLocalValue)) {
|
||||
bai->setAccessKind(SILAccessKind::Modify);
|
||||
return {selfOrLocalValue, false};
|
||||
}
|
||||
|
||||
unsigned index = 0;
|
||||
inst->forEachInitializedProperty([&](VarDecl *property) {
|
||||
arguments.push_back(emitFieldReference(
|
||||
selfRef, property,
|
||||
/*emitDestroy=*/inst->isPropertyAlreadyInitialized(index)));
|
||||
index++;
|
||||
});
|
||||
return {b.createBeginAccess(loc, selfOrLocalValue,
|
||||
SILAccessKind::Modify,
|
||||
SILAccessEnforcement::Dynamic,
|
||||
/*noNestedConflict=*/false,
|
||||
/*fromBuiltin=*/false),
|
||||
/*needsEndAccess=*/true};
|
||||
};
|
||||
|
||||
auto initializeAddress = [&b](SILLocation loc, SILValue src, SILValue dest) {
|
||||
ASSERT(dest->getType().isAddress());
|
||||
auto qualifier = src->getType().isTrivial(b.getFunction())
|
||||
? StoreOwnershipQualifier::Trivial
|
||||
: StoreOwnershipQualifier::Init;
|
||||
b.createStore(loc, src, dest, qualifier);
|
||||
};
|
||||
|
||||
// Set-up the arguments for the apply.
|
||||
SmallVector<SILValue> arguments;
|
||||
SILValue selfRef = nullptr;
|
||||
bool needInsertEndAccess = false;
|
||||
|
||||
if (convention.useLoweredAddresses()) {
|
||||
// First, emit all of the properties listed in `initializes`. They
|
||||
// are passed as indirect results.
|
||||
if (inLocalContext) {
|
||||
// add the local projection which is for the _x backing local storage
|
||||
arguments.push_back(selfOrLocalValue);
|
||||
} else {
|
||||
std::tie(selfRef, needInsertEndAccess) = emitBeginModifyOfSelf();
|
||||
|
||||
unsigned index = 0;
|
||||
inst->forEachInitializedProperty([&](VarDecl *property) {
|
||||
arguments.push_back(emitFieldReference(
|
||||
selfRef, property,
|
||||
/*emitDestroy=*/inst->isPropertyAlreadyInitialized(index)));
|
||||
index++;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Now emit `initialValue` which is the only argument specified
|
||||
@@ -270,7 +288,40 @@ lowerAssignOrInitInstruction(SILBuilderWithScope &b,
|
||||
for (auto *property : inst->getAccessedProperties())
|
||||
arguments.push_back(emitFieldReference(selfRef, property));
|
||||
|
||||
b.createApply(loc, initFn, SubstitutionMap(), arguments);
|
||||
|
||||
// Actually emit the apply.
|
||||
auto apply = b.createApply(loc, initFn, SubstitutionMap(), arguments);
|
||||
ASSERT(apply->getNumResults() == 1 && "multi-result not handled yet");
|
||||
|
||||
|
||||
// Handle direct results in the case of -enable-sil-opaque-values
|
||||
if (!convention.useLoweredAddresses()) {
|
||||
// Write the result(s) to the field(s) to be initialized.
|
||||
if (inLocalContext) {
|
||||
initializeAddress(loc, apply->getResult(0), selfOrLocalValue);
|
||||
} else {
|
||||
std::tie(selfRef, needInsertEndAccess) = emitBeginModifyOfSelf();
|
||||
|
||||
SILValue result = apply->getResult(0);
|
||||
|
||||
ASSERT(!result->getType().isTuple() && "insert destructure_tuple?");
|
||||
|
||||
SmallVector<SILValue> results;
|
||||
results.push_back(result);
|
||||
|
||||
ASSERT(results.size() == inst->getNumInitializedProperties());
|
||||
|
||||
unsigned index = 0;
|
||||
inst->forEachInitializedProperty([&](VarDecl *property) {
|
||||
auto fieldRef = emitFieldReference(
|
||||
selfRef, property,
|
||||
/*emitDestroy=*/inst->isPropertyAlreadyInitialized(index));
|
||||
|
||||
initializeAddress(loc, results[index], fieldRef);
|
||||
index++;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (selfRef) {
|
||||
if (isRefSelf) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %target-run-simple-swift | %FileCheck %s
|
||||
// RUN: %target-run-simple-swift(-Xfrontend -enable-sil-opaque-values) | %FileCheck %s
|
||||
// REQUIRES: executable_test
|
||||
|
||||
protocol Observed: AnyObject {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -emit-module -o %t -enable-library-evolution %S/Inputs/property_wrapper_defs.swift
|
||||
// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -primary-file %s -I %t | %FileCheck %s
|
||||
// RUN: %target-swift-emit-silgen -sil-verify-all -Xllvm -sil-print-types -primary-file %s -I %t | %FileCheck %s --check-prefixes CHECK,ADR
|
||||
|
||||
// RUN: %target-swift-frontend -emit-module -o %t -enable-library-evolution %S/Inputs/property_wrapper_defs.swift -enable-sil-opaque-values
|
||||
// RUN: %target-swift-emit-silgen -sil-verify-all -Xllvm -sil-print-types -primary-file %s -I %t -enable-sil-opaque-values | %FileCheck %s --check-prefixes CHECK,OV
|
||||
|
||||
import property_wrapper_defs
|
||||
|
||||
@propertyWrapper
|
||||
@@ -58,18 +62,22 @@ func forceHasMemberwiseInit() {
|
||||
|
||||
// variable initialization expression of HasMemberwiseInit._x
|
||||
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers17HasMemberwiseInitV2_x33_{{.*}}AA7WrapperVySbGvpfi : $@convention(thin) <T where T : DefaultInit> () -> Wrapper<Bool> {
|
||||
// CHECK: bb0:
|
||||
// CHECK: integer_literal $Builtin.Int1, 0
|
||||
// CHECK-NOT: return
|
||||
// CHECK: function_ref @$sSb22_builtinBooleanLiteralSbBi1__tcfC : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool
|
||||
// CHECK-NOT: return
|
||||
// CHECK: function_ref @$s17property_wrappers7WrapperV5valueACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin Wrapper<τ_0_0>.Type) -> @out Wrapper<τ_0_0> // user: %9
|
||||
// CHECK: function_ref @$s17property_wrappers7WrapperV5valueACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin Wrapper<τ_0_0>.Type) -> @out Wrapper<τ_0_0>
|
||||
// CHECK: return {{%.*}} : $Wrapper<Bool>
|
||||
|
||||
// variable initialization expression of HasMemberwiseInit.$y
|
||||
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers17HasMemberwiseInitV2_y33_{{.*}}23WrapperWithInitialValueVyxGvpfi : $@convention(thin) <T where T : DefaultInit> () -> @out
|
||||
// CHECK: bb0(%0 : $*T):
|
||||
// ADR: bb0(%0 : $*T):
|
||||
// OV: bb0:
|
||||
// CHECK-NOT: return
|
||||
// CHECK: witness_method $T, #DefaultInit.init!allocator : <Self where Self : DefaultInit> (Self.Type) -> () -> Self : $@convention(witness_method: DefaultInit) <τ_0_0 where τ_0_0 : DefaultInit> (@thick τ_0_0.Type) -> @out τ_0_0
|
||||
// ADR: return {{%.*}} : $()
|
||||
// OV: return {{%.*}} : $T
|
||||
|
||||
// variable initialization expression of HasMemberwiseInit._z
|
||||
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers17HasMemberwiseInitV2_z33_{{.*}}23WrapperWithInitialValueVySiGvpfi : $@convention(thin) <T where T : DefaultInit> () -> WrapperWithInitialValue<Int> {
|
||||
@@ -78,6 +86,7 @@ func forceHasMemberwiseInit() {
|
||||
// CHECK: integer_literal $Builtin.IntLiteral, 17
|
||||
// CHECK-NOT: return
|
||||
// CHECK: function_ref @$s17property_wrappers23WrapperWithInitialValueV07wrappedF0ACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin WrapperWithInitialValue<τ_0_0>.Type) -> @out WrapperWithInitialValue<τ_0_0>
|
||||
// CHECK: return {{%.*}} : $WrapperWithInitialValue<Int>
|
||||
|
||||
// variable initialization expression of HasMemberwiseInit._p
|
||||
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers17HasMemberwiseInitV2_p33_{{.*}}23WrapperWithInitialValueVySbGvpfi : $@convention(thin) <T where T : DefaultInit> () -> Bool {
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
// RUN: %target-codesign %t/a.out
|
||||
// RUN: %target-run %t/a.out | %FileCheck %s
|
||||
|
||||
// RUN: %target-build-swift %s -Xfrontend -enable-sil-opaque-values -o %t/a.out
|
||||
// RUN: %target-codesign %t/a.out
|
||||
// RUN: %target-run %t/a.out | %FileCheck %s
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
@propertyWrapper
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %target-swift-frontend -emit-sil -verify %s
|
||||
// RUN: %target-swift-frontend -enable-sil-opaque-values -emit-sil -verify %s
|
||||
|
||||
@propertyWrapper
|
||||
final class ClassWrapper<T> {
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
// RUN: %target-codesign %t/a.out
|
||||
// RUN: %target-run %t/a.out
|
||||
|
||||
// RUN: %target-build-swift %s -Xfrontend -enable-sil-opaque-values -o %t/a.out
|
||||
// RUN: %target-codesign %t/a.out
|
||||
// RUN: %target-run %t/a.out
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
import StdlibUnittest
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-swift-frontend -enable-sil-opaque-values -parse-as-library -emit-sil -O %s | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -sil-verify-all -enable-sil-opaque-values -parse-as-library -emit-sil -O %s | %FileCheck %s
|
||||
|
||||
// Verify the arguments. When AccessPathVerification runs, it will be checked
|
||||
// that the ParamDecl that AddressLowering synthesizes has a specifier
|
||||
@@ -9,3 +9,17 @@
|
||||
public func min<T: Comparable>(_ x: T, _ y: T) -> T {
|
||||
return y < x ? y : x
|
||||
}
|
||||
|
||||
|
||||
// This example use to produce invalid SIL after RawSILInstLowering of assign_or_init
|
||||
@propertyWrapper
|
||||
struct WrapperWithInitialValue<T> {
|
||||
var wrappedValue: T
|
||||
}
|
||||
public protocol TestProtocol {}
|
||||
public class TestClass<T> {
|
||||
@WrapperWithInitialValue var value: T
|
||||
init<U: TestProtocol>(value: T, protocol: U) {
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-build-swift %s -module-name=a -o %t/a.out
|
||||
// RUN: %target-codesign %t/a.out
|
||||
// RUN: %target-run %t/a.out | %FileCheck %s
|
||||
|
||||
// RUN: %target-build-swift %s -Xfrontend -enable-sil-opaque-values -module-name=a -o %t/a.out
|
||||
// RUN: %target-codesign %t/a.out
|
||||
// RUN: %target-run %t/a.out | %FileCheck %s
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
@propertyWrapper struct D<Value> {
|
||||
|
||||
Reference in New Issue
Block a user