From 7f36c34daf633dcade3a3bab9cdcf14a34fed3cd Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Tue, 5 Apr 2022 13:32:24 -0400 Subject: 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. --- source/slang/slang-lower-to-ir.cpp | 80 ++++++++++++++++------ tests/bugs/meta-2.slang | 18 +++++ tests/bugs/meta-2.slang.expected.txt | 4 ++ .../generic/generic-func-static-const-var.slang | 24 +++++++ .../generic-struct-func-static-const-var.slang | 21 ++++++ tests/experiments/generic/meta-2.slang | 23 ------- 6 files changed, 127 insertions(+), 43 deletions(-) create mode 100644 tests/bugs/meta-2.slang create mode 100644 tests/bugs/meta-2.slang.expected.txt create mode 100644 tests/experiments/generic/generic-func-static-const-var.slang create mode 100644 tests/experiments/generic/generic-struct-func-static-const-var.slang delete mode 100644 tests/experiments/generic/meta-2.slang 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 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()); + + 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 // 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 // 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 // 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 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(decl) || as(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(decl)) return true; + // If we have a variable declaration that is *static* and *const* we can lower to a generic + if (auto varDecl = as(decl)) + { + if (varDecl->hasModifier() && varDecl->hasModifier()) + { + 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/bugs/meta-2.slang b/tests/bugs/meta-2.slang new file mode 100644 index 000000000..6dd5541c4 --- /dev/null +++ b/tests/bugs/meta-2.slang @@ -0,0 +1,18 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +struct GetValue +{ + static const int Value = N; +}; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int index = dispatchThreadID.x; + + outputBuffer[index] = GetValue<10>::Value; +} + 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 outputBuffer; + +struct GetValue2 +{ + 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 outputBuffer; + +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] = getValue<10>(); +} + diff --git a/tests/experiments/generic/meta-2.slang b/tests/experiments/generic/meta-2.slang deleted file mode 100644 index 98ae09ce5..000000000 --- a/tests/experiments/generic/meta-2.slang +++ /dev/null @@ -1,23 +0,0 @@ -//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj - -/* A test meta programing. - -CRASHES the compiler(!). Stack overrun. - */ - -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer -RWStructuredBuffer outputBuffer; - -struct GetValue -{ - static const int Value = N; -}; - -[numthreads(4, 1, 1)] -void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) -{ - int index = dispatchThreadID.x; - - outputBuffer[index] = GetValue<10>::Value; -} - -- cgit v1.2.3