diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2022-04-05 13:32:24 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-05 13:32:24 -0400 |
| commit | 7f36c34daf633dcade3a3bab9cdcf14a34fed3cd (patch) | |
| tree | 2eb61dc9a51da5dc0e997e993d63a1070c064f8f | |
| parent | f58f36eedac6c11e30d60201f43bb4fb1be70bee (diff) | |
Handling static const variables in generics (#2171)
* #include an absolute path didn't work - because paths were taken to always be relative.
* Meta-2 test works.
* Add new generic test for static const variable in a function in a generic.
* Generic function with static const variable doesn't work.
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 80 | ||||
| -rw-r--r-- | tests/bugs/meta-2.slang (renamed from tests/experiments/generic/meta-2.slang) | 7 | ||||
| -rw-r--r-- | tests/bugs/meta-2.slang.expected.txt | 4 | ||||
| -rw-r--r-- | tests/experiments/generic/generic-func-static-const-var.slang | 24 | ||||
| -rw-r--r-- | tests/experiments/generic/generic-struct-func-static-const-var.slang | 21 |
5 files changed, 110 insertions, 26 deletions
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 779034979..bca8bd5b6 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -5723,9 +5723,35 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> return paramVal; } - LoweredValInfo lowerConstantDeclCommon(VarDeclBase* decl, IRGenContext* subContext) + LoweredValInfo lowerConstantDeclCommon(VarDeclBase* decl) { - auto builder = subContext->irBuilder; + // It's constant, so shoul dhave this modifier + SLANG_ASSERT(decl->hasModifier<ConstModifier>()); + + NestedContext nested(this); + auto subBuilder = nested.getBuilder(); + auto subContext = nested.getContext(); + IRGeneric* outerGeneric = emitOuterGenerics(subContext, decl, decl); + + // TODO(JS): Is this right? + // + // If we *are* in a generic, then outputting this in the (current) generic scope would be correct. + // If we *aren't* we want to go the level above for insertion + // + // Just inserting into the parent doesn't work with a generic that holds a function that has a static const + // variable. + // + // This tries to match the behavior of previous `lowerFunctionStaticConstVarDecl` functionality + if (!outerGeneric && isFunctionStaticVarDecl(decl)) + { + // We need to insert the constant at a level above + // the function being emitted. This will usually + // be the global scope, but it might be an outer + // generic if we are lowering a generic function. + + subBuilder->setInsertInto(subBuilder->getFunc()->getParent()); + } + auto initExpr = decl->initExpr; // We want to be able to support cases where a global constant is defined in @@ -5752,7 +5778,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // a global constant IR node with the right type. // auto irType = lowerType(subContext, decl->getType()); - irConstant = builder->emitGlobalConstant(irType); + irConstant = subBuilder->emitGlobalConstant(irType); } else { @@ -5768,7 +5794,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // We construct a distinct IR instruction to represent the // constant itself, with the value as an operand. // - irConstant = builder->emitGlobalConstant( + irConstant = subBuilder->emitGlobalConstant( irInitVal->getFullType(), irInitVal); } @@ -5776,24 +5802,30 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // All of the attributes/decorations we can attach // belong on the IR constant node. // + addLinkageDecoration(context, irConstant, decl); + addNameHint(context, irConstant, decl); addVarDecorations(context, irConstant, decl); + getBuilder()->addHighLevelDeclDecoration(irConstant, decl); + // Finish of generic + + auto loweredValue = LoweredValInfo::simple(finishOuterGenerics(subBuilder, irConstant, outerGeneric)); + // Register the value that was emitted as the value // for any references to the constant from elsewhere // in the code. // - auto constantVal = LoweredValInfo::simple(irConstant); - setGlobalValue(context, decl, constantVal); + setGlobalValue(context, decl, loweredValue); - return constantVal; + return loweredValue; } LoweredValInfo lowerGlobalConstantDecl(VarDecl* decl) { - return lowerConstantDeclCommon(decl, context); + return lowerConstantDeclCommon(decl); } LoweredValInfo lowerGlobalVarDecl(VarDecl* decl) @@ -5919,18 +5951,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> LoweredValInfo lowerFunctionStaticConstVarDecl( VarDeclBase* decl) { - // We need to insert the constant at a level above - // the function being emitted. This will usually - // be the global scope, but it might be an outer - // generic if we are lowering a generic function. - // - NestedContext nestedContext(this); - auto subBuilder = nestedContext.getBuilder(); - auto subContext = nestedContext.getContext(); - - subBuilder->setInsertInto(subBuilder->getFunc()->getParent()); - - return lowerConstantDeclCommon(decl, subContext); + return lowerConstantDeclCommon(decl); } LoweredValInfo lowerFunctionStaticVarDecl( @@ -7590,6 +7611,13 @@ LoweredValInfo ensureDecl( env = env->outer; } + // If we have a decl that's a generic value/type decl then something has gone seriously + // wrong + if (as<GenericValueParamDecl>(decl) || as<GenericTypeParamDecl>(decl)) + { + SLANG_UNEXPECTED("Generic type/value shouldn't be handled here!"); + } + IRBuilder subIRBuilder(context->irBuilder->getSharedBuilder()); subIRBuilder.setInsertInto(subIRBuilder.getModule()); @@ -7625,6 +7653,15 @@ bool canDeclLowerToAGeneric(Decl* decl) // a generic that returns a type (a simple type-level function). if(as<TypeDefDecl>(decl)) return true; + // If we have a variable declaration that is *static* and *const* we can lower to a generic + if (auto varDecl = as<VarDecl>(decl)) + { + if (varDecl->hasModifier<HLSLStaticModifier>() && varDecl->hasModifier<ConstModifier>()) + { + return true; + } + } + return false; } @@ -7674,6 +7711,9 @@ LoweredValInfo emitDeclRef( Substitutions* subst, IRType* type) { + const auto initialSubst = subst; + SLANG_UNUSED(initialSubst); + // We need to proceed by considering the specializations that // have been put in place. diff --git a/tests/experiments/generic/meta-2.slang b/tests/bugs/meta-2.slang index 98ae09ce5..6dd5541c4 100644 --- a/tests/experiments/generic/meta-2.slang +++ b/tests/bugs/meta-2.slang @@ -1,9 +1,4 @@ -//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj - -/* A test meta programing. - -CRASHES the compiler(!). Stack overrun. - */ +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj //TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer RWStructuredBuffer<int> outputBuffer; diff --git a/tests/bugs/meta-2.slang.expected.txt b/tests/bugs/meta-2.slang.expected.txt new file mode 100644 index 000000000..f7bacac93 --- /dev/null +++ b/tests/bugs/meta-2.slang.expected.txt @@ -0,0 +1,4 @@ +A +A +A +A diff --git a/tests/experiments/generic/generic-func-static-const-var.slang b/tests/experiments/generic/generic-func-static-const-var.slang new file mode 100644 index 000000000..2c8ea0398 --- /dev/null +++ b/tests/experiments/generic/generic-func-static-const-var.slang @@ -0,0 +1,24 @@ +//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj -Xslang -dump-ir + +/* Doesn't work correctly failing in emit with a 'generic' instruction that is not expected. */ + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +struct GetValue2<let N : int> +{ + static int getValue() + { + static const int v = N; + return v; + } +}; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int index = dispatchThreadID.x; + + outputBuffer[index] = GetValue2<20>::getValue(); +} + diff --git a/tests/experiments/generic/generic-struct-func-static-const-var.slang b/tests/experiments/generic/generic-struct-func-static-const-var.slang new file mode 100644 index 000000000..db6fc6225 --- /dev/null +++ b/tests/experiments/generic/generic-struct-func-static-const-var.slang @@ -0,0 +1,21 @@ +//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj -Xslang -dump-ir + +/* Doesn't work correctly failing in emit with a 'generic' instruction that is not expected. */ + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +static int getValue<let N: int>() +{ + static const int v = N; + return v; +} + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int index = dispatchThreadID.x; + + outputBuffer[index] = getValue<10>(); +} + |
