diff options
Diffstat (limited to 'source/slang/ir.cpp')
| -rw-r--r-- | source/slang/ir.cpp | 113 |
1 files changed, 105 insertions, 8 deletions
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 4a0a371d8..677429e32 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -1770,6 +1770,55 @@ namespace Slang (IRInst* const*) caseTypes); } + IRType* IRBuilder::getBindExistentialsType( + IRInst* baseType, + UInt slotArgCount, + IRInst* const* slotArgs) + { + // If we are trying to bind an interface type, then + // we will go ahead and simplify the instruction + // away impmediately. + // + if(as<IRInterfaceType>(baseType)) + { + if(slotArgCount >= 1) + { + // We are being asked to emit `BindExistentials(someInterface, someConcreteType, ...)` + // so we just want to return `ExistentialBox<someConcreteType>`. + // + auto concreteType = (IRType*) slotArgs[0]; + auto ptrType = getPtrType(kIROp_ExistentialBoxType, concreteType); + return ptrType; + } + } + + return (IRType*) findOrEmitHoistableInst( + this, + getTypeKind(), + kIROp_BindExistentialsType, + baseType, + slotArgCount, + (IRInst* const*) slotArgs); + } + + IRType* IRBuilder::getBindExistentialsType( + IRInst* baseType, + UInt slotArgCount, + IRUse const* slotArgUses) + { + List<IRInst*> slotArgs; + for( UInt ii = 0; ii < slotArgCount; ++ii ) + { + slotArgs.Add(slotArgUses[ii].get()); + } + return getBindExistentialsType( + baseType, + slotArgCount, + slotArgs.Buffer()); + } + + + void IRBuilder::setDataType(IRInst* inst, IRType* dataType) { if (auto oldRateQualifiedType = as<IRRateQualifiedType>(inst->getFullType())) @@ -1983,6 +2032,46 @@ namespace Slang return emitIntrinsicInst(type, kIROp_MakeExistential, SLANG_COUNT_OF(args), args); } + IRInst* IRBuilder::emitWrapExistential( + IRType* type, + IRInst* value, + UInt slotArgCount, + IRInst* const* slotArgs) + { + // If we are wrapping a single concrete value into + // an interface type, then this is really a `makeExistential` + // + // TODO: We may want to check for a `specialize` of a generic interface as well. + // + if(as<IRInterfaceType>(type)) + { + if(slotArgCount >= 2) + { + // We are being asked to emit `wrapExistential(value, concreteType, witnessTable, ...) : someInterface` + // + // We also know that a concrete value being wrapped will always be an existential box, + // so we expect that `value : ExistentialBox<T>` for some `T`. + // + // We want to emit `makeExistential(load(value), witnessTable)`. + // + auto deref = emitLoad(value); + return emitMakeExistential(type, deref, slotArgs[1]); + } + } + + IRInst* fixedArgs[] = {value}; + auto inst = createInstImpl<IRInst>( + this, + kIROp_WrapExistential, + type, + SLANG_COUNT_OF(fixedArgs), + fixedArgs, + slotArgCount, + slotArgs); + addInst(inst); + return inst; + } + IRModule* IRBuilder::createModule() { auto module = new IRModule(); @@ -2283,6 +2372,20 @@ namespace Slang } IRInst* IRBuilder::emitLoad( + IRType* type, + IRInst* ptr) + { + auto inst = createInst<IRLoad>( + this, + kIROp_Load, + type, + ptr); + + addInst(inst); + return inst; + } + + IRInst* IRBuilder::emitLoad( IRInst* ptr) { // Note: a `load` operation does not consider the rate @@ -2324,14 +2427,7 @@ namespace Slang valueType = rateType->getValueType(); } - auto inst = createInst<IRLoad>( - this, - kIROp_Load, - valueType, - ptr); - - addInst(inst); - return inst; + return emitLoad(valueType, ptr); } IRInst* IRBuilder::emitStore( @@ -4046,6 +4142,7 @@ namespace Slang case kIROp_ExtractExistentialType: case kIROp_ExtractExistentialValue: case kIROp_ExtractExistentialWitnessTable: + case kIROp_WrapExistential: return false; } } |
