Commit 9eedea03 by Zhenyao Mo

Fix code styles in OutputGLSLBase, SymbolTable, and Types.

I came across these three classes in the last CL, so do some cleanup as I touched these classes. BUG= TEST=webgl conformance, no regressions Change-Id: I2819bab5965fcb4917f85c2eded571a7f95ab9a2 Reviewed-on: https://chromium-review.googlesource.com/199423Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Tested-by: 's avatarZhenyao Mo <zmo@chromium.org>
parent 487456a3
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
namespace namespace
{ {
TString arrayBrackets(const TType& type) TString arrayBrackets(const TType &type)
{ {
ASSERT(type.isArray()); ASSERT(type.isArray());
TInfoSinkBase out; TInfoSinkBase out;
...@@ -19,13 +19,14 @@ TString arrayBrackets(const TType& type) ...@@ -19,13 +19,14 @@ TString arrayBrackets(const TType& type)
return TString(out.c_str()); return TString(out.c_str());
} }
bool isSingleStatement(TIntermNode* node) { bool isSingleStatement(TIntermNode *node)
if (const TIntermAggregate* aggregate = node->getAsAggregate()) {
if (const TIntermAggregate *aggregate = node->getAsAggregate())
{ {
return (aggregate->getOp() != EOpFunction) && return (aggregate->getOp() != EOpFunction) &&
(aggregate->getOp() != EOpSequence); (aggregate->getOp() != EOpSequence);
} }
else if (const TIntermSelection* selection = node->getAsSelectionNode()) else if (const TIntermSelection *selection = node->getAsSelectionNode())
{ {
// Ternary operators are usually part of an assignment operator. // Ternary operators are usually part of an assignment operator.
// This handles those rare cases in which they are all by themselves. // This handles those rare cases in which they are all by themselves.
...@@ -39,11 +40,11 @@ bool isSingleStatement(TIntermNode* node) { ...@@ -39,11 +40,11 @@ bool isSingleStatement(TIntermNode* node) {
} }
} // namespace } // namespace
TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy, ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap& nameMap, NameMap &nameMap,
TSymbolTable& symbolTable, TSymbolTable &symbolTable,
int shaderVersion) int shaderVersion)
: TIntermTraverser(true, true, true), : TIntermTraverser(true, true, true),
mObjSink(objSink), mObjSink(objSink),
...@@ -58,32 +59,35 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, ...@@ -58,32 +59,35 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink,
mDeclaredStructs.push_back(ScopedDeclaredStructs()); mDeclaredStructs.push_back(ScopedDeclaredStructs());
} }
void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr) void TOutputGLSLBase::writeTriplet(
Visit visit, const char *preStr, const char *inStr, const char *postStr)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
if (visit == PreVisit && preStr) if (visit == PreVisit && preStr)
{
out << preStr; out << preStr;
}
else if (visit == InVisit && inStr) else if (visit == InVisit && inStr)
{
out << inStr; out << inStr;
}
else if (visit == PostVisit && postStr) else if (visit == PostVisit && postStr)
{
out << postStr; out << postStr;
}
} }
void TOutputGLSLBase::writeVariableType(const TType& type) void TOutputGLSLBase::writeBuiltInFunctionTriplet(
Visit visit, const char *preStr, bool useEmulatedFunction)
{
TString preString = useEmulatedFunction ?
BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr) : preStr;
writeTriplet(visit, preString.c_str(), ", ", ")");
}
void TOutputGLSLBase::writeVariableType(const TType &type)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
TQualifier qualifier = type.getQualifier(); TQualifier qualifier = type.getQualifier();
// TODO(alokp): Validate qualifier for variable declarations. // TODO(alokp): Validate qualifier for variable declarations.
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal)) if (qualifier != EvqTemporary && qualifier != EvqGlobal)
out << type.getQualifierString() << " "; out << type.getQualifierString() << " ";
// Declare the struct if we have not done so already. // Declare the struct if we have not done so already.
if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct())) if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
{ {
declareStruct(type.getStruct()); declareStruct(type.getStruct());
mDeclaredStructs[mDeclaredStructs.size() - 1].push_back(type.getStruct()); mDeclaredStructs[mDeclaredStructs.size() - 1].push_back(type.getStruct());
...@@ -96,19 +100,19 @@ void TOutputGLSLBase::writeVariableType(const TType& type) ...@@ -96,19 +100,19 @@ void TOutputGLSLBase::writeVariableType(const TType& type)
} }
} }
void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
for (TIntermSequence::const_iterator iter = args.begin(); for (TIntermSequence::const_iterator iter = args.begin();
iter != args.end(); ++iter) iter != args.end(); ++iter)
{ {
const TIntermSymbol* arg = (*iter)->getAsSymbolNode(); const TIntermSymbol *arg = (*iter)->getAsSymbolNode();
ASSERT(arg != NULL); ASSERT(arg != NULL);
const TType& type = arg->getType(); const TType &type = arg->getType();
writeVariableType(type); writeVariableType(type);
const TString& name = arg->getSymbol(); const TString &name = arg->getSymbol();
if (!name.empty()) if (!name.empty())
out << " " << hashName(name); out << " " << hashName(name);
if (type.isArray()) if (type.isArray())
...@@ -120,23 +124,24 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) ...@@ -120,23 +124,24 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args)
} }
} }
const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, const ConstantUnion *TOutputGLSLBase::writeConstantUnion(
const ConstantUnion* pConstUnion) const TType &type, const ConstantUnion *pConstUnion)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
if (type.getBasicType() == EbtStruct) if (type.getBasicType() == EbtStruct)
{ {
const TStructure* structure = type.getStruct(); const TStructure *structure = type.getStruct();
out << hashName(structure->name()) << "("; out << hashName(structure->name()) << "(";
const TFieldList& fields = structure->fields(); const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i) for (size_t i = 0; i < fields.size(); ++i)
{ {
const TType* fieldType = fields[i]->type(); const TType *fieldType = fields[i]->type();
ASSERT(fieldType != NULL); ASSERT(fieldType != NULL);
pConstUnion = writeConstantUnion(*fieldType, pConstUnion); pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
if (i != fields.size() - 1) out << ", "; if (i != fields.size() - 1)
out << ", ";
} }
out << ")"; out << ")";
} }
...@@ -144,26 +149,35 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, ...@@ -144,26 +149,35 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
{ {
size_t size = type.getObjectSize(); size_t size = type.getObjectSize();
bool writeType = size > 1; bool writeType = size > 1;
if (writeType) out << getTypeName(type) << "("; if (writeType)
out << getTypeName(type) << "(";
for (size_t i = 0; i < size; ++i, ++pConstUnion) for (size_t i = 0; i < size; ++i, ++pConstUnion)
{ {
switch (pConstUnion->getType()) switch (pConstUnion->getType())
{ {
case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break; case EbtFloat:
case EbtInt: out << pConstUnion->getIConst(); break; out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst()));
case EbtBool: out << pConstUnion->getBConst(); break; break;
case EbtInt:
out << pConstUnion->getIConst();
break;
case EbtBool:
out << pConstUnion->getBConst();
break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
if (i != size - 1) out << ", "; if (i != size - 1)
out << ", ";
} }
if (writeType) out << ")"; if (writeType)
out << ")";
} }
return pConstUnion; return pConstUnion;
} }
void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node)) if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node))
out << mLoopUnrollStack.getLoopIndexValue(node); out << mLoopUnrollStack.getLoopIndexValue(node);
else else
...@@ -173,15 +187,15 @@ void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) ...@@ -173,15 +187,15 @@ void TOutputGLSLBase::visitSymbol(TIntermSymbol* node)
out << arrayBrackets(node->getType()); out << arrayBrackets(node->getType());
} }
void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node) void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
{ {
writeConstantUnion(node->getType(), node->getUnionArrayPointer()); writeConstantUnion(node->getType(), node->getUnionArrayPointer());
} }
bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
{ {
bool visitChildren = true; bool visitChildren = true;
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
switch (node->getOp()) switch (node->getOp())
{ {
case EOpInitialize: case EOpInitialize:
...@@ -192,10 +206,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) ...@@ -192,10 +206,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
mDeclaringVariables = false; mDeclaringVariables = false;
} }
break; break;
case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break; case EOpAssign:
case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break; writeTriplet(visit, "(", " = ", ")");
case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break; break;
case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break; case EOpAddAssign:
writeTriplet(visit, "(", " += ", ")");
break;
case EOpSubAssign:
writeTriplet(visit, "(", " -= ", ")");
break;
case EOpDivAssign:
writeTriplet(visit, "(", " /= ", ")");
break;
// Notice the fall-through. // Notice the fall-through.
case EOpMulAssign: case EOpMulAssign:
case EOpVectorTimesMatrixAssign: case EOpVectorTimesMatrixAssign:
...@@ -213,12 +235,11 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) ...@@ -213,12 +235,11 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
{ {
if (visit == InVisit) if (visit == InVisit)
{ {
if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
out << "[int(clamp(float("; out << "[int(clamp(float(";
} else { else
out << "[webgl_int_clamp("; out << "[webgl_int_clamp(";
} }
}
else if (visit == PostVisit) else if (visit == PostVisit)
{ {
int maxSize; int maxSize;
...@@ -235,13 +256,12 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) ...@@ -235,13 +256,12 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
maxSize = leftType.getNominalSize() - 1; maxSize = leftType.getNominalSize() - 1;
} }
if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
out << "), 0.0, float(" << maxSize << ")))]"; out << "), 0.0, float(" << maxSize << ")))]";
} else { else
out << ", 0, " << maxSize << ")]"; out << ", 0, " << maxSize << ")]";
} }
} }
}
else else
{ {
writeTriplet(visit, NULL, "[", "]"); writeTriplet(visit, NULL, "[", "]");
...@@ -256,9 +276,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) ...@@ -256,9 +276,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
// The node itself represents ".". The struct field "bar" is // The node itself represents ".". The struct field "bar" is
// actually stored as an index into TStructure::fields. // actually stored as an index into TStructure::fields.
out << "."; out << ".";
const TStructure* structure = node->getLeft()->getType().getStruct(); const TStructure *structure = node->getLeft()->getType().getStruct();
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
const TField* field = structure->fields()[index->getIConst(0)]; const TField *field = structure->fields()[index->getIConst(0)];
TString fieldName = field->name(); TString fieldName = field->name();
if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion)) if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion))
...@@ -272,39 +292,70 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) ...@@ -272,39 +292,70 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
if (visit == InVisit) if (visit == InVisit)
{ {
out << "."; out << ".";
TIntermAggregate* rightChild = node->getRight()->getAsAggregate(); TIntermAggregate *rightChild = node->getRight()->getAsAggregate();
TIntermSequence& sequence = rightChild->getSequence(); TIntermSequence &sequence = rightChild->getSequence();
for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit) for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
{ {
TIntermConstantUnion* element = (*sit)->getAsConstantUnion(); TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
ASSERT(element->getBasicType() == EbtInt); ASSERT(element->getBasicType() == EbtInt);
ASSERT(element->getNominalSize() == 1); ASSERT(element->getNominalSize() == 1);
const ConstantUnion& data = element->getUnionArrayPointer()[0]; const ConstantUnion& data = element->getUnionArrayPointer()[0];
ASSERT(data.getType() == EbtInt); ASSERT(data.getType() == EbtInt);
switch (data.getIConst()) switch (data.getIConst())
{ {
case 0: out << "x"; break; case 0:
case 1: out << "y"; break; out << "x";
case 2: out << "z"; break; break;
case 3: out << "w"; break; case 1:
default: UNREACHABLE(); break; out << "y";
break;
case 2:
out << "z";
break;
case 3:
out << "w";
break;
default:
UNREACHABLE();
} }
} }
visitChildren = false; visitChildren = false;
} }
break; break;
case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break; case EOpAdd:
case EOpSub: writeTriplet(visit, "(", " - ", ")"); break; writeTriplet(visit, "(", " + ", ")");
case EOpMul: writeTriplet(visit, "(", " * ", ")"); break; break;
case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break; case EOpSub:
case EOpMod: UNIMPLEMENTED(); break; writeTriplet(visit, "(", " - ", ")");
case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break; break;
case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break; case EOpMul:
case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break; writeTriplet(visit, "(", " * ", ")");
case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break; break;
case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break; case EOpDiv:
case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break; writeTriplet(visit, "(", " / ", ")");
break;
case EOpMod:
UNIMPLEMENTED();
break;
case EOpEqual:
writeTriplet(visit, "(", " == ", ")");
break;
case EOpNotEqual:
writeTriplet(visit, "(", " != ", ")");
break;
case EOpLessThan:
writeTriplet(visit, "(", " < ", ")");
break;
case EOpGreaterThan:
writeTriplet(visit, "(", " > ", ")");
break;
case EOpLessThanEqual:
writeTriplet(visit, "(", " <= ", ")");
break;
case EOpGreaterThanEqual:
writeTriplet(visit, "(", " >= ", ")");
break;
// Notice the fall-through. // Notice the fall-through.
case EOpVectorTimesScalar: case EOpVectorTimesScalar:
...@@ -315,16 +366,23 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) ...@@ -315,16 +366,23 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
writeTriplet(visit, "(", " * ", ")"); writeTriplet(visit, "(", " * ", ")");
break; break;
case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break; case EOpLogicalOr:
case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break; writeTriplet(visit, "(", " || ", ")");
case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break; break;
default: UNREACHABLE(); break; case EOpLogicalXor:
writeTriplet(visit, "(", " ^^ ", ")");
break;
case EOpLogicalAnd:
writeTriplet(visit, "(", " && ", ")");
break;
default:
UNREACHABLE();
} }
return visitChildren; return visitChildren;
} }
bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
{ {
TString preString; TString preString;
TString postString = ")"; TString postString = ")";
...@@ -344,69 +402,149 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) ...@@ -344,69 +402,149 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node)
case EOpConvFloatToBool: case EOpConvFloatToBool:
switch (node->getOperand()->getType().getNominalSize()) switch (node->getOperand()->getType().getNominalSize())
{ {
case 1: preString = "bool("; break; case 1:
case 2: preString = "bvec2("; break; preString = "bool(";
case 3: preString = "bvec3("; break; break;
case 4: preString = "bvec4("; break; case 2:
default: UNREACHABLE(); preString = "bvec2(";
break;
case 3:
preString = "bvec3(";
break;
case 4:
preString = "bvec4(";
break;
default:
UNREACHABLE();
} }
break; break;
case EOpConvBoolToFloat: case EOpConvBoolToFloat:
case EOpConvIntToFloat: case EOpConvIntToFloat:
switch (node->getOperand()->getType().getNominalSize()) switch (node->getOperand()->getType().getNominalSize())
{ {
case 1: preString = "float("; break; case 1:
case 2: preString = "vec2("; break; preString = "float(";
case 3: preString = "vec3("; break; break;
case 4: preString = "vec4("; break; case 2:
default: UNREACHABLE(); preString = "vec2(";
break;
case 3:
preString = "vec3(";
break;
case 4:
preString = "vec4(";
break;
default:
UNREACHABLE();
} }
break; break;
case EOpConvFloatToInt: case EOpConvFloatToInt:
case EOpConvBoolToInt: case EOpConvBoolToInt:
switch (node->getOperand()->getType().getNominalSize()) switch (node->getOperand()->getType().getNominalSize())
{ {
case 1: preString = "int("; break; case 1:
case 2: preString = "ivec2("; break; preString = "int(";
case 3: preString = "ivec3("; break; break;
case 4: preString = "ivec4("; break; case 2:
default: UNREACHABLE(); preString = "ivec2(";
break;
case 3:
preString = "ivec3(";
break;
case 4:
preString = "ivec4(";
break;
default:
UNREACHABLE();
} }
break; break;
case EOpRadians: preString = "radians("; break; case EOpRadians:
case EOpDegrees: preString = "degrees("; break; preString = "radians(";
case EOpSin: preString = "sin("; break; break;
case EOpCos: preString = "cos("; break; case EOpDegrees:
case EOpTan: preString = "tan("; break; preString = "degrees(";
case EOpAsin: preString = "asin("; break; break;
case EOpAcos: preString = "acos("; break; case EOpSin:
case EOpAtan: preString = "atan("; break; preString = "sin(";
break;
case EOpCos:
preString = "cos(";
break;
case EOpTan:
preString = "tan(";
break;
case EOpAsin:
preString = "asin(";
break;
case EOpAcos:
preString = "acos(";
break;
case EOpAtan:
preString = "atan(";
break;
case EOpExp: preString = "exp("; break; case EOpExp:
case EOpLog: preString = "log("; break; preString = "exp(";
case EOpExp2: preString = "exp2("; break; break;
case EOpLog2: preString = "log2("; break; case EOpLog:
case EOpSqrt: preString = "sqrt("; break; preString = "log(";
case EOpInverseSqrt: preString = "inversesqrt("; break; break;
case EOpExp2:
preString = "exp2(";
break;
case EOpLog2:
preString = "log2(";
break;
case EOpSqrt:
preString = "sqrt(";
break;
case EOpInverseSqrt:
preString = "inversesqrt(";
break;
case EOpAbs: preString = "abs("; break; case EOpAbs:
case EOpSign: preString = "sign("; break; preString = "abs(";
case EOpFloor: preString = "floor("; break; break;
case EOpCeil: preString = "ceil("; break; case EOpSign:
case EOpFract: preString = "fract("; break; preString = "sign(";
break;
case EOpFloor:
preString = "floor(";
break;
case EOpCeil:
preString = "ceil(";
break;
case EOpFract:
preString = "fract(";
break;
case EOpLength: preString = "length("; break; case EOpLength:
case EOpNormalize: preString = "normalize("; break; preString = "length(";
break;
case EOpNormalize:
preString = "normalize(";
break;
case EOpDFdx: preString = "dFdx("; break; case EOpDFdx:
case EOpDFdy: preString = "dFdy("; break; preString = "dFdx(";
case EOpFwidth: preString = "fwidth("; break; break;
case EOpDFdy:
preString = "dFdy(";
break;
case EOpFwidth:
preString = "fwidth(";
break;
case EOpAny: preString = "any("; break; case EOpAny:
case EOpAll: preString = "all("; break; preString = "any(";
break;
case EOpAll:
preString = "all(";
break;
default: UNREACHABLE(); break; default:
UNREACHABLE();
} }
if (visit == PreVisit && node->getUseEmulatedFunction()) if (visit == PreVisit && node->getUseEmulatedFunction())
...@@ -416,9 +554,9 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) ...@@ -416,9 +554,9 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node)
return true; return true;
} }
bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
if (node->usesTernaryOperator()) if (node->usesTernaryOperator())
{ {
...@@ -453,15 +591,15 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) ...@@ -453,15 +591,15 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node)
return false; return false;
} }
bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
bool visitChildren = true; bool visitChildren = true;
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
TString preString; TString preString;
bool delayedWrite = false; bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
switch (node->getOp()) switch (node->getOp())
{ {
case EOpSequence: { case EOpSequence:
// Scope the sequences except when at the global scope. // Scope the sequences except when at the global scope.
if (depth > 0) if (depth > 0)
{ {
...@@ -470,11 +608,10 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -470,11 +608,10 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
} }
incrementDepth(node); incrementDepth(node);
const TIntermSequence& sequence = node->getSequence(); for (TIntermSequence::const_iterator iter = node->getSequence().begin();
for (TIntermSequence::const_iterator iter = sequence.begin(); iter != node->getSequence().end(); ++iter)
iter != sequence.end(); ++iter)
{ {
TIntermNode* node = *iter; TIntermNode *node = *iter;
ASSERT(node != NULL); ASSERT(node != NULL);
node->traverse(this); node->traverse(this);
...@@ -491,8 +628,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -491,8 +628,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
} }
visitChildren = false; visitChildren = false;
break; break;
} case EOpPrototype:
case EOpPrototype: {
// Function declaration. // Function declaration.
ASSERT(visit == PreVisit); ASSERT(visit == PreVisit);
writeVariableType(node->getType()); writeVariableType(node->getType());
...@@ -504,7 +640,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -504,7 +640,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
visitChildren = false; visitChildren = false;
break; break;
}
case EOpFunction: { case EOpFunction: {
// Function definition. // Function definition.
ASSERT(visit == PreVisit); ASSERT(visit == PreVisit);
...@@ -515,18 +650,18 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -515,18 +650,18 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
// Function definition node contains one or two children nodes // Function definition node contains one or two children nodes
// representing function parameters and function body. The latter // representing function parameters and function body. The latter
// is not present in case of empty function bodies. // is not present in case of empty function bodies.
const TIntermSequence& sequence = node->getSequence(); const TIntermSequence &sequence = node->getSequence();
ASSERT((sequence.size() == 1) || (sequence.size() == 2)); ASSERT((sequence.size() == 1) || (sequence.size() == 2));
TIntermSequence::const_iterator seqIter = sequence.begin(); TIntermSequence::const_iterator seqIter = sequence.begin();
// Traverse function parameters. // Traverse function parameters.
TIntermAggregate* params = (*seqIter)->getAsAggregate(); TIntermAggregate *params = (*seqIter)->getAsAggregate();
ASSERT(params != NULL); ASSERT(params != NULL);
ASSERT(params->getOp() == EOpParameters); ASSERT(params->getOp() == EOpParameters);
params->traverse(this); params->traverse(this);
// Traverse function body. // Traverse function body.
TIntermAggregate* body = ++seqIter != sequence.end() ? TIntermAggregate *body = ++seqIter != sequence.end() ?
(*seqIter)->getAsAggregate() : NULL; (*seqIter)->getAsAggregate() : NULL;
visitCodeBlock(body); visitCodeBlock(body);
decrementDepth(); decrementDepth();
...@@ -538,19 +673,13 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -538,19 +673,13 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
case EOpFunctionCall: case EOpFunctionCall:
// Function call. // Function call.
if (visit == PreVisit) if (visit == PreVisit)
{
out << hashFunctionName(node->getName()) << "("; out << hashFunctionName(node->getName()) << "(";
}
else if (visit == InVisit) else if (visit == InVisit)
{
out << ", "; out << ", ";
}
else else
{
out << ")"; out << ")";
}
break; break;
case EOpParameters: { case EOpParameters:
// Function parameters. // Function parameters.
ASSERT(visit == PreVisit); ASSERT(visit == PreVisit);
out << "("; out << "(";
...@@ -558,13 +687,12 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -558,13 +687,12 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
out << ")"; out << ")";
visitChildren = false; visitChildren = false;
break; break;
} case EOpDeclaration:
case EOpDeclaration: {
// Variable declaration. // Variable declaration.
if (visit == PreVisit) if (visit == PreVisit)
{ {
const TIntermSequence& sequence = node->getSequence(); const TIntermSequence &sequence = node->getSequence();
const TIntermTyped* variable = sequence.front()->getAsTyped(); const TIntermTyped *variable = sequence.front()->getAsTyped();
writeVariableType(variable->getType()); writeVariableType(variable->getType());
out << " "; out << " ";
mDeclaringVariables = true; mDeclaringVariables = true;
...@@ -579,26 +707,55 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -579,26 +707,55 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
mDeclaringVariables = false; mDeclaringVariables = false;
} }
break; break;
} case EOpConstructFloat:
case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; writeTriplet(visit, "float(", NULL, ")");
case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break; break;
case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break; case EOpConstructVec2:
case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break; writeBuiltInFunctionTriplet(visit, "vec2(", false);
case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break; break;
case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break; case EOpConstructVec3:
case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break; writeBuiltInFunctionTriplet(visit, "vec3(", false);
case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break; break;
case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break; case EOpConstructVec4:
case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break; writeBuiltInFunctionTriplet(visit, "vec4(", false);
case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break; break;
case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break; case EOpConstructBool:
case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break; writeTriplet(visit, "bool(", NULL, ")");
case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break; break;
case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break; case EOpConstructBVec2:
writeBuiltInFunctionTriplet(visit, "bvec2(", false);
break;
case EOpConstructBVec3:
writeBuiltInFunctionTriplet(visit, "bvec3(", false);
break;
case EOpConstructBVec4:
writeBuiltInFunctionTriplet(visit, "bvec4(", false);
break;
case EOpConstructInt:
writeTriplet(visit, "int(", NULL, ")");
break;
case EOpConstructIVec2:
writeBuiltInFunctionTriplet(visit, "ivec2(", false);
break;
case EOpConstructIVec3:
writeBuiltInFunctionTriplet(visit, "ivec3(", false);
break;
case EOpConstructIVec4:
writeBuiltInFunctionTriplet(visit, "ivec4(", false);
break;
case EOpConstructMat2:
writeBuiltInFunctionTriplet(visit, "mat2(", false);
break;
case EOpConstructMat3:
writeBuiltInFunctionTriplet(visit, "mat3(", false);
break;
case EOpConstructMat4:
writeBuiltInFunctionTriplet(visit, "mat4(", false);
break;
case EOpConstructStruct: case EOpConstructStruct:
if (visit == PreVisit) if (visit == PreVisit)
{ {
const TType& type = node->getType(); const TType &type = node->getType();
ASSERT(type.getBasicType() == EbtStruct); ASSERT(type.getBasicType() == EbtStruct);
out << hashName(type.getStruct()->name()) << "("; out << hashName(type.getStruct()->name()) << "(";
} }
...@@ -612,44 +769,86 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -612,44 +769,86 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
} }
break; break;
case EOpLessThan: preString = "lessThan("; delayedWrite = true; break; case EOpLessThan:
case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break; writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction);
case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break; break;
case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break; case EOpGreaterThan:
case EOpVectorEqual: preString = "equal("; delayedWrite = true; break; writeBuiltInFunctionTriplet(visit, "greaterThan(", useEmulatedFunction);
case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break; break;
case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break; case EOpLessThanEqual:
writeBuiltInFunctionTriplet(visit, "lessThanEqual(", useEmulatedFunction);
case EOpMod: preString = "mod("; delayedWrite = true; break; break;
case EOpPow: preString = "pow("; delayedWrite = true; break; case EOpGreaterThanEqual:
case EOpAtan: preString = "atan("; delayedWrite = true; break; writeBuiltInFunctionTriplet(visit, "greaterThanEqual(", useEmulatedFunction);
case EOpMin: preString = "min("; delayedWrite = true; break; break;
case EOpMax: preString = "max("; delayedWrite = true; break; case EOpVectorEqual:
case EOpClamp: preString = "clamp("; delayedWrite = true; break; writeBuiltInFunctionTriplet(visit, "equal(", useEmulatedFunction);
case EOpMix: preString = "mix("; delayedWrite = true; break; break;
case EOpStep: preString = "step("; delayedWrite = true; break; case EOpVectorNotEqual:
case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break; writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
break;
case EOpDistance: preString = "distance("; delayedWrite = true; break; case EOpComma:
case EOpDot: preString = "dot("; delayedWrite = true; break; writeTriplet(visit, NULL, ", ", NULL);
case EOpCross: preString = "cross("; delayedWrite = true; break; break;
case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break;
case EOpReflect: preString = "reflect("; delayedWrite = true; break; case EOpMod:
case EOpRefract: preString = "refract("; delayedWrite = true; break; writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction);
case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break; break;
case EOpPow:
default: UNREACHABLE(); break; writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction);
} break;
if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction()) case EOpAtan:
preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString); writeBuiltInFunctionTriplet(visit, "atan(", useEmulatedFunction);
if (delayedWrite) break;
writeTriplet(visit, preString.c_str(), ", ", ")"); case EOpMin:
writeBuiltInFunctionTriplet(visit, "min(", useEmulatedFunction);
break;
case EOpMax:
writeBuiltInFunctionTriplet(visit, "max(", useEmulatedFunction);
break;
case EOpClamp:
writeBuiltInFunctionTriplet(visit, "clamp(", useEmulatedFunction);
break;
case EOpMix:
writeBuiltInFunctionTriplet(visit, "mix(", useEmulatedFunction);
break;
case EOpStep:
writeBuiltInFunctionTriplet(visit, "step(", useEmulatedFunction);
break;
case EOpSmoothStep:
writeBuiltInFunctionTriplet(visit, "smoothstep(", useEmulatedFunction);
break;
case EOpDistance:
writeBuiltInFunctionTriplet(visit, "distance(", useEmulatedFunction);
break;
case EOpDot:
writeBuiltInFunctionTriplet(visit, "dot(", useEmulatedFunction);
break;
case EOpCross:
writeBuiltInFunctionTriplet(visit, "cross(", useEmulatedFunction);
break;
case EOpFaceForward:
writeBuiltInFunctionTriplet(visit, "faceforward(", useEmulatedFunction);
break;
case EOpReflect:
writeBuiltInFunctionTriplet(visit, "reflect(", useEmulatedFunction);
break;
case EOpRefract:
writeBuiltInFunctionTriplet(visit, "refract(", useEmulatedFunction);
break;
case EOpMul:
writeBuiltInFunctionTriplet(visit, "matrixCompMult(", useEmulatedFunction);
break;
default:
UNREACHABLE();
}
return visitChildren; return visitChildren;
} }
bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
incrementDepth(node); incrementDepth(node);
// Loop header. // Loop header.
...@@ -730,21 +929,31 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) ...@@ -730,21 +929,31 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node)
return false; return false;
} }
bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node) bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node)
{ {
switch (node->getFlowOp()) switch (node->getFlowOp())
{ {
case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break; case EOpKill:
case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break; writeTriplet(visit, "discard", NULL, NULL);
case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break; break;
case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break; case EOpBreak:
default: UNREACHABLE(); break; writeTriplet(visit, "break", NULL, NULL);
break;
case EOpContinue:
writeTriplet(visit, "continue", NULL, NULL);
break;
case EOpReturn:
writeTriplet(visit, "return ", NULL, NULL);
break;
default:
UNREACHABLE();
} }
return true; return true;
} }
void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { void TOutputGLSLBase::visitCodeBlock(TIntermNode *node)
{
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
if (node != NULL) if (node != NULL)
{ {
...@@ -760,7 +969,7 @@ void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { ...@@ -760,7 +969,7 @@ void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) {
} }
} }
TString TOutputGLSLBase::getTypeName(const TType& type) TString TOutputGLSLBase::getTypeName(const TType &type)
{ {
TInfoSinkBase out; TInfoSinkBase out;
if (type.isMatrix()) if (type.isMatrix())
...@@ -772,10 +981,17 @@ TString TOutputGLSLBase::getTypeName(const TType& type) ...@@ -772,10 +981,17 @@ TString TOutputGLSLBase::getTypeName(const TType& type)
{ {
switch (type.getBasicType()) switch (type.getBasicType())
{ {
case EbtFloat: out << "vec"; break; case EbtFloat:
case EbtInt: out << "ivec"; break; out << "vec";
case EbtBool: out << "bvec"; break; break;
default: UNREACHABLE(); break; case EbtInt:
out << "ivec";
break;
case EbtBool:
out << "bvec";
break;
default:
UNREACHABLE();
} }
out << type.getNominalSize(); out << type.getNominalSize();
} }
...@@ -789,7 +1005,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type) ...@@ -789,7 +1005,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type)
return TString(out.c_str()); return TString(out.c_str());
} }
TString TOutputGLSLBase::hashName(const TString& name) TString TOutputGLSLBase::hashName(const TString &name)
{ {
if (mHashFunction == NULL || name.empty()) if (mHashFunction == NULL || name.empty())
return name; return name;
...@@ -801,30 +1017,28 @@ TString TOutputGLSLBase::hashName(const TString& name) ...@@ -801,30 +1017,28 @@ TString TOutputGLSLBase::hashName(const TString& name)
return hashedName; return hashedName;
} }
TString TOutputGLSLBase::hashVariableName(const TString& name) TString TOutputGLSLBase::hashVariableName(const TString &name)
{ {
if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL) if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL)
return name; return name;
return hashName(name); return hashName(name);
} }
TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name) TString TOutputGLSLBase::hashFunctionName(const TString &mangled_name)
{ {
TString name = TFunction::unmangleName(mangled_name); TString name = TFunction::unmangleName(mangled_name);
if (mSymbolTable.findBuiltIn(mangled_name, mShaderVersion) != NULL || name == "main") if (mSymbolTable.findBuiltIn(mangled_name, mShaderVersion) != NULL || name == "main")
{
return translateTextureFunction(name); return translateTextureFunction(name);
}
return hashName(name); return hashName(name);
} }
bool TOutputGLSLBase::structDeclared(const TStructure* structure) const bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
{ {
ASSERT(structure); ASSERT(structure);
ASSERT(mDeclaredStructs.size() > 0); ASSERT(mDeclaredStructs.size() > 0);
for (size_t ii = mDeclaredStructs.size(); ii > 0; --ii) for (size_t ii = mDeclaredStructs.size(); ii > 0; --ii)
{ {
const ScopedDeclaredStructs& scope = mDeclaredStructs[ii - 1]; const ScopedDeclaredStructs &scope = mDeclaredStructs[ii - 1];
for (size_t jj = 0; jj < scope.size(); ++jj) for (size_t jj = 0; jj < scope.size(); ++jj)
{ {
if (scope[jj]->equals(*structure)) if (scope[jj]->equals(*structure))
...@@ -834,15 +1048,15 @@ bool TOutputGLSLBase::structDeclared(const TStructure* structure) const ...@@ -834,15 +1048,15 @@ bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
return false; return false;
} }
void TOutputGLSLBase::declareStruct(const TStructure* structure) void TOutputGLSLBase::declareStruct(const TStructure *structure)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase &out = objSink();
out << "struct " << hashName(structure->name()) << "{\n"; out << "struct " << hashName(structure->name()) << "{\n";
const TFieldList& fields = structure->fields(); const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i) for (size_t i = 0; i < fields.size(); ++i)
{ {
const TField* field = fields[i]; const TField *field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision())) if (writeVariablePrecision(field->type()->getPrecision()))
out << " "; out << " ";
out << getTypeName(*field->type()) << " " << hashName(field->name()); out << getTypeName(*field->type()) << " " << hashName(field->name());
......
...@@ -15,52 +15,53 @@ ...@@ -15,52 +15,53 @@
class TOutputGLSLBase : public TIntermTraverser class TOutputGLSLBase : public TIntermTraverser
{ {
public: public:
TOutputGLSLBase(TInfoSinkBase& objSink, TOutputGLSLBase(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy, ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap& nameMap, NameMap &nameMap,
TSymbolTable& symbolTable, TSymbolTable& symbolTable,
int shaderVersion); int shaderVersion);
protected: protected:
TInfoSinkBase& objSink() { return mObjSink; } TInfoSinkBase &objSink() { return mObjSink; }
void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr); void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr);
void writeVariableType(const TType& type); void writeVariableType(const TType &type);
virtual bool writeVariablePrecision(TPrecision precision) = 0; virtual bool writeVariablePrecision(TPrecision precision) = 0;
void writeFunctionParameters(const TIntermSequence& args); void writeFunctionParameters(const TIntermSequence &args);
const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *pConstUnion);
TString getTypeName(const TType& type); TString getTypeName(const TType &type);
virtual void visitSymbol(TIntermSymbol* node); virtual void visitSymbol(TIntermSymbol *node);
virtual void visitConstantUnion(TIntermConstantUnion* node); virtual void visitConstantUnion(TIntermConstantUnion *node);
virtual bool visitBinary(Visit visit, TIntermBinary* node); virtual bool visitBinary(Visit visit, TIntermBinary *node);
virtual bool visitUnary(Visit visit, TIntermUnary* node); virtual bool visitUnary(Visit visit, TIntermUnary *node);
virtual bool visitSelection(Visit visit, TIntermSelection* node); virtual bool visitSelection(Visit visit, TIntermSelection *node);
virtual bool visitAggregate(Visit visit, TIntermAggregate* node); virtual bool visitAggregate(Visit visit, TIntermAggregate *node);
virtual bool visitLoop(Visit visit, TIntermLoop* node); virtual bool visitLoop(Visit visit, TIntermLoop *node);
virtual bool visitBranch(Visit visit, TIntermBranch* node); virtual bool visitBranch(Visit visit, TIntermBranch *node);
void visitCodeBlock(TIntermNode* node);
void visitCodeBlock(TIntermNode *node);
// Return the original name if hash function pointer is NULL; // Return the original name if hash function pointer is NULL;
// otherwise return the hashed name. // otherwise return the hashed name.
TString hashName(const TString& name); TString hashName(const TString &name);
// Same as hashName(), but without hashing built-in variables. // Same as hashName(), but without hashing built-in variables.
TString hashVariableName(const TString& name); TString hashVariableName(const TString &name);
// Same as hashName(), but without hashing built-in functions. // Same as hashName(), but without hashing built-in functions.
TString hashFunctionName(const TString& mangled_name); TString hashFunctionName(const TString &mangled_name);
// Used to translate function names for differences between ESSL and GLSL // Used to translate function names for differences between ESSL and GLSL
virtual TString translateTextureFunction(TString& name) { return name; } virtual TString translateTextureFunction(TString &name) { return name; }
private: private:
bool structDeclared(const TStructure* structure) const; bool structDeclared(const TStructure *structure) const;
void declareStruct(const TStructure* structure); void declareStruct(const TStructure *structure);
void pushDeclaredStructsScope(); void pushDeclaredStructsScope();
void popDeclaredStructsScope(); void popDeclaredStructsScope();
TInfoSinkBase& mObjSink; void writeBuiltInFunctionTriplet(Visit visit, const char *preStr, bool useEmulatedFunction);
TInfoSinkBase &mObjSink;
bool mDeclaringVariables; bool mDeclaringVariables;
// Structs are declared as the tree is traversed. This list contains all // Structs are declared as the tree is traversed. This list contains all
...@@ -80,9 +81,9 @@ private: ...@@ -80,9 +81,9 @@ private:
// name hashing. // name hashing.
ShHashFunction64 mHashFunction; ShHashFunction64 mHashFunction;
NameMap& mNameMap; NameMap &mNameMap;
TSymbolTable& mSymbolTable; TSymbolTable &mSymbolTable;
const int mShaderVersion; const int mShaderVersion;
}; };
......
...@@ -44,12 +44,13 @@ TSymbolTableLevel::~TSymbolTableLevel() ...@@ -44,12 +44,13 @@ TSymbolTableLevel::~TSymbolTableLevel()
// performance operation, and only intended for symbol tables that // performance operation, and only intended for symbol tables that
// live across a large number of compiles. // live across a large number of compiles.
// //
void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) void TSymbolTableLevel::relateToOperator(const char *name, TOperator op)
{ {
tLevel::iterator it; for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
for (it = level.begin(); it != level.end(); ++it) { {
if ((*it).second->isFunction()) { if ((*it).second->isFunction())
TFunction* function = static_cast<TFunction*>((*it).second); {
TFunction *function = static_cast<TFunction*>((*it).second);
if (function->getName() == name) if (function->getName() == name)
function->relateToOperator(op); function->relateToOperator(op);
} }
...@@ -62,17 +63,17 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) ...@@ -62,17 +63,17 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
// performance operation, and only intended for symbol tables that // performance operation, and only intended for symbol tables that
// live across a large number of compiles. // live across a large number of compiles.
// //
void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) void TSymbolTableLevel::relateToExtension(const char *name, const TString &ext)
{ {
for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
TSymbol* symbol = it->second; {
if (symbol->getName() == name) { TSymbol *symbol = it->second;
if (symbol->getName() == name)
symbol->relateToExtension(ext); symbol->relateToExtension(ext);
} }
}
} }
TSymbol::TSymbol(const TSymbol& copyOf) TSymbol::TSymbol(const TSymbol &copyOf)
{ {
name = NewPoolTString(copyOf.name->c_str()); name = NewPoolTString(copyOf.name->c_str());
uniqueId = copyOf.uniqueId; uniqueId = copyOf.uniqueId;
...@@ -85,8 +86,10 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI ...@@ -85,8 +86,10 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI
do do
{ {
if (level == ESSL3_BUILTINS && shaderVersion != 300) level--; if (level == ESSL3_BUILTINS && shaderVersion != 300)
if (level == ESSL1_BUILTINS && shaderVersion != 100) level--; level--;
if (level == ESSL1_BUILTINS && shaderVersion != 100)
level--;
symbol = table[level]->find(name); symbol = table[level]->find(name);
} }
...@@ -104,8 +107,10 @@ TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) ...@@ -104,8 +107,10 @@ TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion)
{ {
for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
{ {
if (level == ESSL3_BUILTINS && shaderVersion != 300) level--; if (level == ESSL3_BUILTINS && shaderVersion != 300)
if (level == ESSL1_BUILTINS && shaderVersion != 100) level--; level--;
if (level == ESSL1_BUILTINS && shaderVersion != 100)
level--;
TSymbol *symbol = table[level]->find(name); TSymbol *symbol = table[level]->find(name);
...@@ -121,3 +126,92 @@ TSymbolTable::~TSymbolTable() ...@@ -121,3 +126,92 @@ TSymbolTable::~TSymbolTable()
while (table.size() > 0) while (table.size() > 0)
pop(); pop();
} }
void TSymbolTable::insertBuiltIn(
ESymbolLevel level, TType *rvalue, const char *name,
TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5)
{
if (ptype1->getBasicType() == EbtGSampler2D)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
return;
}
if (ptype1->getBasicType() == EbtGSampler3D)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
return;
}
if (ptype1->getBasicType() == EbtGSamplerCube)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
return;
}
if (ptype1->getBasicType() == EbtGSampler2DArray)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
return;
}
TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
TType *types[] = {ptype1, ptype2, ptype3, ptype4, ptype5};
for (size_t ii = 0; ii < sizeof(types) / sizeof(types[0]); ++ii)
{
if (types[ii])
{
TParameter param = {NULL, types[ii]};
function->addParameter(param);
}
}
insert(level, *function);
}
TPrecision TSymbolTable::getDefaultPrecision(TBasicType type)
{
if (!SupportsPrecision(type))
return EbpUndefined;
// unsigned integers use the same precision as signed
TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
int level = static_cast<int>(precisionStack.size()) - 1;
assert(level >= 0); // Just to be safe. Should not happen.
// If we dont find anything we return this. Should we error check this?
TPrecision prec = EbpUndefined;
while (level >= 0)
{
PrecisionStackLevel::iterator it = precisionStack[level]->find(baseType);
if (it != precisionStack[level]->end())
{
prec = (*it).second;
break;
}
level--;
}
return prec;
}
...@@ -36,25 +36,55 @@ ...@@ -36,25 +36,55 @@
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/intermediate.h" #include "compiler/translator/intermediate.h"
//
// Symbol base class. (Can build functions or variables out of these...) // Symbol base class. (Can build functions or variables out of these...)
// class TSymbol
class TSymbol { {
public: public:
POOL_ALLOCATOR_NEW_DELETE(); POOL_ALLOCATOR_NEW_DELETE();
TSymbol(const TString* n) : uniqueId(0), name(n) { } TSymbol(const TString *n)
virtual ~TSymbol() { /* don't delete name, it's from the pool */ } : uniqueId(0),
name(n)
const TString& getName() const { return *name; } {
virtual const TString& getMangledName() const { return getName(); } }
virtual bool isFunction() const { return false; } virtual ~TSymbol()
virtual bool isVariable() const { return false; } {
void setUniqueId(int id) { uniqueId = id; } // don't delete name, it's from the pool
int getUniqueId() const { return uniqueId; } }
void relateToExtension(const TString& ext) { extension = ext; }
const TString& getExtension() const { return extension; } const TString &getName() const
{
private: return *name;
}
virtual const TString &getMangledName() const
{
return getName();
}
virtual bool isFunction() const
{
return false;
}
virtual bool isVariable() const
{
return false;
}
void setUniqueId(int id)
{
uniqueId = id;
}
int getUniqueId() const
{
return uniqueId;
}
void relateToExtension(const TString &ext)
{
extension = ext;
}
const TString &getExtension() const
{
return extension;
}
private:
DISALLOW_COPY_AND_ASSIGN(TSymbol); DISALLOW_COPY_AND_ASSIGN(TSymbol);
int uniqueId; // For real comparing during code generation int uniqueId; // For real comparing during code generation
...@@ -62,7 +92,6 @@ private: ...@@ -62,7 +92,6 @@ private:
TString extension; TString extension;
}; };
//
// Variable class, meaning a symbol that's not a function. // Variable class, meaning a symbol that's not a function.
// //
// There could be a separate class heirarchy for Constant variables; // There could be a separate class heirarchy for Constant variables;
...@@ -71,18 +100,41 @@ private: ...@@ -71,18 +100,41 @@ private:
// seem worth having separate classes, and "getConst" can't simply return // seem worth having separate classes, and "getConst" can't simply return
// different values for different types polymorphically, so this is // different values for different types polymorphically, so this is
// just simple and pragmatic. // just simple and pragmatic.
// class TVariable : public TSymbol
class TVariable : public TSymbol { {
public: public:
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { } TVariable(const TString *name, const TType &t, bool uT = false)
virtual ~TVariable() { } : TSymbol(name),
virtual bool isVariable() const { return true; } type(t),
TType& getType() { return type; } userType(uT),
const TType& getType() const { return type; } unionArray(0)
bool isUserType() const { return userType; } {
void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); } }
virtual ~TVariable()
ConstantUnion* getConstPointer() {
}
virtual bool isVariable() const
{
return true;
}
TType &getType()
{
return type;
}
const TType &getType() const
{
return type;
}
bool isUserType() const
{
return userType;
}
void setQualifier(TQualifier qualifier)
{
type.setQualifier(qualifier);
}
ConstantUnion *getConstPointer()
{ {
if (!unionArray) if (!unionArray)
unionArray = new ConstantUnion[type.getObjectSize()]; unionArray = new ConstantUnion[type.getObjectSize()];
...@@ -90,9 +142,12 @@ public: ...@@ -90,9 +142,12 @@ public:
return unionArray; return unionArray;
} }
ConstantUnion* getConstPointer() const { return unionArray; } ConstantUnion *getConstPointer() const
{
return unionArray;
}
void shareConstPointer( ConstantUnion *constArray) void shareConstPointer(ConstantUnion *constArray)
{ {
if (unionArray == constArray) if (unionArray == constArray)
return; return;
...@@ -101,69 +156,101 @@ public: ...@@ -101,69 +156,101 @@ public:
unionArray = constArray; unionArray = constArray;
} }
private: private:
DISALLOW_COPY_AND_ASSIGN(TVariable); DISALLOW_COPY_AND_ASSIGN(TVariable);
TType type; TType type;
bool userType; bool userType;
// we are assuming that Pool Allocator will free the memory allocated to unionArray // we are assuming that Pool Allocator will free the memory
// when this object is destroyed // allocated to unionArray when this object is destroyed.
ConstantUnion *unionArray; ConstantUnion *unionArray;
}; };
//
// The function sub-class of symbols and the parser will need to // The function sub-class of symbols and the parser will need to
// share this definition of a function parameter. // share this definition of a function parameter.
// struct TParameter
struct TParameter { {
TString *name; TString *name;
TType *type; TType *type;
}; };
//
// The function sub-class of a symbol. // The function sub-class of a symbol.
// class TFunction : public TSymbol
class TFunction : public TSymbol { {
public: public:
TFunction(TOperator o) : TFunction(TOperator o)
TSymbol(0), : TSymbol(0),
returnType(TType(EbtVoid, EbpUndefined)), returnType(TType(EbtVoid, EbpUndefined)),
op(o), op(o),
defined(false) { } defined(false)
TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : {
TSymbol(name), }
TFunction(const TString *name, TType &retType, TOperator tOp = EOpNull)
: TSymbol(name),
returnType(retType), returnType(retType),
mangledName(TFunction::mangleName(*name)), mangledName(TFunction::mangleName(*name)),
op(tOp), op(tOp),
defined(false) { } defined(false)
{
}
virtual ~TFunction(); virtual ~TFunction();
virtual bool isFunction() const { return true; } virtual bool isFunction() const
{
return true;
}
static TString mangleName(const TString& name) { return name + '('; } static TString mangleName(const TString &name)
static TString unmangleName(const TString& mangledName) {
return name + '(';
}
static TString unmangleName(const TString &mangledName)
{ {
return TString(mangledName.c_str(), mangledName.find_first_of('(')); return TString(mangledName.c_str(), mangledName.find_first_of('('));
} }
void addParameter(TParameter& p) void addParameter(TParameter &p)
{ {
parameters.push_back(p); parameters.push_back(p);
mangledName = mangledName + p.type->getMangledName(); mangledName = mangledName + p.type->getMangledName();
} }
const TString& getMangledName() const { return mangledName; } const TString &getMangledName() const
const TType& getReturnType() const { return returnType; } {
return mangledName;
}
const TType &getReturnType() const
{
return returnType;
}
void relateToOperator(TOperator o) { op = o; } void relateToOperator(TOperator o)
TOperator getBuiltInOp() const { return op; } {
op = o;
}
TOperator getBuiltInOp() const
{
return op;
}
void setDefined() { defined = true; } void setDefined()
bool isDefined() { return defined; } {
defined = true;
}
bool isDefined()
{
return defined;
}
size_t getParamCount() const { return parameters.size(); } size_t getParamCount() const
const TParameter& getParam(size_t i) const { return parameters[i]; } {
return parameters.size();
}
const TParameter &getParam(size_t i) const
{
return parameters[i];
}
private: private:
DISALLOW_COPY_AND_ASSIGN(TFunction); DISALLOW_COPY_AND_ASSIGN(TFunction);
typedef TVector<TParameter> TParamList; typedef TVector<TParameter> TParamList;
...@@ -174,36 +261,38 @@ private: ...@@ -174,36 +261,38 @@ private:
bool defined; bool defined;
}; };
//
// Interface block name sub-symbol // Interface block name sub-symbol
//
class TInterfaceBlockName : public TSymbol class TInterfaceBlockName : public TSymbol
{ {
public: public:
TInterfaceBlockName(const TString *name) TInterfaceBlockName(const TString *name)
: TSymbol(name) : TSymbol(name)
{} {
}
virtual ~TInterfaceBlockName() {} virtual ~TInterfaceBlockName()
{
}
}; };
class TSymbolTableLevel { class TSymbolTableLevel
public: {
typedef TMap<TString, TSymbol*> tLevel; public:
typedef TMap<TString, TSymbol *> tLevel;
typedef tLevel::const_iterator const_iterator; typedef tLevel::const_iterator const_iterator;
typedef const tLevel::value_type tLevelPair; typedef const tLevel::value_type tLevelPair;
typedef std::pair<tLevel::iterator, bool> tInsertResult; typedef std::pair<tLevel::iterator, bool> tInsertResult;
TSymbolTableLevel() { } TSymbolTableLevel()
{
}
~TSymbolTableLevel(); ~TSymbolTableLevel();
bool insert(const TString &name, TSymbol &symbol) bool insert(const TString &name, TSymbol &symbol)
{ {
symbol.setUniqueId(++uniqueId); symbol.setUniqueId(++uniqueId);
//
// returning true means symbol was added to the table // returning true means symbol was added to the table
//
tInsertResult result = level.insert(tLevelPair(name, &symbol)); tInsertResult result = level.insert(tLevelPair(name, &symbol));
return result.second; return result.second;
...@@ -214,7 +303,7 @@ public: ...@@ -214,7 +303,7 @@ public:
return insert(symbol.getMangledName(), symbol); return insert(symbol.getMangledName(), symbol);
} }
TSymbol* find(const TString& name) const TSymbol *find(const TString &name) const
{ {
tLevel::const_iterator it = level.find(name); tLevel::const_iterator it = level.find(name);
if (it == level.end()) if (it == level.end())
...@@ -223,10 +312,10 @@ public: ...@@ -223,10 +312,10 @@ public:
return (*it).second; return (*it).second;
} }
void relateToOperator(const char* name, TOperator op); void relateToOperator(const char *name, TOperator op);
void relateToExtension(const char* name, const TString& ext); void relateToExtension(const char *name, const TString &ext);
protected: protected:
tLevel level; tLevel level;
static int uniqueId; // for unique identification in code generation static int uniqueId; // for unique identification in code generation
}; };
...@@ -240,27 +329,33 @@ enum ESymbolLevel ...@@ -240,27 +329,33 @@ enum ESymbolLevel
GLOBAL_LEVEL = 3 GLOBAL_LEVEL = 3
}; };
class TSymbolTable { class TSymbolTable
public: {
public:
TSymbolTable() TSymbolTable()
{ {
//
// The symbol table cannot be used until push() is called, but // The symbol table cannot be used until push() is called, but
// the lack of an initial call to push() can be used to detect // the lack of an initial call to push() can be used to detect
// that the symbol table has not been preloaded with built-ins. // that the symbol table has not been preloaded with built-ins.
//
} }
~TSymbolTable(); ~TSymbolTable();
//
// When the symbol table is initialized with the built-ins, there should // When the symbol table is initialized with the built-ins, there should
// 'push' calls, so that built-ins are at level 0 and the shader // 'push' calls, so that built-ins are at level 0 and the shader
// globals are at level 1. // globals are at level 1.
// bool isEmpty()
bool isEmpty() { return table.empty(); } {
bool atBuiltInLevel() { return currentLevel() <= LAST_BUILTIN_LEVEL; } return table.empty();
bool atGlobalLevel() { return currentLevel() <= GLOBAL_LEVEL; } }
bool atBuiltInLevel()
{
return currentLevel() <= LAST_BUILTIN_LEVEL;
}
bool atGlobalLevel()
{
return currentLevel() <= GLOBAL_LEVEL;
}
void push() void push()
{ {
table.push_back(new TSymbolTableLevel); table.push_back(new TSymbolTableLevel);
...@@ -288,134 +383,61 @@ public: ...@@ -288,134 +383,61 @@ public:
bool insertConstInt(ESymbolLevel level, const char *name, int value) bool insertConstInt(ESymbolLevel level, const char *name, int value)
{ {
TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); TVariable *constant = new TVariable(
NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
constant->getConstPointer()->setIConst(value); constant->getConstPointer()->setIConst(value);
return insert(level, *constant); return insert(level, *constant);
} }
void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name,
{ TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0,
if (ptype1->getBasicType() == EbtGSampler2D) TType *ptype4 = 0, TType *ptype5 = 0);
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
return;
}
else if (ptype1->getBasicType() == EbtGSampler3D)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
return;
}
else if (ptype1->getBasicType() == EbtGSamplerCube)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
return;
}
else if (ptype1->getBasicType() == EbtGSampler2DArray)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
return;
}
TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
TParameter param1 = {NULL, ptype1};
function->addParameter(param1);
if (ptype2) TSymbol *find(const TString &name, int shaderVersion,
{ bool *builtIn = NULL, bool *sameScope = NULL);
TParameter param2 = {NULL, ptype2};
function->addParameter(param2);
}
if (ptype3)
{
TParameter param3 = {NULL, ptype3};
function->addParameter(param3);
}
if (ptype4)
{
TParameter param4 = {NULL, ptype4};
function->addParameter(param4);
}
if (ptype5)
{
TParameter param5 = {NULL, ptype5};
function->addParameter(param5);
}
insert(level, *function);
}
TSymbol *find(const TString &name, int shaderVersion, bool *builtIn = NULL, bool *sameScope = NULL);
TSymbol *findBuiltIn(const TString &name, int shaderVersion); TSymbol *findBuiltIn(const TString &name, int shaderVersion);
TSymbolTableLevel *getOuterLevel() { TSymbolTableLevel *getOuterLevel()
{
assert(currentLevel() >= 1); assert(currentLevel() >= 1);
return table[currentLevel() - 1]; return table[currentLevel() - 1];
} }
void relateToOperator(ESymbolLevel level, const char* name, TOperator op) { void relateToOperator(ESymbolLevel level, const char *name, TOperator op)
{
table[level]->relateToOperator(name, op); table[level]->relateToOperator(name, op);
} }
void relateToExtension(ESymbolLevel level, const char* name, const TString& ext) { void relateToExtension(ESymbolLevel level, const char *name, const TString &ext)
{
table[level]->relateToExtension(name, ext); table[level]->relateToExtension(name, ext);
} }
void dump(TInfoSink &infoSink) const; void dump(TInfoSink &infoSink) const;
bool setDefaultPrecision(const TPublicType& type, TPrecision prec) { bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
{
if (!SupportsPrecision(type.type)) if (!SupportsPrecision(type.type))
return false; return false;
if (type.isAggregate()) if (type.isAggregate())
return false; // Not allowed to set for aggregate types return false; // Not allowed to set for aggregate types
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
(*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value // Uses map operator [], overwrites the current value
(*precisionStack[indexOfLastElement])[type.type] = prec;
return true; return true;
} }
// Searches down the precisionStack for a precision qualifier for the specified TBasicType // Searches down the precisionStack for a precision qualifier
TPrecision getDefaultPrecision( TBasicType type){ // for the specified TBasicType
TPrecision getDefaultPrecision(TBasicType type);
if (!SupportsPrecision(type))
return EbpUndefined;
// unsigned integers use the same precision as signed
TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
int level = static_cast<int>(precisionStack.size()) - 1; private:
assert(level >= 0); // Just to be safe. Should not happen. ESymbolLevel currentLevel() const
PrecisionStackLevel::iterator it; {
TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this? return static_cast<ESymbolLevel>(table.size() - 1);
while (level >= 0) {
it = precisionStack[level]->find(baseType);
if (it != precisionStack[level]->end()) {
prec = (*it).second;
break;
}
level--;
}
return prec;
} }
private: std::vector<TSymbolTableLevel *> table;
ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
std::vector<TSymbolTableLevel*> table;
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
std::vector< PrecisionStackLevel*> precisionStack; std::vector< PrecisionStackLevel *> precisionStack;
}; };
#endif // _SYMBOL_TABLE_INCLUDED_ #endif // _SYMBOL_TABLE_INCLUDED_
...@@ -19,9 +19,7 @@ TType::TType(const TPublicType &p) ...@@ -19,9 +19,7 @@ TType::TType(const TPublicType &p)
interfaceBlock(0), structure(0) interfaceBlock(0), structure(0)
{ {
if (p.userDef) if (p.userDef)
{
structure = p.userDef->getStruct(); structure = p.userDef->getStruct();
}
} }
bool TType::equals(const TType &other) const bool TType::equals(const TType &other) const
...@@ -34,13 +32,9 @@ bool TType::equals(const TType &other) const ...@@ -34,13 +32,9 @@ bool TType::equals(const TType &other) const
return false; return false;
} }
if (interfaceBlock && !interfaceBlock->equals(*(other.interfaceBlock))) if (interfaceBlock && !interfaceBlock->equals(*(other.interfaceBlock)))
{
return false; return false;
}
if (structure && !structure->equals(*(other.structure))) if (structure && !structure->equals(*(other.structure)))
{
return false; return false;
}
return true; return true;
} }
...@@ -89,30 +83,77 @@ TString TType::buildMangledName() const ...@@ -89,30 +83,77 @@ TString TType::buildMangledName() const
switch (type) switch (type)
{ {
case EbtFloat: mangledName += 'f'; break; case EbtFloat:
case EbtInt: mangledName += 'i'; break; mangledName += 'f';
case EbtUInt: mangledName += 'u'; break; break;
case EbtBool: mangledName += 'b'; break; case EbtInt:
case EbtSampler2D: mangledName += "s2"; break; mangledName += 'i';
case EbtSampler3D: mangledName += "s3"; break; break;
case EbtSamplerCube: mangledName += "sC"; break; case EbtUInt:
case EbtSampler2DArray: mangledName += "s2a"; break; mangledName += 'u';
case EbtSamplerExternalOES: mangledName += "sext"; break; break;
case EbtSampler2DRect: mangledName += "s2r"; break; case EbtBool:
case EbtISampler2D: mangledName += "is2"; break; mangledName += 'b';
case EbtISampler3D: mangledName += "is3"; break; break;
case EbtISamplerCube: mangledName += "isC"; break; case EbtSampler2D:
case EbtISampler2DArray: mangledName += "is2a"; break; mangledName += "s2";
case EbtUSampler2D: mangledName += "us2"; break; break;
case EbtUSampler3D: mangledName += "us3"; break; case EbtSampler3D:
case EbtUSamplerCube: mangledName += "usC"; break; mangledName += "s3";
case EbtUSampler2DArray: mangledName += "us2a"; break; break;
case EbtSampler2DShadow: mangledName += "s2s"; break; case EbtSamplerCube:
case EbtSamplerCubeShadow: mangledName += "sCs"; break; mangledName += "sC";
case EbtSampler2DArrayShadow: mangledName += "s2as"; break; break;
case EbtStruct: mangledName += structure->mangledName(); break; case EbtSampler2DArray:
case EbtInterfaceBlock: mangledName += interfaceBlock->mangledName(); break; mangledName += "s2a";
default: UNREACHABLE(); break;
case EbtSamplerExternalOES:
mangledName += "sext";
break;
case EbtSampler2DRect:
mangledName += "s2r";
break;
case EbtISampler2D:
mangledName += "is2";
break;
case EbtISampler3D:
mangledName += "is3";
break;
case EbtISamplerCube:
mangledName += "isC";
break;
case EbtISampler2DArray:
mangledName += "is2a";
break;
case EbtUSampler2D:
mangledName += "us2";
break;
case EbtUSampler3D:
mangledName += "us3";
break;
case EbtUSamplerCube:
mangledName += "usC";
break;
case EbtUSampler2DArray:
mangledName += "us2a";
break;
case EbtSampler2DShadow:
mangledName += "s2s";
break;
case EbtSamplerCubeShadow:
mangledName += "sCs";
break;
case EbtSampler2DArrayShadow:
mangledName += "s2as";
break;
case EbtStruct:
mangledName += structure->mangledName();
break;
case EbtInterfaceBlock:
mangledName += interfaceBlock->mangledName();
break;
default:
UNREACHABLE();
} }
if (isMatrix()) if (isMatrix())
...@@ -160,8 +201,9 @@ size_t TType::getObjectSize() const ...@@ -160,8 +201,9 @@ size_t TType::getObjectSize() const
bool TStructure::containsArrays() const bool TStructure::containsArrays() const
{ {
for (size_t i = 0; i < mFields->size(); ++i) { for (size_t i = 0; i < mFields->size(); ++i)
const TType* fieldType = (*mFields)[i]->type(); {
const TType *fieldType = (*mFields)[i]->type();
if (fieldType->isArray() || fieldType->isStructureContainingArrays()) if (fieldType->isArray() || fieldType->isStructureContainingArrays())
return true; return true;
} }
...@@ -183,7 +225,8 @@ TString TFieldListCollection::buildMangledName() const ...@@ -183,7 +225,8 @@ TString TFieldListCollection::buildMangledName() const
size_t TFieldListCollection::calculateObjectSize() const size_t TFieldListCollection::calculateObjectSize() const
{ {
size_t size = 0; size_t size = 0;
for (size_t i = 0; i < mFields->size(); ++i) { for (size_t i = 0; i < mFields->size(); ++i)
{
size_t fieldSize = (*mFields)[i]->type()->getObjectSize(); size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
if (fieldSize > INT_MAX - size) if (fieldSize > INT_MAX - size)
size = INT_MAX; size = INT_MAX;
...@@ -196,8 +239,7 @@ size_t TFieldListCollection::calculateObjectSize() const ...@@ -196,8 +239,7 @@ size_t TFieldListCollection::calculateObjectSize() const
int TStructure::calculateDeepestNesting() const int TStructure::calculateDeepestNesting() const
{ {
int maxNesting = 0; int maxNesting = 0;
for (size_t i = 0; i < mFields->size(); ++i) { for (size_t i = 0; i < mFields->size(); ++i)
maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
}
return 1 + maxNesting; return 1 + maxNesting;
} }
...@@ -18,46 +18,71 @@ class TType; ...@@ -18,46 +18,71 @@ class TType;
class TField class TField
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(); POOL_ALLOCATOR_NEW_DELETE();
TField(TType* type, TString* name, const TSourceLoc& line) : mType(type), mName(name), mLine(line) {} TField(TType *type, TString *name, const TSourceLoc &line)
: mType(type),
mName(name),
mLine(line)
{
}
// TODO(alokp): We should only return const type. // TODO(alokp): We should only return const type.
// Fix it by tweaking grammar. // Fix it by tweaking grammar.
TType* type() { return mType; } TType *type()
const TType* type() const { return mType; } {
return mType;
}
const TType *type() const
{
return mType;
}
const TString& name() const { return *mName; } const TString &name() const
const TSourceLoc& line() const { return mLine; } {
return *mName;
}
const TSourceLoc &line() const
{
return mLine;
}
bool equals(const TField &other) const; bool equals(const TField &other) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(TField); DISALLOW_COPY_AND_ASSIGN(TField);
TType* mType; TType *mType;
TString* mName; TString *mName;
TSourceLoc mLine; TSourceLoc mLine;
}; };
typedef TVector<TField*> TFieldList; typedef TVector<TField *> TFieldList;
inline TFieldList* NewPoolTFieldList() inline TFieldList *NewPoolTFieldList()
{ {
void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
return new(memory) TFieldList; return new(memory) TFieldList;
} }
class TFieldListCollection class TFieldListCollection
{ {
public: public:
const TString& name() const { return *mName; } const TString &name() const
const TFieldList& fields() const { return *mFields; } {
return *mName;
}
const TFieldList &fields() const
{
return *mFields;
}
const TString& mangledName() const { const TString &mangledName() const
{
if (mMangledName.empty()) if (mMangledName.empty())
mMangledName = buildMangledName(); mMangledName = buildMangledName();
return mMangledName; return mMangledName;
} }
size_t objectSize() const { size_t objectSize() const
{
if (mObjectSize == 0) if (mObjectSize == 0)
mObjectSize = calculateObjectSize(); mObjectSize = calculateObjectSize();
return mObjectSize; return mObjectSize;
...@@ -65,18 +90,19 @@ public: ...@@ -65,18 +90,19 @@ public:
virtual bool equals(const TFieldListCollection &other) const; virtual bool equals(const TFieldListCollection &other) const;
protected: protected:
TFieldListCollection(const TString* name, TFieldList* fields) TFieldListCollection(const TString *name, TFieldList *fields)
: mName(name), : mName(name),
mFields(fields), mFields(fields),
mObjectSize(0) { mObjectSize(0)
{
} }
TString buildMangledName() const; TString buildMangledName() const;
size_t calculateObjectSize() const; size_t calculateObjectSize() const;
virtual TString mangledNamePrefix() const = 0; virtual TString mangledNamePrefix() const = 0;
const TString* mName; const TString *mName;
TFieldList* mFields; TFieldList *mFields;
mutable TString mMangledName; mutable TString mMangledName;
mutable size_t mObjectSize; mutable size_t mObjectSize;
...@@ -85,23 +111,28 @@ protected: ...@@ -85,23 +111,28 @@ protected:
// May also represent interface blocks // May also represent interface blocks
class TStructure : public TFieldListCollection class TStructure : public TFieldListCollection
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(); POOL_ALLOCATOR_NEW_DELETE();
TStructure(const TString* name, TFieldList* fields) TStructure(const TString *name, TFieldList *fields)
: TFieldListCollection(name, fields), : TFieldListCollection(name, fields),
mDeepestNesting(0) { mDeepestNesting(0)
{
} }
int deepestNesting() const { int deepestNesting() const
{
if (mDeepestNesting == 0) if (mDeepestNesting == 0)
mDeepestNesting = calculateDeepestNesting(); mDeepestNesting = calculateDeepestNesting();
return mDeepestNesting; return mDeepestNesting;
} }
bool containsArrays() const; bool containsArrays() const;
private: private:
DISALLOW_COPY_AND_ASSIGN(TStructure); DISALLOW_COPY_AND_ASSIGN(TStructure);
virtual TString mangledNamePrefix() const { return "struct-"; } virtual TString mangledNamePrefix() const
{
return "struct-";
}
int calculateDeepestNesting() const; int calculateDeepestNesting() const;
mutable int mDeepestNesting; mutable int mDeepestNesting;
...@@ -109,30 +140,53 @@ private: ...@@ -109,30 +140,53 @@ private:
class TInterfaceBlock : public TFieldListCollection class TInterfaceBlock : public TFieldListCollection
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(); POOL_ALLOCATOR_NEW_DELETE();
TInterfaceBlock(const TString* name, TFieldList* fields, const TString* instanceName, int arraySize, const TLayoutQualifier& layoutQualifier) TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName,
int arraySize, const TLayoutQualifier &layoutQualifier)
: TFieldListCollection(name, fields), : TFieldListCollection(name, fields),
mInstanceName(instanceName), mInstanceName(instanceName),
mArraySize(arraySize), mArraySize(arraySize),
mBlockStorage(layoutQualifier.blockStorage), mBlockStorage(layoutQualifier.blockStorage),
mMatrixPacking(layoutQualifier.matrixPacking) { mMatrixPacking(layoutQualifier.matrixPacking)
{
} }
const TString& instanceName() const { return *mInstanceName; } const TString &instanceName() const
bool hasInstanceName() const { return mInstanceName != NULL; } {
bool isArray() const { return mArraySize > 0; } return *mInstanceName;
int arraySize() const { return mArraySize; } }
TLayoutBlockStorage blockStorage() const { return mBlockStorage; } bool hasInstanceName() const
TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; } {
return mInstanceName != NULL;
}
bool isArray() const
{
return mArraySize > 0;
}
int arraySize() const
{
return mArraySize;
}
TLayoutBlockStorage blockStorage() const
{
return mBlockStorage;
}
TLayoutMatrixPacking matrixPacking() const
{
return mMatrixPacking;
}
virtual bool equals(const TInterfaceBlock &other) const; virtual bool equals(const TInterfaceBlock &other) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock); DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock);
virtual TString mangledNamePrefix() const { return "iblock-"; } virtual TString mangledNamePrefix() const
{
return "iblock-";
}
const TString* mInstanceName; // for interface block instance names const TString *mInstanceName; // for interface block instance names
int mArraySize; // 0 if not an array int mArraySize; // 0 if not an array
TLayoutBlockStorage mBlockStorage; TLayoutBlockStorage mBlockStorage;
TLayoutMatrixPacking mMatrixPacking; TLayoutMatrixPacking mMatrixPacking;
...@@ -143,72 +197,171 @@ private: ...@@ -143,72 +197,171 @@ private:
// //
class TType class TType
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(); POOL_ALLOCATOR_NEW_DELETE();
TType() {} TType()
TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1) : {
type(t), precision(EbpUndefined), qualifier(EvqGlobal), layoutQualifier(TLayoutQualifier::create()), primarySize(ps), secondarySize(ss), array(false), arraySize(0), }
TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1)
: type(t), precision(EbpUndefined), qualifier(EvqGlobal),
layoutQualifier(TLayoutQualifier::create()),
primarySize(ps), secondarySize(ss), array(false), arraySize(0),
interfaceBlock(0), structure(0) interfaceBlock(0), structure(0)
{ {
} }
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, unsigned char ps = 1, unsigned char ss = 1, bool a = false) : TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary,
type(t), precision(p), qualifier(q), layoutQualifier(TLayoutQualifier::create()), primarySize(ps), secondarySize(ss), array(a), arraySize(0), unsigned char ps = 1, unsigned char ss = 1, bool a = false)
: type(t), precision(p), qualifier(q),
layoutQualifier(TLayoutQualifier::create()),
primarySize(ps), secondarySize(ss), array(a), arraySize(0),
interfaceBlock(0), structure(0) interfaceBlock(0), structure(0)
{ {
} }
explicit TType(const TPublicType &p); explicit TType(const TPublicType &p);
TType(TStructure* userDef, TPrecision p = EbpUndefined) : TType(TStructure *userDef, TPrecision p = EbpUndefined)
type(EbtStruct), precision(p), qualifier(EvqTemporary), layoutQualifier(TLayoutQualifier::create()), primarySize(1), secondarySize(1), array(false), arraySize(0), : type(EbtStruct), precision(p), qualifier(EvqTemporary),
layoutQualifier(TLayoutQualifier::create()),
primarySize(1), secondarySize(1), array(false), arraySize(0),
interfaceBlock(0), structure(userDef) interfaceBlock(0), structure(userDef)
{ {
} }
TType(TInterfaceBlock* interfaceBlockIn, TQualifier qualifierIn, TLayoutQualifier layoutQualifierIn, int arraySizeIn) : TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn,
type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn), layoutQualifier(layoutQualifierIn), primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn), TLayoutQualifier layoutQualifierIn, int arraySizeIn)
: type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn),
layoutQualifier(layoutQualifierIn),
primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn),
interfaceBlock(interfaceBlockIn), structure(0) interfaceBlock(interfaceBlockIn), structure(0)
{ {
} }
TBasicType getBasicType() const { return type; } TBasicType getBasicType() const
void setBasicType(TBasicType t) { type = t; } {
return type;
}
void setBasicType(TBasicType t)
{
type = t;
}
TPrecision getPrecision() const { return precision; } TPrecision getPrecision() const
void setPrecision(TPrecision p) { precision = p; } {
return precision;
}
void setPrecision(TPrecision p)
{
precision = p;
}
TQualifier getQualifier() const { return qualifier; } TQualifier getQualifier() const
void setQualifier(TQualifier q) { qualifier = q; } {
return qualifier;
}
void setQualifier(TQualifier q)
{
qualifier = q;
}
TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } TLayoutQualifier getLayoutQualifier() const
void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } {
return layoutQualifier;
}
void setLayoutQualifier(TLayoutQualifier lq)
{
layoutQualifier = lq;
}
int getNominalSize() const { return primarySize; } int getNominalSize() const
int getSecondarySize() const { return secondarySize; } {
int getCols() const { ASSERT(isMatrix()); return primarySize; } return primarySize;
int getRows() const { ASSERT(isMatrix()); return secondarySize; } }
void setPrimarySize(unsigned char ps) { primarySize = ps; } int getSecondarySize() const
void setSecondarySize(unsigned char ss) { secondarySize = ss; } {
return secondarySize;
}
int getCols() const
{
ASSERT(isMatrix());
return primarySize;
}
int getRows() const
{
ASSERT(isMatrix());
return secondarySize;
}
void setPrimarySize(unsigned char ps)
{
primarySize = ps;
}
void setSecondarySize(unsigned char ss)
{
secondarySize = ss;
}
// Full size of single instance of type // Full size of single instance of type
size_t getObjectSize() const; size_t getObjectSize() const;
bool isMatrix() const { return primarySize > 1 && secondarySize > 1; } bool isMatrix() const
bool isArray() const { return array ? true : false; } {
int getArraySize() const { return arraySize; } return primarySize > 1 && secondarySize > 1;
void setArraySize(int s) { array = true; arraySize = s; } }
void clearArrayness() { array = false; arraySize = 0; } bool isArray() const
{
return array ? true : false;
}
int getArraySize() const
{
return arraySize;
}
void setArraySize(int s)
{
array = true;
arraySize = s;
}
void clearArrayness()
{
array = false;
arraySize = 0;
}
TInterfaceBlock* getInterfaceBlock() const { return interfaceBlock; } TInterfaceBlock *getInterfaceBlock() const
void setInterfaceBlock(TInterfaceBlock* interfaceBlockIn) { interfaceBlock = interfaceBlockIn; } {
bool isInterfaceBlock() const { return type == EbtInterfaceBlock; } return interfaceBlock;
}
void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
{
interfaceBlock = interfaceBlockIn;
}
bool isInterfaceBlock() const
{
return type == EbtInterfaceBlock;
}
bool isVector() const { return primarySize > 1 && secondarySize == 1; } bool isVector() const
bool isScalar() const { return primarySize == 1 && secondarySize == 1 && !structure; } {
bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); } return primarySize > 1 && secondarySize == 1;
}
bool isScalar() const
{
return primarySize == 1 && secondarySize == 1 && !structure;
}
bool isScalarInt() const
{
return isScalar() && (type == EbtInt || type == EbtUInt);
}
TStructure* getStruct() const { return structure; } TStructure *getStruct() const
void setStruct(TStructure* s) { structure = s; } {
return structure;
}
void setStruct(TStructure *s)
{
structure = s;
}
const TString& getMangledName() { const TString &getMangledName()
if (mangled.empty()) { {
if (mangled.empty())
{
mangled = buildMangledName(); mangled = buildMangledName();
mangled += ';'; mangled += ';';
} }
...@@ -220,13 +373,15 @@ public: ...@@ -220,13 +373,15 @@ public:
// precision here. // precision here.
bool equals(const TType &other) const; bool equals(const TType &other) const;
bool sameElementType(const TType& right) const { bool sameElementType(const TType &right) const
{
return type == right.type && return type == right.type &&
primarySize == right.primarySize && primarySize == right.primarySize &&
secondarySize == right.secondarySize && secondarySize == right.secondarySize &&
structure == right.structure; structure == right.structure;
} }
bool operator==(const TType& right) const { bool operator==(const TType &right) const
{
return type == right.type && return type == right.type &&
primarySize == right.primarySize && primarySize == right.primarySize &&
secondarySize == right.secondarySize && secondarySize == right.secondarySize &&
...@@ -234,23 +389,40 @@ public: ...@@ -234,23 +389,40 @@ public:
structure == right.structure; structure == right.structure;
// don't check the qualifier, it's not ever what's being sought after // don't check the qualifier, it's not ever what's being sought after
} }
bool operator!=(const TType& right) const { bool operator!=(const TType &right) const
{
return !operator==(right); return !operator==(right);
} }
bool operator<(const TType& right) const { bool operator<(const TType &right) const
if (type != right.type) return type < right.type; {
if (primarySize != right.primarySize) return primarySize < right.primarySize; if (type != right.type)
if (secondarySize != right.secondarySize) return secondarySize < right.secondarySize; return type < right.type;
if (array != right.array) return array < right.array; if (primarySize != right.primarySize)
if (arraySize != right.arraySize) return arraySize < right.arraySize; return primarySize < right.primarySize;
if (structure != right.structure) return structure < right.structure; if (secondarySize != right.secondarySize)
return secondarySize < right.secondarySize;
if (array != right.array)
return array < right.array;
if (arraySize != right.arraySize)
return arraySize < right.arraySize;
if (structure != right.structure)
return structure < right.structure;
return false; return false;
} }
const char* getBasicString() const { return ::getBasicString(type); } const char *getBasicString() const
const char* getPrecisionString() const { return ::getPrecisionString(precision); } {
const char* getQualifierString() const { return ::getQualifierString(qualifier); } return ::getBasicString(type);
}
const char *getPrecisionString() const
{
return ::getPrecisionString(precision);
}
const char *getQualifierString() const
{
return ::getQualifierString(qualifier);
}
TString getCompleteString() const; TString getCompleteString() const;
// If this type is a struct, returns the deepest struct nesting of // If this type is a struct, returns the deepest struct nesting of
...@@ -265,15 +437,17 @@ public: ...@@ -265,15 +437,17 @@ public:
// For type "nesting2", this method would return 2 -- the number // For type "nesting2", this method would return 2 -- the number
// of structures through which indirection must occur to reach the // of structures through which indirection must occur to reach the
// deepest field (nesting2.field1.position). // deepest field (nesting2.field1.position).
int getDeepestStructNesting() const { int getDeepestStructNesting() const
{
return structure ? structure->deepestNesting() : 0; return structure ? structure->deepestNesting() : 0;
} }
bool isStructureContainingArrays() const { bool isStructureContainingArrays() const
{
return structure ? structure->containsArrays() : false; return structure ? structure->containsArrays() : false;
} }
protected: protected:
TString buildMangledName() const; TString buildMangledName() const;
size_t getStructSize() const; size_t getStructSize() const;
void computeDeepestStructNesting(); void computeDeepestStructNesting();
...@@ -288,10 +462,10 @@ protected: ...@@ -288,10 +462,10 @@ protected:
int arraySize; int arraySize;
// 0 unless this is an interface block, or interface block member variable // 0 unless this is an interface block, or interface block member variable
TInterfaceBlock* interfaceBlock; TInterfaceBlock *interfaceBlock;
// 0 unless this is a struct // 0 unless this is a struct
TStructure* structure; TStructure *structure;
mutable TString mangled; mutable TString mangled;
}; };
...@@ -315,10 +489,10 @@ struct TPublicType ...@@ -315,10 +489,10 @@ struct TPublicType
unsigned char secondarySize; // rows of matrix unsigned char secondarySize; // rows of matrix
bool array; bool array;
int arraySize; int arraySize;
TType* userDef; TType *userDef;
TSourceLoc line; TSourceLoc line;
void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln) void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln)
{ {
type = bt; type = bt;
layoutQualifier = TLayoutQualifier::create(); layoutQualifier = TLayoutQualifier::create();
......
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