diff options
Diffstat (limited to 'source/slang/ir-bind-existentials.cpp')
| -rw-r--r-- | source/slang/ir-bind-existentials.cpp | 128 |
1 files changed, 54 insertions, 74 deletions
diff --git a/source/slang/ir-bind-existentials.cpp b/source/slang/ir-bind-existentials.cpp index 7188e2503..f87a7d233 100644 --- a/source/slang/ir-bind-existentials.cpp +++ b/source/slang/ir-bind-existentials.cpp @@ -198,7 +198,7 @@ struct BindExistentialSlots // We only care about parameters that are associated // with one or more existential slots. // - auto resInfo = varLayout->FindResourceInfo(LayoutResourceKind::ExistentialSlot); + auto resInfo = varLayout->FindResourceInfo(LayoutResourceKind::ExistentialTypeParam); if(!resInfo) return; @@ -208,7 +208,7 @@ struct BindExistentialSlots // UInt firstSlot = resInfo->index; UInt slotCount = 0; - if(auto typeResInfo = varLayout->getTypeLayout()->FindResourceInfo(LayoutResourceKind::ExistentialSlot)) + if(auto typeResInfo = varLayout->getTypeLayout()->FindResourceInfo(LayoutResourceKind::ExistentialTypeParam)) slotCount = UInt(typeResInfo->count.getFiniteValue()); // At this point we know that the parameter consumes @@ -266,12 +266,9 @@ struct BindExistentialSlots // We are going to alter the type of the // given `inst` based on information in - // the `slotArgs`, but the exact kind - // of modification will depend on the - // original type of `inst`. + // the `slotArgs`. auto fullType = inst->getFullType(); - auto type = inst->getDataType(); SharedIRBuilder sharedBuilder; sharedBuilder.session = module->getSession(); @@ -280,81 +277,64 @@ struct BindExistentialSlots IRBuilder builder; builder.sharedBuilder = &sharedBuilder; - // The easy case is when the `type` of `inst` - // is directly an interface type. + // Every argument that is filling an existential + // type param/slot comprises both a type and + // a witness table, so the total number of operands + // is twice the number of slots we are filling. // - if( auto interfaceType = as<IRInterfaceType>(type) ) - { - // An intereface-type parameter will use a - // single slot, which consits of a pair of - // operands. - // - // The first operand is the concrete type - // we want to plug in. - // - auto newType = (IRType*) slotArgs[0].get(); - - // The second operand is a witness that - // the concrete type conforms to the interface - // used for the original parameter. - // - auto newWitnessTable = slotArgs[1].get(); + UInt slotOperandCount = slotCount*2; + List<IRInst*> slotOperands; + for(UInt ii = 0; ii < slotOperandCount; ++ii) + slotOperands.Add(slotArgs[ii].get()); + + // We are going to create a proxy type that represents + // the results of plugging all the information + // from the existential slots into the original type. + // + auto newType = builder.getBindExistentialsType( + fullType, + slotOperandCount, + slotOperands.Buffer()); - // We are going to replace the (interface) type of - // the parameter with the new (concrete) type. - // - builder.setDataType(inst, newType); + // We will replace the type of the original parameter + // with the new proxy type. + // + builder.setDataType(inst, newType); - // Next we want to replace all uses of `inst` (which - // expect a value of its old type) with a fresh - // `makeExistential(...)` instruction that refers to - // `inst` with its new type. - // - // Note: we make a copy of the list of uses for `inst` - // before going through and replacing them, because - // during the replacement we make *more* uses of `inst`, - // as an operand to the `makeExistential` instructions. - // We only want to replace the old uses, and not the - // new ones we'll be making. - // - List<IRUse*> usesToReplace; - for(auto use = inst->firstUse; use; use = use->nextUse ) - usesToReplace.Add(use); + // Next we want to replace all uses of `inst` (which + // expect a value of its old type) with a fresh + // `wrapExistential(...)` instruction that refers to + // `inst` with its new type. + // + // Note: we make a copy of the list of uses for `inst` + // before going through and replacing them, because + // during the replacement we make *more* uses of `inst`, + // as an operand to the `makeExistential` instructions. + // We only want to replace the old uses, and not the + // new ones we'll be making. + // + List<IRUse*> usesToReplace; + for(auto use = inst->firstUse; use; use = use->nextUse ) + usesToReplace.Add(use); - // Now we can loop over our list of uses and replace each. - // - for(auto use : usesToReplace) - { - // First we emit a `makeExisential` right before the - // use site. - // - builder.setInsertBefore(use->getUser()); - auto newVal = builder.emitMakeExistential( - fullType, - inst, - newWitnessTable); - - // Second we make the use site point at the new - // value instead. - // - use->set(newVal); - } - } - else + // Now we can loop over our list of uses and replace each. + // + for(auto use : usesToReplace) { - // TODO: We eventually need to handle cases where there - // are: - // - // * Arrays over existential types; e.g.: `IFoo[3]` - // - // * Structs with existential-type fields. - // - // * Constant buffers or other "containers" over existentials; e.g., `ConstantBuffer<IFoo>` + // First we emit a `makeExisential` right before the + // use site. // - // * Nested combinations of the above; e.g., a `ConstantBuffer` - // of a struct with a field that is an array of `IFoo`. + builder.setInsertBefore(use->getUser()); + auto newVal = builder.emitWrapExistential( + fullType, + inst, + slotOperandCount, + slotOperands.Buffer()); + + // Second we make the use site point at the new + // value instead. // - SLANG_UNIMPLEMENTED_X("shader parameters with nested existentials"); + use->set(newVal); } } }; |
