mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
SIL optimizer: add the LetPropertyLowering pass
It lowers let property accesses of classes.
Lowering consists of two tasks:
* In class initializers, insert `end_init_let_ref` instructions at places where all let-fields are initialized.
This strictly separates the life-range of the class into a region where let fields are still written during
initialization and a region where let fields are truly immutable.
* Add the `[immutable]` flag to all `ref_element_addr` instructions (for let-fields) which are in the "immutable"
region. This includes the region after an inserted `end_init_let_ref` in an class initializer, but also all
let-field accesses in other functions than the initializer and the destructor.
This pass should run after DefiniteInitialization but before RawSILInstLowering (because it relies on `mark_uninitialized` still present in the class initializer).
Note that it's not mandatory to run this pass. If it doesn't run, SIL is still correct.
Simplified example (after lowering):
bb0(%0 : @owned C): // = self of the class initializer
%1 = mark_uninitialized %0
%2 = ref_element_addr %1, #C.l // a let-field
store %init_value to %2
%3 = end_init_let_ref %1 // inserted by lowering
%4 = ref_element_addr [immutable] %3, #C.l // set to immutable by lowering
%5 = load %4
This commit is contained in:
@@ -13,6 +13,7 @@ swift_compiler_sources(Optimizer
|
||||
ComputeSideEffects.swift
|
||||
DeadStoreElimination.swift
|
||||
InitializeStaticGlobals.swift
|
||||
LetPropertyLowering.swift
|
||||
ObjectOutliner.swift
|
||||
ObjCBridgingOptimization.swift
|
||||
MergeCondFails.swift
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
//===--- LetPropertyLowering.swift -----------------------------------------==//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import SIL
|
||||
|
||||
/// Lowers let property accesses of classes.
|
||||
///
|
||||
/// Lowering consists of two tasks:
|
||||
///
|
||||
/// * In class initializers, insert `end_init_let_ref` instructions at places where all let-fields are initialized.
|
||||
/// This strictly separates the life-range of the class into a region where let fields are still written during
|
||||
/// initialization and a region where let fields are truly immutable.
|
||||
///
|
||||
/// * Add the `[immutable]` flag to all `ref_element_addr` instructions (for let-fields) which are in the "immutable"
|
||||
/// region. This includes the region after an inserted `end_init_let_ref` in an class initializer, but also all
|
||||
/// let-field accesses in other functions than the initializer and the destructor.
|
||||
///
|
||||
/// This pass should run after DefiniteInitialization but before RawSILInstLowering (because it relies on
|
||||
/// `mark_uninitialized` still present in the class initializer).
|
||||
///
|
||||
/// Note that it's not mandatory to run this pass. If it doesn't run, SIL is still correct.
|
||||
///
|
||||
/// Simplified example (after lowering):
|
||||
///
|
||||
/// bb0(%0 : @owned C): // = self of the class initializer
|
||||
/// %1 = mark_uninitialized %0
|
||||
/// %2 = ref_element_addr %1, #C.l // a let-field
|
||||
/// store %init_value to %2
|
||||
/// %3 = end_init_let_ref %1 // inserted by lowering
|
||||
/// %4 = ref_element_addr [immutable] %3, #C.l // set to immutable by lowering
|
||||
/// %5 = load %4
|
||||
///
|
||||
let letPropertyLowering = FunctionPass(name: "let-property-lowering") {
|
||||
(function: Function, context: FunctionPassContext) in
|
||||
|
||||
assert(context.silStage == .raw, "let-property-lowering must run before RawSILInstLowering")
|
||||
|
||||
if context.hadError {
|
||||
// If DefiniteInitialization (or other passes) already reported an error, we cannot assume valid SIL anymore.
|
||||
return
|
||||
}
|
||||
|
||||
if function.isDestructor {
|
||||
// Let-fields are not immutable in the class destructor.
|
||||
return
|
||||
}
|
||||
|
||||
for inst in function.instructions {
|
||||
switch inst {
|
||||
|
||||
// First task of lowering: insert `end_init_let_ref` instructions in class initializers.
|
||||
case let markUninitialized as MarkUninitializedInst
|
||||
where markUninitialized.type.isClass &&
|
||||
// TODO: support move-only classes
|
||||
!markUninitialized.type.isMoveOnly &&
|
||||
// We only have to do that for root classes because derived classes call the super-initializer
|
||||
// _after_ all fields in the derived class are already initialized.
|
||||
markUninitialized.kind == .rootSelf:
|
||||
|
||||
insertEndInitInstructions(for: markUninitialized, context)
|
||||
|
||||
// Second task of lowering: set the `immutable` flags.
|
||||
case let rea as RefElementAddrInst
|
||||
where rea.fieldIsLet && !rea.isInUninitializedRegion &&
|
||||
// TODO: support move-only classes
|
||||
!rea.instance.type.isMoveOnly:
|
||||
rea.set(isImmutable: true, context)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func insertEndInitInstructions(for markUninitialized: MarkUninitializedInst, _ context: FunctionPassContext) {
|
||||
assert(!markUninitialized.type.isAddress, "self of class should not be an address")
|
||||
|
||||
// The region which contains all let-field initializations, including any partial
|
||||
// let-field de-initializations (in case of a fail-able or throwing initializer).
|
||||
var initRegion = InstructionRange(begin: markUninitialized, context)
|
||||
defer { initRegion.deinitialize() }
|
||||
|
||||
constructLetInitRegion(of: markUninitialized, result: &initRegion, context)
|
||||
|
||||
insertEndInitInstructions(for: markUninitialized, atEndOf: initRegion, context)
|
||||
}
|
||||
|
||||
private func insertEndInitInstructions(
|
||||
for markUninitialized: MarkUninitializedInst,
|
||||
atEndOf initRegion: InstructionRange,
|
||||
_ context: FunctionPassContext
|
||||
) {
|
||||
var ssaUpdater = SSAUpdater(type: markUninitialized.type, ownership: .owned, context)
|
||||
ssaUpdater.addAvailableValue(markUninitialized, in: markUninitialized.parentBlock)
|
||||
|
||||
for endInst in initRegion.ends {
|
||||
let builder = Builder(after: endInst, context)
|
||||
let newValue = builder.createEndInitLetRef(operand: markUninitialized)
|
||||
ssaUpdater.addAvailableValue(newValue, in: endInst.parentBlock)
|
||||
}
|
||||
|
||||
for exitInst in initRegion.exits {
|
||||
let builder = Builder(before: exitInst, context)
|
||||
let newValue = builder.createEndInitLetRef(operand: markUninitialized)
|
||||
ssaUpdater.addAvailableValue(newValue, in: exitInst.parentBlock)
|
||||
}
|
||||
|
||||
for use in markUninitialized.uses {
|
||||
if !initRegion.inclusiveRangeContains(use.instruction) &&
|
||||
!(use.instruction is EndInitLetRefInst)
|
||||
{
|
||||
use.set(to: ssaUpdater.getValue(atEndOf: use.instruction.parentBlock), context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func constructLetInitRegion(
|
||||
of markUninitialized: MarkUninitializedInst,
|
||||
result initRegion: inout InstructionRange,
|
||||
_ context: FunctionPassContext
|
||||
) {
|
||||
// Adding the initial `mark_uninitialized` ensures that a single `end_init_let_ref` is inserted (after the
|
||||
// `mark_uninitialized`) in case there are no let-field accesses at all.
|
||||
// Note that we have to insert an `end_init_let_ref` even if there are no let-field initializations, because
|
||||
// derived classes could have let-field initializations in their initializers (which eventually call the
|
||||
// root-class initializer).
|
||||
initRegion.insert(markUninitialized)
|
||||
|
||||
var beginBorrows = Stack<BeginBorrowInst>(context)
|
||||
defer { beginBorrows.deinitialize() }
|
||||
|
||||
for inst in markUninitialized.parentFunction.instructions {
|
||||
switch inst {
|
||||
case let assign as AssignInst
|
||||
where assign.destination.isLetFieldAddress(of: markUninitialized):
|
||||
assert(assign.assignOwnership == .initialize)
|
||||
initRegion.insert(inst)
|
||||
|
||||
case let store as StoreInst
|
||||
where store.destination.isLetFieldAddress(of: markUninitialized):
|
||||
assert(store.storeOwnership != .assign)
|
||||
initRegion.insert(inst)
|
||||
|
||||
case let copy as CopyAddrInst
|
||||
where copy.destination.isLetFieldAddress(of: markUninitialized):
|
||||
assert(copy.isInitializationOfDest)
|
||||
initRegion.insert(inst)
|
||||
|
||||
case let beginAccess as BeginAccessInst
|
||||
where beginAccess.accessKind == .Deinit &&
|
||||
beginAccess.address.isLetFieldAddress(of: markUninitialized):
|
||||
// Include let-field partial de-initializations in the region.
|
||||
initRegion.insert(inst)
|
||||
|
||||
case let beginBorrow as BeginBorrowInst:
|
||||
beginBorrows.append(beginBorrow)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Extend the region to whole borrow scopes to avoid that we insert an `end_init_let_ref` in the
|
||||
// middle of a borrow scope.
|
||||
for beginBorrow in beginBorrows where initRegion.contains(beginBorrow) {
|
||||
initRegion.insert(contentsOf: beginBorrow.endBorrows)
|
||||
}
|
||||
}
|
||||
|
||||
private extension RefElementAddrInst {
|
||||
var isInUninitializedRegion: Bool {
|
||||
var root = self.instance
|
||||
while true {
|
||||
switch root {
|
||||
case let beginBorrow as BeginBorrowInst:
|
||||
root = beginBorrow.borrowedValue
|
||||
case let loadBorrow as LoadBorrowInst:
|
||||
// Initializers of derived classes store `self` into a stack location from where
|
||||
// it's loaded via a `load_borrow`.
|
||||
root = loadBorrow.address
|
||||
case is MarkUninitializedInst:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension Value {
|
||||
func isLetFieldAddress(of markUninitialized: MarkUninitializedInst) -> Bool {
|
||||
if case .class(let rea) = self.accessBase,
|
||||
rea.fieldIsLet,
|
||||
rea.instance.referenceRoot == markUninitialized
|
||||
{
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ private func registerSwiftPasses() {
|
||||
registerPass(stackProtection, { stackProtection.run($0) })
|
||||
|
||||
// Function passes
|
||||
registerPass(letPropertyLowering, { letPropertyLowering.run($0) })
|
||||
registerPass(mergeCondFailsPass, { mergeCondFailsPass.run($0) })
|
||||
registerPass(computeEscapeEffects, { computeEscapeEffects.run($0) })
|
||||
registerPass(computeSideEffects, { computeSideEffects.run($0) })
|
||||
|
||||
@@ -355,6 +355,8 @@ IRGEN_PASS(PackMetadataMarkerInserter, "pack-metadata-marker-inserter",
|
||||
"Insert markers where pack metadata might be de/allocated.")
|
||||
PASS(PerformanceSILLinker, "performance-linker",
|
||||
"Deserialize all referenced SIL functions")
|
||||
SWIFT_FUNCTION_PASS(LetPropertyLowering, "let-property-lowering",
|
||||
"Lowers accesses to let properties of classes")
|
||||
PASS(RawSILInstLowering, "raw-sil-inst-lowering",
|
||||
"Lower all raw SIL instructions to canonical equivalents.")
|
||||
PASS(TempLValueOpt, "temp-lvalue-opt",
|
||||
|
||||
@@ -1644,6 +1644,8 @@ public:
|
||||
/// Adjoint: adj[x] += adj[y]
|
||||
void visitMoveValueInst(MoveValueInst *mvi) { visitValueOwnershipInst(mvi); }
|
||||
|
||||
void visitEndInitLetRefInst(EndInitLetRefInst *eir) { visitValueOwnershipInst(eir); }
|
||||
|
||||
/// Handle `begin_access` instruction.
|
||||
/// Original: y = begin_access x
|
||||
/// Adjoint: nothing
|
||||
|
||||
@@ -3702,25 +3702,14 @@ static bool checkDefiniteInitialization(SILFunction &Fn) {
|
||||
BlockStates blockStates(&Fn);
|
||||
|
||||
for (auto &BB : Fn) {
|
||||
for (auto I = BB.begin(), E = BB.end(); I != E;) {
|
||||
SILInstruction *Inst = &*I;
|
||||
|
||||
auto *MUI = dyn_cast<MarkUninitializedInst>(Inst);
|
||||
if (!MUI) {
|
||||
++I;
|
||||
continue;
|
||||
for (SILInstruction &inst : BB) {
|
||||
if (auto *MUI = dyn_cast<MarkUninitializedInst>(&inst)) {
|
||||
processMemoryObject(MUI, blockStates);
|
||||
Changed = true;
|
||||
// mark_uninitialized needs to remain in SIL for mandatory passes which
|
||||
// follow DI, like LetPropertyLowering.
|
||||
// It will be eventually removed by RawSILInstLowering.
|
||||
}
|
||||
|
||||
// Then process the memory object.
|
||||
processMemoryObject(MUI, blockStates);
|
||||
|
||||
// Move off of the MUI only after we have processed memory objects. The
|
||||
// lifetime checker may rewrite instructions, so it is important to not
|
||||
// move onto the next element until after it runs.
|
||||
++I;
|
||||
MUI->replaceAllUsesWith(MUI->getOperand());
|
||||
MUI->eraseFromParent();
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -546,6 +546,30 @@ static bool diagnoseNonSendableFromDeinit(ModuleDecl *module,
|
||||
return true;
|
||||
}
|
||||
|
||||
class OperandWorklist {
|
||||
SmallVector<Operand *, 32> worklist;
|
||||
SmallPtrSet<Operand *, 16> visited;
|
||||
|
||||
public:
|
||||
Operand *pop() {
|
||||
if (worklist.empty())
|
||||
return nullptr;
|
||||
return worklist.pop_back_val();
|
||||
}
|
||||
|
||||
void pushIfNotVisited(Operand *op) {
|
||||
if (visited.insert(op).second) {
|
||||
worklist.push_back(op);
|
||||
}
|
||||
}
|
||||
|
||||
void pushUsesOfValueIfNotVisited(SILValue value) {
|
||||
for (Operand *use : value->getUses()) {
|
||||
pushIfNotVisited(use);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Analyzes a function for uses of `self` and records the kinds of isolation
|
||||
/// required.
|
||||
/// \param selfParam the parameter of \c getFunction() that should be
|
||||
@@ -556,13 +580,12 @@ void AnalysisInfo::analyze(const SILArgument *selfParam) {
|
||||
ModuleDecl *module = getFunction()->getModule().getSwiftModule();
|
||||
|
||||
// Use a worklist to track the uses left to be searched.
|
||||
SmallVector<Operand *, 32> worklist;
|
||||
OperandWorklist worklist;
|
||||
|
||||
// Seed with direct users of `self`
|
||||
worklist.append(selfParam->use_begin(), selfParam->use_end());
|
||||
worklist.pushUsesOfValueIfNotVisited(selfParam);
|
||||
|
||||
while (!worklist.empty()) {
|
||||
Operand *operand = worklist.pop_back_val();
|
||||
while (Operand *operand = worklist.pop()) {
|
||||
SILInstruction *user = operand->getUser();
|
||||
|
||||
// First, check if this is an apply that involves `self`
|
||||
@@ -651,12 +674,20 @@ void AnalysisInfo::analyze(const SILArgument *selfParam) {
|
||||
break;
|
||||
|
||||
case SILInstructionKind::BeginAccessInst:
|
||||
case SILInstructionKind::BeginBorrowInst: {
|
||||
case SILInstructionKind::BeginBorrowInst:
|
||||
case SILInstructionKind::EndInitLetRefInst: {
|
||||
auto *svi = cast<SingleValueInstruction>(user);
|
||||
worklist.append(svi->use_begin(), svi->use_end());
|
||||
worklist.pushUsesOfValueIfNotVisited(svi);
|
||||
break;
|
||||
}
|
||||
|
||||
case SILInstructionKind::BranchInst: {
|
||||
auto *arg = cast<BranchInst>(user)->getArgForOperand(operand);
|
||||
worklist.pushUsesOfValueIfNotVisited(arg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
// don't follow this instruction.
|
||||
LLVM_DEBUG(llvm::dbgs() << DEBUG_TYPE << " def-use walk skipping: "
|
||||
|
||||
@@ -103,6 +103,7 @@ static void addOwnershipModelEliminatorPipeline(SILPassPipelinePlan &P) {
|
||||
/// order.
|
||||
static void addDefiniteInitialization(SILPassPipelinePlan &P) {
|
||||
P.addDefiniteInitialization();
|
||||
P.addLetPropertyLowering();
|
||||
P.addRawSILInstLowering();
|
||||
}
|
||||
|
||||
|
||||
@@ -448,6 +448,14 @@ bool ValueToDeclInferrer::infer(
|
||||
foundDeclFromUse |= valueUseInferrer.findDecls(use, value);
|
||||
});
|
||||
|
||||
for (Operand *use : value->getUses()) {
|
||||
if (auto *eir = dyn_cast<EndInitLetRefInst>(use->getUser())) {
|
||||
rcfi.visitRCUses(eir, [&](Operand *use) {
|
||||
foundDeclFromUse |= valueUseInferrer.findDecls(use, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, we could not infer any argument. See if we can look up the
|
||||
// def-use graph and come up with a good location after looking through
|
||||
// loads and projections.
|
||||
|
||||
@@ -1301,6 +1301,8 @@ CastOptimizer::optimizeCheckedCastBranchInst(CheckedCastBranchInst *Inst) {
|
||||
// checked_cast_br %1, ....
|
||||
if (auto *FoundIERI = dyn_cast<InitExistentialRefInst>(Op)) {
|
||||
SILValue op = FoundIERI->getOperand();
|
||||
if (auto *eir = dyn_cast<EndInitLetRefInst>(op))
|
||||
op = eir->getOperand();
|
||||
if (!isa<AllocRefInst>(op))
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
// REQUIRES: concurrency
|
||||
// REQUIRES: asserts
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
actor A {
|
||||
var x: String = "Hello"
|
||||
@@ -44,20 +45,21 @@ actor C {
|
||||
}
|
||||
// CHECK-LABEL: sil hidden @$s21default_actor_definit1CC1yACSgSi_tcfc
|
||||
// CHECK: builtin "initializeDefaultActor"(%1 : $C)
|
||||
// CHECK: [[X:%.*]] = ref_element_addr %1 : $C, #C.x
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: [[X:%.*]] = ref_element_addr [[EI]] : $C, #C.x
|
||||
// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [init] [static] [[X]] : $*String
|
||||
// CHECK-NEXT: store {{.*}} to [[ACCESS]] : $*String
|
||||
// CHECK-NEXT: end_access [[ACCESS]] : $*String
|
||||
// CHECK: cond_br {{%.*}}, bb1, bb2
|
||||
// CHECK: bb1:
|
||||
// CHECK: ref_element_addr %1 : $C, #C.y
|
||||
// CHECK: ref_element_addr [[EI]] : $C, #C.y
|
||||
// CHECK: br bb3
|
||||
// CHECK: bb2:
|
||||
// CHECK: [[X:%.*]] = ref_element_addr %1 : $C, #C.x
|
||||
// CHECK: [[X:%.*]] = ref_element_addr [[EI]] : $C, #C.x
|
||||
// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [deinit] [static] [[X]] : $*String
|
||||
// CHECK-NEXT: destroy_addr [[ACCESS]] : $*String
|
||||
// CHECK-NEXT: end_access [[ACCESS]] : $*String
|
||||
// CHECK: builtin "destroyDefaultActor"(%1 : $C)
|
||||
// CHECK: builtin "destroyDefaultActor"([[EI]] : $C)
|
||||
// CHECK: br bb3
|
||||
// CHECK-LABEL: end sil function '$s21default_actor_definit1CC1yACSgSi_tcfc'
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// RUN: %target-swift-frontend -module-name default_deinit -primary-file %s -emit-sil -verify -disable-availability-checking -I %t | %FileCheck %s --enable-var-scope --dump-input=fail
|
||||
// REQUIRES: concurrency
|
||||
// REQUIRES: distributed
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
/// The convention in this test is that the Swift declaration comes before its FileCheck lines.
|
||||
|
||||
@@ -55,9 +56,10 @@ distributed actor MyDistActor {
|
||||
// CHECK: return [[SELF]]
|
||||
|
||||
// CHECK: [[ERROR_BB]]([[ERRVAL:%[0-9]+]] : $any Error):
|
||||
// CHECK-NEXT: [[MU:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK-NEXT: = metatype $@thick MyDistActor.Type
|
||||
// CHECK-NEXT: = builtin "destroyDefaultActor"([[SELF]] : $MyDistActor) : $()
|
||||
// CHECK-NEXT: dealloc_partial_ref [[SELF]]
|
||||
// CHECK-NEXT: = builtin "destroyDefaultActor"([[MU]] : $MyDistActor) : $()
|
||||
// CHECK-NEXT: dealloc_partial_ref [[MU]]
|
||||
// CHECK: throw [[ERRVAL]] : $any Error
|
||||
|
||||
// CHECK: } // end sil function '$s14default_deinit11MyDistActorCACyKcfc'
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// RUN: %target-swift-frontend -module-name default_deinit -primary-file %s -emit-sil -verify -disable-availability-checking -I %t | %FileCheck %s --enable-var-scope --dump-input=fail
|
||||
// REQUIRES: concurrency
|
||||
// REQUIRES: distributed
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
/// The convention in this test is that the Swift declaration comes before its FileCheck lines.
|
||||
|
||||
@@ -89,8 +90,9 @@ distributed actor MyDistActor {
|
||||
// CHECK: [[SYSTEM_ACC:%[0-9]+]] = begin_access [deinit] [static] [[REF_SYS_D2]] : $*FakeActorSystem
|
||||
// CHECK: destroy_addr [[SYSTEM_ACC]] : $*FakeActorSystem
|
||||
// CHECK: end_access [[SYSTEM_ACC]] : $*FakeActorSystem
|
||||
// CHECK: builtin "destroyDefaultActor"([[SELF]] : $MyDistActor) : $()
|
||||
// CHECK: dealloc_partial_ref [[SELF]]
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK: builtin "destroyDefaultActor"([[EI]] : $MyDistActor) : $()
|
||||
// CHECK: dealloc_partial_ref [[EI]]
|
||||
// CHECK: throw
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// RUN: %target-swift-frontend -module-name default_deinit -primary-file %s -emit-sil -verify -disable-availability-checking -I %t | %FileCheck %s --enable-var-scope --dump-input=fail
|
||||
// REQUIRES: concurrency
|
||||
// REQUIRES: distributed
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
/// The convention in this test is that the Swift declaration comes before its FileCheck lines.
|
||||
|
||||
@@ -93,8 +94,9 @@ distributed actor MyDistActor {
|
||||
// CHECK: [[SYSTEM_ACC:%[0-9]+]] = begin_access [deinit] [static] [[REF_SYS_D2]] : $*FakeRoundtripActorSystem
|
||||
// CHECK: destroy_addr [[SYSTEM_ACC]] : $*FakeRoundtripActorSystem
|
||||
// CHECK: end_access [[SYSTEM_ACC]] : $*FakeRoundtripActorSystem
|
||||
// CHECK: builtin "destroyDefaultActor"([[SELF]] : $MyDistActor) : $()
|
||||
// CHECK: dealloc_partial_ref [[SELF]]
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK: builtin "destroyDefaultActor"([[EI]] : $MyDistActor) : $()
|
||||
// CHECK: dealloc_partial_ref [[EI]]
|
||||
// CHECK: throw
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// RUN: %target-swift-frontend -module-name default_deinit -primary-file %s -emit-sil -verify -disable-availability-checking -I %t | %FileCheck %s --enable-var-scope --dump-input=fail
|
||||
// REQUIRES: concurrency
|
||||
// REQUIRES: distributed
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
/// The convention in this test is that the Swift declaration comes before its FileCheck lines.
|
||||
|
||||
@@ -21,10 +22,10 @@ distributed actor MyDistActor {
|
||||
// CHECK: [[SYS_RESOLVE_RESULT:%[0-9]+]] = function_ref @$s27FakeDistributedActorSystems0a9RoundtripC6SystemC7resolve2id2asxSgAA0C7AddressV_xmtK0B00bC0RzlF
|
||||
|
||||
// CHECK: [[ACTOR_INSTANCE:%[0-9]+]] = builtin "initializeDistributedRemoteActor"(%7 : $@thick MyDistActor.Type) : $MyDistActor
|
||||
// CHECK: [[ID_PROPERTY:%[0-9]+]] = ref_element_addr [[ACTOR_INSTANCE]] : $MyDistActor, #MyDistActor.id
|
||||
// CHECK: [[ID_PROPERTY:%[0-9]+]] = ref_element_addr [immutable] [[ACTOR_INSTANCE]] : $MyDistActor, #MyDistActor.id
|
||||
// CHECK: retain_value [[ACTOR_ID_ARG]] : $ActorAddress
|
||||
// CHECK: store [[ACTOR_ID_ARG]] to [[ID_PROPERTY]] : $*ActorAddress
|
||||
// CHECK: [[SYSTEM_PROPERTY:%[0-9]+]] = ref_element_addr [[ACTOR_INSTANCE]] : $MyDistActor, #MyDistActor.actorSystem
|
||||
// CHECK: [[SYSTEM_PROPERTY:%[0-9]+]] = ref_element_addr [immutable] [[ACTOR_INSTANCE]] : $MyDistActor, #MyDistActor.actorSystem
|
||||
// CHECK: strong_retain [[SYSTEM_ARG]] : $FakeRoundtripActorSystem
|
||||
// CHECK: store [[SYSTEM_ARG]] to [[SYSTEM_PROPERTY]] : $*FakeRoundtripActorSystem
|
||||
// CHECK: br bb5([[ACTOR_INSTANCE]] : $MyDistActor)
|
||||
|
||||
@@ -39,7 +39,7 @@ distributed actor Greeter {
|
||||
// CHECK: [[TYPE:%[0-9]+]] = metatype $@thick Greeter.Type
|
||||
|
||||
// CHECK: [[INSTANCE:%[0-9]+]] = builtin "initializeDistributedRemoteActor"([[TYPE]] : $@thick Greeter.Type) : $Greeter
|
||||
// CHECK: [[ID_PROPERTY:%[0-9]+]] = ref_element_addr [[INSTANCE]] : $Greeter, #Greeter.id
|
||||
// CHECK: [[ID_PROPERTY:%[0-9]+]] = ref_element_addr [immutable] [[INSTANCE]] : $Greeter, #Greeter.id
|
||||
// Note specifically that we don't [take] in the below copy_addr:
|
||||
// CHECK: copy_addr [[ADDRESS_ARG]] to [init] [[ID_PROPERTY]] : $*NotLoadableActorAddress
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ func useNode(n: Base) -> Int {
|
||||
|
||||
// CHECK-LABEL: sil [noinline] @$s9arc_crash14testMayReleaseAA4BaseCyF : $@convention(thin) () -> @owned Base {
|
||||
// CHECK: [[BASE:%.*]] = alloc_ref $Base
|
||||
// CHECK: strong_retain [[BASE]] : $Base
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[BASE]]
|
||||
// CHECK: strong_retain [[EI]] : $Base
|
||||
// CHECK: apply %{{.*}} : $@convention(thin) (@owned Queue) -> ()
|
||||
// CHECK-LABEL: } // end sil function '$s9arc_crash14testMayReleaseAA4BaseCyF'
|
||||
@inline(never)
|
||||
|
||||
@@ -14,9 +14,10 @@ func borrow(_ c: C)
|
||||
|
||||
// CHECK-LABEL: sil {{.*}}@test_hoist_over_non_barrier : {{.*}} {
|
||||
// CHECK: [[INSTANCE:%[^,]+]] = alloc_ref
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[INSTANCE]]
|
||||
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrow
|
||||
// CHECK: apply [[BORROW]]([[INSTANCE]])
|
||||
// CHECK: strong_release [[INSTANCE]]
|
||||
// CHECK: apply [[BORROW]]([[EI]])
|
||||
// CHECK: strong_release [[EI]]
|
||||
// CHECK: [[NON_BARRIER:%[^,]+]] = function_ref @non_barrier
|
||||
// CHECK: apply [[NON_BARRIER]]()
|
||||
// CHECK-LABEL: } // end sil function 'test_hoist_over_non_barrier'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// RUN: %target-swift-frontend -module-name test -disable-availability-checking -swift-version 5 -sil-verify-all -emit-sil %s | %FileCheck --enable-var-scope --implicit-check-not='hop_to_executor' %s
|
||||
|
||||
// REQUIRES: concurrency
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
enum ActingError<T> : Error {
|
||||
case forgotLine
|
||||
@@ -15,14 +16,16 @@ actor BoringActor {
|
||||
// CHECK-LABEL: sil hidden @$s4test11BoringActorCACyYacfc : $@convention(method) @async (@owned BoringActor) -> @owned BoringActor {
|
||||
// CHECK: bb0([[SELF:%[0-9]+]] : $BoringActor):
|
||||
// CHECK: initializeDefaultActor
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]]
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK-NEXT: hop_to_executor [[EI]]
|
||||
// CHECK: } // end sil function '$s4test11BoringActorCACyYacfc'
|
||||
init() async {}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test11BoringActorC4sizeACSi_tYacfc : $@convention(method) @async (Int, @owned BoringActor) -> @owned BoringActor {
|
||||
// CHECK: bb0({{%[0-9]+}} : $Int, [[SELF:%[0-9]+]] : $BoringActor):
|
||||
// CHECK: initializeDefaultActor
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]]
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK-NEXT: hop_to_executor [[EI]]
|
||||
// CHECK: } // end sil function '$s4test11BoringActorC4sizeACSi_tYacfc'
|
||||
init(size: Int) async {
|
||||
var sz = size
|
||||
@@ -47,14 +50,16 @@ actor BoringActor {
|
||||
// CHECK-LABEL: sil hidden @$s4test11BoringActorC6crashyACSgyt_tYacfc : $@convention(method) @async (@owned BoringActor) -> @owned Optional<BoringActor> {
|
||||
// CHECK: bb0([[SELF:%[0-9]+]] : $BoringActor):
|
||||
// CHECK: initializeDefaultActor
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]]
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK-NEXT: hop_to_executor [[EI]]
|
||||
// CHECK: } // end sil function '$s4test11BoringActorC6crashyACSgyt_tYacfc'
|
||||
init!(crashy: Void) async { return nil }
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test11BoringActorC5nillyACSgSi_tYacfc : $@convention(method) @async (Int, @owned BoringActor) -> @owned Optional<BoringActor> {
|
||||
// CHECK: bb0({{%[0-9]+}} : $Int, [[SELF:%[0-9]+]] : $BoringActor):
|
||||
// CHECK: initializeDefaultActor
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]]
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK-NEXT: hop_to_executor [[EI]]
|
||||
// CHECK: } // end sil function '$s4test11BoringActorC5nillyACSgSi_tYacfc'
|
||||
init?(nilly: Int) async {
|
||||
guard nilly > 0 else { return nil }
|
||||
@@ -70,9 +75,10 @@ actor BoringActor {
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test14SingleVarActorCACyYacfc : $@convention(method) @async (@owned SingleVarActor) -> @owned SingleVarActor {
|
||||
// CHECK: bb0([[SELF:%[0-9]+]] : $SingleVarActor):
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK: store {{%[0-9]+}} to [[ACCESS:%[0-9]+]]
|
||||
// CHECK-NEXT: end_access [[ACCESS]]
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]] : $SingleVarActor
|
||||
// CHECK-NEXT: hop_to_executor [[EI]] : $SingleVarActor
|
||||
// CHECK: store {{%[0-9]+}} to {{%[0-9]+}}
|
||||
// CHECK: } // end sil function '$s4test14SingleVarActorCACyYacfc'
|
||||
init() async {
|
||||
@@ -82,11 +88,12 @@ actor BoringActor {
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test14SingleVarActorC10iterationsACSi_tYacfc : $@convention(method) @async (Int, @owned SingleVarActor) -> @owned SingleVarActor {
|
||||
// CHECK: bb0({{%[0-9]+}} : $Int, [[SELF:%[0-9]+]] : $SingleVarActor):
|
||||
// CHECK: [[MYVAR_REF:%[0-9]+]] = ref_element_addr [[SELF]] : $SingleVarActor, #SingleVarActor.myVar
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK: [[MYVAR_REF:%[0-9]+]] = ref_element_addr [[EI]] : $SingleVarActor, #SingleVarActor.myVar
|
||||
// CHECK: [[MYVAR:%[0-9]+]] = begin_access [init] [static] [[MYVAR_REF]] : $*Int
|
||||
// CHECK: store {{%[0-9]+}} to [[MYVAR]] : $*Int
|
||||
// CHECK-NEXT: end_access [[MYVAR]]
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]] : $SingleVarActor
|
||||
// CHECK-NEXT: hop_to_executor [[EI]] : $SingleVarActor
|
||||
// CHECK: } // end sil function '$s4test14SingleVarActorC10iterationsACSi_tYacfc'
|
||||
init(iterations: Int) async {
|
||||
var iter = iterations
|
||||
@@ -99,17 +106,18 @@ actor BoringActor {
|
||||
// CHECK-LABEL: sil hidden @$s4test14SingleVarActorC2b12b2ACSb_SbtYacfc : $@convention(method) @async (Bool, Bool, @owned SingleVarActor) -> @owned SingleVarActor {
|
||||
// CHECK: bb0({{%[0-9]+}} : $Bool, {{%[0-9]+}} : $Bool, [[SELF:%[0-9]+]] : $SingleVarActor):
|
||||
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK: store {{%[0-9]+}} to [[A1:%[0-9]+]] : $*Int
|
||||
// CHECK-NEXT: end_access [[A1]]
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]] : $SingleVarActor
|
||||
// CHECK-NEXT: hop_to_executor [[EI]] : $SingleVarActor
|
||||
|
||||
// CHECK: store {{%[0-9]+}} to [[A2:%[0-9]+]] : $*Int
|
||||
// CHECK-NEXT: end_access [[A2]]
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]] : $SingleVarActor
|
||||
// CHECK-NEXT: hop_to_executor [[EI]] : $SingleVarActor
|
||||
|
||||
// CHECK: store {{%[0-9]+}} to [[A3:%[0-9]+]] : $*Int
|
||||
// CHECK-NEXT: end_access [[A3]]
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]] : $SingleVarActor
|
||||
// CHECK-NEXT: hop_to_executor [[EI]] : $SingleVarActor
|
||||
|
||||
// CHECK: } // end sil function '$s4test14SingleVarActorC2b12b2ACSb_SbtYacfc'
|
||||
init(b1: Bool, b2: Bool) async {
|
||||
@@ -171,15 +179,17 @@ actor DefaultInit {
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test11DefaultInitCACyYacfc : $@convention(method) @async (@owned DefaultInit) -> @owned DefaultInit {
|
||||
// CHECK: bb0([[SELF:%[0-9]+]] : $DefaultInit):
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK: store {{%[0-9]+}} to {{%[0-9]+}} : $*ActingError<Int>
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]] : $DefaultInit
|
||||
// CHECK-NEXT: hop_to_executor [[EI]] : $DefaultInit
|
||||
// CHECK: } // end sil function '$s4test11DefaultInitCACyYacfc'
|
||||
init() async {}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test11DefaultInitC5nillyACSgSb_tYacfc : $@convention(method) @async (Bool, @owned DefaultInit) -> @owned Optional<DefaultInit> {
|
||||
// CHECK: bb0({{%[0-9]+}} : $Bool, [[SELF:%[0-9]+]] : $DefaultInit):
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK: store {{%[0-9]+}} to {{%[0-9]+}} : $*ActingError<Int>
|
||||
// CHECK-NEXT: hop_to_executor [[SELF]] : $DefaultInit
|
||||
// CHECK-NEXT: hop_to_executor [[EI]] : $DefaultInit
|
||||
// CHECK: } // end sil function '$s4test11DefaultInitC5nillyACSgSb_tYacfc'
|
||||
init?(nilly: Bool) async {
|
||||
guard nilly else { return nil }
|
||||
@@ -195,11 +205,12 @@ actor MultiVarActor {
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test13MultiVarActorC10doNotThrowACSb_tYaKcfc : $@convention(method) @async (Bool, @owned MultiVarActor) -> (@owned MultiVarActor, @error any Error) {
|
||||
// CHECK: bb0({{%[0-9]+}} : $Bool, [[SELF:%[0-9]+]] : $MultiVarActor):
|
||||
// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MultiVarActor, #MultiVarActor.firstVar
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[SELF]]
|
||||
// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[EI]] : $MultiVarActor, #MultiVarActor.firstVar
|
||||
// CHECK: [[VAR:%[0-9]+]] = begin_access [init] [static] [[REF]] : $*Int
|
||||
// CHECK: store {{%[0-9]+}} to [[VAR]] : $*Int
|
||||
// CHECK-NEXT: end_access [[VAR]]
|
||||
// CHECK-NEXT: hop_to_executor %1 : $MultiVarActor
|
||||
// CHECK-NEXT: hop_to_executor [[EI]] : $MultiVarActor
|
||||
// CHECK: } // end sil function '$s4test13MultiVarActorC10doNotThrowACSb_tYaKcfc'
|
||||
init(doNotThrow: Bool) async throws {
|
||||
secondVar = 0
|
||||
|
||||
@@ -723,8 +723,9 @@ class FailableBaseClass {
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s35definite_init_failable_initializers17FailableBaseClassC28failBeforeFullInitializationACSgyt_tcfc
|
||||
// CHECK: bb0(%0 : $FailableBaseClass):
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %0
|
||||
// CHECK: [[METATYPE:%.*]] = metatype $@thick FailableBaseClass.Type
|
||||
// CHECK: dealloc_partial_ref %0 : $FailableBaseClass, [[METATYPE]]
|
||||
// CHECK: dealloc_partial_ref [[EI]] : $FailableBaseClass, [[METATYPE]]
|
||||
// CHECK: [[RESULT:%.*]] = enum $Optional<FailableBaseClass>, #Optional.none!enumelt
|
||||
// CHECK: return [[RESULT]]
|
||||
init?(failBeforeFullInitialization: ()) {
|
||||
@@ -733,12 +734,13 @@ class FailableBaseClass {
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s35definite_init_failable_initializers17FailableBaseClassC27failAfterFullInitializationACSgyt_tcfc
|
||||
// CHECK: bb0(%0 : $FailableBaseClass):
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %0
|
||||
// CHECK: [[CANARY:%.*]] = apply
|
||||
// CHECK-NEXT: [[MEMBER_ADDR:%.*]] = ref_element_addr %0
|
||||
// CHECK-NEXT: [[MEMBER_ADDR:%.*]] = ref_element_addr [[EI]]
|
||||
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [init] [static] [[MEMBER_ADDR]] : $*Canary
|
||||
// CHECK-NEXT: store [[CANARY]] to [[WRITE]]
|
||||
// CHECK-NEXT: end_access [[WRITE]] : $*Canary
|
||||
// CHECK-NEXT: strong_release %0
|
||||
// CHECK-NEXT: strong_release [[EI]]
|
||||
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableBaseClass>, #Optional.none!enumelt
|
||||
// CHECK-NEXT: return [[NEW_SELF]]
|
||||
init?(failAfterFullInitialization: ()) {
|
||||
|
||||
@@ -244,7 +244,7 @@ bb0(%0 : $*T, %1 : $*T):
|
||||
// CHECK-NEXT: copy_addr [[PB]] to [init] %0 : $*T
|
||||
|
||||
destroy_value %ba : $<τ_0_0> { var τ_0_0 } <T>
|
||||
// CHECK-NEXT: destroy_value %2
|
||||
// CHECK-NEXT: destroy_value %3
|
||||
%9 = tuple ()
|
||||
return %9 : $()
|
||||
}
|
||||
@@ -266,7 +266,7 @@ bb0:
|
||||
|
||||
// This should become an initialization.
|
||||
store_weak %4 to %c : $*@sil_weak Optional<SomeClass>
|
||||
// CHECK-NEXT: store_weak [[C1]] to [init] %1
|
||||
// CHECK-NEXT: store_weak [[C1]] to [init] %2
|
||||
|
||||
destroy_value %4 : $Optional<SomeClass>
|
||||
// CHECK-NEXT: destroy_value [[C1]]
|
||||
@@ -275,7 +275,7 @@ bb0:
|
||||
// CHECK-NEXT: [[C2:%[0-9]+]] = apply
|
||||
|
||||
store_weak %8 to %c : $*@sil_weak Optional<SomeClass>
|
||||
// CHECK-NEXT: store_weak [[C2]] to %1
|
||||
// CHECK-NEXT: store_weak [[C2]] to %2
|
||||
|
||||
destroy_value %8 : $Optional<SomeClass>
|
||||
// CHECK-NEXT: destroy_value [[C2]]
|
||||
@@ -376,7 +376,7 @@ bb0(%0 : $*SomeClass, %1 : @owned $SomeClass):
|
||||
sil_global @int_global : $Int
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_tlc
|
||||
// CHECK-NOT: mark_uninitialized
|
||||
// CHECK: mark_uninitialized
|
||||
// CHECK: return
|
||||
sil [ossa] @test_tlc : $() -> () {
|
||||
%0 = global_addr @int_global : $*Int
|
||||
@@ -395,8 +395,9 @@ sil [ossa] @use : $@convention(thin) (@in P) -> ()
|
||||
// CHECK-LABEL: sil [ossa] @release_not_constructed
|
||||
sil [ossa] @release_not_constructed : $@convention(thin) () -> () {
|
||||
bb0: // CHECK: bb0:
|
||||
%3 = alloc_stack $SomeClass
|
||||
// CHECK-NEXT: alloc_stack
|
||||
%3 = alloc_stack $SomeClass
|
||||
// CHECK-NEXT: mark_uninitialized
|
||||
%c = mark_uninitialized [var] %3 : $*SomeClass
|
||||
|
||||
|
||||
@@ -445,7 +446,7 @@ entry(%a : $*C):
|
||||
|
||||
%q = init_existential_addr %b : $*P, $C
|
||||
|
||||
// CHECK: copy_addr {{.*}} to [init] %2 : $*C
|
||||
// CHECK: copy_addr {{.*}} to [init] %3 : $*C
|
||||
copy_addr %a to [init] %q : $*C
|
||||
%u = function_ref @use : $@convention(thin) (@in P) -> ()
|
||||
%v = apply %u(%b) : $@convention(thin) (@in P) -> ()
|
||||
@@ -495,6 +496,7 @@ sil [ossa] @conditionalInitOrAssign : $@convention(thin) (Builtin.Int1) -> () {
|
||||
bb0(%0 : $Builtin.Int1):
|
||||
// CHECK: [[CONTROL:%[0-9]+]] = alloc_stack $Builtin.Int1
|
||||
// CHECK: [[CLASSVAL:%[0-9]+]] = alloc_stack [dynamic_lifetime] $SomeClass
|
||||
// CHECK: [[MU:%[0-9]+]] = mark_uninitialized [var] [[CLASSVAL]]
|
||||
// CHECK: integer_literal $Builtin.Int1, 0
|
||||
// CHECK: store
|
||||
%5 = alloc_stack $SomeClass
|
||||
@@ -511,7 +513,7 @@ bb1:
|
||||
// updates the control variable to say that it is initialized.
|
||||
// CHECK: integer_literal $Builtin.Int1, -1
|
||||
// CHECK: store {{.*}} to [trivial] [[CONTROL]]
|
||||
// CHECK: assign [[V1]] to [init] [[CLASSVAL]]
|
||||
// CHECK: assign [[V1]] to [init] [[MU]]
|
||||
assign %12 to %6 : $*SomeClass // id: %13
|
||||
br bb3 // id: %14
|
||||
|
||||
@@ -529,10 +531,10 @@ bb3:
|
||||
// CHECK: load [trivial] [[CONTROL]]
|
||||
// CHECK: cond_br
|
||||
// CHECK: bb4:
|
||||
// CHECK: destroy_addr [[CLASSVAL]]
|
||||
// CHECK: destroy_addr [[MU]]
|
||||
// CHECK: br bb6
|
||||
// CHECK: bb6:
|
||||
// CHECK: assign [[V2]] to [init] [[CLASSVAL]]
|
||||
// CHECK: assign [[V2]] to [init] [[MU]]
|
||||
assign %17 to %6 : $*SomeClass // id: %18
|
||||
destroy_addr %6 : $*SomeClass // id: %19
|
||||
dealloc_stack %5 : $*SomeClass // id: %20
|
||||
@@ -546,13 +548,14 @@ bb3:
|
||||
// CHECK-LABEL: sil [ossa] @conditionalInitOrAssignAllocBox : $@convention(thin) () -> () {
|
||||
// CHECK: bb0:
|
||||
// CHECK: [[BOX:%.*]] = alloc_box
|
||||
// CHECK: [[MU:%.*]] = mark_uninitialized [var] [[BOX]]
|
||||
//
|
||||
// CHECK: bb1:
|
||||
// CHECK: destroy_value [[BOX]]
|
||||
// CHECK: destroy_value [[MU]]
|
||||
// CHECK: br bb3
|
||||
//
|
||||
// CHECK: bb2:
|
||||
// CHECK: dealloc_box [[BOX]]
|
||||
// CHECK: dealloc_box [[MU]]
|
||||
// CHECK: br bb3
|
||||
//
|
||||
// CHECK: bb3:
|
||||
@@ -587,7 +590,7 @@ bb3:
|
||||
// pointer. LLDB shouldn't do this, but until it is removed and validated we
|
||||
// need a test for this.
|
||||
// CHECK-LABEL: sil [ossa] @lldb_unsupported_markuninitialized_testcase : $@convention(thin) (UnsafeMutablePointer<Any>) -> () {
|
||||
// CHECK-NOT: mark_uninitialized [var]
|
||||
// CHECK: mark_uninitialized [var]
|
||||
// CHECK: } // end sil function 'lldb_unsupported_markuninitialized_testcase'
|
||||
sil [ossa] @lldb_unsupported_markuninitialized_testcase : $@convention(thin) (UnsafeMutablePointer<Any>) -> () {
|
||||
bb0(%0 : $UnsafeMutablePointer<Any>):
|
||||
|
||||
@@ -13,7 +13,8 @@ sil @closureTakeVal : $@convention(thin) (@guaranteed { let S }) -> ()
|
||||
|
||||
// CHECK-LABEL: sil hidden [ossa] @letControlFlowDependentInitializationNoEscape : $@convention(thin) () -> () {
|
||||
// CHECK: [[STACK:%.*]] = alloc_stack
|
||||
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[STACK]]
|
||||
// CHECK: [[MU:%.*]] = mark_uninitialized [var] [[STACK]]
|
||||
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[MU]]
|
||||
// CHECK: cond_br undef, [[LHS_BB:bb[0-9]+]], [[RHS_BB:bb[0-9]+]]
|
||||
//
|
||||
// CHECK: [[LHS_BB]]:
|
||||
@@ -68,7 +69,8 @@ bb3:
|
||||
|
||||
// CHECK-LABEL: sil hidden [ossa] @letControlFlowDependentInitializationEscape : $@convention(thin) () -> () {
|
||||
// CHECK: [[BOX:%.*]] = alloc_box
|
||||
// CHECK: [[PROJECT:%.*]] = project_box [[BOX]]
|
||||
// CHECK: [[MU:%.*]] = mark_uninitialized [var] [[BOX]]
|
||||
// CHECK: [[PROJECT:%.*]] = project_box [[MU]]
|
||||
// CHECK: cond_br undef, [[LHS_BB:bb[0-9]+]], [[RHS_BB:bb[0-9]+]]
|
||||
//
|
||||
// CHECK: [[LHS_BB]]:
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// output. At least until -enable-copy-propagation has been around
|
||||
// long enough in the same form to be worth rewriting CHECK lines.
|
||||
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
class OtherClass {}
|
||||
|
||||
class FirstClass {
|
||||
@@ -12,6 +14,7 @@ class FirstClass {
|
||||
// CHECK-LABEL: sil hidden @$s24definite_init_root_class10FirstClassC1nACSgs5Int32V_tcfc : $@convention(method) (Int32, @owned FirstClass) -> @owned Optional<FirstClass>
|
||||
init?(n: Int32) {
|
||||
// CHECK: [[CONTROL:%.*]] = alloc_stack $Builtin.Int1
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Int1, 0
|
||||
// CHECK: store [[ZERO]] to [[CONTROL]] : $*Builtin.Int1
|
||||
|
||||
@@ -30,8 +33,8 @@ class FirstClass {
|
||||
// CHECK: [[METATYPE:%.*]] = metatype $@thick OtherClass.Type
|
||||
// CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass
|
||||
// CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass
|
||||
// CHECK: [[X_ADDR:%.*]] = ref_element_addr %1 : $FirstClass, #FirstClass.x
|
||||
// CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] %15 : $*OtherClass
|
||||
// CHECK: [[X_ADDR:%.*]] = ref_element_addr [[EI]] : $FirstClass, #FirstClass.x
|
||||
// CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] [[X_ADDR]] : $*OtherClass
|
||||
// CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int1, -1
|
||||
// CHECK: store [[ONE]] to [[CONTROL]] : $*Builtin.Int1
|
||||
// CHECK: store [[OTHER]] to [[X_ACCESS]] : $*OtherClass
|
||||
@@ -50,7 +53,7 @@ class FirstClass {
|
||||
// CHECK: br bb5
|
||||
|
||||
// CHECK: bb4:
|
||||
// CHECK: [[RESULT:%.*]] = enum $Optional<FirstClass>, #Optional.some!enumelt, %1 : $FirstClass
|
||||
// CHECK: [[RESULT:%.*]] = enum $Optional<FirstClass>, #Optional.some!enumelt, [[EI]] : $FirstClass
|
||||
// CHECK: br bb12([[RESULT]] : $Optional<FirstClass>)
|
||||
|
||||
// CHECK: bb5:
|
||||
@@ -58,7 +61,7 @@ class FirstClass {
|
||||
// CHECK: cond_br [[BIT]], bb6, bb7
|
||||
|
||||
// CHECK: bb6:
|
||||
// CHECK: strong_release %1 : $FirstClass
|
||||
// CHECK: strong_release [[EI]] : $FirstClass
|
||||
// CHECK: br bb11
|
||||
|
||||
// CHECK: bb7:
|
||||
@@ -66,7 +69,7 @@ class FirstClass {
|
||||
// CHECK: cond_br [[BIT]], bb8, bb9
|
||||
|
||||
// CHECK: bb8:
|
||||
// CHECK: [[X_ADDR:%.*]] = ref_element_addr %1 : $FirstClass, #FirstClass.x
|
||||
// CHECK: [[X_ADDR:%.*]] = ref_element_addr [[EI]] : $FirstClass, #FirstClass.x
|
||||
// CHECK: [[X_ACCESS:%.*]] = begin_access [deinit] [static] [[X_ADDR]] : $*OtherClass
|
||||
// CHECK: destroy_addr [[X_ACCESS]] : $*OtherClass
|
||||
// CHECK: end_access [[X_ACCESS]] : $*OtherClass
|
||||
@@ -76,7 +79,7 @@ class FirstClass {
|
||||
// CHECK: br bb10
|
||||
|
||||
// CHECK: [[METATYPE:%.*]] = metatype $@thick FirstClass.Type
|
||||
// CHECK: dealloc_partial_ref %1 : $FirstClass, [[METATYPE]] : $@thick FirstClass.Type
|
||||
// CHECK: dealloc_partial_ref [[EI]] : $FirstClass, [[METATYPE]] : $@thick FirstClass.Type
|
||||
// CHECK: br bb11
|
||||
|
||||
// CHECK: bb11:
|
||||
@@ -96,6 +99,7 @@ class SecondClass {
|
||||
// CHECK-LABEL: sil hidden @$s24definite_init_root_class11SecondClassC1nACSgs5Int32V_tcfc : $@convention(method) (Int32, @owned SecondClass) -> @owned Optional<SecondClass> {
|
||||
init?(n: Int32) {
|
||||
// CHECK: [[CONTROL:%.*]] = alloc_stack $Builtin.Int2
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Int2, 0
|
||||
// CHECK: store [[ZERO]] to [[CONTROL]] : $*Builtin.Int2
|
||||
|
||||
@@ -114,7 +118,7 @@ class SecondClass {
|
||||
// CHECK: [[METATYPE:%.*]] = metatype $@thick OtherClass.Type
|
||||
// CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass
|
||||
// CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass
|
||||
// CHECK: [[X_ADDR:%.*]] = ref_element_addr %1 : $SecondClass, #SecondClass.x
|
||||
// CHECK: [[X_ADDR:%.*]] = ref_element_addr [[EI]] : $SecondClass, #SecondClass.x
|
||||
// CHECK: [[X_ACCESS:%.*]] = begin_access [init] [static] [[X_ADDR]] : $*OtherClass
|
||||
// CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int2, 1
|
||||
// CHECK: store [[ONE]] to [[CONTROL]] : $*Builtin.Int2
|
||||
@@ -137,7 +141,7 @@ class SecondClass {
|
||||
// CHECK: [[METATYPE:%.*]] = metatype $@thick OtherClass.Type
|
||||
// CHECK: [[INIT:%.*]] = function_ref @$s24definite_init_root_class10OtherClassCACycfC : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass
|
||||
// CHECK: [[OTHER:%.*]] = apply [[INIT]]([[METATYPE]]) : $@convention(method) (@thick OtherClass.Type) -> @owned OtherClass
|
||||
// CHECK: [[Y_ADDR:%.*]] = ref_element_addr %1 : $SecondClass, #SecondClass.y
|
||||
// CHECK: [[Y_ADDR:%.*]] = ref_element_addr [[EI]] : $SecondClass, #SecondClass.y
|
||||
// CHECK: [[Y_ACCESS:%.*]] = begin_access [init] [static] [[Y_ADDR]] : $*OtherClass
|
||||
// CHECK: [[THREE:%.*]] = integer_literal $Builtin.Int2, -1
|
||||
// CHECK: store [[THREE]] to [[CONTROL]] : $*Builtin.Int2
|
||||
@@ -157,7 +161,7 @@ class SecondClass {
|
||||
// CHECK: br bb7
|
||||
|
||||
// CHECK: bb6:
|
||||
// CHECK: [[RESULT:%.*]] = enum $Optional<SecondClass>, #Optional.some!enumelt, %1 : $SecondClass
|
||||
// CHECK: [[RESULT:%.*]] = enum $Optional<SecondClass>, #Optional.some!enumelt, [[EI]] : $SecondClass
|
||||
// CHECK: br bb17([[RESULT]] : $Optional<SecondClass>)
|
||||
|
||||
// CHECK: bb7:
|
||||
@@ -167,7 +171,7 @@ class SecondClass {
|
||||
// CHECK: cond_br [[BIT]], bb8, bb9
|
||||
|
||||
// CHECK: bb8:
|
||||
// CHECK: strong_release %1 : $SecondClass
|
||||
// CHECK: strong_release [[EI]] : $SecondClass
|
||||
// CHECK: br bb16
|
||||
|
||||
// CHECK: bb9:
|
||||
@@ -176,7 +180,7 @@ class SecondClass {
|
||||
// CHECK: cond_br [[BIT]], bb10, bb11
|
||||
|
||||
// CHECK: bb10:
|
||||
// CHECK: [[X_ADDR:%.*]] = ref_element_addr %1 : $SecondClass, #SecondClass.x
|
||||
// CHECK: [[X_ADDR:%.*]] = ref_element_addr [[EI]] : $SecondClass, #SecondClass.x
|
||||
// CHECK: [[X_ACCESS:%.*]] = begin_access [deinit] [static] [[X_ADDR]] : $*OtherClass
|
||||
// CHECK: destroy_addr [[X_ACCESS]] : $*OtherClass
|
||||
// CHECK: end_access [[X_ACCESS]] : $*OtherClass
|
||||
@@ -193,7 +197,7 @@ class SecondClass {
|
||||
// CHECK: cond_br [[BIT]], bb13, bb14
|
||||
|
||||
// CHECK: bb13:
|
||||
// CHECK: [[Y_ADDR:%.*]] = ref_element_addr %1 : $SecondClass, #SecondClass.y
|
||||
// CHECK: [[Y_ADDR:%.*]] = ref_element_addr [[EI]] : $SecondClass, #SecondClass.y
|
||||
// CHECK: [[Y_ACCESS:%.*]] = begin_access [deinit] [static] [[Y_ADDR]] : $*OtherClass
|
||||
// CHECK: destroy_addr [[Y_ACCESS]] : $*OtherClass
|
||||
// CHECK: end_access [[Y_ACCESS]] : $*OtherClass
|
||||
@@ -204,7 +208,7 @@ class SecondClass {
|
||||
|
||||
// CHECK: bb15:
|
||||
// CHECK: [[METATYPE:%.*]] = metatype $@thick SecondClass.Type
|
||||
// CHECK: dealloc_partial_ref %1 : $SecondClass, [[METATYPE]] : $@thick SecondClass.Type
|
||||
// CHECK: dealloc_partial_ref [[EI]] : $SecondClass, [[METATYPE]] : $@thick SecondClass.Type
|
||||
// CHECK: br bb16
|
||||
|
||||
// CHECK: bb16:
|
||||
|
||||
@@ -625,14 +625,16 @@ bb0:
|
||||
|
||||
(%2,%3) = begin_cow_mutation %0 : $Derived
|
||||
%4 = end_cow_mutation %3 : $Derived
|
||||
%4b = begin_dealloc_ref %4 : $Derived of %0 : $Derived
|
||||
%4a = end_init_let_ref %4 : $Derived
|
||||
%4b = begin_dealloc_ref %4a : $Derived of %0 : $Derived
|
||||
%5 = upcast %4b : $Derived to $X
|
||||
%6 = init_existential_ref %5 : $X : $X, $ClassP
|
||||
%7 = open_existential_ref %6 : $ClassP to $@opened("53729A20-8747-11EB-82C4-D0817AD9985D", ClassP) Self
|
||||
|
||||
(%8,%9) = begin_cow_mutation %1 : $Derived
|
||||
%10 = end_cow_mutation %9 : $Derived
|
||||
%10b = begin_dealloc_ref %10 : $Derived of %1 : $Derived
|
||||
%10a = end_init_let_ref %10 : $Derived
|
||||
%10b = begin_dealloc_ref %10a : $Derived of %1 : $Derived
|
||||
%11 = upcast %10b : $Derived to $X
|
||||
%12 = init_existential_ref %11 : $X : $X, $ClassP
|
||||
%13 = open_existential_ref %12 : $ClassP to $@opened("12345678-8747-11EB-82C4-D0817AD9985D", ClassP) Self
|
||||
@@ -653,14 +655,16 @@ bb0(%0 : $DerivedZ):
|
||||
%3 = alloc_ref $DerivedZ
|
||||
(%4,%5) = begin_cow_mutation %3 : $DerivedZ
|
||||
%6 = end_cow_mutation %5 : $DerivedZ
|
||||
%6b = begin_dealloc_ref %6 : $DerivedZ of %3 : $DerivedZ
|
||||
%6a = end_init_let_ref %6 : $DerivedZ
|
||||
%6b = begin_dealloc_ref %6a : $DerivedZ of %3 : $DerivedZ
|
||||
%7 = upcast %6b : $DerivedZ to $Z
|
||||
%8 = ref_element_addr %7 : $Z, #Z.y
|
||||
store %1 to %8 : $*Y
|
||||
|
||||
(%10,%11) = begin_cow_mutation %0 : $DerivedZ
|
||||
%12 = end_cow_mutation %11 : $DerivedZ
|
||||
%13 = upcast %12 : $DerivedZ to $Z
|
||||
%12a = end_init_let_ref %12 : $DerivedZ
|
||||
%13 = upcast %12a : $DerivedZ to $Z
|
||||
%14 = ref_element_addr %13 : $Z, #Z.y
|
||||
store %2 to %14 : $*Y
|
||||
|
||||
|
||||
@@ -42,30 +42,32 @@ final class TestIndirectionThroughStorage {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering29TestIndirectionThroughStorageC4name3ageACSS_Sitcfc : $@convention(method) (@owned String, Int, @owned TestIndirectionThroughStorage) -> @owned TestIndirectionThroughStorage
|
||||
// CHECK: [[SELF:%.*]] = mark_uninitialized [rootself] %2
|
||||
// CHECK: [[STORAGE_REF:%.*]] = ref_element_addr {{.*}} : $TestIndirectionThroughStorage, #TestIndirectionThroughStorage._storage
|
||||
// CHECK: [[STORAGE_INIT:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC8_storage33_DE106275C2F16FB3D05881E72FBD87C8LLAA0H0_pAC1TAaFPRts_XPvpfi : $@convention(thin) () -> @out any Storage<TestIndirectionThroughStorage>
|
||||
// CHECK-NEXT: {{.*}} = apply [[STORAGE_INIT]]([[STORAGE_REF]]) : $@convention(thin) () -> @out any Storage<TestIndirectionThroughStorage>
|
||||
// Initialization:
|
||||
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.name, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
|
||||
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.age, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
|
||||
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.name, self [[SELF]] : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
|
||||
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.age, self [[SELF]] : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
|
||||
// Explicit set:
|
||||
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.name, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
|
||||
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self %2 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
|
||||
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.name, self [[SELF]] : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
|
||||
// CHECK: assign_or_init [set] #TestIndirectionThroughStorage.age, self [[SELF]] : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
|
||||
init(name: String, age: Int) {
|
||||
self.name = name
|
||||
self.age = age
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden [ossa] @$s23assign_or_init_lowering29TestIndirectionThroughStorageC7storageAcA0H0_pAC1TAaEPRts_XP_tcfc : $@convention(method) (@in any Storage<TestIndirectionThroughStorage>, @owned TestIndirectionThroughStorage) -> @owned TestIndirectionThroughStorage
|
||||
// CHECK: [[SELF:%.*]] = mark_uninitialized [rootself] %1
|
||||
// CHECK: [[STORAGE_REF:%.*]] = ref_element_addr {{.*}} : $TestIndirectionThroughStorage, #TestIndirectionThroughStorage._storage
|
||||
// CHECK: [[STORAGE_INIT:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC8_storage33_DE106275C2F16FB3D05881E72FBD87C8LLAA0H0_pAC1TAaFPRts_XPvpfi : $@convention(thin) () -> @out any Storage<TestIndirectionThroughStorage>
|
||||
// CHECK-NEXT: {{.*}} = apply [[STORAGE_INIT]]([[STORAGE_REF]]) : $@convention(thin) () -> @out any Storage<TestIndirectionThroughStorage>
|
||||
// Initialization:
|
||||
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.name, self %1 : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
|
||||
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.age, self %1 : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
|
||||
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.name, self [[SELF]] : $TestIndirectionThroughStorage, value {{.*}} : $String, init {{.*}} : $@convention(thin) (@owned String, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (@owned String) -> ()
|
||||
// CHECK: assign_or_init [init] #TestIndirectionThroughStorage.age, self [[SELF]] : $TestIndirectionThroughStorage, value {{.*}} : $Optional<Int>, init {{.*}} : $@convention(thin) (Optional<Int>, @inout any Storage<TestIndirectionThroughStorage>) -> (), set {{.*}} : $@callee_guaranteed (Optional<Int>) -> ()
|
||||
// Explicit set:
|
||||
// CHECK: [[STORAGE_SETTER:%.*]] = function_ref @$s23assign_or_init_lowering29TestIndirectionThroughStorageC7storageAA0H0_pAC1TAaEPRts_XPvs : $@convention(method) (@in any Storage<TestIndirectionThroughStorage>, @guaranteed TestIndirectionThroughStorage) -> ()
|
||||
// CHECK-NEXT: {{.*}} = apply [[STORAGE_SETTER]]({{.*}}, %1) : $@convention(method) (@in any Storage<TestIndirectionThroughStorage>, @guaranteed TestIndirectionThroughStorage) -> ()
|
||||
// CHECK-NEXT: {{.*}} = apply [[STORAGE_SETTER]]({{.*}}, [[SELF]]) : $@convention(method) (@in any Storage<TestIndirectionThroughStorage>, @guaranteed TestIndirectionThroughStorage) -> ()
|
||||
init(storage: any Storage<TestIndirectionThroughStorage>) {
|
||||
self.storage = storage
|
||||
}
|
||||
@@ -219,26 +221,28 @@ func test_default_inits() {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_VADycfC : $@convention(method) (@thin Test1.Type) -> Test1
|
||||
// CHECK: [[SELF:%.*]] = mark_uninitialized [rootself] %1
|
||||
// CHECK: [[DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivpfi : $@convention(thin) () -> Int
|
||||
// CHECK-NEXT: [[INIT_VAL:%.*]] = apply [[DEFAULT]]() : $@convention(thin) () -> Int
|
||||
// CHECK-NEXT: [[SELF_REF:%.*]] = begin_access [modify] [static] %1 : $*Test1
|
||||
// CHECK-NEXT: [[SELF_REF:%.*]] = begin_access [modify] [static] [[SELF]] : $*Test1
|
||||
// CHECK: [[INIT_ACCESSOR:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivi : $@convention(thin) (Int) -> @out Int
|
||||
// CHECK: [[SETTER_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivs : $@convention(method) (Int, @inout Test1) -> ()
|
||||
// CHECK-NEXT: [[SETTER:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]([[SELF_REF]]) : $@convention(method) (Int, @inout Test1) -> ()
|
||||
// CHECK-NEXT: assign_or_init [init] #<abstract function>Test1.x, self %1 : $*Test1, value [[INIT_VAL]] : $Int, init [[INIT_ACCESSOR]] : $@convention(thin) (Int) -> @out Int, set [[SETTER]] : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK-NEXT: assign_or_init [init] #<abstract function>Test1.x, self %2 : $*Test1, value [[INIT_VAL]] : $Int, init [[INIT_ACCESSOR]] : $@convention(thin) (Int) -> @out Int, set [[SETTER]] : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK-NEXT: end_access [[SELF_REF]] : $*Test1
|
||||
// CHECK-NEXT: destroy_value [[SETTER]] : $@callee_guaranteed (Int) -> ()
|
||||
init() {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xADSi_tcfC : $@convention(method) (Int, @thin Test1.Type) -> Test1
|
||||
// CHECK: [[SELF:%.*]] = mark_uninitialized [rootself] %2
|
||||
// CHECK: [[DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivpfi : $@convention(thin) () -> Int
|
||||
// CHECK-NEXT: [[INIT_VAL:%.*]] = apply [[DEFAULT]]() : $@convention(thin) () -> Int
|
||||
// CHECK-NEXT: [[SELF_REF:%.*]] = begin_access [modify] [static] %2 : $*Test1
|
||||
// CHECK-NEXT: [[SELF_REF:%.*]] = begin_access [modify] [static] [[SELF]] : $*Test1
|
||||
// CHECK: [[INIT_ACCESSOR:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivi : $@convention(thin) (Int) -> @out Int
|
||||
// CHECK: [[SETTER_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test1L_V1xSivs : $@convention(method) (Int, @inout Test1) -> ()
|
||||
// CHECK-NEXT: [[SETTER:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]([[SELF_REF]]) : $@convention(method) (Int, @inout Test1) -> ()
|
||||
// CHECK-NEXT: assign_or_init [init] #<abstract function>Test1.x, self %2 : $*Test1, value [[INIT_VAL]] : $Int, init [[INIT_ACCESSOR]] : $@convention(thin) (Int) -> @out Int, set [[SETTER]] : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK-NEXT: assign_or_init [init] #<abstract function>Test1.x, self %3 : $*Test1, value [[INIT_VAL]] : $Int, init [[INIT_ACCESSOR]] : $@convention(thin) (Int) -> @out Int, set [[SETTER]] : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK-NEXT: end_access [[SELF_REF]] : $*Test1
|
||||
// CHECK-NEXT: destroy_value [[SETTER]] : $@callee_guaranteed (Int) -> ()
|
||||
//
|
||||
@@ -263,6 +267,7 @@ func test_default_inits() {
|
||||
var y: Int
|
||||
|
||||
// CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_CADyxGycfc : $@convention(method) <T where T : Initializable> (@owned Test2<T>) -> @owned Test2<T>
|
||||
// CHECK: [[SL:%.*]] = mark_uninitialized [rootself] %0
|
||||
// CHECK: [[DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1xx_SStvpfi : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> (@out τ_0_0, @owned String)
|
||||
// CHECK-NEXT: [[T:%.*]] = alloc_stack $T
|
||||
// CHECK-NEXT: [[STR:%.*]] = apply [[DEFAULT]]<T>([[T]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> (@out τ_0_0, @owned String)
|
||||
@@ -274,9 +279,9 @@ func test_default_inits() {
|
||||
// CHECK: [[INIT_ACCESSOR_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1xx_SStvi : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String) -> @out (τ_0_0, String)
|
||||
// CHECK-NEXT: [[INIT_ACCESSOR:%.*]] = partial_apply [callee_guaranteed] [[INIT_ACCESSOR_REF]]<T>() : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String) -> @out (τ_0_0, String)
|
||||
// CHECK: [[SETTER_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1xx_SStvs : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String, @guaranteed Test2<τ_0_0>) -> ()
|
||||
// CHECK-NEXT: [[SELF:%.*]] = copy_value %0 : $Test2<T>
|
||||
// CHECK-NEXT: [[SELF:%.*]] = copy_value [[SL]] : $Test2<T>
|
||||
// CHECK-NEXT: [[SETTER:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]<T>([[SELF]]) : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String, @guaranteed Test2<τ_0_0>) -> ()
|
||||
// CHECK-NEXT: assign_or_init [init] #<abstract function>Test2.x, self %0 : $Test2<T>, value [[NEW_VALUE]] : $*(T, String), init [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK-NEXT: assign_or_init [init] #<abstract function>Test2.x, self [[SL]] : $Test2<T>, value [[NEW_VALUE]] : $*(T, String), init [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK-NEXT: destroy_value [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK-NEXT: destroy_value [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String)
|
||||
// CHECK-NEXT: dealloc_stack [[NEW_VALUE]] : $*(T, String)
|
||||
@@ -286,6 +291,7 @@ func test_default_inits() {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1x1yADyxGx_SSt_Sitcfc : $@convention(method) <T where T : Initializable> (@in T, @owned String, Int, @owned Test2<T>) -> @owned Test2<T>
|
||||
// CHECK: [[SL:%.*]] = mark_uninitialized [rootself] %3
|
||||
// CHECK: [[DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1xx_SStvpfi : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> (@out τ_0_0, @owned String)
|
||||
// CHECK-NEXT: [[T:%.*]] = alloc_stack $T
|
||||
// CHECK-NEXT: [[STR:%.*]] = apply [[DEFAULT]]<T>([[T]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> (@out τ_0_0, @owned String)
|
||||
@@ -297,17 +303,17 @@ func test_default_inits() {
|
||||
// CHECK: [[INIT_ACCESSOR_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1xx_SStvi : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String) -> @out (τ_0_0, String)
|
||||
// CHECK-NEXT: [[INIT_ACCESSOR:%.*]] = partial_apply [callee_guaranteed] [[INIT_ACCESSOR_REF]]<T>() : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String) -> @out (τ_0_0, String)
|
||||
// CHECK: [[SETTER_REF:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test2L_C1xx_SStvs : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String, @guaranteed Test2<τ_0_0>) -> ()
|
||||
// CHECK-NEXT: [[SELF:%.*]] = copy_value %3 : $Test2<T>
|
||||
// CHECK-NEXT: [[SELF:%.*]] = copy_value [[SL]] : $Test2<T>
|
||||
// CHECK-NEXT: [[SETTER:%.*]] = partial_apply [callee_guaranteed] [[SETTER_REF]]<T>([[SELF]]) : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @owned String, @guaranteed Test2<τ_0_0>) -> ()
|
||||
// CHECK-NEXT: assign_or_init [init] #<abstract function>Test2.x, self %3 : $Test2<T>, value [[NEW_VALUE]] : $*(T, String), init [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK-NEXT: assign_or_init [init] #<abstract function>Test2.x, self [[SL]] : $Test2<T>, value [[NEW_VALUE]] : $*(T, String), init [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK-NEXT: destroy_value [[SETTER]] : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK-NEXT: destroy_value [[INIT_ACCESSOR]] : $@callee_guaranteed (@in T, @owned String) -> @out (T, String)
|
||||
// CHECK-NEXT: dealloc_stack [[NEW_VALUE]] : $*(T, String)
|
||||
// CHECK-NEXT: dealloc_stack [[T]] : $*T
|
||||
//
|
||||
// CHECK: assign_or_init [init] [assign=0] #<abstract function>Test2.x, self %3 : $Test2<T>, value {{.*}} : $*(T, String), init {{.*}} : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set {{.*}} : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK: assign_or_init [init] [assign=0] #<abstract function>Test2.x, self [[SL]] : $Test2<T>, value {{.*}} : $*(T, String), init {{.*}} : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set {{.*}} : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK: assign %2 to [init] [[Y_REF:%.*]] : $*Int
|
||||
// CHECK: assign_or_init [set] #<abstract function>Test2.x, self %3 : $Test2<T>, value {{.*}} : $*(T, String), init {{.*}} : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set {{.*}} : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
// CHECK: assign_or_init [set] #<abstract function>Test2.x, self [[SL]] : $Test2<T>, value {{.*}} : $*(T, String), init {{.*}} : $@callee_guaranteed (@in T, @owned String) -> @out (T, String), set {{.*}} : $@callee_guaranteed (@in T, @owned String) -> ()
|
||||
init(x: (T, String), y: Int) {
|
||||
self.x = x
|
||||
self.y = y
|
||||
@@ -364,12 +370,13 @@ func test_default_inits() {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_CADycfc : $@convention(method) (@owned Test4) -> @owned Test4
|
||||
// CHECK: [[SL:%.*]] = mark_uninitialized [rootself] %0
|
||||
// CHECK: [[X_DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_C1xSivpfi : $@convention(thin) () -> Int
|
||||
// CHECK-NEXT: [[X_VALUE:%.*]] = apply [[X_DEFAULT]]() : $@convention(thin) () -> Int
|
||||
// CHECK: assign_or_init [init] #<abstract function>Test4.x, self %0 : $Test4, value [[X_VALUE]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set undef : $@convention(thin) (Int) -> @out Int
|
||||
// CHECK: assign_or_init [init] #<abstract function>Test4.x, self [[SL]] : $Test4, value [[X_VALUE]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set undef : $@convention(thin) (Int) -> @out Int
|
||||
// CHECK: [[Y_DEFAULT:%.*]] = function_ref @$s23assign_or_init_lowering18test_default_initsyyF5Test4L_C1ySSvpfi : $@convention(thin) () -> @owned String
|
||||
// CHECK-NEXT: [[Y_VALUE:%.*]] = apply [[Y_DEFAULT]]() : $@convention(thin) () -> @owned String
|
||||
// CHECK: assign_or_init [init] #<abstract function>Test4.y, self %0 : $Test4, value [[Y_VALUE]] : $String, init {{.*}} : $@convention(thin) (@owned String) -> @out String, set undef : $@convention(thin) (@owned String) -> @out String
|
||||
// CHECK: assign_or_init [init] #<abstract function>Test4.y, self [[SL]] : $Test4, value [[Y_VALUE]] : $String, init {{.*}} : $@convention(thin) (@owned String) -> @out String, set undef : $@convention(thin) (@owned String) -> @out String
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,7 +393,8 @@ func test_handling_of_superclass_properties() {
|
||||
|
||||
class Person : Entity {
|
||||
// CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering38test_handling_of_superclass_propertiesyyF6PersonL_C3ageADSi_tcfc : $@convention(method) (Int, @owned Person) -> @owned Person
|
||||
// CHECK: [[SELF:%.*]] = load [copy] %2 : $*Person
|
||||
// CHECK: [[SL:%.*]] = mark_uninitialized [derivedself] %2
|
||||
// CHECK: [[SELF:%.*]] = load [copy] [[SL]] : $*Person
|
||||
// CHECK-NEXT: [[SELF_AS_ENTITY:%.*]] = upcast [[SELF]] : $Person to $Entity
|
||||
// CHECK-NEXT: [[AGE_SETTER:%.*]] = class_method [[SELF_AS_ENTITY]] : $Entity, #<abstract function>Entity.age!setter : (Entity) -> (Int) -> (), $@convention(method) (Int, @guaranteed Entity) -> ()
|
||||
// CHECK-NEXT: {{.*}} = apply [[AGE_SETTER]](%0, [[SELF_AS_ENTITY]]) : $@convention(method) (Int, @guaranteed Entity) -> ()
|
||||
@@ -417,9 +425,9 @@ func test_handling_of_nonmutating_set() {
|
||||
// CHECK-LABEL: sil private [ossa] @$s23assign_or_init_lowering32test_handling_of_nonmutating_setyyF4TestL_V5countADSi_tcfC : $@convention(method) (Int, @thin Test.Type) -> Test
|
||||
// CHECK: [[INIT_VALUE:%.*]] = function_ref @$s23assign_or_init_lowering32test_handling_of_nonmutating_setyyF4TestL_V5countSivpfi : $@convention(thin) () -> Int
|
||||
// CHECK-NEXT: [[VALUE:%.*]] = apply [[INIT_VALUE]]() : $@convention(thin) () -> Int
|
||||
// CHECK: assign_or_init [init] #<abstract function>Test.count, self %2 : $*Test, value [[VALUE]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK: assign_or_init [set] #<abstract function>Test.count, self %2 : $*Test, value %0 : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK: assign_or_init [set] #<abstract function>Test.count, self %2 : $*Test, value [[ZERO:%.*]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK: assign_or_init [init] #<abstract function>Test.count, self %3 : $*Test, value [[VALUE]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK: assign_or_init [set] #<abstract function>Test.count, self %3 : $*Test, value %0 : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
|
||||
// CHECK: assign_or_init [set] #<abstract function>Test.count, self %3 : $*Test, value [[ZERO:%.*]] : $Int, init {{.*}} : $@convention(thin) (Int) -> @out Int, set {{.*}} : $@callee_guaranteed (Int) -> ()
|
||||
init(count: Int) {
|
||||
self.count = count
|
||||
self.count = 0
|
||||
|
||||
@@ -28,18 +28,19 @@ public class Test {
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @$s14init_accessors4TestCACycfc : $@convention(method) (@owned Test) -> @owned Test
|
||||
//
|
||||
// CHECK: [[MU:%.*]] = mark_uninitialized [rootself] %0 : $Test
|
||||
// CHECK: [[DEFAULT_VALUE_INIT:%.*]] = function_ref @$s14init_accessors4TestC5stateAC5StateOvpfi : $@convention(thin) () -> @out Test.State
|
||||
// CHECK-NEXT: [[DEFAULT_VALUE_SLOT:%.*]] = alloc_stack $Test.State
|
||||
// CHECK-NEXT: {{.*}} = apply [[DEFAULT_VALUE_INIT]]([[DEFAULT_VALUE_SLOT]]) : $@convention(thin) () -> @out Test.State
|
||||
// CHECK-NEXT: [[DEFAULT_VALUE:%.*]] = load [take] [[DEFAULT_VALUE_SLOT]] : $*Test.State
|
||||
// CHECK: [[NEW_VALUE:%.*]] = alloc_stack $Test.State
|
||||
// CHECK-NEXT: store [[DEFAULT_VALUE]] to [init] [[NEW_VALUE]] : $*Test.State
|
||||
// CHECK: assign_or_init [init] #Test.state, self %0 : $Test, value [[NEW_VALUE]] : $*Test.State, init {{.*}} : $@convention(thin) (@in Test.State) -> @out Test.State, set {{.*}} : $@callee_guaranteed (@in Test.State) -> ()
|
||||
// CHECK: assign_or_init [init] #Test.state, self [[MU]] : $Test, value [[NEW_VALUE]] : $*Test.State, init {{.*}} : $@convention(thin) (@in Test.State) -> @out Test.State, set {{.*}} : $@callee_guaranteed (@in Test.State) -> ()
|
||||
//
|
||||
// CHECK: [[START_STATE:%.*]] = enum $Test.State, #Test.State.start!enumelt
|
||||
// CHECK-NEXT: [[NEW_VALUE:%.*]] = alloc_stack $Test.State
|
||||
// CHECK-NEXT: store [[START_STATE]] to [trivial] [[NEW_VALUE]] : $*Test.State
|
||||
// CHECK: assign_or_init [set] #Test.state, self %0 : $Test, value [[NEW_VALUE]] : $*Test.State, init {{.*}} : $@convention(thin) (@in Test.State) -> @out Test.State, set {{.*}} : $@callee_guaranteed (@in Test.State) -> ()
|
||||
// CHECK: assign_or_init [set] #Test.state, self [[MU]] : $Test, value [[NEW_VALUE]] : $*Test.State, init {{.*}} : $@convention(thin) (@in Test.State) -> @out Test.State, set {{.*}} : $@callee_guaranteed (@in Test.State) -> ()
|
||||
public init() {
|
||||
state = .start
|
||||
}
|
||||
|
||||
@@ -80,9 +80,12 @@ _ = Z().capturesSelf()
|
||||
// CHECK: apply [[F]](%{{.+}}, %{{.+}}) : $@convention(method) (Int, @thick C.Type) -> @owned C
|
||||
|
||||
// CHECK: [[Z:%.*]] = alloc_ref $Z
|
||||
// CHECK: [[C:%.*]] = upcast [[Z]]
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[C]]
|
||||
// CHECK: [[DC:%.*]] = unchecked_ref_cast [[EI]]
|
||||
// CHECK: function_ref inline_self.Z.capturesSelf() -> Self
|
||||
// CHECK: [[F:%[0-9]+]] = function_ref @$s11inline_self1ZC12capturesSelfACXDyF : $@convention(method) (@guaranteed Z) -> @owned Z
|
||||
// CHECK: apply [[F]]([[Z]]) : $@convention(method) (@guaranteed Z) -> @owned
|
||||
// CHECK: apply [[F]]([[DC]]) : $@convention(method) (@guaranteed Z) -> @owned
|
||||
// CHECK: return
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s11inline_self1ZC16callCapturesSelfACXDyF : $@convention(method)
|
||||
|
||||
256
test/SILOptimizer/let-property-lowering.sil
Normal file
256
test/SILOptimizer/let-property-lowering.sil
Normal file
@@ -0,0 +1,256 @@
|
||||
// RUN: %target-sil-opt %s -let-property-lowering | %FileCheck %s
|
||||
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
sil_stage raw
|
||||
|
||||
import Builtin
|
||||
import Swift
|
||||
import SwiftShims
|
||||
|
||||
class C {
|
||||
@_hasStorage let a: Int
|
||||
}
|
||||
|
||||
class B {
|
||||
}
|
||||
|
||||
class D : B {
|
||||
@_hasStorage let a: Int
|
||||
}
|
||||
|
||||
class E {
|
||||
@_hasStorage let a: Int
|
||||
@_hasStorage let b: Int
|
||||
@_hasStorage var c: Int
|
||||
}
|
||||
|
||||
sil @unknown_func : $@convention(thin) (@guaranteed C) -> ()
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_init_store :
|
||||
// CHECK: ref_element_addr %3
|
||||
// CHECK-NEXT: store
|
||||
// CHECK-NEXT: end_borrow
|
||||
// CHECK-NEXT: [[EI:%.*]] = end_init_let_ref %2
|
||||
// CHECK-NEXT: [[B:%.*]] = begin_borrow [[EI]]
|
||||
// CHECK-NEXT: [[A:%.*]] = ref_element_addr [immutable] [[B]]
|
||||
// CHECK-NEXT: load [trivial] [[A]]
|
||||
// CHECK: return [[EI]]
|
||||
// CHECK: } // end sil function 'test_init_store'
|
||||
sil [ossa] @test_init_store : $@convention(thin) (@owned C, Int) -> @owned C {
|
||||
bb0(%0 : @owned $C, %1 : $Int):
|
||||
%2 = mark_uninitialized [rootself] %0 : $C
|
||||
%3 = begin_borrow %2 : $C
|
||||
%4 = ref_element_addr %3 : $C, #C.a
|
||||
store %1 to [trivial] %4 : $*Int
|
||||
end_borrow %3 : $C
|
||||
%7 = begin_borrow %2 : $C
|
||||
%8 = ref_element_addr %7 : $C, #C.a
|
||||
%9 = load [trivial] %8 : $*Int
|
||||
end_borrow %7 : $C
|
||||
return %2 : $C
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_let_read :
|
||||
// CHECK: ref_element_addr [immutable] %0
|
||||
// CHECK: } // end sil function 'test_let_read'
|
||||
sil [ossa] @test_let_read : $@convention(thin) (@guaranteed C) -> Int {
|
||||
bb0(%0 : @guaranteed $C):
|
||||
%1 = ref_element_addr %0 : $C, #C.a
|
||||
%2 = load [trivial] %1 : $*Int
|
||||
return %2 : $Int
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_init_assign :
|
||||
// CHECK: ref_element_addr %3
|
||||
// CHECK-NEXT: assign
|
||||
// CHECK-NEXT: end_borrow
|
||||
// CHECK-NEXT: [[EI:%.*]] = end_init_let_ref %2
|
||||
// CHECK-NEXT: [[B:%.*]] = begin_borrow [[EI]]
|
||||
// CHECK-NEXT: [[A:%.*]] = ref_element_addr [immutable] [[B]]
|
||||
// CHECK-NEXT: load [trivial] [[A]]
|
||||
// CHECK: return [[EI]]
|
||||
// CHECK: } // end sil function 'test_init_assign'
|
||||
sil [ossa] @test_init_assign : $@convention(thin) (@owned C, Int) -> @owned C {
|
||||
bb0(%0 : @owned $C, %1 : $Int):
|
||||
%2 = mark_uninitialized [rootself] %0 : $C
|
||||
%3 = begin_borrow %2 : $C
|
||||
%4 = ref_element_addr %3 : $C, #C.a
|
||||
assign %1 to [init] %4 : $*Int
|
||||
end_borrow %3 : $C
|
||||
%7 = begin_borrow %2 : $C
|
||||
%8 = ref_element_addr %7 : $C, #C.a
|
||||
%9 = load [trivial] %8 : $*Int
|
||||
end_borrow %7 : $C
|
||||
return %2 : $C
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_init_copy_addr :
|
||||
// CHECK: ref_element_addr %3
|
||||
// CHECK-NEXT: copy_addr
|
||||
// CHECK-NEXT: end_borrow
|
||||
// CHECK-NEXT: [[EI:%.*]] = end_init_let_ref %2
|
||||
// CHECK-NEXT: [[B:%.*]] = begin_borrow [[EI]]
|
||||
// CHECK-NEXT: [[A:%.*]] = ref_element_addr [immutable] [[B]]
|
||||
// CHECK-NEXT: load [trivial] [[A]]
|
||||
// CHECK: return [[EI]]
|
||||
// CHECK: } // end sil function 'test_init_copy_addr'
|
||||
sil [ossa] @test_init_copy_addr : $@convention(thin) (@owned C, @in Int) -> @owned C {
|
||||
bb0(%0 : @owned $C, %1 : $*Int):
|
||||
%2 = mark_uninitialized [rootself] %0 : $C
|
||||
%3 = begin_borrow %2 : $C
|
||||
%4 = ref_element_addr %3 : $C, #C.a
|
||||
copy_addr %1 to [init] %4 : $*Int
|
||||
end_borrow %3 : $C
|
||||
%7 = begin_borrow %2 : $C
|
||||
%8 = ref_element_addr %7 : $C, #C.a
|
||||
%9 = load [trivial] %8 : $*Int
|
||||
end_borrow %7 : $C
|
||||
return %2 : $C
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_empty :
|
||||
// CHECK: %1 = mark_uninitialized [rootself] %0
|
||||
// CHECK-NEXT: %2 = end_init_let_ref %1
|
||||
// CHECK: return %2
|
||||
// CHECK: } // end sil function 'test_empty'
|
||||
sil [ossa] @test_empty : $@convention(thin) (@owned C) -> @owned C {
|
||||
bb0(%0 : @owned $C):
|
||||
%1 = mark_uninitialized [rootself] %0 : $C
|
||||
return %1 : $C
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_multiple_fields :
|
||||
// CHECK: ref_element_addr {{.*}}, #E.a
|
||||
// CHECK: ref_element_addr {{.*}}, #E.b
|
||||
// CHECK: end_borrow
|
||||
// CHECK-NEXT: [[EI:%.*]] = end_init_let_ref
|
||||
// CHECK-NEXT: begin_borrow [[EI]]
|
||||
// CHECK: ref_element_addr {{.*}}, #E.c
|
||||
// CHECK: return [[EI]]
|
||||
// CHECK: } // end sil function 'test_multiple_fields'
|
||||
sil [ossa] @test_multiple_fields : $@convention(thin) (@owned E, Int) -> @owned E {
|
||||
bb0(%0 : @owned $E, %1 : $Int):
|
||||
%2 = mark_uninitialized [rootself] %0 : $E
|
||||
%3 = begin_borrow %2 : $E
|
||||
%4 = ref_element_addr %3 : $E, #E.a
|
||||
store %1 to [trivial] %4 : $*Int
|
||||
end_borrow %3 : $E
|
||||
%6 = begin_borrow %2 : $E
|
||||
%7 = ref_element_addr %6 : $E, #E.b
|
||||
store %1 to [trivial] %7 : $*Int
|
||||
end_borrow %6 : $E
|
||||
%10 = begin_borrow %2 : $E
|
||||
%11 = ref_element_addr %10 : $E, #E.c
|
||||
store %1 to [trivial] %11 : $*Int
|
||||
end_borrow %10 : $E
|
||||
return %2 : $E
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_derived :
|
||||
// CHECK-NOT: end_init_let_ref
|
||||
// CHECK: [[B:%.*]] = load_borrow
|
||||
// CHECK-NEXT: ref_element_addr [[B]]
|
||||
// CHECK-NOT: end_init_let_ref
|
||||
// CHECK: } // end sil function 'test_derived'
|
||||
sil [ossa] @test_derived : $@convention(thin) (@owned D, Int) -> @owned D {
|
||||
bb0(%0 : @owned $D, %1 : $Int):
|
||||
%2 = alloc_stack $D
|
||||
%3 = mark_uninitialized [derivedself] %2 : $*D
|
||||
store %0 to [init] %3 : $*D
|
||||
%5 = load_borrow %3 : $*D
|
||||
%6 = ref_element_addr %5 : $D, #D.a
|
||||
assign %1 to [init] %6 : $*Int
|
||||
end_borrow %5 : $D
|
||||
%9 = load [take] %2 : $*D
|
||||
dealloc_stack %2 : $*D
|
||||
return %9 : $D
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_multi_block1 :
|
||||
// CHECK: bb1:
|
||||
// CHECK: end_borrow
|
||||
// CHECK-NEXT: [[EI1:%.*]] = end_init_let_ref %2
|
||||
// CHECK-NEXT: br bb3([[EI1]] : $C)
|
||||
// CHECK: bb2:
|
||||
// CHECK: end_borrow
|
||||
// CHECK-NEXT: [[EI2:%.*]] = end_init_let_ref %2
|
||||
// CHECK-NEXT: br bb3([[EI2]] : $C)
|
||||
// CHECK: bb3([[P:%.*]] : @owned $C):
|
||||
// CHECK-NEXT: return [[P]]
|
||||
// CHECK: } // end sil function 'test_multi_block1'
|
||||
sil [ossa] @test_multi_block1 : $@convention(thin) (@owned C, Int) -> @owned C {
|
||||
bb0(%0 : @owned $C, %1 : $Int):
|
||||
%2 = mark_uninitialized [rootself] %0 : $C
|
||||
cond_br undef, bb1, bb2
|
||||
bb1:
|
||||
%3 = begin_borrow %2 : $C
|
||||
%4 = ref_element_addr %3 : $C, #C.a
|
||||
store %1 to [trivial] %4 : $*Int
|
||||
end_borrow %3 : $C
|
||||
br bb3
|
||||
bb2:
|
||||
%7 = begin_borrow %2 : $C
|
||||
%8 = ref_element_addr %7 : $C, #C.a
|
||||
store %1 to [trivial] %8 : $*Int
|
||||
end_borrow %7 : $C
|
||||
br bb3
|
||||
bb3:
|
||||
return %2 : $C
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @test_multi_block2 :
|
||||
// CHECK: bb1:
|
||||
// CHECK: end_borrow
|
||||
// CHECK-NEXT: end_init_let_ref %2
|
||||
// CHECK: bb2:
|
||||
// CHECK-NEXT: end_init_let_ref %2
|
||||
// CHECK-NEXT: unreachable
|
||||
// CHECK: bb3:
|
||||
// CHECK: } // end sil function 'test_multi_block2'
|
||||
sil [ossa] @test_multi_block2 : $@convention(thin) (@owned C, Int) -> @owned C {
|
||||
bb0(%0 : @owned $C, %1 : $Int):
|
||||
%2 = mark_uninitialized [rootself] %0 : $C
|
||||
cond_br undef, bb1, bb2
|
||||
bb1:
|
||||
%3 = begin_borrow %2 : $C
|
||||
%4 = ref_element_addr %3 : $C, #C.a
|
||||
store %1 to [trivial] %4 : $*Int
|
||||
end_borrow %3 : $C
|
||||
br bb3
|
||||
bb2:
|
||||
unreachable
|
||||
bb3:
|
||||
return %2 : $C
|
||||
}
|
||||
// CHECK-LABEL: sil [ossa] @test_partial_deinitialization :
|
||||
// CHECK: bb1:
|
||||
// CHECK: end_borrow
|
||||
// CHECK-NEXT: end_init_let_ref %2
|
||||
// CHECK: bb2:
|
||||
// CHECK: end_borrow
|
||||
// CHECK-NEXT: end_init_let_ref %2
|
||||
// CHECK: bb3:
|
||||
// CHECK: } // end sil function 'test_partial_deinitialization'
|
||||
sil [ossa] @test_partial_deinitialization : $@convention(thin) (@owned C, Int) -> @owned C {
|
||||
bb0(%0 : @owned $C, %1 : $Int):
|
||||
%2 = mark_uninitialized [rootself] %0 : $C
|
||||
cond_br undef, bb1, bb2
|
||||
bb1:
|
||||
%3 = begin_borrow %2 : $C
|
||||
%4 = ref_element_addr %3 : $C, #C.a
|
||||
store %1 to [trivial] %4 : $*Int
|
||||
end_borrow %3 : $C
|
||||
br bb3
|
||||
bb2:
|
||||
%7 = begin_borrow %2 : $C
|
||||
%8 = ref_element_addr %7 : $C, #C.a
|
||||
%9 = begin_access [deinit] [static] %8 : $*Int
|
||||
destroy_addr %9 : $*Int
|
||||
end_access %9 : $*Int
|
||||
end_borrow %7 : $C
|
||||
unreachable
|
||||
bb3:
|
||||
return %2 : $C
|
||||
}
|
||||
|
||||
193
test/SILOptimizer/let-property-lowering.swift
Normal file
193
test/SILOptimizer/let-property-lowering.swift
Normal file
@@ -0,0 +1,193 @@
|
||||
// RUN: %target-swift-frontend -emit-sil -module-name=test %s | %FileCheck %s
|
||||
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test6testitySiAA1CCF :
|
||||
// CHECK: ref_element_addr [immutable] %0 : $C, #C.a
|
||||
// CHECK: } // end sil function '$s4test6testitySiAA1CCF'
|
||||
@discardableResult
|
||||
func testit(_ c: C) -> Int {
|
||||
return c.a
|
||||
}
|
||||
|
||||
class C {
|
||||
final let a: Int
|
||||
final var b: Int
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1CCACycfc :
|
||||
// CHECK: ref_element_addr %0 : $C, #C.a
|
||||
// CHECK: store
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %0
|
||||
// CHECK: ref_element_addr [[EI]] : $C, #C.b
|
||||
// CHECK: store
|
||||
// CHECK: [[A:%.*]] = ref_element_addr [immutable] [[EI]] : $C, #C.a
|
||||
// CHECK: [[L:%.*]] = load [[A]]
|
||||
// CHECK: apply {{.*}}([[L]])
|
||||
// CHECK: } // end sil function '$s4test1CCACycfc'
|
||||
init() {
|
||||
self.a = 1
|
||||
self.b = 2
|
||||
takeint(self.a)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1CC1bACSgSb_tcfc :
|
||||
// CHECK: bb1:
|
||||
// CHECK: ref_element_addr %1 : $C, #C.a
|
||||
// CHECK: store
|
||||
// CHECK: [[EI1:%.*]] = end_init_let_ref %1
|
||||
// CHECK: ref_element_addr [[EI1]] : $C, #C.b
|
||||
// CHECK: store
|
||||
// CHECK: apply {{.*}}([[EI1]])
|
||||
// CHECK: br bb3([[EI1]] : $C)
|
||||
// CHECK: bb2:
|
||||
// CHECK: ref_element_addr %1 : $C, #C.a
|
||||
// CHECK: store
|
||||
// CHECK: [[EI2:%.*]] = end_init_let_ref %1
|
||||
// CHECK: ref_element_addr [[EI2]] : $C, #C.b
|
||||
// CHECK: store
|
||||
// CHECK: apply {{.*}}([[EI2]])
|
||||
// CHECK: br bb3([[EI2]] : $C)
|
||||
// CHECK: bb3([[P:%.*]] : $C):
|
||||
// CHECK: [[O:%.*]] = enum $Optional<C>, #Optional.some!enumelt, [[P]]
|
||||
// CHECK: return [[O]]
|
||||
// CHECK: } // end sil function '$s4test1CC1bACSgSb_tcfc'
|
||||
init?(b: Bool) {
|
||||
if b {
|
||||
self.a = 1
|
||||
self.b = 2
|
||||
testit(self)
|
||||
} else {
|
||||
self.a = 3
|
||||
self.b = 4
|
||||
testit(self)
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1CC1cACSb_tcfc :
|
||||
// CHECK: [[A:%.*]] = ref_element_addr %1 : $C, #C.a
|
||||
// CHECK: store {{.*}} to [[A]] : $*Int
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: bb1:
|
||||
// CHEKC: ref_element_addr [[EI]] : $C, #C.b
|
||||
// CHECK: return [[EI]]
|
||||
// CHECK: } // end sil function '$s4test1CC1cACSb_tcfc'
|
||||
init(c: Bool) {
|
||||
self.a = 1
|
||||
repeat {
|
||||
self.b = 2
|
||||
} while pred()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1CC1dACSgSb_tcfc :
|
||||
// CHECK: ref_element_addr %1 : $C, #C.a
|
||||
// CHECK-NEXT: store
|
||||
// CHECK: ref_element_addr %1 : $C, #C.a
|
||||
// CHECK-NEXT: begin_access [deinit]
|
||||
// CHECK: end_access
|
||||
// CHECK: end_init_let_ref %1
|
||||
// CHECK: } // end sil function '$s4test1CC1dACSgSb_tcfc'
|
||||
init?(d: Bool) {
|
||||
self.a = 1
|
||||
return nil
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1CC1eACSgSb_tcfc :
|
||||
// CHECK: ref_element_addr %1 : $C, #C.a
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: ref_element_addr [[EI]] : $C, #C.b
|
||||
// CHECK: apply {{.*}}([[EI]])
|
||||
// CHECK: } // end sil function '$s4test1CC1eACSgSb_tcfc'
|
||||
init?(e: Bool) {
|
||||
self.a = 1
|
||||
self.b = 2
|
||||
testit(self)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1CC1fACSb_tKcfc :
|
||||
// CHECK: ref_element_addr %1 : $C, #C.a
|
||||
// CHECK-NEXT: store
|
||||
// CHECK: ref_element_addr %1 : $C, #C.a
|
||||
// CHECK-NEXT: begin_access [deinit]
|
||||
// CHECK: end_access
|
||||
// CHECK: end_init_let_ref %1
|
||||
// CHECK: } // end sil function '$s4test1CC1fACSb_tKcfc'
|
||||
init(f: Bool) throws {
|
||||
self.a = 1
|
||||
throw E()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1CC1gACSb_tKcfc :
|
||||
// CHECK: ref_element_addr %1 : $C, #C.a
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: ref_element_addr [[EI]] : $C, #C.b
|
||||
// CHECK: apply {{.*}}([[EI]])
|
||||
// CHECK: } // end sil function '$s4test1CC1gACSb_tKcfc'
|
||||
init(g: Bool) throws {
|
||||
self.a = 1
|
||||
self.b = 2
|
||||
testit(self)
|
||||
throw E()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1CC1hACSgSb_tcfc :
|
||||
// CHECK: bb1:
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: enum {{.*}} #Optional.none
|
||||
// CHECK: bb2:
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: enum {{.*}} #Optional.some!enumelt, [[EI]]
|
||||
// CHECK: } // end sil function '$s4test1CC1hACSgSb_tcfc'
|
||||
init?(h: Bool) {
|
||||
self.a = 1
|
||||
if h {
|
||||
return nil
|
||||
}
|
||||
self.b = 2
|
||||
}
|
||||
}
|
||||
|
||||
class X {
|
||||
final let c: C
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1XCyAcA1CCcfc :
|
||||
// CHECK: ref_element_addr %1 : $X, #X.c
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %1
|
||||
// CHECK: return [[EI]]
|
||||
// CHECK: } // end sil function '$s4test1XCyAcA1CCcfc'
|
||||
init(_ c: C) {
|
||||
self.c = c
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1XCfd :
|
||||
// CHECK: ref_element_addr %0 : $X, #X.c
|
||||
// CHECK: ref_element_addr %0 : $X, #X.c
|
||||
// CHECK: } // end sil function '$s4test1XCfd'
|
||||
deinit {
|
||||
testit(c)
|
||||
}
|
||||
}
|
||||
|
||||
class D : C {
|
||||
final let c: Int
|
||||
|
||||
// CHECK-LABEL: sil hidden @$s4test1DCACycfc :
|
||||
// CHECK-NOT: end_init_let_ref
|
||||
// CHECK: ref_element_addr %0 : $D, #D.c
|
||||
// CHECK-NOT: end_init_let_ref
|
||||
// CHECK: } // end sil function '$s4test1DCACycfc'
|
||||
override init() {
|
||||
self.c = 27
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
func takeint(_ i: Int) {
|
||||
}
|
||||
|
||||
func pred() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
struct E : Error {}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// Check that it doesn't crash with properties in ObjC extensions
|
||||
|
||||
// CHECK-LABEL: sil @$s4test0A13ObjcInterfaceySiSo0bC0CF
|
||||
// CHECK: ref_element_addr %0 : $ObjcInterface, #ObjcInterface.i
|
||||
// CHECK: ref_element_addr [immutable] %0 : $ObjcInterface, #ObjcInterface.i
|
||||
// CHECK: } // end sil function '$s4test0A13ObjcInterfaceySiSo0bC0CF'
|
||||
public func testObjcInterface(_ x: ObjcInterface) -> Int {
|
||||
return x.i
|
||||
|
||||
@@ -12,11 +12,12 @@ func barrier()
|
||||
|
||||
// CHECK-LABEL: sil {{.*}} [lexical_lifetimes] @funky : {{.*}} {
|
||||
// CHECK: [[INSTANCE:%[^,]+]] = alloc_ref $C
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref [[INSTANCE]]
|
||||
// CHECK: [[BORROW:%[^,]+]] = function_ref @borrow
|
||||
// CHECK: apply [[BORROW]]([[INSTANCE]])
|
||||
// CHECK: apply [[BORROW]]([[EI]])
|
||||
// CHECK: [[BARRIER:%[^,]+]] = function_ref @barrier
|
||||
// CHECK: apply [[BARRIER]]()
|
||||
// CHECK: strong_release [[INSTANCE]]
|
||||
// CHECK: strong_release [[EI]]
|
||||
// CHECK-LABEL: } // end sil function 'funky'
|
||||
@_silgen_name("funky")
|
||||
@_lexicalLifetimes
|
||||
|
||||
@@ -24,7 +24,8 @@ struct ListEntry<T> : ~Copyable {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil private [ossa] @boxInit : $@convention(method) <T> (@in _Node<T>, @owned _Box<T>) -> @owned _Box<T> {
|
||||
// CHECK: bb0([[INPUT:%.*]] : $*_Node<T>, [[SELF:%.*]] : @owned
|
||||
// CHECK: bb0([[INPUT:%.*]] : $*_Node<T>, %1 : @owned
|
||||
// CHECK: [[SELF:%.*]] = mark_uninitialized [rootself] %1
|
||||
// CHECK: [[BORROW_SELF:%.*]] = begin_borrow [[SELF]]
|
||||
// CHECK: [[REF:%.*]] = ref_element_addr [[BORROW_SELF]]
|
||||
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[REF]]
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// A test that makes sure end to end in a copyable class containing a
|
||||
// non-copyable type, in the init, we only have a single destroy_addr.
|
||||
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
public struct MO: ~Copyable {
|
||||
var x: Int8 = 0
|
||||
deinit { print("destroyed MO") }
|
||||
@@ -15,15 +17,16 @@ public class MOHaver {
|
||||
// CHECK-LABEL: sil hidden @$s028moveonly_class_inits_end_to_D07MOHaverCACycfc : $@convention(method) (@owned MOHaver) -> @owned MOHaver {
|
||||
// CHECK: bb0([[ARG:%.*]] :
|
||||
// CHECK-NEXT: debug_value [[ARG]]
|
||||
// CHECK-NEXT: [[EI:%.*]] = end_init_let_ref [[ARG]]
|
||||
// CHECK-NEXT: [[META:%.*]] = metatype
|
||||
// CHECK-NEXT: function_ref MO.init()
|
||||
// CHECK-NEXT: [[FUNC:%.*]] = function_ref @$s028moveonly_class_inits_end_to_D02MOVACycfC :
|
||||
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FUNC]]([[META]])
|
||||
// CHECK-NEXT: [[REF:%.*]] = ref_element_addr [[ARG]]
|
||||
// CHECK-NEXT: [[REF:%.*]] = ref_element_addr [[EI]]
|
||||
// CHECK-NEXT: [[REF_ACCESS:%.*]] = begin_access [modify] [dynamic] [[REF]]
|
||||
// CHECK-NEXT: store [[RESULT]] to [[REF_ACCESS]]
|
||||
// CHECK-NEXT: end_access [[REF_ACCESS]]
|
||||
// CHECK-NEXT: return [[ARG]]
|
||||
// CHECK-NEXT: return [[EI]]
|
||||
// CHECK-NEXT: } // end sil function '$s028moveonly_class_inits_end_to_D07MOHaverCACycfc'
|
||||
init() {
|
||||
self.mo = MO()
|
||||
|
||||
27
test/SILOptimizer/redundant_load_elimination.swift
Normal file
27
test/SILOptimizer/redundant_load_elimination.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
// RUN: %target-swift-frontend -parse-as-library -module-name test %s -O -emit-sil | %FileCheck %s
|
||||
|
||||
// REQUIRES: swift_in_compiler
|
||||
|
||||
|
||||
public final class C {
|
||||
let i: Int
|
||||
|
||||
init(i: Int) {
|
||||
self.i = i
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil @$s4test0A8LetField_1fSi_SitAA1CC_yyXEtF :
|
||||
// CHECK: [[A:%.*]] = ref_element_addr [immutable] %0 : $C, #C.i
|
||||
// CHECK: [[L:%.*]] = load [[A]]
|
||||
// CHECK: apply
|
||||
// CHECK-NOT: load
|
||||
// CHECK: tuple ([[L]] : $Int, [[L]] : $Int)
|
||||
// CHECK: } // end sil function '$s4test0A8LetField_1fSi_SitAA1CC_yyXEtF'
|
||||
public func testLetField(_ c: C, f: () -> ()) -> (Int, Int) {
|
||||
let a = c.i
|
||||
f()
|
||||
let b = c.i
|
||||
return (a, b)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ extension P {
|
||||
|
||||
final class C: P {}
|
||||
// CHECK-LABEL: sil @$s32sil_combine_concrete_existential14testReturnSelfAA1P_pyF : $@convention(thin) () -> @owned any P {
|
||||
// CHECK: [[E1:%.*]] = init_existential_ref %0 : $C : $C, $any P
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %0
|
||||
// CHECK: [[E1:%.*]] = init_existential_ref [[EI]] : $C : $C, $any P
|
||||
// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $any P to $@opened("{{.*}}", any P) Self
|
||||
// CHECK: [[F1:%.*]] = function_ref @$s32sil_combine_concrete_existential1PPAAE10returnSelfxyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
|
||||
// CHECK: [[C1:%.*]] = apply [[F1]]<@opened("{{.*}}", any P) Self>([[O1]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0
|
||||
@@ -59,7 +60,8 @@ final class CC: PP {
|
||||
|
||||
// The first apply has been devirtualized and inlined. The second remains unspecialized.
|
||||
// CHECK-LABEL: sil @$s32sil_combine_concrete_existential29testWitnessReturnOptionalSelfAA2PP_pSgyF : $@convention(thin) () -> @owned Optional<any PP> {
|
||||
// CHECK: [[E1:%.*]] = init_existential_ref %0 : $CC : $CC, $any PP
|
||||
// CHECK: [[EI:%.*]] = end_init_let_ref %0
|
||||
// CHECK: [[E1:%.*]] = init_existential_ref [[EI]] : $CC : $CC, $any PP
|
||||
// CHECK: [[O1:%.*]] = open_existential_ref [[E1]] : $any PP to $@opened("{{.*}}", any PP) Self
|
||||
// CHECK: [[E2:%.*]] = init_existential_ref %{{.*}} : $@opened("{{.*}}", any PP) Self : $@opened("{{.*}}", any PP) Self, $any PP
|
||||
// CHECK: [[O2:%.*]] = open_existential_ref [[E2]] : $any PP to $@opened("{{.*}}", any PP) Self
|
||||
|
||||
@@ -119,7 +119,7 @@ public class Other {
|
||||
// CHECK: bb0
|
||||
// CHECK: debug_value
|
||||
// CHECK: integer_literal
|
||||
// CHECK: [[R1:%.*]] = ref_element_addr %0 : $Other, #Other.z
|
||||
// CHECK: [[R1:%.*]] = ref_element_addr [immutable] %0 : $Other, #Other.z
|
||||
// CHECK: [[O1:%.*]] = open_existential_addr immutable_access [[R1]] : $*any DerivedProtocol to $*@opened("{{.*}}", any DerivedProtocol) Self
|
||||
// CHECK: [[W1:%.*]] = witness_method $@opened("{{.*}}", any DerivedProtocol) Self, #DerivedProtocol.foo : <Self where Self : DerivedProtocol> (Self) -> () -> Int, [[O1]] : $*@opened("{{.*}}", any DerivedProtocol) Self : $@convention(witness_method: DerivedProtocol) <τ_0_0 where τ_0_0 : DerivedProtocol> (@in_guaranteed τ_0_0) -> Int
|
||||
// CHECK: apply [[W1]]<@opened("{{.*}}", any DerivedProtocol) Self>([[O1]]) : $@convention(witness_method: DerivedProtocol) <τ_0_0 where τ_0_0 : DerivedProtocol> (@in_guaranteed τ_0_0) -> Int
|
||||
@@ -129,7 +129,7 @@ public class Other {
|
||||
// CHECK: tuple_extract
|
||||
// CHECK: tuple_extract
|
||||
// CHECK: cond_fail
|
||||
// CHECK: [[R2:%.*]] = ref_element_addr %0 : $Other, #Other.p
|
||||
// CHECK: [[R2:%.*]] = ref_element_addr [immutable] %0 : $Other, #Other.p
|
||||
// CHECK: [[O2:%.*]] = open_existential_addr immutable_access [[R2]] : $*any PublicProtocol to $*@opened("{{.*}}", any PublicProtocol) Self
|
||||
// CHECK: [[W2:%.*]] = witness_method $@opened("{{.*}}", any PublicProtocol) Self, #PublicProtocol.foo : <Self where Self : PublicProtocol> (Self) -> () -> Int, [[O2]] : $*@opened("{{.*}}", any PublicProtocol) Self : $@convention(witness_method: PublicProtocol) <τ_0_0 where τ_0_0 : PublicProtocol> (@in_guaranteed τ_0_0) -> Int
|
||||
// CHECK: apply [[W2]]<@opened("{{.*}}", any PublicProtocol) Self>([[O2]]) : $@convention(witness_method: PublicProtocol) <τ_0_0 where τ_0_0 : PublicProtocol> (@in_guaranteed τ_0_0) -> Int
|
||||
@@ -143,7 +143,7 @@ public class Other {
|
||||
// CHECK: tuple_extract
|
||||
// CHECK: tuple_extract
|
||||
// CHECK: cond_fail
|
||||
// CHECK: [[R3:%.*]] = ref_element_addr %0 : $Other, #Other.r
|
||||
// CHECK: [[R3:%.*]] = ref_element_addr [immutable] %0 : $Other, #Other.r
|
||||
// CHECK: [[O3:%.*]] = open_existential_addr immutable_access [[R3]] : $*any GenericProtocol to $*@opened("{{.*}}", any GenericProtocol) Self
|
||||
// CHECK: [[W3:%.*]] = witness_method $@opened("{{.*}}", any GenericProtocol) Self, #GenericProtocol.foo : <Self where Self : GenericProtocol> (Self) -> () -> Int, [[O3]] : $*@opened("{{.*}}", any GenericProtocol) Self : $@convention(witness_method: GenericProtocol) <τ_0_0 where τ_0_0 : GenericProtocol> (@in_guaranteed τ_0_0) -> Int
|
||||
// CHECK: apply [[W3]]<@opened("{{.*}}", any GenericProtocol) Self>([[O3]]) : $@convention(witness_method: GenericProtocol) <τ_0_0 where τ_0_0 : GenericProtocol> (@in_guaranteed τ_0_0) -> Int
|
||||
@@ -152,7 +152,7 @@ public class Other {
|
||||
// CHECK: tuple_extract
|
||||
// CHECK: tuple_extract
|
||||
// CHECK: cond_fail
|
||||
// CHECK: [[R4:%.*]] = ref_element_addr %0 : $Other, #Other.s
|
||||
// CHECK: [[R4:%.*]] = ref_element_addr [immutable] %0 : $Other, #Other.s
|
||||
// CHECK: [[O4:%.*]] = open_existential_addr immutable_access %36 : $*any MultipleConformanceProtocol to $*@opened("{{.*}}", any MultipleConformanceProtocol) Self
|
||||
// CHECK: [[W4:%.*]] = witness_method $@opened("{{.*}}", any MultipleConformanceProtocol) Self, #MultipleConformanceProtocol.foo : <Self where Self : MultipleConformanceProtocol> (Self) -> () -> Int, %37 : $*@opened("{{.*}}", any MultipleConformanceProtocol) Self : $@convention(witness_method: MultipleConformanceProtocol) <τ_0_0 where τ_0_0 : MultipleConformanceProtocol> (@in_guaranteed τ_0_0) -> Int
|
||||
// CHECK: apply [[W4]]<@opened("{{.*}}", any MultipleConformanceProtocol) Self>(%37) : $@convention(witness_method: MultipleConformanceProtocol) <τ_0_0 where τ_0_0 : MultipleConformanceProtocol> (@in_guaranteed τ_0_0) -> Int
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
// EXTRACT-INIT-LABEL: sil @$s5basic7VehicleC1nACSi_tcfc : $@convention(method) (Int, @owned Vehicle) -> @owned Vehicle {
|
||||
// EXTRACT-INIT: bb0
|
||||
// EXTRACT-INIT-NEXT: end_init_let_ref
|
||||
// EXTRACT-INIT-NEXT: ref_element_addr
|
||||
// EXTRACT-INIT-NEXT: begin_access [init] [static]
|
||||
// EXTRACT-INIT-NEXT: store
|
||||
|
||||
@@ -29,7 +29,7 @@ public func myPrint(_ k: Klass) { print(k) }
|
||||
// OPT: bb0([[UNMANAGED:%.*]] :
|
||||
// OPT: [[UNMANAGED_REF:%.*]] = struct_extract [[UNMANAGED]]
|
||||
// OPT: [[REF:%.*]] = unmanaged_to_ref [[UNMANAGED_REF]]
|
||||
// OPT: [[REF_ELT_ADDR:%.*]] = ref_element_addr [[REF]] : $KlassContainer, #KlassContainer.k
|
||||
// OPT: [[REF_ELT_ADDR:%.*]] = ref_element_addr [immutable] [[REF]] : $KlassContainer, #KlassContainer.k
|
||||
// OPT: [[VALUE:%.*]] = load [[REF_ELT_ADDR]]
|
||||
// OPT: apply {{%.*}}([[VALUE]])
|
||||
// OPT: } // end sil function '$s12unmanaged_rc12useUnmanagedyys0D0VyAA14KlassContainerCGF'
|
||||
|
||||
Reference in New Issue
Block a user