|
37 | 37 | ///
|
38 | 38 | /// 1. Reused-storage: Some operations are guaranteed to reuse their operand's
|
39 | 39 | /// 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. |
41 | 41 | ///
|
42 | 42 | /// // %data's storage must reuse storage allocated for %enum
|
43 | 43 | /// %data = unchecked_enum_data %enum : $Optional<T>, #Optional.some!enumelt
|
@@ -2503,12 +2503,6 @@ class UseRewriter : SILInstructionVisitor<UseRewriter> {
|
2503 | 2503 | // types.
|
2504 | 2504 | void visitOpenExistentialValueInst(OpenExistentialValueInst *openExistential);
|
2505 | 2505 |
|
2506 |
| - void visitOpenExistentialBoxValueInst( |
2507 |
| - OpenExistentialBoxValueInst *openExistentialBox) { |
2508 |
| - // FIXME: Unimplemented |
2509 |
| - llvm::report_fatal_error("Unimplemented OpenExistentialBox use."); |
2510 |
| - } |
2511 |
| - |
2512 | 2506 | void visitReturnInst(ReturnInst *returnInst) {
|
2513 | 2507 | // Returns are rewritten for any function with indirect results after
|
2514 | 2508 | // opaque value rewriting.
|
@@ -2931,11 +2925,18 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
|
2931 | 2925 | addrMat.initializeComposingUse(&initExistentialValue->getOperandRef());
|
2932 | 2926 | }
|
2933 | 2927 |
|
2934 |
| - // Project an opaque value out of a box-type existential. |
2935 | 2928 | 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 | + markRewritten(openExistentialBoxValue, openAddr); |
2939 | 2940 | }
|
2940 | 2941 |
|
2941 | 2942 | // Load an opaque value.
|
@@ -2970,6 +2971,14 @@ class DefRewriter : SILInstructionVisitor<DefRewriter> {
|
2970 | 2971 | for (Operand &operand : tupleInst->getAllOperands())
|
2971 | 2972 | addrMat.initializeComposingUse(&operand);
|
2972 | 2973 | }
|
| 2974 | + |
| 2975 | + void markRewritten(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 | + } |
2973 | 2982 | };
|
2974 | 2983 | } // end anonymous namespace
|
2975 | 2984 |
|
@@ -3124,7 +3133,8 @@ static void deleteRewrittenInstructions(AddressLoweringState &pass) {
|
3124 | 3133 | }
|
3125 | 3134 | }
|
3126 | 3135 | LLVM_DEBUG(llvm::dbgs() << "DEAD "; deadInst->dump());
|
3127 |
| - if (!isa<OpenExistentialValueInst>(deadInst)) { |
| 3136 | + if (!isa<OpenExistentialValueInst>(deadInst) && |
| 3137 | + !isa<OpenExistentialBoxValueInst>(deadInst)) { |
3128 | 3138 | pass.deleter.forceDeleteWithUsers(deadInst);
|
3129 | 3139 | continue;
|
3130 | 3140 | }
|
|
0 commit comments