diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 146 |
1 files changed, 23 insertions, 123 deletions
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 06e463d7d..f1a7c477b 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -5676,79 +5676,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> return false; } - IRInst* defaultSpecializeOuterGeneric( - IRInst* outerVal, - IRType* type, - GenericDecl* genericDecl) - { - auto builder = getBuilder(); - - // We need to specialize any generics that are further out... - auto specialiedOuterVal = defaultSpecializeOuterGenerics( - outerVal, - builder->getGenericKind(), - genericDecl); - - List<IRInst*> genericArgs; - - // Walk the parameters of the generic, and emit an argument for each, - // which will be a reference to binding for that parameter in the - // current scope. - // - // First we start with type and value parameters, - // in the order they were declared. - for (auto member : genericDecl->members) - { - if (auto typeParamDecl = as<GenericTypeParamDecl>(member)) - { - genericArgs.add(getSimpleVal(context, ensureDecl(context, typeParamDecl))); - } - else if (auto valDecl = as<GenericValueParamDecl>(member)) - { - genericArgs.add(getSimpleVal(context, ensureDecl(context, valDecl))); - } - } - // Then we emit constraint parameters, again in - // declaration order. - for (auto member : genericDecl->members) - { - if (auto constraintDecl = as<GenericTypeConstraintDecl>(member)) - { - genericArgs.add(getSimpleVal(context, ensureDecl(context, constraintDecl))); - } - } - - return builder->emitSpecializeInst(type, specialiedOuterVal, genericArgs.getCount(), genericArgs.getBuffer()); - } - - IRInst* defaultSpecializeOuterGenerics( - IRInst* val, - IRType* type, - Decl* decl) - { - if(!val) return nullptr; - - auto parentVal = val->getParent(); - while(parentVal) - { - if(as<IRGeneric>(parentVal)) - break; - parentVal = parentVal->getParent(); - } - if(!parentVal) - return val; - - for(auto pp = decl->parentDecl; pp; pp = pp->parentDecl) - { - if(auto genericAncestor = as<GenericDecl>(pp)) - { - return defaultSpecializeOuterGeneric(parentVal, type, genericAncestor); - } - } - - return val; - } - struct NestedContext { IRGenEnv subEnvStorage; @@ -5798,16 +5725,30 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> if(decl->hasModifier<ConstModifier>()) return lowerFunctionStaticConstVarDecl(decl); - // A global variable may need to be generic, if one - // of the outer declarations is generic. + // A function-scope `static` variable is effectively a global, + // and a simple solution here would be to try to emit this + // variable directly into the global scope. + // + // The one major wrinkle we need to deal with is the way that + // a function-scope `static` variable could be nested under + // a generic, leading to the situation that different instances + // of that same generic would need distinct storage for that + // variable declaration. + // + // We will handle that constraint by carefully nesting the + // IR global variable under the parent of its containing + // function. + // + auto parent = getBuilder()->insertIntoParent; + if(auto block = as<IRBlock>(parent)) + parent = block->getParent(); + NestedContext nestedContext(this); auto subBuilder = nestedContext.getBuilder(); auto subContext = nestedContext.getContext(); - subBuilder->setInsertInto(subBuilder->getModule()->getModuleInst()); - auto outerGeneric = emitOuterGenerics(subContext, decl, decl); + subBuilder->setInsertBefore(parent); IRType* subVarType = lowerType(subContext, decl->getType()); - IRGlobalValueWithCode* irGlobal = subBuilder->createGlobalVar(subVarType); addVarDecorations(subContext, irGlobal, decl); @@ -5816,46 +5757,14 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> subBuilder->addHighLevelDeclDecoration(irGlobal, decl); - // We are inside of a function, and that function might be generic, - // in which case the `static` variable will be lowered to another - // generic. Let's start with a terrible example: - // - // interface IHasCount { int getCount(); } - // int incrementCounter<T : IHasCount >(T val) { - // static int counter = 0; - // counter += val.getCount(); - // return counter; - // } - // - // In this case, `incrementCounter` will lower to a function - // nested in a generic, while `counter` will be lowered to - // a global variable nested in a *different* generic. - // The net result is something like this: - // - // int counter<T:IHasCount> = 0; - // - // int incrementCounter<T:IHasCount>(T val) { - // counter<T> += val.getCount(); - // return counter<T>; - // - // The references to `counter` inside of `incrementCounter` - // become references to `counter<T>`. - // - // At the IR level, this means that the value we install - // for `decl` needs to be a specialized reference to `irGlobal`, - // for any outer generics. - // - IRType* varType = lowerType(context, decl->getType()); - IRType* varPtrType = getBuilder()->getPtrType(varType); - auto irSpecializedGlobal = defaultSpecializeOuterGenerics(irGlobal, varPtrType, decl); - LoweredValInfo globalVal = LoweredValInfo::ptr(irSpecializedGlobal); + LoweredValInfo globalVal = LoweredValInfo::ptr(irGlobal); setValue(context, decl, globalVal); // A `static` variable with an initializer needs special handling, // at least if the initializer isn't a compile-time constant. if( auto initExpr = decl->initExpr ) { - // We must create an ordinary global `bool isInitialized = false` + // We must create another global `bool isInitialized = false` // to represent whether we've initialized this before. // Then emit code like: // @@ -5867,14 +5776,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // or not generating it in the first place. That is a bit // more complexity than I'm ready for at the moment. // - - // Of course, if we are under a generic, then the Boolean - // variable need to be generic as well! - NestedContext nestedBoolContext(this); - auto boolBuilder = nestedBoolContext.getBuilder(); - auto boolContext = nestedBoolContext.getContext(); - boolBuilder->setInsertInto(boolBuilder->getModule()->getModuleInst()); - emitOuterGenerics(boolContext, decl, decl); + auto boolBuilder = subBuilder; auto irBoolType = boolBuilder->getBoolType(); auto irBool = boolBuilder->createGlobalVar(irBoolType); @@ -5882,7 +5784,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> boolBuilder->setInsertInto(boolBuilder->createBlock()); boolBuilder->emitReturn(boolBuilder->getBoolValue(false)); - auto boolVal = LoweredValInfo::ptr(defaultSpecializeOuterGenerics(irBool, irBoolType, decl)); + auto boolVal = LoweredValInfo::ptr(irBool); // Okay, with our global Boolean created, we can move on to @@ -5904,8 +5806,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> builder->insertBlock(afterBlock); } - irGlobal->moveToEnd(); - finishOuterGenerics(subBuilder, irGlobal, outerGeneric); return globalVal; } |
