Skip to content

Commit d50005b

Browse files
committed
Add support for open_existential_box_value in Address Lowering
1 parent 16c277f commit d50005b

File tree

2 files changed

+53
-12
lines changed

2 files changed

+53
-12
lines changed

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
///
3838
/// 1. Reused-storage: Some operations are guaranteed to reuse their operand's
3939
/// storage. This includes extracting an enum payload and opening an existential
40-
/// value. This is required avoid introducing new copies or moves.
40+
/// value. This is required to avoid introducing new copies or moves.
4141
///
4242
/// // %data's storage must reuse storage allocated for %enum
4343
/// %data = unchecked_enum_data %enum : $Optional<T>, #Optional.some!enumelt
@@ -2503,12 +2503,6 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
25032503
// types.
25042504
void visitOpenExistentialValueInst(OpenExistentialValueInst *openExistential);
25052505

2506-
void visitOpenExistentialBoxValueInst(
2507-
OpenExistentialBoxValueInst *openExistentialBox) {
2508-
// FIXME: Unimplemented
2509-
llvm::report_fatal_error("Unimplemented OpenExistentialBox use.");
2510-
}
2511-
25122506
void visitReturnInst(ReturnInst *returnInst) {
25132507
// Returns are rewritten for any function with indirect results after
25142508
// opaque value rewriting.
@@ -2931,11 +2925,18 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
29312925
addrMat.initializeComposingUse(&initExistentialValue->getOperandRef());
29322926
}
29332927

2934-
// Project an opaque value out of a box-type existential.
29352928
void visitOpenExistentialBoxValueInst(
2936-
OpenExistentialBoxValueInst *openExistentialBox) {
2937-
// FIXME: Unimplemented
2938-
llvm::report_fatal_error("Unimplemented OpenExistentialBoxValue def.");
2929+
OpenExistentialBoxValueInst *openExistentialBoxValue) {
2930+
// Replace the module's openedArchetypesDef
2931+
pass.getModule()->willDeleteInstruction(openExistentialBoxValue);
2932+
2933+
auto *openAddr = builder.createOpenExistentialBox(
2934+
openExistentialBoxValue->getLoc(),
2935+
openExistentialBoxValue->getOperand(),
2936+
openExistentialBoxValue->getType().getAddressType());
2937+
2938+
openExistentialBoxValue->replaceAllTypeDependentUsesWith(openAddr);
2939+
setStorageAddress(openExistentialBoxValue, openAddr);
29392940
}
29402941

29412942
// Load an opaque value.
@@ -2970,6 +2971,14 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
29702971
for (Operand &operand : tupleInst->getAllOperands())
29712972
addrMat.initializeComposingUse(&operand);
29722973
}
2974+
2975+
void setStorageAddress(SILValue oldValue, SILValue addr) {
2976+
auto &storage = pass.valueStorageMap.getStorage(oldValue);
2977+
// getReusedStorageOperand() ensures that oldValue does not already have
2978+
// separate storage. So there's no need to delete its alloc_stack.
2979+
assert(!storage.storageAddress || storage.storageAddress == addr);
2980+
storage.storageAddress = addr;
2981+
}
29732982
};
29742983
} // end anonymous namespace
29752984

@@ -3124,7 +3133,8 @@ static void deleteRewrittenInstructions(AddressLoweringState &pass) {
31243133
}
31253134
}
31263135
LLVM_DEBUG(llvm::dbgs() << "DEAD "; deadInst->dump());
3127-
if (!isa<OpenExistentialValueInst>(deadInst)) {
3136+
if (!isa<OpenExistentialValueInst>(deadInst) &&
3137+
!isa<OpenExistentialBoxValueInst>(deadInst)) {
31283138
pass.deleter.forceDeleteWithUsers(deadInst);
31293139
continue;
31303140
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-sil-opt -address-lowering -enable-sil-opaque-values -sil-verify-all %s | %FileCheck %s
2+
//
3+
import Builtin
4+
import Swift
5+
6+
sil_stage raw
7+
8+
// CHECK-LABEL: sil [ossa] @test_open_existential_box_value : $@convention(thin) (@in Error) -> () {
9+
// CHECK: [[ALLOC:%.*]] = alloc_stack $Any
10+
// CHECK: [[VAL:%.*]] = load [take] %0 : $*Error
11+
// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [[VAL]] : $Error
12+
// CHECK: [[OPENADDR:%.*]] = open_existential_box [[BORROW]] : $Error to $*@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
13+
// CHECK: [[INIT:%.*]] = init_existential_addr [[ALLOC]] : $*Any, $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
14+
// CHECK: copy_addr [[OPENADDR]] to [initialization] [[INIT]] : $*@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
15+
// CHECK: destroy_addr [[ALLOC]] : $*Any
16+
// CHECK: end_borrow [[BORROW]] : $Error
17+
// CHECK: destroy_value [[VAL]] : $Error
18+
// CHECK: dealloc_stack [[ALLOC]] : $*Any
19+
// CHECK-LABEL: } // end sil function 'test_open_existential_box_value'
20+
sil [ossa] @test_open_existential_box_value : $@convention(thin) (@in Error) -> () {
21+
bb0(%0 : @owned $Error):
22+
%1 = begin_borrow [lexical] %0 : $Error
23+
%2 = open_existential_box_value %1 : $Error to $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
24+
%3 = copy_value %2 : $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error
25+
%4 = init_existential_value %3 : $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error, $@opened("169A6848-B636-11EC-83C4-D0817AD59B9D") Error, $Any
26+
destroy_value %4 : $Any
27+
end_borrow %1 : $Error
28+
destroy_value %0 : $Error
29+
%ret = tuple ()
30+
return %ret : $()
31+
}

0 commit comments

Comments
 (0)