|
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 | + setStorageAddress(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 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 | + } |
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