Commit 98ad4853 by John Kessenich

HLSL: Support {...} initializer lists that are too short.

parent 1c989040
struct outs {
int a;
float b;
bool c;
float4 v;
};
static float4 gv = {0,0,1};
static float gfa[3] = {0,0};
outs PixelShaderFunction(float4 input) : COLOR0
{
outs o2 = { 3 };
outs o4;
o4.v = gv * gfa[2];
outs o1 = { };
// outs o3 = (outs)0;
// o4 = (outs)0;
o4.c = o1.c;
return o4;
}
\ No newline at end of file
...@@ -2,5 +2,5 @@ ...@@ -2,5 +2,5 @@
// For the version, it uses the latest git tag followed by the number of commits. // For the version, it uses the latest git tag followed by the number of commits.
// For the date, it uses the current date (when then script is run). // For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "Overload400-PrecQual.1664" #define GLSLANG_REVISION "Overload400-PrecQual.1665"
#define GLSLANG_DATE "27-Nov-2016" #define GLSLANG_DATE "27-Nov-2016"
...@@ -858,6 +858,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat ...@@ -858,6 +858,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EOpLogicalAnd: case EOpLogicalAnd:
case EOpLogicalOr: case EOpLogicalOr:
case EOpLogicalXor: case EOpLogicalXor:
case EOpConstructStruct:
return true; return true;
default: default:
break; break;
...@@ -1185,6 +1186,17 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceL ...@@ -1185,6 +1186,17 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceL
} }
// //
// Make an aggregate with an empty sequence.
//
TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc)
{
TIntermAggregate* aggNode = new TIntermAggregate;
aggNode->setLoc(loc);
return aggNode;
}
//
// For "if" test nodes. There are three children; a condition, // For "if" test nodes. There are three children; a condition,
// a true path, and a false path. The two paths are in the // a true path, and a false path. The two paths are in the
// nodePair. // nodePair.
......
...@@ -221,6 +221,7 @@ public: ...@@ -221,6 +221,7 @@ public:
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
TIntermAggregate* makeAggregate(TIntermNode* node); TIntermAggregate* makeAggregate(TIntermNode* node);
TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
TIntermAggregate* makeAggregate(const TSourceLoc&);
TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc); TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
bool areAllChildConst(TIntermAggregate* aggrNode); bool areAllChildConst(TIntermAggregate* aggrNode);
TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
......
...@@ -157,6 +157,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -157,6 +157,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.numericsuffixes.frag", "main"}, {"hlsl.numericsuffixes.frag", "main"},
{"hlsl.numthreads.comp", "main_aux1"}, {"hlsl.numthreads.comp", "main_aux1"},
{"hlsl.overload.frag", "PixelShaderFunction"}, {"hlsl.overload.frag", "PixelShaderFunction"},
{"hlsl.partialInit.frag", "PixelShaderFunction"},
{"hlsl.pp.line.frag", "main"}, {"hlsl.pp.line.frag", "main"},
{"hlsl.precise.frag", "main"}, {"hlsl.precise.frag", "main"},
{"hlsl.promote.binary.frag", "main"}, {"hlsl.promote.binary.frag", "main"},
......
...@@ -1896,7 +1896,8 @@ bool HlslGrammar::acceptExpression(TIntermTyped*& node) ...@@ -1896,7 +1896,8 @@ bool HlslGrammar::acceptExpression(TIntermTyped*& node)
} }
// initializer // initializer
// : LEFT_BRACE initializer_list RIGHT_BRACE // : LEFT_BRACE RIGHT_BRACE
// | LEFT_BRACE initializer_list RIGHT_BRACE
// //
// initializer_list // initializer_list
// : assignment_expression COMMA assignment_expression COMMA ... // : assignment_expression COMMA assignment_expression COMMA ...
...@@ -1907,8 +1908,15 @@ bool HlslGrammar::acceptInitializer(TIntermTyped*& node) ...@@ -1907,8 +1908,15 @@ bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
if (! acceptTokenClass(EHTokLeftBrace)) if (! acceptTokenClass(EHTokLeftBrace))
return false; return false;
// initializer_list // RIGHT_BRACE
TSourceLoc loc = token.loc; TSourceLoc loc = token.loc;
if (acceptTokenClass(EHTokRightBrace)) {
// a zero-length initializer list
node = intermediate.makeAggregate(loc);
return true;
}
// initializer_list
node = nullptr; node = nullptr;
do { do {
// assignment_expression // assignment_expression
......
...@@ -4594,7 +4594,8 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm ...@@ -4594,7 +4594,8 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
// constructor-style subtree, allowing the rest of the code to operate // constructor-style subtree, allowing the rest of the code to operate
// identically for both kinds of initializers. // identically for both kinds of initializers.
// //
initializer = convertInitializerList(loc, variable->getType(), initializer); if (initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull)
initializer = convertInitializerList(loc, variable->getType(), initializer);
if (! initializer) { if (! initializer) {
// error recovery; don't leave const without constant values // error recovery; don't leave const without constant values
if (qualifier == EvqConst) if (qualifier == EvqConst)
...@@ -4679,8 +4680,15 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co ...@@ -4679,8 +4680,15 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
// see if we have bottomed out in the tree within the initializer-list part // see if we have bottomed out in the tree within the initializer-list part
TIntermAggregate* initList = initializer->getAsAggregate(); TIntermAggregate* initList = initializer->getAsAggregate();
if (! initList || initList->getOp() != EOpNull) if (! initList || initList->getOp() != EOpNull) {
return initializer; // We don't have a list, but if it's a scalar and the 'type' is a
// composite, we need to lengthen below to make it useful.
// Otherwise, this is an already formed object to initialize with.
if (type.isScalar() || !initializer->getType().isScalar())
return initializer;
else
initList = intermediate.makeAggregate(initializer);
}
// Of the initializer-list set of nodes, need to process bottom up, // Of the initializer-list set of nodes, need to process bottom up,
// so recurse deep, then process on the way up. // so recurse deep, then process on the way up.
...@@ -4694,7 +4702,8 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co ...@@ -4694,7 +4702,8 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
arrayType.newArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below arrayType.newArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below
// edit array sizes to fill in unsized dimensions // edit array sizes to fill in unsized dimensions
arrayType.changeOuterArraySize((int)initList->getSequence().size()); if (type.isImplicitlySizedArray())
arrayType.changeOuterArraySize((int)initList->getSequence().size());
TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped(); TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped();
if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() && if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() &&
arrayType.getArraySizes().getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) { arrayType.getArraySizes().getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) {
...@@ -4704,8 +4713,12 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co ...@@ -4704,8 +4713,12 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
} }
} }
// lengthen list to be long enough
lengthenList(loc, initList->getSequence(), arrayType.getOuterArraySize());
// recursively process each element
TType elementType(arrayType, 0); // dereferenced type TType elementType(arrayType, 0); // dereferenced type
for (size_t i = 0; i < initList->getSequence().size(); ++i) { for (int i = 0; i < arrayType.getOuterArraySize(); ++i) {
initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped()); initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped());
if (initList->getSequence()[i] == nullptr) if (initList->getSequence()[i] == nullptr)
return nullptr; return nullptr;
...@@ -4713,6 +4726,9 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co ...@@ -4713,6 +4726,9 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
return addConstructor(loc, initList, arrayType); return addConstructor(loc, initList, arrayType);
} else if (type.isStruct()) { } else if (type.isStruct()) {
// lengthen list to be long enough
lengthenList(loc, initList->getSequence(), type.getStruct()->size());
if (type.getStruct()->size() != initList->getSequence().size()) { if (type.getStruct()->size() != initList->getSequence().size()) {
error(loc, "wrong number of structure members", "initializer list", ""); error(loc, "wrong number of structure members", "initializer list", "");
return nullptr; return nullptr;
...@@ -4728,6 +4744,9 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co ...@@ -4728,6 +4744,9 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
// a series of rows and columns. We can just use the list directly as // a series of rows and columns. We can just use the list directly as
// a constructor; no further processing needed. // a constructor; no further processing needed.
} else { } else {
// lengthen list to be long enough
lengthenList(loc, initList->getSequence(), type.getMatrixCols());
if (type.getMatrixCols() != (int)initList->getSequence().size()) { if (type.getMatrixCols() != (int)initList->getSequence().size()) {
error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str()); error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str());
return nullptr; return nullptr;
...@@ -4740,6 +4759,10 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co ...@@ -4740,6 +4759,10 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
} }
} }
} else if (type.isVector()) { } else if (type.isVector()) {
// lengthen list to be long enough
lengthenList(loc, initList->getSequence(), type.getVectorSize());
// error check; we're at bottom, so work is finished below
if (type.getVectorSize() != (int)initList->getSequence().size()) { if (type.getVectorSize() != (int)initList->getSequence().size()) {
error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str()); error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
return nullptr; return nullptr;
...@@ -4749,7 +4772,7 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co ...@@ -4749,7 +4772,7 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
error(loc, "scalar expected one element:", "initializer list", type.getCompleteString().c_str()); error(loc, "scalar expected one element:", "initializer list", type.getCompleteString().c_str());
return nullptr; return nullptr;
} }
} else { } else {
error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str()); error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
return nullptr; return nullptr;
} }
...@@ -4761,9 +4784,19 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co ...@@ -4761,9 +4784,19 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
emulatedConstructorArguments = initList->getSequence()[0]; emulatedConstructorArguments = initList->getSequence()[0];
else else
emulatedConstructorArguments = initList; emulatedConstructorArguments = initList;
return addConstructor(loc, emulatedConstructorArguments, type); return addConstructor(loc, emulatedConstructorArguments, type);
} }
// Lengthen list to be long enough to cover any gap from the current list size
// to 'size'. If the list is longer, do nothing.
// The value to lengthen with is the default for short lists.
void HlslParseContext::lengthenList(const TSourceLoc& loc, TIntermSequence& list, int size)
{
for (int c = (int)list.size(); c < size; ++c)
list.push_back(intermediate.addConstantUnion(0, loc));
}
// //
// Test for the correctness of the parameters passed to various constructor functions // Test for the correctness of the parameters passed to various constructor functions
// and also convert them to the right data type, if allowed and required. // and also convert them to the right data type, if allowed and required.
......
...@@ -128,6 +128,7 @@ public: ...@@ -128,6 +128,7 @@ public:
const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
void declareTypedef(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0); void declareTypedef(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0);
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, TType&, TIntermTyped* initializer = 0); TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, TType&, TIntermTyped* initializer = 0);
void lengthenList(const TSourceLoc&, TIntermSequence& list, int size);
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment