summaryrefslogtreecommitdiffstats
path: root/source/slang/ir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/ir.cpp')
-rw-r--r--source/slang/ir.cpp113
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;
}
}