summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ir-lower-existential.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-08-25 10:27:22 -0700
committerGitHub <noreply@github.com>2021-08-25 10:27:22 -0700
commit33f7e1599cbecb32c23787b37b2bf3b34bdd5c84 (patch)
tree1fcdadfa1d03a21668606439402e80e6a754162c /source/slang/slang-ir-lower-existential.cpp
parent3b0b920608928f8cb39dc9116043d5a8644149c3 (diff)
Add `createDynamicObject` stdlib function. (#1923)
This function takes a user provided `typeID` and arbitrary typed value, and turns them into an existential value whose `witnessTableID` is `typeID` and whose `anyValue` is the user provided value. This allows the users to pack the runtime type id info in arbitrary way.
Diffstat (limited to 'source/slang/slang-ir-lower-existential.cpp')
-rw-r--r--source/slang/slang-ir-lower-existential.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/source/slang/slang-ir-lower-existential.cpp b/source/slang/slang-ir-lower-existential.cpp
index c85d7af63..ac46fa46f 100644
--- a/source/slang/slang-ir-lower-existential.cpp
+++ b/source/slang/slang-ir-lower-existential.cpp
@@ -46,6 +46,48 @@ namespace Slang
inst->removeAndDeallocate();
}
+ // Translates `createExistentialObject` insts, which takes a user defined
+ // type id and user defined value and turns into an existential value,
+ // into a `makeTuple` inst that makes the tuple representing the lowered
+ // existential value.
+ void processCreateExistentialObject(IRCreateExistentialObject* inst)
+ {
+ IRBuilder builderStorage;
+ auto builder = &builderStorage;
+ builder->sharedBuilder = &sharedContext->sharedBuilderStorage;
+ builder->setInsertBefore(inst);
+
+ // The result type of this `createExistentialObject` inst should already
+ // be lowered into a `TupleType(rttiType, WitnessTableIDType, AnyValueType)`
+ // in the previous `lowerGenericType` pass.
+ auto tupleType = inst->getDataType();
+ auto witnessTableIdType = cast<IRWitnessTableIDType>(tupleType->getOperand(1));
+ auto anyValueType = cast<IRAnyValueType>(tupleType->getOperand(2));
+
+ // Create a null value for `rttiObject` for now since it will not be used.
+ IRInst* rttiObject = builder->getIntValue(builder->getIntType(), 0);
+
+ // Pack the user provided value into `AnyValue`.
+ IRInst* packedValue = inst->getValue();
+ if (packedValue->getDataType()->getOp() != kIROp_AnyValueType)
+ packedValue = builder->emitPackAnyValue(anyValueType, packedValue);
+
+ // Use the user provided `typeID` value as the witness table ID field in the
+ // newly constructed tuple.
+ // All `WitnessTableID` types are lowered into `uint2`s, so we need to create
+ // a `uint2` value from `typeID` to stay consistent with the convention.
+ IRInst* vectorArgs[2] = {
+ inst->getTypeID(), builder->getIntValue(builder->getUIntType(), 0)};
+ auto uint2Type = builder->getVectorType(
+ builder->getUIntType(), builder->getIntValue(builder->getIntType(), 2));
+ IRInst* typeIdValue = builder->emitMakeVector(uint2Type, 2, vectorArgs);
+ typeIdValue = builder->emitBitCast(witnessTableIdType, typeIdValue);
+ IRInst* tupleArgs[] = {rttiObject, typeIdValue, packedValue};
+ auto tuple = builder->emitMakeTuple(tupleType, 3, tupleArgs);
+ inst->replaceUsesWith(tuple);
+ inst->removeAndDeallocate();
+ }
+
IRInst* extractTupleElement(IRBuilder* builder, IRInst* value, UInt index)
{
auto tupleType = cast<IRTupleType>(sharedContext->lowerType(builder, value->getDataType()));
@@ -138,6 +180,10 @@ namespace Slang
{
processMakeExistential(makeExistential);
}
+ else if (auto createExistentialObject = as<IRCreateExistentialObject>(inst))
+ {
+ processCreateExistentialObject(createExistentialObject);
+ }
else if (auto getValueFromBoundInterface = as<IRGetValueFromBoundInterface>(inst))
{
processGetValueFromBoundInterface(getValueFromBoundInterface);