Commit 72e3589c by Olli Etuaho Committed by Commit Bot

Refactor debug output of types

Instead of passing around strings from TType::getCompleteString(), add a stream operator to InfoSinkBase that takes a TType. This makes the compiler executable a few kilobytes smaller and will help with getting rid of TString altogether. BUG=angleproject:2267 TEST=angle_unittests Change-Id: I31a6693b40a28824b3959e19ad3c0a2ce0f0a35f Reviewed-on: https://chromium-review.googlesource.com/1107712Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 66c2f4af
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/ImmutableString.h" #include "compiler/translator/ImmutableString.h"
#include "compiler/translator/Types.h"
namespace sh namespace sh
{ {
...@@ -33,6 +34,39 @@ TInfoSinkBase &TInfoSinkBase::operator<<(const ImmutableString &str) ...@@ -33,6 +34,39 @@ TInfoSinkBase &TInfoSinkBase::operator<<(const ImmutableString &str)
return *this; return *this;
} }
TInfoSinkBase &TInfoSinkBase::operator<<(const TType &type)
{
if (type.isInvariant())
sink.append("invariant ");
if (type.getQualifier() != EvqTemporary && type.getQualifier() != EvqGlobal)
{
sink.append(type.getQualifierString());
sink.append(" ");
}
if (type.getPrecision() != EbpUndefined)
{
sink.append(type.getPrecisionString());
sink.append(" ");
}
if (type.isArray())
{
for (auto arraySizeIter = type.getArraySizes()->rbegin();
arraySizeIter != type.getArraySizes()->rend(); ++arraySizeIter)
{
*this << "array[" << (*arraySizeIter) << "] of ";
}
}
if (type.isMatrix())
{
*this << type.getCols() << "X" << type.getRows() << " matrix of ";
}
else if (type.isVector())
*this << type.getNominalSize() << "-component vector of ";
sink.append(type.getBasicString());
return *this;
}
void TInfoSinkBase::location(int file, int line) void TInfoSinkBase::location(int file, int line)
{ {
TPersistStringStream stream; TPersistStringStream stream;
......
...@@ -16,6 +16,7 @@ namespace sh ...@@ -16,6 +16,7 @@ namespace sh
{ {
class ImmutableString; class ImmutableString;
class TType;
// Returns the fractional part of the given floating-point number. // Returns the fractional part of the given floating-point number.
inline float fractionalPart(float f) inline float fractionalPart(float f)
...@@ -69,6 +70,8 @@ class TInfoSinkBase ...@@ -69,6 +70,8 @@ class TInfoSinkBase
} }
TInfoSinkBase &operator<<(const ImmutableString &str); TInfoSinkBase &operator<<(const ImmutableString &str);
TInfoSinkBase &operator<<(const TType &type);
// Make sure floats are written with correct precision. // Make sure floats are written with correct precision.
TInfoSinkBase &operator<<(float f) TInfoSinkBase &operator<<(float f)
{ {
......
...@@ -160,7 +160,6 @@ class TIntermTyped : public TIntermNode ...@@ -160,7 +160,6 @@ class TIntermTyped : public TIntermNode
bool isScalar() const { return getType().isScalar(); } bool isScalar() const { return getType().isScalar(); }
bool isScalarInt() const { return getType().isScalarInt(); } bool isScalarInt() const { return getType().isScalarInt(); }
const char *getBasicString() const { return getType().getBasicString(); } const char *getBasicString() const { return getType().getBasicString(); }
TString getCompleteString() const { return getType().getCompleteString(); }
unsigned int getOutermostArraySize() const { return getType().getOutermostArraySize(); } unsigned int getOutermostArraySize() const { return getType().getOutermostArraySize(); }
......
...@@ -96,7 +96,7 @@ void TOutputTraverser::visitSymbol(TIntermSymbol *node) ...@@ -96,7 +96,7 @@ void TOutputTraverser::visitSymbol(TIntermSymbol *node)
mOut << "'" << node->getName() << "' "; mOut << "'" << node->getName() << "' ";
} }
mOut << "(symbol id " << node->uniqueId().get() << ") "; mOut << "(symbol id " << node->uniqueId().get() << ") ";
mOut << "(" << node->getCompleteString() << ")"; mOut << "(" << node->getType() << ")";
mOut << "\n"; mOut << "\n";
} }
...@@ -107,7 +107,7 @@ bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) ...@@ -107,7 +107,7 @@ bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
node->writeOffsetsAsXYZW(&mOut); node->writeOffsetsAsXYZW(&mOut);
mOut << ")"; mOut << ")";
mOut << " (" << node->getCompleteString() << ")"; mOut << " (" << node->getType() << ")";
mOut << "\n"; mOut << "\n";
return true; return true;
} }
...@@ -262,7 +262,7 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) ...@@ -262,7 +262,7 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
mOut << "<unknown op>"; mOut << "<unknown op>";
} }
mOut << " (" << node->getCompleteString() << ")"; mOut << " (" << node->getType() << ")";
mOut << "\n"; mOut << "\n";
...@@ -345,7 +345,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) ...@@ -345,7 +345,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
break; break;
} }
mOut << " (" << node->getCompleteString() << ")"; mOut << " (" << node->getType() << ")";
mOut << "\n"; mOut << "\n";
...@@ -370,15 +370,14 @@ void TOutputTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node) ...@@ -370,15 +370,14 @@ void TOutputTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node)
{ {
OutputTreeText(mOut, node, getCurrentIndentDepth()); OutputTreeText(mOut, node, getCurrentIndentDepth());
OutputFunction(mOut, "Function Prototype", node->getFunction()); OutputFunction(mOut, "Function Prototype", node->getFunction());
mOut << " (" << node->getCompleteString() << ")"; mOut << " (" << node->getType() << ")";
mOut << "\n"; mOut << "\n";
size_t paramCount = node->getFunction()->getParamCount(); size_t paramCount = node->getFunction()->getParamCount();
for (size_t i = 0; i < paramCount; ++i) for (size_t i = 0; i < paramCount; ++i)
{ {
const TVariable *param = node->getFunction()->getParam(i); const TVariable *param = node->getFunction()->getParam(i);
OutputTreeText(mOut, node, getCurrentIndentDepth() + 1); OutputTreeText(mOut, node, getCurrentIndentDepth() + 1);
mOut << "parameter: " << param->name() << " (" << param->getType().getCompleteString() mOut << "parameter: " << param->name() << " (" << param->getType() << ")";
<< ")";
} }
} }
...@@ -447,7 +446,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -447,7 +446,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
break; break;
} }
mOut << " (" << node->getCompleteString() << ")"; mOut << " (" << node->getType() << ")";
mOut << "\n"; mOut << "\n";
...@@ -475,7 +474,7 @@ bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node) ...@@ -475,7 +474,7 @@ bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
OutputTreeText(mOut, node, getCurrentIndentDepth()); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Ternary selection"; mOut << "Ternary selection";
mOut << " (" << node->getCompleteString() << ")\n"; mOut << " (" << node->getType() << ")\n";
++mIndentDepth; ++mIndentDepth;
......
...@@ -367,25 +367,26 @@ void TParseContext::outOfRangeError(bool isError, ...@@ -367,25 +367,26 @@ void TParseContext::outOfRangeError(bool isError,
// //
// Same error message for all places assignments don't work. // Same error message for all places assignments don't work.
// //
void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right) void TParseContext::assignError(const TSourceLoc &line,
const char *op,
const TType &left,
const TType &right)
{ {
std::stringstream reasonStream; TInfoSinkBase reasonStream;
reasonStream << "cannot convert from '" << right << "' to '" << left << "'"; reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
std::string reason = reasonStream.str(); error(line, reasonStream.c_str(), op);
error(line, reason.c_str(), op);
} }
// //
// Same error message for all places unary operations don't work. // Same error message for all places unary operations don't work.
// //
void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand) void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, const TType &operand)
{ {
std::stringstream reasonStream; TInfoSinkBase reasonStream;
reasonStream << "wrong operand type - no operation '" << op reasonStream << "wrong operand type - no operation '" << op
<< "' exists that takes an operand of type " << operand << "' exists that takes an operand of type " << operand
<< " (or there is no acceptable conversion)"; << " (or there is no acceptable conversion)";
std::string reason = reasonStream.str(); error(line, reasonStream.c_str(), op);
error(line, reason.c_str(), op);
} }
// //
...@@ -393,16 +394,15 @@ void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString ...@@ -393,16 +394,15 @@ void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString
// //
void TParseContext::binaryOpError(const TSourceLoc &line, void TParseContext::binaryOpError(const TSourceLoc &line,
const char *op, const char *op,
TString left, const TType &left,
TString right) const TType &right)
{ {
std::stringstream reasonStream; TInfoSinkBase reasonStream;
reasonStream << "wrong operand types - no operation '" << op reasonStream << "wrong operand types - no operation '" << op
<< "' exists that takes a left-hand operand of type '" << left << "' exists that takes a left-hand operand of type '" << left
<< "' and a right operand of type '" << right << "' and a right operand of type '" << right
<< "' (or there is no acceptable conversion)"; << "' (or there is no acceptable conversion)";
std::string reason = reasonStream.str(); error(line, reasonStream.c_str(), op);
error(line, reason.c_str(), op);
} }
void TParseContext::checkPrecisionSpecified(const TSourceLoc &line, void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
...@@ -1045,8 +1045,9 @@ bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line, ...@@ -1045,8 +1045,9 @@ bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line,
{ {
if (mShaderVersion < 310 && elementType.isArray()) if (mShaderVersion < 310 && elementType.isArray())
{ {
error(line, "cannot declare arrays of arrays", TInfoSinkBase typeString;
TType(elementType).getCompleteString().c_str()); typeString << TType(elementType);
error(line, "cannot declare arrays of arrays", typeString.c_str());
return false; return false;
} }
return true; return true;
...@@ -1076,8 +1077,10 @@ bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &index ...@@ -1076,8 +1077,10 @@ bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &index
sh::IsVarying(elementType.qualifier) && sh::IsVarying(elementType.qualifier) &&
!IsGeometryShaderInput(mShaderType, elementType.qualifier)) !IsGeometryShaderInput(mShaderType, elementType.qualifier))
{ {
TInfoSinkBase typeString;
typeString << TType(elementType);
error(indexLocation, "cannot declare arrays of structs of this qualifier", error(indexLocation, "cannot declare arrays of structs of this qualifier",
TType(elementType).getCompleteString().c_str()); typeString.c_str());
return false; return false;
} }
return checkIsValidQualifierForArray(indexLocation, elementType); return checkIsValidQualifierForArray(indexLocation, elementType);
...@@ -1922,10 +1925,9 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, ...@@ -1922,10 +1925,9 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
{ {
if (EvqConst != initializer->getType().getQualifier()) if (EvqConst != initializer->getType().getQualifier())
{ {
std::stringstream reasonStream; TInfoSinkBase reasonStream;
reasonStream << "assigning non-constant to '" << type->getCompleteString() << "'"; reasonStream << "assigning non-constant to '" << *type << "'";
std::string reason = reasonStream.str(); error(line, reasonStream.c_str(), "=");
error(line, reason.c_str(), "=");
// We're still going to declare the variable to avoid extra error messages. // We're still going to declare the variable to avoid extra error messages.
type->setQualifier(EvqTemporary); type->setQualifier(EvqTemporary);
...@@ -1975,8 +1977,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line, ...@@ -1975,8 +1977,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
if (!binaryOpCommonCheck(EOpInitialize, intermSymbol, initializer, line)) if (!binaryOpCommonCheck(EOpInitialize, intermSymbol, initializer, line))
{ {
assignError(line, "=", variable->getType().getCompleteString(), assignError(line, "=", variable->getType(), initializer->getType());
initializer->getCompleteString());
return false; return false;
} }
...@@ -3396,8 +3397,10 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, ...@@ -3396,8 +3397,10 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
if (type.isStructureContainingArrays()) if (type.isStructureContainingArrays())
{ {
// ESSL 1.00.17 section 6.1 Function Definitions // ESSL 1.00.17 section 6.1 Function Definitions
TInfoSinkBase typeString;
typeString << TType(type);
error(location, "structures containing arrays can't be function return values", error(location, "structures containing arrays can't be function return values",
TType(type).getCompleteString().c_str()); typeString.c_str());
} }
} }
...@@ -4871,7 +4874,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, ...@@ -4871,7 +4874,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() || if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
child->isVector()) child->isVector())
{ {
unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); unaryOpError(loc, GetOperatorString(op), child->getType());
return nullptr; return nullptr;
} }
break; break;
...@@ -4879,7 +4882,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, ...@@ -4879,7 +4882,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) || if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
child->isMatrix() || child->isArray()) child->isMatrix() || child->isArray())
{ {
unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); unaryOpError(loc, GetOperatorString(op), child->getType());
return nullptr; return nullptr;
} }
break; break;
...@@ -4893,7 +4896,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, ...@@ -4893,7 +4896,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
child->getBasicType() == EbtBool || child->isArray() || child->getBasicType() == EbtBool || child->isArray() ||
IsOpaqueType(child->getBasicType())) IsOpaqueType(child->getBasicType()))
{ {
unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); unaryOpError(loc, GetOperatorString(op), child->getType());
return nullptr; return nullptr;
} }
break; break;
...@@ -4904,7 +4907,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, ...@@ -4904,7 +4907,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
if (child->getMemoryQualifier().writeonly) if (child->getMemoryQualifier().writeonly)
{ {
unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); unaryOpError(loc, GetOperatorString(op), child->getType());
return nullptr; return nullptr;
} }
...@@ -5327,8 +5330,7 @@ TIntermTyped *TParseContext::addBinaryMath(TOperator op, ...@@ -5327,8 +5330,7 @@ TIntermTyped *TParseContext::addBinaryMath(TOperator op,
TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
if (node == 0) if (node == 0)
{ {
binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
right->getCompleteString());
return left; return left;
} }
return node; return node;
...@@ -5342,8 +5344,7 @@ TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, ...@@ -5342,8 +5344,7 @@ TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
if (node == nullptr) if (node == nullptr)
{ {
binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
right->getCompleteString());
node = CreateBoolNode(false); node = CreateBoolNode(false);
node->setLine(loc); node->setLine(loc);
} }
...@@ -5374,7 +5375,7 @@ TIntermTyped *TParseContext::addAssign(TOperator op, ...@@ -5374,7 +5375,7 @@ TIntermTyped *TParseContext::addAssign(TOperator op,
} }
if (node == nullptr) if (node == nullptr)
{ {
assignError(loc, "assign", left->getCompleteString(), right->getCompleteString()); assignError(loc, "assign", left->getType(), right->getType());
return left; return left;
} }
if (op != EOpAssign) if (op != EOpAssign)
...@@ -5885,12 +5886,10 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, ...@@ -5885,12 +5886,10 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
if (trueExpression->getType() != falseExpression->getType()) if (trueExpression->getType() != falseExpression->getType())
{ {
std::stringstream reasonStream; TInfoSinkBase reasonStream;
reasonStream << "mismatching ternary operator operand types '" reasonStream << "mismatching ternary operator operand types '" << trueExpression->getType()
<< trueExpression->getCompleteString() << " and '" << " and '" << falseExpression->getType() << "'";
<< falseExpression->getCompleteString() << "'"; error(loc, reasonStream.c_str(), "?:");
std::string reason = reasonStream.str();
error(loc, reason.c_str(), "?:");
return falseExpression; return falseExpression;
} }
if (IsOpaqueType(trueExpression->getBasicType())) if (IsOpaqueType(trueExpression->getBasicType()))
......
...@@ -109,9 +109,12 @@ class TParseContext : angle::NonCopyable ...@@ -109,9 +109,12 @@ class TParseContext : angle::NonCopyable
int vecSize, int vecSize,
TVector<int> *fieldOffsets); TVector<int> *fieldOffsets);
void assignError(const TSourceLoc &line, const char *op, TString left, TString right); void assignError(const TSourceLoc &line, const char *op, const TType &left, const TType &right);
void unaryOpError(const TSourceLoc &line, const char *op, TString operand); void unaryOpError(const TSourceLoc &line, const char *op, const TType &operand);
void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right); void binaryOpError(const TSourceLoc &line,
const char *op,
const TType &left,
const TType &right);
// Check functions - the ones that return bool return false if an error was generated. // Check functions - the ones that return bool return false if an error was generated.
......
...@@ -396,33 +396,6 @@ const char *TType::getBuiltInTypeNameString() const ...@@ -396,33 +396,6 @@ const char *TType::getBuiltInTypeNameString() const
return getBasicString(); return getBasicString();
} }
TString TType::getCompleteString() const
{
TStringStream stream;
if (invariant)
stream << "invariant ";
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
stream << getQualifierString() << " ";
if (precision != EbpUndefined)
stream << getPrecisionString() << " ";
if (mArraySizes)
{
for (auto arraySizeIter = mArraySizes->rbegin(); arraySizeIter != mArraySizes->rend();
++arraySizeIter)
{
stream << "array[" << (*arraySizeIter) << "] of ";
}
}
if (isMatrix())
stream << getCols() << "X" << getRows() << " matrix of ";
else if (isVector())
stream << getNominalSize() << "-component vector of ";
stream << getBasicString();
return stream.str();
}
int TType::getDeepestStructNesting() const int TType::getDeepestStructNesting() const
{ {
return mStructure ? mStructure->deepestNesting() : 0; return mStructure ? mStructure->deepestNesting() : 0;
......
...@@ -291,8 +291,6 @@ class TType ...@@ -291,8 +291,6 @@ class TType
const char *getBuiltInTypeNameString() const; const char *getBuiltInTypeNameString() 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
// any field in the struct. For example: // any field in the struct. For example:
// struct nesting1 { // struct nesting1 {
......
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