From f65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Tue, 29 Oct 2024 14:49:26 +0800 Subject: format * format * Minor test fixes * enable checking cpp format in ci --- source/slang/slang-ir-lower-existential.cpp | 474 ++++++++++++++-------------- 1 file changed, 240 insertions(+), 234 deletions(-) (limited to 'source/slang/slang-ir-lower-existential.cpp') diff --git a/source/slang/slang-ir-lower-existential.cpp b/source/slang/slang-ir-lower-existential.cpp index 13f46e914..c4ee6e6fc 100644 --- a/source/slang/slang-ir-lower-existential.cpp +++ b/source/slang/slang-ir-lower-existential.cpp @@ -1,288 +1,294 @@ // 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" #include "slang-ir-util.h" +#include "slang-ir.h" namespace Slang { - bool isCPUTarget(TargetRequest* targetReq); - bool isCUDATarget(TargetRequest* targetReq); +bool isCPUTarget(TargetRequest* targetReq); +bool isCUDATarget(TargetRequest* targetReq); - struct ExistentialLoweringContext +struct ExistentialLoweringContext +{ + SharedGenericsLoweringContext* sharedContext; + + void processMakeExistential(IRMakeExistentialWithRTTI* inst) { - SharedGenericsLoweringContext* sharedContext; + IRBuilder builderStorage(sharedContext->module); + auto builder = &builderStorage; + builder->setInsertBefore(inst); + auto value = inst->getWrappedValue(); + auto valueType = sharedContext->lowerType(builder, value->getDataType()); + if (valueType->getOp() == kIROp_ComPtrType) + return; + auto witnessTableType = + cast(inst->getWitnessTable()->getDataType()); + auto interfaceType = witnessTableType->getConformanceType(); + if (interfaceType->findDecoration()) + return; + auto witnessTableIdType = builder->getWitnessTableIDType((IRType*)interfaceType); + auto anyValueSize = sharedContext->getInterfaceAnyValueSize(interfaceType, inst->sourceLoc); + auto anyValueType = builder->getAnyValueType(anyValueSize); + auto rttiType = builder->getRTTIHandleType(); + auto tupleType = builder->getTupleType(rttiType, witnessTableIdType, anyValueType); - void processMakeExistential(IRMakeExistentialWithRTTI* inst) + IRInst* rttiObject = inst->getRTTI(); + if (auto type = as(rttiObject)) { - IRBuilder builderStorage(sharedContext->module); - auto builder = &builderStorage; - builder->setInsertBefore(inst); - auto value = inst->getWrappedValue(); - auto valueType = sharedContext->lowerType(builder, value->getDataType()); - if (valueType->getOp() == kIROp_ComPtrType) - return; - auto witnessTableType = cast(inst->getWitnessTable()->getDataType()); - auto interfaceType = witnessTableType->getConformanceType(); - if (interfaceType->findDecoration()) - return; - auto witnessTableIdType = builder->getWitnessTableIDType((IRType*)interfaceType); - auto anyValueSize = sharedContext->getInterfaceAnyValueSize(interfaceType, inst->sourceLoc); - auto anyValueType = builder->getAnyValueType(anyValueSize); - auto rttiType = builder->getRTTIHandleType(); - auto tupleType = builder->getTupleType(rttiType, witnessTableIdType, anyValueType); - - IRInst* rttiObject = inst->getRTTI(); - if (auto type = as(rttiObject)) - { - rttiObject = sharedContext->maybeEmitRTTIObject(type); - rttiObject = builder->emitGetAddress(rttiType, rttiObject); - } - IRInst* packedValue = value; - if (valueType->getOp() != kIROp_AnyValueType) - packedValue = builder->emitPackAnyValue(anyValueType, value); - IRInst* tupleArgs[] = {rttiObject, inst->getWitnessTable(), packedValue}; - auto tuple = builder->emitMakeTuple(tupleType, 3, tupleArgs); - inst->replaceUsesWith(tuple); - inst->removeAndDeallocate(); + rttiObject = sharedContext->maybeEmitRTTIObject(type); + rttiObject = builder->emitGetAddress(rttiType, rttiObject); } + IRInst* packedValue = value; + if (valueType->getOp() != kIROp_AnyValueType) + packedValue = builder->emitPackAnyValue(anyValueType, value); + IRInst* tupleArgs[] = {rttiObject, inst->getWitnessTable(), packedValue}; + auto tuple = builder->emitMakeTuple(tupleType, 3, tupleArgs); + inst->replaceUsesWith(tuple); + 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(sharedContext->module); - auto builder = &builderStorage; - builder->setInsertBefore(inst); + // 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(sharedContext->module); + auto builder = &builderStorage; + 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(tupleType->getOperand(1)); - auto anyValueType = cast(tupleType->getOperand(2)); + // 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(tupleType->getOperand(1)); + auto anyValueType = cast(tupleType->getOperand(2)); - // Create a null value for `rttiObject` for now since it will not be used. - auto uint2Type = builder->getVectorType( - builder->getUIntType(), builder->getIntValue(builder->getIntType(), 2)); - IRInst* zero = builder->getIntValue(builder->getUIntType(), 0); - IRInst* zeroVectorArgs[] = { zero, zero }; - IRInst* rttiObject = builder->emitMakeVector(uint2Type, 2, zeroVectorArgs); + // Create a null value for `rttiObject` for now since it will not be used. + auto uint2Type = builder->getVectorType( + builder->getUIntType(), + builder->getIntValue(builder->getIntType(), 2)); + IRInst* zero = builder->getIntValue(builder->getUIntType(), 0); + IRInst* zeroVectorArgs[] = {zero, zero}; + IRInst* rttiObject = builder->emitMakeVector(uint2Type, 2, zeroVectorArgs); - // Pack the user provided value into `AnyValue`. - IRInst* packedValue = inst->getValue(); - if (packedValue->getDataType()->getOp() != kIROp_AnyValueType) - packedValue = builder->emitPackAnyValue(anyValueType, packedValue); + // 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)}; - - 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(); - } + // 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)}; - IRInst* extractTupleElement(IRBuilder* builder, IRInst* value, UInt index) - { - auto tupleType = cast(sharedContext->lowerType(builder, value->getDataType())); - auto getElement = builder->emitGetTupleElement( - (IRType*)tupleType->getOperand(index), - value, - index); - return getElement; - } + 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(); + } - void processExtractExistentialElement(IRInst* extractInst, UInt elementId) - { - IRBuilder builderStorage(sharedContext->module); - auto builder = &builderStorage; - builder->setInsertBefore(extractInst); + IRInst* extractTupleElement(IRBuilder* builder, IRInst* value, UInt index) + { + auto tupleType = cast(sharedContext->lowerType(builder, value->getDataType())); + auto getElement = + builder->emitGetTupleElement((IRType*)tupleType->getOperand(index), value, index); + return getElement; + } - IRInst* element = nullptr; - if (isComInterfaceType(extractInst->getOperand(0)->getDataType())) - { - // If this is an COM interface, the elements (witness table/rtti) are just the interface value itself. - element = extractInst->getOperand(0); - } - else - { - element = extractTupleElement(builder, extractInst->getOperand(0), elementId); - } - extractInst->replaceUsesWith(element); - extractInst->removeAndDeallocate(); - } + void processExtractExistentialElement(IRInst* extractInst, UInt elementId) + { + IRBuilder builderStorage(sharedContext->module); + auto builder = &builderStorage; + builder->setInsertBefore(extractInst); - void processExtractExistentialValue(IRExtractExistentialValue* inst) + IRInst* element = nullptr; + if (isComInterfaceType(extractInst->getOperand(0)->getDataType())) { - processExtractExistentialElement(inst, 2); + // If this is an COM interface, the elements (witness table/rtti) are just the interface + // value itself. + element = extractInst->getOperand(0); } - - void processExtractExistentialWitnessTable(IRExtractExistentialWitnessTable* inst) + else { - processExtractExistentialElement(inst, 1); + element = extractTupleElement(builder, extractInst->getOperand(0), elementId); } + extractInst->replaceUsesWith(element); + extractInst->removeAndDeallocate(); + } - void processExtractExistentialType(IRExtractExistentialType* extractInst) - { - IRBuilder builderStorage(sharedContext->module); - auto builder = &builderStorage; - builder->setInsertBefore(extractInst); + void processExtractExistentialValue(IRExtractExistentialValue* inst) + { + processExtractExistentialElement(inst, 2); + } + + void processExtractExistentialWitnessTable(IRExtractExistentialWitnessTable* inst) + { + processExtractExistentialElement(inst, 1); + } + + void processExtractExistentialType(IRExtractExistentialType* extractInst) + { + IRBuilder builderStorage(sharedContext->module); + auto builder = &builderStorage; + builder->setInsertBefore(extractInst); - IRInst* element = nullptr; - IRInst* anyValueType = nullptr; - if (isComInterfaceType(extractInst->getOperand(0)->getDataType())) + IRInst* element = nullptr; + IRInst* anyValueType = nullptr; + if (isComInterfaceType(extractInst->getOperand(0)->getDataType())) + { + // If this is an COM interface, the elements (witness table/rtti) are just the interface + // value itself. + element = extractInst->getOperand(0); + } + else + { + element = extractTupleElement(builder, extractInst->getOperand(0), 0); + if (auto tupleType = as(extractInst->getOperand(0)->getDataType())) { - // If this is an COM interface, the elements (witness table/rtti) are just the interface value itself. - element = extractInst->getOperand(0); + anyValueType = tupleType->getOperand(2); } - else + } + + // If this instruction is used as a type, we need to replace it with the lowered type, + // which should be an AnyValueType. + // If it is used as a value, then we can replace it with the extracted element. + auto isTypeUse = [](IRUse* use) -> bool + { + auto user = use->getUser(); + if (as(user)) + return true; + if (use == &use->getUser()->typeUse) + return true; + return false; + }; + traverseUses( + extractInst, + [&](IRUse* use) { - element = extractTupleElement(builder, extractInst->getOperand(0), 0); - if (auto tupleType = as(extractInst->getOperand(0)->getDataType())) + if (anyValueType && isTypeUse(use)) { - anyValueType = tupleType->getOperand(2); + builder->replaceOperand(use, anyValueType); + return; } - } + builder->replaceOperand(use, element); + }); + } - // If this instruction is used as a type, we need to replace it with the lowered type, - // which should be an AnyValueType. - // If it is used as a value, then we can replace it with the extracted element. - auto isTypeUse = [](IRUse* use) -> bool - { - auto user = use->getUser(); - if (as(user)) - return true; - if (use == &use->getUser()->typeUse) - return true; - return false; - }; - traverseUses(extractInst, [&](IRUse* use) - { - if (anyValueType && isTypeUse(use)) - { - builder->replaceOperand(use, anyValueType); - return; - } - builder->replaceOperand(use, element); - }); + void processGetValueFromBoundInterface(IRGetValueFromBoundInterface* inst) + { + IRBuilder builderStorage(sharedContext->module); + auto builder = &builderStorage; + builder->setInsertBefore(inst); + if (inst->getDataType()->getOp() == kIROp_ClassType) + { + return; } + // A value of interface will lower as a tuple, and + // the third element of that tuple represents the + // concrete value that was put into the existential. + // + auto element = extractTupleElement(builder, inst->getOperand(0), 2); + auto elementType = element->getDataType(); - void processGetValueFromBoundInterface(IRGetValueFromBoundInterface* inst) + // There are two cases we expect to see for that + // tuple element. + // + IRInst* replacement = nullptr; + if (as(elementType)) { - IRBuilder builderStorage(sharedContext->module); - auto builder = &builderStorage; - builder->setInsertBefore(inst); - if (inst->getDataType()->getOp() == kIROp_ClassType) - { - return; - } - // A value of interface will lower as a tuple, and - // the third element of that tuple represents the - // concrete value that was put into the existential. + // The first case is when legacy static specialization + // is applied, and the element is a "pseudo-pointer." // - auto element = extractTupleElement(builder, inst->getOperand(0), 2); - auto elementType = element->getDataType(); - - // There are two cases we expect to see for that - // tuple element. + // Semantically, we should emit a (pseudo-)load from the pseudo-pointer + // to go from `PseudoPtr` to `T`. // - IRInst* replacement = nullptr; - if(as(elementType)) - { - // The first case is when legacy static specialization - // is applied, and the element is a "pseudo-pointer." - // - // Semantically, we should emit a (pseudo-)load from the pseudo-pointer - // to go from `PseudoPtr` to `T`. - // - // TODO: Actually introduce and emit a "psedudo-load" instruction - // here. For right now we are just using the value directly and - // downstream passes seem okay with it, but it isn't really - // type-correct to be doing this. - // - replacement = element; - } - else - { - // The second case is when the dynamic-dispatch layout is - // being used, and the element is an "any-value." - // - // In this case we need to emit an unpacking operation - // to get from `AnyValue` to `T`. - // - SLANG_ASSERT(as(elementType)); - replacement = builder->emitUnpackAnyValue(inst->getFullType(), element); - } - - inst->replaceUsesWith(replacement); - inst->removeAndDeallocate(); + // TODO: Actually introduce and emit a "psedudo-load" instruction + // here. For right now we are just using the value directly and + // downstream passes seem okay with it, but it isn't really + // type-correct to be doing this. + // + replacement = element; } - - void processInst(IRInst* inst) + else { - if (auto makeExistential = as(inst)) - { - processMakeExistential(makeExistential); - } - else if (auto createExistentialObject = as(inst)) - { - processCreateExistentialObject(createExistentialObject); - } - else if (auto getValueFromBoundInterface = as(inst)) - { - processGetValueFromBoundInterface(getValueFromBoundInterface); - } - else if (auto extractExistentialVal = as(inst)) - { - processExtractExistentialValue(extractExistentialVal); - } - else if (auto extractExistentialType = as(inst)) - { - processExtractExistentialType(extractExistentialType); - } - else if (auto extractExistentialWitnessTable = as(inst)) - { - processExtractExistentialWitnessTable(extractExistentialWitnessTable); - } + // The second case is when the dynamic-dispatch layout is + // being used, and the element is an "any-value." + // + // In this case we need to emit an unpacking operation + // to get from `AnyValue` to `T`. + // + SLANG_ASSERT(as(elementType)); + replacement = builder->emitUnpackAnyValue(inst->getFullType(), element); } - void processModule() + inst->replaceUsesWith(replacement); + inst->removeAndDeallocate(); + } + + void processInst(IRInst* inst) + { + if (auto makeExistential = as(inst)) + { + processMakeExistential(makeExistential); + } + else if (auto createExistentialObject = as(inst)) + { + processCreateExistentialObject(createExistentialObject); + } + else if (auto getValueFromBoundInterface = as(inst)) + { + processGetValueFromBoundInterface(getValueFromBoundInterface); + } + else if (auto extractExistentialVal = as(inst)) + { + processExtractExistentialValue(extractExistentialVal); + } + else if (auto extractExistentialType = as(inst)) { - sharedContext->addToWorkList(sharedContext->module->getModuleInst()); + processExtractExistentialType(extractExistentialType); + } + else if (auto extractExistentialWitnessTable = as(inst)) + { + processExtractExistentialWitnessTable(extractExistentialWitnessTable); + } + } - while (sharedContext->workList.getCount() != 0) - { - IRInst* inst = sharedContext->workList.getLast(); + void processModule() + { + sharedContext->addToWorkList(sharedContext->module->getModuleInst()); - sharedContext->workList.removeLast(); - sharedContext->workListSet.remove(inst); + while (sharedContext->workList.getCount() != 0) + { + IRInst* inst = sharedContext->workList.getLast(); - processInst(inst); + sharedContext->workList.removeLast(); + sharedContext->workListSet.remove(inst); - for (auto child = inst->getLastChild(); child; child = child->getPrevInst()) - { - sharedContext->addToWorkList(child); - } + 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(); - } +void lowerExistentials(SharedGenericsLoweringContext* sharedContext) +{ + ExistentialLoweringContext context; + context.sharedContext = sharedContext; + context.processModule(); } +} // namespace Slang -- cgit v1.2.3