diff options
| author | Yong He <yonghe@outlook.com> | 2020-08-14 10:04:32 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-14 10:04:32 -0700 |
| commit | b37a7770d9781515f70047665d12680a5838406d (patch) | |
| tree | 19b322499f920c23a868bd0db2e54a628d76a41d /source/slang/slang-ir-lower-existential.cpp | |
| parent | 99366e7c37e8b537b4eac8f3104db7296ceba586 (diff) | |
Lower existential types. (#1497)
Co-authored-by: Tim Foley <tfoleyNV@users.noreply.github.com>
Diffstat (limited to 'source/slang/slang-ir-lower-existential.cpp')
| -rw-r--r-- | source/slang/slang-ir-lower-existential.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/source/slang/slang-ir-lower-existential.cpp b/source/slang/slang-ir-lower-existential.cpp new file mode 100644 index 000000000..af47a1dfe --- /dev/null +++ b/source/slang/slang-ir-lower-existential.cpp @@ -0,0 +1,149 @@ +// slang-ir-lower-generic-existential.cpp + +#include "slang-ir-lower-existential.h" +#include "slang-ir-generics-lowering-context.h" +#include "slang-ir.h" +#include "slang-ir-insts.h" + +namespace Slang +{ + struct ExistentialLoweringContext + { + SharedGenericsLoweringContext* sharedContext; + + void processMakeExistential(IRMakeExistential* inst) + { + IRBuilder builderStorage; + auto builder = &builderStorage; + builder->sharedBuilder = &sharedContext->sharedBuilderStorage; + builder->setInsertBefore(inst); + + auto value = inst->getWrappedValue(); + auto valueType = sharedContext->lowerType(builder, value->getDataType()); + auto witnessTableType = cast<IRWitnessTableType>(inst->getWitnessTable()->getDataType()); + auto interfaceType = witnessTableType->getConformanceType(); + auto anyValueSize = sharedContext->getInterfaceAnyValueSize(interfaceType, inst->sourceLoc); + auto anyValueType = builder->getAnyValueType(anyValueSize); + auto rttiType = builder->getPtrType(builder->getRTTIType()); + auto tupleType = builder->getTupleType(anyValueType, witnessTableType, rttiType); + + IRInst* rttiObject = nullptr; + if (valueType->op != kIROp_AnyValueType) + { + rttiObject = sharedContext->maybeEmitRTTIObject(valueType); + rttiObject = builder->emitGetAddress( + builder->getPtrType(builder->getRTTIType()), + rttiObject); + } + else + { + rttiObject = valueType; + } + IRInst* packedValue = value; + if (valueType->op != kIROp_AnyValueType) + packedValue = builder->emitPackAnyValue(anyValueType, value); + IRInst* tupleArgs[] = { packedValue, inst->getWitnessTable(), rttiObject }; + 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())); + auto getElement = builder->emitGetTupleElement( + (IRType*)tupleType->getOperand(index), + value, + index); + return getElement; + } + + void processExtractExistentialElement(IRInst* extractInst, UInt elementId) + { + IRBuilder builderStorage; + auto builder = &builderStorage; + builder->sharedBuilder = &sharedContext->sharedBuilderStorage; + builder->setInsertBefore(extractInst); + + auto element = extractTupleElement(builder, extractInst->getOperand(0), elementId); + extractInst->replaceUsesWith(element); + extractInst->removeAndDeallocate(); + } + + void processExtractExistentialValue(IRExtractExistentialValue* inst) + { + processExtractExistentialElement(inst, 0); + } + + void processExtractExistentialWitnessTable(IRExtractExistentialWitnessTable* inst) + { + processExtractExistentialElement(inst, 1); + } + + void processExtractExistentialType(IRExtractExistentialType* inst) + { + processExtractExistentialElement(inst, 2); + } + + void processInst(IRInst* inst) + { + if (auto makeExistential = as<IRMakeExistential>(inst)) + { + processMakeExistential(makeExistential); + } + else if (auto extractExistentialVal = as<IRExtractExistentialValue>(inst)) + { + processExtractExistentialValue(extractExistentialVal); + } + else if (auto extractExistentialType = as<IRExtractExistentialType>(inst)) + { + processExtractExistentialType(extractExistentialType); + } + else if (auto extractExistentialWitnessTable = as<IRExtractExistentialWitnessTable>(inst)) + { + processExtractExistentialWitnessTable(extractExistentialWitnessTable); + } + } + + void processModule() + { + // We start by initializing our shared IR building state, + // since we will re-use that state for any code we + // generate along the way. + // + SharedIRBuilder* sharedBuilder = &sharedContext->sharedBuilderStorage; + sharedBuilder->module = sharedContext->module; + sharedBuilder->session = sharedContext->module->session; + + sharedContext->addToWorkList(sharedContext->module->getModuleInst()); + + while (sharedContext->workList.getCount() != 0) + { + // We will then iterate until our work list goes dry. + // + while (sharedContext->workList.getCount() != 0) + { + IRInst* inst = sharedContext->workList.getLast(); + + sharedContext->workList.removeLast(); + sharedContext->workListSet.Remove(inst); + + processInst(inst); + + for (auto child = inst->getLastChild(); child; child = child->getPrevInst()) + { + sharedContext->addToWorkList(child); + } + } + } + } + }; + + + void lowerExistentials(SharedGenericsLoweringContext* sharedContext) + { + ExistentialLoweringContext context; + context.sharedContext = sharedContext; + context.processModule(); + } +} |
