diff options
Diffstat (limited to 'source/slang/ir-legalize-types.cpp')
| -rw-r--r-- | source/slang/ir-legalize-types.cpp | 302 |
1 files changed, 142 insertions, 160 deletions
diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp index 7e380e237..20efc02b1 100644 --- a/source/slang/ir-legalize-types.cpp +++ b/source/slang/ir-legalize-types.cpp @@ -98,28 +98,11 @@ struct IRTypeLegalizationContext }; static void registerLegalizedValue( - IRTypeLegalizationContext* context, - IRInst* irValue, - LegalVal const& legalVal) -{ - context->mapValToLegalVal.Add(irValue, legalVal); -} - -static void maybeRegisterLegalizedGlobal( IRTypeLegalizationContext* context, - IRGlobalValue* irGlobalVar, + IRInst* irValue, LegalVal const& legalVal) { - // Check the mangled name of the symbol and don't register - // symbols that don't have an external name (currently - // indicated by them having an empty name string). - if (getText(irGlobalVar->mangledName).Length() == 0) - return; - - // Otherwise, register the legalized value for this symbol - // under its mangled name, so that other code can still - // find the right value(s) to use after legalization. - context->typeLegalizationContext->mapMangledNameToLegalIRValue.AddIfNotExists(irGlobalVar->mangledName, legalVal); + context->mapValToLegalVal[irValue] = legalVal; } struct IRGlobalNameInfo @@ -138,16 +121,16 @@ static LegalVal declareVars( static LegalType legalizeType( IRTypeLegalizationContext* context, - Type* type) + IRType* type) { return legalizeType(context->typeLegalizationContext, type); } // Legalize a type, and then expect it to // result in a simple type. -static RefPtr<Type> legalizeSimpleType( +static IRType* legalizeSimpleType( IRTypeLegalizationContext* context, - Type* type) + IRType* type) { auto legalType = legalizeType(context, type); switch (legalType.flavor) @@ -179,7 +162,7 @@ static LegalVal legalizeOperand( } static void getArgumentValues( - List<IRInst*> & instArgs, + List<IRInst*> & instArgs, LegalVal val) { switch (val.flavor) @@ -224,15 +207,15 @@ static LegalVal legalizeCall( IRCall* callInst) { // TODO: implement legalization of non-simple return types - auto retType = legalizeType(context, callInst->type); + auto retType = legalizeType(context, callInst->getFullType()); SLANG_ASSERT(retType.flavor == LegalType::Flavor::simple); - + List<IRInst*> instArgs; for (auto i = 1u; i < callInst->getOperandCount(); i++) getArgumentValues(instArgs, legalizeOperand(context, callInst->getOperand(i))); return LegalVal::simple(context->builder->emitCallInst( - callInst->type, + callInst->getFullType(), callInst->func.get(), instArgs.Count(), instArgs.Buffer())); @@ -279,7 +262,7 @@ static LegalVal legalizeLoad( for (auto ee : legalPtrVal.getTuple()->elements) { TuplePseudoVal::Element element; - element.mangledName = ee.mangledName; + element.key = ee.key; element.val = legalizeLoad(context, ee.val); tupleVal->elements.Add(element); @@ -353,7 +336,7 @@ static LegalVal legalizeFieldAddress( IRTypeLegalizationContext* context, LegalType type, LegalVal legalPtrOperand, - DeclRef<Decl> fieldDeclRef) + IRStructKey* fieldKey) { auto builder = context->builder; @@ -364,17 +347,15 @@ static LegalVal legalizeFieldAddress( builder->emitFieldAddress( type.getSimple(), legalPtrOperand.getSimple(), - builder->getDeclRefVal(fieldDeclRef))); + fieldKey)); case LegalVal::Flavor::pair: { - String mangledFieldName = getMangledName(fieldDeclRef.getDecl()); - // There are two sides, the ordinary and the special, // and we basically just dispatch to both of them. auto pairVal = legalPtrOperand.getPair(); auto pairInfo = pairVal->pairInfo; - auto pairElement = pairInfo->findElement(mangledFieldName); + auto pairElement = pairInfo->findElement(fieldKey); if (!pairElement) { SLANG_UNEXPECTED("didn't find tuple element"); @@ -400,18 +381,11 @@ static LegalVal legalizeFieldAddress( if (pairElement->flags & PairInfo::kFlag_hasOrdinary) { - // Note: the ordinary side of the pair is expected - // to be a filtered `struct` type, and so it will - // have different field declarations than the - // oridinal type. The element of the `PairInfo` - // structure stores the correct field decl-ref to use - // as `ordinaryFieldDeclRef`. - ordinaryVal = legalizeFieldAddress( context, ordinaryType, pairVal->ordinaryVal, - pairElement->ordinaryFieldDeclRef); + fieldKey); } if (pairElement->flags & PairInfo::kFlag_hasSpecial) @@ -420,7 +394,7 @@ static LegalVal legalizeFieldAddress( context, specialType, pairVal->specialVal, - fieldDeclRef); + fieldKey); } return LegalVal::pair(ordinaryVal, specialVal, fieldPairInfo); } @@ -428,8 +402,6 @@ static LegalVal legalizeFieldAddress( case LegalVal::Flavor::tuple: { - String mangledFieldName = getMangledName(fieldDeclRef.getDecl()); - // The operand is a tuple of pointer-like // values, we want to extract the element // corresponding to a field. We will handle @@ -438,7 +410,7 @@ static LegalVal legalizeFieldAddress( auto ptrTupleInfo = legalPtrOperand.getTuple(); for (auto ee : ptrTupleInfo->elements) { - if (ee.mangledName == mangledFieldName) + if (ee.key == fieldKey) { return ee.val; } @@ -465,15 +437,13 @@ static LegalVal legalizeFieldAddress( { // We don't expect any legalization to affect // the "field" argument. - auto fieldOperand = legalFieldOperand.getSimple(); - assert(fieldOperand->op == kIROp_decl_ref); - auto fieldDeclRef = ((IRDeclRef*)fieldOperand)->declRef; + auto fieldKey = legalFieldOperand.getSimple(); return legalizeFieldAddress( context, type, legalPtrOperand, - fieldDeclRef); + (IRStructKey*) fieldKey); } static LegalVal legalizeGetElementPtr( @@ -548,7 +518,7 @@ static LegalVal legalizeGetElementPtr( auto elemType = tupleType->elements[ee].type; TuplePseudoVal::Element resElem; - resElem.mangledName = ptrElem.mangledName; + resElem.key = ptrElem.key; resElem.val = legalizeGetElementPtr( context, elemType, @@ -646,8 +616,8 @@ static LegalVal legalizeLocalVar( case LegalType::Flavor::simple: // Easy case: the type is usable as-is, and we // should just do that. - irLocalVar->type = context->session->getPtrType( - maybeSimpleType.getSimple()); + irLocalVar->setFullType(context->builder->getPtrType( + maybeSimpleType.getSimple())); return LegalVal::simple(irLocalVar); default: @@ -684,7 +654,7 @@ static LegalVal legalizeParam( { // Simple case: things were legalized to a simple type, // so we can just use the original parameter as-is. - originalParam->type = legalParamType.getSimple(); + originalParam->setFullType(legalParamType.getSimple()); return LegalVal::simple(originalParam); } else @@ -702,6 +672,17 @@ static LegalVal legalizeParam( } } +static LegalVal legalizeFunc( + IRTypeLegalizationContext* context, + IRFunc* irFunc); + +static LegalVal legalizeGlobalVar( + IRTypeLegalizationContext* context, + IRGlobalVar* irGlobalVar); + +static LegalVal legalizeGlobalConstant( + IRTypeLegalizationContext* context, + IRGlobalConstant* irGlobalConstant); static LegalVal legalizeInst( @@ -717,6 +698,19 @@ static LegalVal legalizeInst( case kIROp_Param: return legalizeParam(context, cast<IRParam>(inst)); + case kIROp_WitnessTable: + // Just skip these. + break; + + case kIROp_Func: + return legalizeFunc(context, cast<IRFunc>(inst)); + + case kIROp_GlobalVar: + return legalizeGlobalVar(context, cast<IRGlobalVar>(inst)); + + case kIROp_GlobalConstant: + return legalizeGlobalConstant(context, cast<IRGlobalConstant>(inst)); + default: break; } @@ -736,7 +730,7 @@ static LegalVal legalizeInst( } // Also legalize the type of the instruction - LegalType legalType = legalizeType(context, inst->type); + LegalType legalType = legalizeType(context, inst->getFullType()); if (!anyComplex && legalType.flavor == LegalType::Flavor::simple) { @@ -749,7 +743,7 @@ static LegalVal legalizeInst( inst->setOperand(aa, legalArg.getSimple()); } - inst->type = legalType.getSimple(); + inst->setFullType(legalType.getSimple()); return LegalVal::simple(inst); } @@ -774,9 +768,8 @@ static LegalVal legalizeInst( // original instruction by removing it from // the IR. // - // TODO: we need to add it to a list of - // instructions to be cleaned up... inst->removeFromParent(); + context->replacedInstructions.Add(inst); // The value to be used when referencing // the original instruction will now be @@ -784,33 +777,35 @@ static LegalVal legalizeInst( return legalVal; } -static void addParamType(IRFuncType * ftype, LegalType t) +static void addParamType(List<IRType*>& ioParamTypes, LegalType t) { switch (t.flavor) { case LegalType::Flavor::none: break; + case LegalType::Flavor::simple: - ftype->paramTypes.Add(t.obj.As<Type>()); + ioParamTypes.Add(t.getSimple()); break; + case LegalType::Flavor::implicitDeref: { - auto imp = t.obj.As<ImplicitDerefType>(); - addParamType(ftype, imp->valueType); + auto imp = t.getImplicitDeref(); + addParamType(ioParamTypes, imp->valueType); break; } case LegalType::Flavor::pair: { auto pairInfo = t.getPair(); - addParamType(ftype, pairInfo->ordinaryType); - addParamType(ftype, pairInfo->specialType); + addParamType(ioParamTypes, pairInfo->ordinaryType); + addParamType(ioParamTypes, pairInfo->specialType); } break; case LegalType::Flavor::tuple: { - auto tup = t.obj.As<TuplePseudoType>(); + auto tup = t.getTuple(); for (auto & elem : tup->elements) - addParamType(ftype, elem.type); + addParamType(ioParamTypes, elem.type); } break; default: @@ -818,54 +813,63 @@ static void addParamType(IRFuncType * ftype, LegalType t) } } -static void legalizeFunc( - IRTypeLegalizationContext* context, - IRFunc* irFunc) +static void legalizeInstsInParent( + IRTypeLegalizationContext* context, + IRParentInst* parent) { - // Overwrite the function's type with - // the result of legalization. - auto newFuncType = new IRFuncType(); - newFuncType->setSession(context->session); - auto oldFuncType = irFunc->type.As<IRFuncType>(); - newFuncType->resultType = legalizeSimpleType(context, oldFuncType->resultType); - for (auto & paramType : oldFuncType->paramTypes) - { - auto legalParamType = legalizeType(context, paramType); - addParamType(newFuncType, legalParamType); - } - irFunc->type = newFuncType; - - // we use this list to store replaced local var insts. - // these old instructions will be freed when we are done. - context->replacedInstructions.Clear(); - - // Go through the blocks of the function - for (auto bb = irFunc->getFirstBlock(); bb; bb = bb->getNextBlock()) + IRInst* nextChild = nullptr; + for(auto child = parent->getFirstChild(); child; child = nextChild) { - // Legalize the instructions inside the block - IRInst* nextInst = nullptr; - for (auto ii = bb->getFirstInst(); ii; ii = nextInst) - { - nextInst = ii->getNextInst(); - - LegalVal legalVal = legalizeInst(context, ii); + nextChild = child->getNextInst(); - registerLegalizedValue(context, ii, legalVal); + if (auto block = as<IRBlock>(child)) + { + legalizeInstsInParent(context, block); + } + else + { + LegalVal legalVal = legalizeInst(context, child); + registerLegalizedValue(context, child, legalVal); } - } +} - // Clean up after any instructions we replaced along the way. - for (auto & lv : context->replacedInstructions) +static LegalVal legalizeFunc( + IRTypeLegalizationContext* context, + IRFunc* irFunc) +{ + // Overwrite the function's type with the result of legalization. + + IRFuncType* oldFuncType = irFunc->getDataType(); + UInt oldParamCount = oldFuncType->getParamCount(); + + // TODO: we should give an error message when the result type of a function + // can't be legalized (e.g., trying to return a texture, or a structue that + // contains one). + IRType* newResultType = legalizeSimpleType(context, oldFuncType->getResultType()); + List<IRType*> newParamTypes; + for (UInt pp = 0; pp < oldParamCount; ++pp) { - lv->deallocate(); + auto legalParamType = legalizeType(context, oldFuncType->getParamType(pp)); + addParamType(newParamTypes, legalParamType); } + + auto newFuncType = context->builder->getFuncType( + newParamTypes.Count(), + newParamTypes.Buffer(), + newResultType); + + context->builder->setDataType(irFunc, newFuncType); + + legalizeInstsInParent(context, irFunc); + + return LegalVal::simple(irFunc); } static LegalVal declareSimpleVar( - IRTypeLegalizationContext* context, + IRTypeLegalizationContext* context, IROp op, - Type* type, + IRType* type, TypeLayout* typeLayout, LegalVarChain* varChain, IRGlobalNameInfo* globalNameInfo) @@ -885,7 +889,7 @@ static LegalVal declareSimpleVar( switch (op) { - case kIROp_global_var: + case kIROp_GlobalVar: { auto globalVar = builder->createGlobalVar(type); globalVar->removeFromParent(); @@ -907,7 +911,7 @@ static LegalVal declareSimpleVar( globalVar->mangledName = context->session->getNameObj(mangledNameStr); } } - + irVar = globalVar; @@ -1008,7 +1012,7 @@ static LegalVal declareVars( for (auto ee : tupleType->elements) { - auto fieldLayout = getFieldLayout(typeLayout, ee.mangledName); + auto fieldLayout = getFieldLayout(typeLayout, getText(ee.key->mangledName)); RefPtr<TypeLayout> fieldTypeLayout = fieldLayout ? fieldLayout->typeLayout : nullptr; // If we are processing layout information, then @@ -1033,7 +1037,7 @@ static LegalVal declareVars( globalNameInfo); TuplePseudoVal::Element element; - element.mangledName = ee.mangledName; + element.key = ee.key; element.val = fieldVal; tupleVal->elements.Add(element); } @@ -1048,7 +1052,7 @@ static LegalVal declareVars( } } -static void legalizeGlobalVar( +static LegalVal legalizeGlobalVar( IRTypeLegalizationContext* context, IRGlobalVar* irGlobalVar) { @@ -1065,9 +1069,11 @@ static void legalizeGlobalVar( case LegalType::Flavor::simple: // Easy case: the type is usable as-is, and we // should just do that. - irGlobalVar->type = context->session->getPtrType( - legalValueType.getSimple()); - break; + context->builder->setDataType( + irGlobalVar, + context->builder->getPtrType( + legalValueType.getSimple())); + return LegalVal::simple(irGlobalVar); default: { @@ -1086,23 +1092,22 @@ static void legalizeGlobalVar( globalNameInfo.globalVar = irGlobalVar; globalNameInfo.counter = 0; - LegalVal newVal = declareVars(context, kIROp_global_var, legalValueType, typeLayout, varChain, &globalNameInfo); + LegalVal newVal = declareVars(context, kIROp_GlobalVar, legalValueType, typeLayout, varChain, &globalNameInfo); // Register the new value as the replacement for the old registerLegalizedValue(context, irGlobalVar, newVal); - // Also register the variable according to its mangled name, if any. - maybeRegisterLegalizedGlobal(context, irGlobalVar, newVal); - // Remove the old global from the module. irGlobalVar->removeFromParent(); - // TODO: actually clean up the global! + context->replacedInstructions.Add(irGlobalVar); + + return newVal; } break; } } -static void legalizeGlobalConstant( +static LegalVal legalizeGlobalConstant( IRTypeLegalizationContext* context, IRGlobalConstant* irGlobalConstant) { @@ -1116,8 +1121,8 @@ static void legalizeGlobalConstant( case LegalType::Flavor::simple: // Easy case: the type is usable as-is, and we // should just do that. - irGlobalConstant->type = legalValueType.getSimple(); - break; + irGlobalConstant->setFullType(legalValueType.getSimple()); + return LegalVal::simple(irGlobalConstant); default: { @@ -1128,46 +1133,17 @@ static void legalizeGlobalConstant( globalNameInfo.counter = 0; // TODO: need to handle initializer here! - LegalVal newVal = declareVars(context, kIROp_global_constant, legalValueType, nullptr, nullptr, &globalNameInfo); + LegalVal newVal = declareVars(context, kIROp_GlobalConstant, legalValueType, nullptr, nullptr, &globalNameInfo); // Register the new value as the replacement for the old registerLegalizedValue(context, irGlobalConstant, newVal); - // Also register the variable according to its mangled name, if any. - maybeRegisterLegalizedGlobal(context, irGlobalConstant, newVal); - // Remove the old global from the module. irGlobalConstant->removeFromParent(); - // TODO: actually clean up the global! - } - break; - } -} - -static void legalizeGlobalValue( - IRTypeLegalizationContext* context, - IRGlobalValue* irValue) -{ - switch (irValue->op) - { - case kIROp_witness_table: - // Just skip these. - break; - - case kIROp_Func: - legalizeFunc(context, (IRFunc*)irValue); - break; - - case kIROp_global_var: - legalizeGlobalVar(context, (IRGlobalVar*)irValue); - break; + context->replacedInstructions.Add(irGlobalConstant); - case kIROp_global_constant: - legalizeGlobalConstant(context, (IRGlobalConstant*)irValue); - break; - - default: - SLANG_UNEXPECTED("unknown global value type"); + return newVal; + } break; } } @@ -1175,19 +1151,14 @@ static void legalizeGlobalValue( static void legalizeTypes( IRTypeLegalizationContext* context) { + // Legalize all the top-level instructions in the module auto module = context->module; - IRInst* next = nullptr; - for(auto ii = module->getGlobalInsts().getFirst(); ii; ii = next) + legalizeInstsInParent(context, module->moduleInst); + + // Clean up after any instructions we replaced along the way. + for (auto& lv : context->replacedInstructions) { - next = ii->getNextInst(); - - // TODO: Once we start having global-scope instructions that - // aren't `IRGlobalValue`s, we'll actually want to handle those - // here too. - auto gv = as<IRGlobalValue>(ii); - if (!gv) - continue; - legalizeGlobalValue(context, gv); + lv->deallocate(); } } @@ -1221,6 +1192,17 @@ void legalizeTypes( legalizeTypes(context); + // Clean up after any type instructions we removed (e.g., + // global `struct` types). + // + // TODO: this logic should probably get paired up with + // the case for `IRTypeLegalizationContext::replacedInstructions`, + // but we haven't yet folded all the legalization logic into + // the IR legalization pass (since it used to apply to the AST too). + for (auto& oldInst : typeLegalizationContext->instsToRemove) + { + oldInst->removeAndDeallocate(); + } } } |
