Commit 7c0ec1ef by Nicolas Capens Committed by Nicolas Capens

Produce constructors instead of conversions.

GLSL only supports explicit conversion through constructors. Therefore the conversion nodes are redundant. BUG=15415045 Change-Id: Ia6bd93c9c4a69d013a4ec82f81826e6ff5c18eb2 Reviewed-on: https://swiftshader-review.googlesource.com/1113Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent c3bfb403
...@@ -32,7 +32,7 @@ const char* getOperatorString(TOperator op) { ...@@ -32,7 +32,7 @@ const char* getOperatorString(TOperator op) {
case EOpDivAssign: return "/="; case EOpDivAssign: return "/=";
// Fall-through. // Fall-through.
case EOpMulAssign: case EOpMulAssign:
case EOpVectorTimesMatrixAssign: case EOpVectorTimesMatrixAssign:
case EOpVectorTimesScalarAssign: case EOpVectorTimesScalarAssign:
case EOpMatrixTimesScalarAssign: case EOpMatrixTimesScalarAssign:
...@@ -77,11 +77,11 @@ const char* getOperatorString(TOperator op) { ...@@ -77,11 +77,11 @@ const char* getOperatorString(TOperator op) {
// Fall-through. // Fall-through.
case EOpConvIntToBool: case EOpConvIntToBool:
case EOpConvFloatToBool: return "bool"; case EOpConvFloatToBool: return "bool";
// Fall-through. // Fall-through.
case EOpConvBoolToFloat: case EOpConvBoolToFloat:
case EOpConvIntToFloat: return "float"; case EOpConvIntToFloat: return "float";
// Fall-through. // Fall-through.
case EOpConvFloatToInt: case EOpConvFloatToInt:
case EOpConvBoolToInt: return "int"; case EOpConvBoolToInt: return "int";
...@@ -176,23 +176,9 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn ...@@ -176,23 +176,9 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
default: break; default: break;
} }
// if (left->getBasicType() != right->getBasicType())
// First try converting the children to compatible types. {
// return 0;
if (left->getType().getStruct() && right->getType().getStruct()) {
if (left->getType() != right->getType())
return 0;
} else {
TIntermTyped* child = addConversion(op, left->getType(), right);
if (child)
right = child;
else {
child = addConversion(op, right->getType(), left);
if (child)
left = child;
else
return 0;
}
} }
// //
...@@ -212,11 +198,10 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn ...@@ -212,11 +198,10 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
// //
// See if we can fold constants. // See if we can fold constants.
// //
TIntermTyped* typedReturnNode = 0;
TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
if (leftTempConstant && rightTempConstant) { if (leftTempConstant && rightTempConstant) {
typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
if (typedReturnNode) if (typedReturnNode)
return typedReturnNode; return typedReturnNode;
...@@ -232,21 +217,21 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn ...@@ -232,21 +217,21 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
// //
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line) TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
{ {
// if (left->getType().getStruct() || right->getType().getStruct())
// Like adding binary math, except the conversion can only go {
// from right to left. if (left->getType() != right->getType())
// {
return 0;
}
}
TIntermBinary* node = new TIntermBinary(op); TIntermBinary* node = new TIntermBinary(op);
if (line == 0) if(line == 0)
line = left->getLine(); line = left->getLine();
node->setLine(line); node->setLine(line);
TIntermTyped* child = addConversion(op, left->getType(), right);
if (child == 0)
return 0;
node->setLeft(left); node->setLeft(left);
node->setRight(child); node->setRight(right);
if (! node->promote(infoSink)) if (! node->promote(infoSink))
return 0; return 0;
...@@ -306,40 +291,6 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, ...@@ -306,40 +291,6 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
default: break; default: break;
} }
//
// Do we need to promote the operand?
//
// Note: Implicit promotions were removed from the language.
//
TBasicType newType = EbtVoid;
switch (op) {
case EOpConstructInt: newType = EbtInt; break;
case EOpConstructBool: newType = EbtBool; break;
case EOpConstructFloat: newType = EbtFloat; break;
default: break;
}
if (newType != EbtVoid) {
child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
child->getNominalSize(),
child->isMatrix(),
child->isArray()),
child);
if (child == 0)
return 0;
}
//
// For constructors, we are now done, it's all in the conversion.
//
switch (op) {
case EOpConstructInt:
case EOpConstructBool:
case EOpConstructFloat:
return child;
default: break;
}
TIntermConstantUnion *childTempConstant = 0; TIntermConstantUnion *childTempConstant = 0;
if (child->getAsConstantUnion()) if (child->getAsConstantUnion())
childTempConstant = child->getAsConstantUnion(); childTempConstant = child->getAsConstantUnion();
...@@ -625,18 +576,9 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T ...@@ -625,18 +576,9 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T
// //
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line) TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
{ {
// if (trueBlock->getType() != falseBlock->getType())
// Get compatible types. {
// return 0;
TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
if (child)
falseBlock = child;
else {
child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
if (child)
trueBlock = child;
else
return 0;
} }
// //
...@@ -809,6 +751,7 @@ bool TIntermOperator::isConstructor() const ...@@ -809,6 +751,7 @@ bool TIntermOperator::isConstructor() const
return false; return false;
} }
} }
// //
// Make sure the type of a unary operator is appropriate for its // Make sure the type of a unary operator is appropriate for its
// combination of operation and operand type. // combination of operation and operand type.
...@@ -869,7 +812,9 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -869,7 +812,9 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
// GLSL ES 2.0 does not support implicit type casting. // GLSL ES 2.0 does not support implicit type casting.
// So the basic type should always match. // So the basic type should always match.
if (left->getBasicType() != right->getBasicType()) if (left->getBasicType() != right->getBasicType())
{
return false; return false;
}
// //
// Base assumption: just make the type the same as the left // Base assumption: just make the type the same as the left
......
...@@ -38,11 +38,11 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV ...@@ -38,11 +38,11 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
for (int i = 0; i < fields.num; ++i) { for (int i = 0; i < fields.num; ++i) {
switch (compString[i]) { switch (compString[i]) {
case 'x': case 'x':
fields.offsets[i] = 0; fields.offsets[i] = 0;
fieldSet[i] = exyzw; fieldSet[i] = exyzw;
break; break;
case 'r': case 'r':
fields.offsets[i] = 0; fields.offsets[i] = 0;
fieldSet[i] = ergba; fieldSet[i] = ergba;
break; break;
...@@ -50,11 +50,11 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV ...@@ -50,11 +50,11 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
fields.offsets[i] = 0; fields.offsets[i] = 0;
fieldSet[i] = estpq; fieldSet[i] = estpq;
break; break;
case 'y': case 'y':
fields.offsets[i] = 1; fields.offsets[i] = 1;
fieldSet[i] = exyzw; fieldSet[i] = exyzw;
break; break;
case 'g': case 'g':
fields.offsets[i] = 1; fields.offsets[i] = 1;
fieldSet[i] = ergba; fieldSet[i] = ergba;
break; break;
...@@ -62,11 +62,11 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV ...@@ -62,11 +62,11 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
fields.offsets[i] = 1; fields.offsets[i] = 1;
fieldSet[i] = estpq; fieldSet[i] = estpq;
break; break;
case 'z': case 'z':
fields.offsets[i] = 2; fields.offsets[i] = 2;
fieldSet[i] = exyzw; fieldSet[i] = exyzw;
break; break;
case 'b': case 'b':
fields.offsets[i] = 2; fields.offsets[i] = 2;
fieldSet[i] = ergba; fieldSet[i] = ergba;
break; break;
...@@ -74,12 +74,11 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV ...@@ -74,12 +74,11 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
fields.offsets[i] = 2; fields.offsets[i] = 2;
fieldSet[i] = estpq; fieldSet[i] = estpq;
break; break;
case 'w':
case 'w':
fields.offsets[i] = 3; fields.offsets[i] = 3;
fieldSet[i] = exyzw; fieldSet[i] = exyzw;
break; break;
case 'a': case 'a':
fields.offsets[i] = 3; fields.offsets[i] = 3;
fieldSet[i] = ergba; fieldSet[i] = ergba;
break; break;
...@@ -176,7 +175,7 @@ void TParseContext::recover() ...@@ -176,7 +175,7 @@ void TParseContext::recover()
// Used by flex/bison to output all syntax and parsing errors. // Used by flex/bison to output all syntax and parsing errors.
// //
void TParseContext::error(TSourceLoc loc, void TParseContext::error(TSourceLoc loc,
const char* reason, const char* token, const char* reason, const char* token,
const char* extraInfo) const char* extraInfo)
{ {
pp::SourceLocation srcLoc; pp::SourceLocation srcLoc;
...@@ -217,7 +216,7 @@ void TParseContext::assignError(int line, const char* op, TString left, TString ...@@ -217,7 +216,7 @@ void TParseContext::assignError(int line, const char* op, TString left, TString
void TParseContext::unaryOpError(int line, const char* op, TString operand) void TParseContext::unaryOpError(int line, const char* op, TString operand)
{ {
std::stringstream extraInfoStream; std::stringstream extraInfoStream;
extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
<< " (or there is no acceptable conversion)"; << " (or there is no acceptable conversion)";
std::string extraInfo = extraInfoStream.str(); std::string extraInfo = extraInfoStream.str();
error(line, " wrong operand type", op, extraInfo.c_str()); error(line, " wrong operand type", op, extraInfo.c_str());
...@@ -232,7 +231,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin ...@@ -232,7 +231,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin
extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
<< "' and a right operand of type '" << right << "' (or there is no acceptable conversion)"; << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
std::string extraInfo = extraInfoStream.str(); std::string extraInfo = extraInfoStream.str();
error(line, " wrong operand types ", op, extraInfo.c_str()); error(line, " wrong operand types ", op, extraInfo.c_str());
} }
bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){ bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
...@@ -283,21 +282,21 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod ...@@ -283,21 +282,21 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
TIntermTyped* rightNode = binaryNode->getRight(); TIntermTyped* rightNode = binaryNode->getRight();
TIntermAggregate *aggrNode = rightNode->getAsAggregate(); TIntermAggregate *aggrNode = rightNode->getAsAggregate();
for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
p != aggrNode->getSequence().end(); p++) { p != aggrNode->getSequence().end(); p++) {
int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
offset[value]++; offset[value]++;
if (offset[value] > 1) { if (offset[value] > 1) {
error(line, " l-value of swizzle cannot have duplicate components", op); error(line, " l-value of swizzle cannot have duplicate components", op);
return true; return true;
} }
} }
} }
return errorReturn; return errorReturn;
default: default:
break; break;
} }
error(line, " l-value required", op); error(line, " l-value required", op);
...@@ -470,7 +469,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction ...@@ -470,7 +469,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
case EOpConstructMat4: case EOpConstructMat4:
constructingMatrix = true; constructingMatrix = true;
break; break;
default: default:
break; break;
} }
...@@ -489,7 +488,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction ...@@ -489,7 +488,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
for (int i = 0; i < function.getParamCount(); ++i) { for (int i = 0; i < function.getParamCount(); ++i) {
const TParameter& param = function.getParam(i); const TParameter& param = function.getParam(i);
size += param.type->getObjectSize(); size += param.type->getObjectSize();
if (constructingMatrix && param.type->isMatrix()) if (constructingMatrix && param.type->isMatrix())
matrixInMatrix = true; matrixInMatrix = true;
if (full) if (full)
...@@ -501,7 +500,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction ...@@ -501,7 +500,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
if (param.type->isArray()) if (param.type->isArray())
arrayArg = true; arrayArg = true;
} }
if (constType) if (constType)
type->setQualifier(EvqConst); type->setQualifier(EvqConst);
...@@ -526,7 +525,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction ...@@ -526,7 +525,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
error(line, "too many arguments", "constructor"); error(line, "too many arguments", "constructor");
return true; return true;
} }
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) { if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
return true; return true;
...@@ -566,7 +565,7 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP ...@@ -566,7 +565,7 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP
if (pubType.type == EbtVoid) { if (pubType.type == EbtVoid) {
error(line, "illegal use of type 'void'", identifier.c_str()); error(line, "illegal use of type 'void'", identifier.c_str());
return true; return true;
} }
return false; return false;
} }
...@@ -580,7 +579,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) ...@@ -580,7 +579,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
error(line, "boolean expression expected", ""); error(line, "boolean expression expected", "");
return true; return true;
} }
return false; return false;
} }
...@@ -594,7 +593,7 @@ bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) ...@@ -594,7 +593,7 @@ bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
error(line, "boolean expression expected", ""); error(line, "boolean expression expected", "");
return true; return true;
} }
return false; return false;
} }
...@@ -604,10 +603,10 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const ...@@ -604,10 +603,10 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
if (pType.type == EbtStruct) { if (pType.type == EbtStruct) {
if (containsSampler(*pType.userDef)) { if (containsSampler(*pType.userDef)) {
error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
return true; return true;
} }
return false; return false;
} else if (IsSampler(pType.type)) { } else if (IsSampler(pType.type)) {
error(line, reason, getBasicString(pType.type)); error(line, reason, getBasicString(pType.type));
...@@ -623,7 +622,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType ...@@ -623,7 +622,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType
if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
pType.type == EbtStruct) { pType.type == EbtStruct) {
error(line, "cannot be used with a structure", getQualifierString(pType.qualifier)); error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
return true; return true;
} }
...@@ -635,7 +634,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType ...@@ -635,7 +634,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType
bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type) bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
{ {
if ((qualifier == EvqOut || qualifier == EvqInOut) && if ((qualifier == EvqOut || qualifier == EvqInOut) &&
type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
error(line, "samplers cannot be output parameters", type.getBasicString()); error(line, "samplers cannot be output parameters", type.getBasicString());
return true; return true;
...@@ -718,7 +717,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) ...@@ -718,7 +717,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
} }
// //
// Do all the semantic checking for declaring an array, with and // Do all the semantic checking for declaring an array, with and
// without a size, and make the right changes to the symbol table. // without a size, and make the right changes to the symbol table.
// //
// size == 0 means no specified size. // size == 0 means no specified size.
...@@ -732,13 +731,13 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t ...@@ -732,13 +731,13 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
// because reserved arrays can be redeclared. // because reserved arrays can be redeclared.
// //
bool builtIn = false; bool builtIn = false;
bool sameScope = false; bool sameScope = false;
TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope); TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
if (symbol == 0 || !sameScope) { if (symbol == 0 || !sameScope) {
if (reservedErrorCheck(line, identifier)) if (reservedErrorCheck(line, identifier))
return true; return true;
variable = new TVariable(&identifier, TType(type)); variable = new TVariable(&identifier, TType(type));
if (type.arraySize) if (type.arraySize)
...@@ -764,7 +763,7 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t ...@@ -764,7 +763,7 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
error(line, "redeclaration of array with size", identifier.c_str()); error(line, "redeclaration of array with size", identifier.c_str());
return true; return true;
} }
if (! variable->getType().sameElementType(TType(type))) { if (! variable->getType().sameElementType(TType(type))) {
error(line, "redeclaration of array with a different type", identifier.c_str()); error(line, "redeclaration of array with a different type", identifier.c_str());
return true; return true;
...@@ -782,7 +781,7 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t ...@@ -782,7 +781,7 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
if (type.arraySize) if (type.arraySize)
variable->getType().setArraySize(type.arraySize); variable->getType().setArraySize(type.arraySize);
} }
if (voidErrorCheck(line, identifier, type)) if (voidErrorCheck(line, identifier, type))
return true; return true;
...@@ -816,7 +815,7 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, ...@@ -816,7 +815,7 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
} }
} }
// we dont want to update the maxArraySize when this flag is not set, we just want to include this // we dont want to update the maxArraySize when this flag is not set, we just want to include this
// node type in the chain of node types so that its updated when a higher maxArraySize comes in. // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
if (!updateFlag) if (!updateFlag)
return false; return false;
...@@ -845,7 +844,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli ...@@ -845,7 +844,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
{ {
// Make the qualifier make sense. // Make the qualifier make sense.
type.qualifier = EvqTemporary; type.qualifier = EvqTemporary;
if (array) if (array)
{ {
error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str()); error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
...@@ -892,7 +891,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType ...@@ -892,7 +891,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType
} }
bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type) bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
{ {
if (qualifier != EvqConst && qualifier != EvqTemporary) { if (qualifier != EvqConst && qualifier != EvqTemporary) {
error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
return true; return true;
...@@ -989,7 +988,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu ...@@ -989,7 +988,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu
// Initializers show up in several places in the grammar. Have one set of // Initializers show up in several places in the grammar. Have one set of
// code to handle them here. // code to handle them here.
// //
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
{ {
TType type = TType(pType); TType type = TType(pType);
...@@ -1008,7 +1007,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu ...@@ -1008,7 +1007,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
if (! symbolTable.insert(*variable)) { if (! symbolTable.insert(*variable)) {
error(line, "redefinition", variable->getName().c_str()); error(line, "redefinition", variable->getName().c_str());
return true; return true;
// don't delete variable, it's used by error recovery, and the pool // don't delete variable, it's used by error recovery, and the pool
// pop will take care of the memory // pop will take care of the memory
} }
} }
...@@ -1035,12 +1034,12 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu ...@@ -1035,12 +1034,12 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
return true; return true;
} }
if (type != initializer->getType()) { if (type != initializer->getType()) {
error(line, " non-matching types for const initializer ", error(line, " non-matching types for const initializer ",
variable->getType().getQualifierString()); variable->getType().getQualifierString());
variable->getType().setQualifier(EvqTemporary); variable->getType().setQualifier(EvqTemporary);
return true; return true;
} }
if (initializer->getAsConstantUnion()) { if (initializer->getAsConstantUnion()) {
ConstantUnion* unionArray = variable->getConstPointer(); ConstantUnion* unionArray = variable->getConstPointer();
if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) { if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
...@@ -1063,7 +1062,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu ...@@ -1063,7 +1062,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
return true; return true;
} }
} }
if (qualifier != EvqConst) { if (qualifier != EvqConst) {
TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line); intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
...@@ -1071,7 +1070,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu ...@@ -1071,7 +1070,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
return true; return true;
} }
} else } else
intermNode = 0; intermNode = 0;
return false; return false;
...@@ -1085,7 +1084,7 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) ...@@ -1085,7 +1084,7 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
bool allConstant = true; bool allConstant = true;
// check if all the child nodes are constants so that they can be inserted into // check if all the child nodes are constants so that they can be inserted into
// the parent node // the parent node
TIntermSequence &sequence = aggrNode->getSequence() ; TIntermSequence &sequence = aggrNode->getSequence() ;
for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
...@@ -1097,85 +1096,44 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) ...@@ -1097,85 +1096,44 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
} }
// This function is used to test for the correctness of the parameters passed to various constructor functions // This function is used to test for the correctness of the parameters passed to various constructor functions
// and also convert them to the right datatype if it is allowed and required. // and also convert them to the right datatype if it is allowed and required.
// //
// Returns 0 for an error or the constructed node (aggregate or typed) for no error. // Returns 0 for an error or the constructed node (aggregate or typed) for no error.
// //
TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line) TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
{ {
if (node == 0) TIntermAggregate *aggregateArguments = arguments->getAsAggregate();
return 0;
TIntermAggregate* aggrNode = node->getAsAggregate(); if(!aggregateArguments)
{
TTypeList::const_iterator memberTypes; aggregateArguments = new TIntermAggregate;
if (op == EOpConstructStruct) aggregateArguments->getSequence().push_back(arguments);
memberTypes = type->getStruct()->begin(); }
TType elementType = *type;
if (type->isArray())
elementType.clearArrayness();
bool singleArg;
if (aggrNode) {
if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
singleArg = true;
else
singleArg = false;
} else
singleArg = true;
TIntermTyped *newNode;
if (singleArg) {
// If structure constructor or array constructor is being called
// for only one parameter inside the structure, we need to call constructStruct function once.
if (type->isArray())
newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
else if (op == EOpConstructStruct)
newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
else
newNode = constructBuiltIn(type, op, node, node->getLine(), false);
if (newNode && newNode->getAsAggregate()) { if(op == EOpConstructStruct)
TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); {
if (constConstructor) TTypeList &fields = *type->getStruct();
return constConstructor; TIntermSequence &args = aggregateArguments->getSequence();
}
return newNode; for(size_t i = 0; i < fields.size(); i++)
} {
if(args[i]->getAsTyped()->getType() != *fields[i].type)
// {
// Handle list of arguments. error(line, "Structure constructor arguments do not match structure fields", "Error");
// recover();
TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor
// if the structure constructor contains more than one parameter, then construct return 0;
// each parameter }
int paramCount = 0; // keeps a track of the constructor parameter number being checked
// for each parameter to the constructor call, check to see if the right type is passed or convert them
// to the right type if possible (and allowed).
// for structure constructors, just check if the right type is passed, no conversion is allowed.
for (TIntermSequence::iterator p = sequenceVector.begin();
p != sequenceVector.end(); p++, paramCount++) {
if (type->isArray())
newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
else if (op == EOpConstructStruct)
newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
else
newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
if (newNode) {
*p = newNode;
} }
} }
TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); // Turn the argument list itself into a constructor
TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
if (constConstructor) TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
if(constConstructor)
{
return constConstructor; return constConstructor;
}
return constructor; return constructor;
} }
...@@ -1204,7 +1162,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co ...@@ -1204,7 +1162,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co
// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
// for the parameter to the constructor (passed to this function). Essentially, it converts // for the parameter to the constructor (passed to this function). Essentially, it converts
// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
// float, then float is converted to int. // float, then float is converted to int.
// //
// Returns 0 for an error or the constructed node. // Returns 0 for an error or the constructed node.
...@@ -1257,7 +1215,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T ...@@ -1257,7 +1215,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T
// //
// Now, if there still isn't an operation to do the construction, and we need one, add one. // Now, if there still isn't an operation to do the construction, and we need one, add one.
// //
// Otherwise, skip out early. // Otherwise, skip out early.
if (subset || (newNode != node && newNode->getType() == *type)) if (subset || (newNode != node && newNode->getType() == *type))
return newNode; return newNode;
...@@ -1280,7 +1238,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int ...@@ -1280,7 +1238,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int
return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
} else { } else {
std::stringstream extraInfoStream; std::stringstream extraInfoStream;
extraInfoStream << "cannot convert parameter " << paramCount extraInfoStream << "cannot convert parameter " << paramCount
<< " from '" << node->getAsTyped()->getType().getBasicString() << " from '" << node->getAsTyped()->getType().getBasicString()
<< "' to '" << type->getBasicString() << "'"; << "' to '" << type->getBasicString() << "'";
std::string extraInfo = extraInfoStream.str(); std::string extraInfo = extraInfoStream.str();
...@@ -1329,18 +1287,18 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy ...@@ -1329,18 +1287,18 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
recover(); recover();
fields.offsets[i] = 0; fields.offsets[i] = 0;
} }
constArray[i] = unionArray[fields.offsets[i]]; constArray[i] = unionArray[fields.offsets[i]];
} }
typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
return typedNode; return typedNode;
} }
// //
// This function returns the column being accessed from a constant matrix. The values are retrieved from // This function returns the column being accessed from a constant matrix. The values are retrieved from
// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
// //
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line) TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
...@@ -1374,8 +1332,8 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T ...@@ -1374,8 +1332,8 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T
// //
// This function returns an element of an array accessed from a constant array. The values are retrieved from // This function returns an element of an array accessed from a constant array. The values are retrieved from
// the symbol table and parse-tree is built for the type of the element. The input // the symbol table and parse-tree is built for the type of the element. The input
// to the function could either be a symbol node (a[0] where a is a constant array)that represents a // to the function could either be a symbol node (a[0] where a is a constant array)that represents a
// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
// //
TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line) TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
...@@ -1411,7 +1369,7 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS ...@@ -1411,7 +1369,7 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
// //
// This function returns the value of a particular field inside a constant structure from the symbol table. // This function returns the value of a particular field inside a constant structure from the symbol table.
// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
// function and returns the parse-tree with the values of the embedded/nested struct. // function and returns the parse-tree with the values of the embedded/nested struct.
// //
...@@ -1485,7 +1443,7 @@ bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldT ...@@ -1485,7 +1443,7 @@ bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldT
// one to the field's struct nesting. // one to the field's struct nesting.
if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) { if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
std::stringstream extraInfoStream; std::stringstream extraInfoStream;
extraInfoStream << "Reference of struct type " << fieldType.getTypeName() extraInfoStream << "Reference of struct type " << fieldType.getTypeName()
<< " exceeds maximum struct nesting of " << kWebGLMaxStructNesting; << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
std::string extraInfo = extraInfoStream.str(); std::string extraInfo = extraInfoStream.str();
error(line, "", "", extraInfo.c_str()); error(line, "", "", extraInfo.c_str());
......
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