diff options
| author | Yong He <yonghe@outlook.com> | 2021-08-25 10:27:22 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-25 10:27:22 -0700 |
| commit | 33f7e1599cbecb32c23787b37b2bf3b34bdd5c84 (patch) | |
| tree | 1fcdadfa1d03a21668606439402e80e6a754162c /source/slang/slang-ir-lower-existential.cpp | |
| parent | 3b0b920608928f8cb39dc9116043d5a8644149c3 (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.cpp | 46 |
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); |
