WIP: HLSL: support global const initializers from non-constant rvalues

Semantic test left over from other source languages is removed, since this is permitted by HLSL.
Also, to support the functionality, a targeted test is performed for this case and it is
turned into a EvqGlobal qualifier to create an AST initialization segment when needed.

Constness is now propagated up aggregate chains during initializer construction.  This
handles hierarchical cases such as the distinction between:

    static const float2 a[2] = { { 1, 2 }, { 3, 4} };

vs

    static const float2 a[2] = { { 1, 2 }, { cbuffer_member, 4} };

The first of which can use a first class constant initalization, and the second cannot.
This commit is contained in:
LoopDawg
2017-07-10 15:43:40 -06:00
parent 652db16ff1
commit 0fca0bafaf
5 changed files with 219 additions and 5 deletions

View File

@@ -7165,6 +7165,21 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, const TStr
if (voidErrorCheck(loc, identifier, type.getBasicType()))
return nullptr;
// Global consts with initializers that are non-const act like EvqGlobal in HLSL.
// This test is implicitly recursive, because initializers propagate constness
// up the aggregate node tree during creation. E.g, for:
// { { 1, 2 }, { 3, 4 } }
// the initializer list is marked EvqConst at the top node, and remains so here. However:
// { 1, { myvar, 2 }, 3 }
// is not a const intializer, and still becomes EvqGlobal here.
const bool nonConstInitializer = (initializer != nullptr && initializer->getQualifier().storage != EvqConst);
if (type.getQualifier().storage == EvqConst && symbolTable.atGlobalLevel() && nonConstInitializer) {
// Force to global
type.getQualifier().storage = EvqGlobal;
}
// make const and initialization consistent
fixConstInit(loc, identifier, type, initializer);
@@ -7345,11 +7360,6 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
variable->getWritableType().getQualifier().storage = EvqTemporary;
return nullptr;
}
if (qualifier == EvqConst && symbolTable.atGlobalLevel() && initializer->getType().getQualifier().storage != EvqConst) {
error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
variable->getWritableType().getQualifier().storage = EvqTemporary;
return nullptr;
}
// Const variables require a constant initializer
if (qualifier == EvqConst) {