Commit 4e4facd4 by alokp@chromium.org

Refactored InfoSink. I have replaced most instances of sprintf with…

Refactored InfoSink. I have replaced most instances of sprintf with std::ostringstream to make it safer. I have made sure that everything still compiles and passes conformance tests. Review URL: http://codereview.appspot.com/1391041 git-svn-id: https://angleproject.googlecode.com/svn/trunk@322 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent e37888d1
...@@ -7,16 +7,16 @@ ...@@ -7,16 +7,16 @@
#ifndef _COMMON_INCLUDED_ #ifndef _COMMON_INCLUDED_
#define _COMMON_INCLUDED_ #define _COMMON_INCLUDED_
#include <assert.h>
#include <stdio.h>
#include <map> #include <map>
#include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
#include "compiler/PoolAlloc.h" #include "compiler/PoolAlloc.h"
typedef int TSourceLoc; typedef int TSourceLoc;
const unsigned int SourceLocLineMask = 0xffff;
const unsigned int SourceLocStringShift = 16;
// //
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
...@@ -35,7 +35,8 @@ typedef int TSourceLoc; ...@@ -35,7 +35,8 @@ typedef int TSourceLoc;
// Pool version of string. // Pool version of string.
// //
typedef pool_allocator<char> TStringAllocator; typedef pool_allocator<char> TStringAllocator;
typedef std::basic_string <char, std::char_traits<char>, TStringAllocator > TString; typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
inline TString* NewPoolTString(const char* s) inline TString* NewPoolTString(const char* s)
{ {
void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
...@@ -43,6 +44,13 @@ inline TString* NewPoolTString(const char* s) ...@@ -43,6 +44,13 @@ inline TString* NewPoolTString(const char* s)
} }
// //
// Persistent string memory. Should only be used for strings that survive
// across compiles/links.
//
#define TPersistString std::string
#define TPersistStringStream std::ostringstream
//
// Pool allocator versions of vectors, lists, and maps // Pool allocator versions of vectors, lists, and maps
// //
template <class T> class TVector : public std::vector<T, pool_allocator<T> > { template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
...@@ -63,49 +71,6 @@ public: ...@@ -63,49 +71,6 @@ public:
TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {} TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
}; };
//
// Persistent string memory. Should only be used for strings that survive
// across compiles/links.
//
typedef std::basic_string<char> TPersistString;
//
// Create a TString object from an integer.
//
inline const TString String(const int i, const int base = 10)
{
char text[16]; // 32 bit ints are at most 10 digits in base 10
#ifdef _WIN32
_itoa(i, text, base);
#else
// we assume base 10 for all cases
sprintf(text, "%d", i);
#endif
return text;
}
const unsigned int SourceLocLineMask = 0xffff;
const unsigned int SourceLocStringShift = 16;
__inline TPersistString FormatSourceLoc(const TSourceLoc loc)
{
char locText[64];
int string = loc >> SourceLocStringShift;
int line = loc & SourceLocLineMask;
if (line)
sprintf(locText, "%d:%d", string, line);
else
sprintf(locText, "%d:? ", string);
return TPersistString(locText);
}
typedef TMap<TString, TString> TPragmaTable; typedef TMap<TString, TString> TPragmaTable;
typedef TMap<TString, TString>::tAllocator TPragmaTableAllocator;
#endif // _COMMON_INCLUDED_ #endif // _COMMON_INCLUDED_
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#ifndef _CONSTANT_UNION_INCLUDED_ #ifndef _CONSTANT_UNION_INCLUDED_
#define _CONSTANT_UNION_INCLUDED_ #define _CONSTANT_UNION_INCLUDED_
#include <assert.h>
class ConstantUnion { class ConstantUnion {
public: public:
......
...@@ -6,50 +6,54 @@ ...@@ -6,50 +6,54 @@
#include "compiler/InfoSink.h" #include "compiler/InfoSink.h"
#ifdef _WIN32 void TInfoSinkBase::prefix(TPrefixType message) {
#include <windows.h> switch(message) {
#endif case EPrefixNone:
break;
void TInfoSinkBase::append(const char *s) case EPrefixWarning:
{ sink.append("WARNING: ");
if (outputStream & EString) { break;
checkMem(strlen(s)); case EPrefixError:
sink.append(s); sink.append("ERROR: ");
break;
case EPrefixInternalError:
sink.append("INTERNAL ERROR: ");
break;
case EPrefixUnimplemented:
sink.append("UNIMPLEMENTED: ");
break;
case EPrefixNote:
sink.append("NOTE: ");
break;
default:
sink.append("UNKOWN ERROR: ");
break;
} }
if (outputStream & EStdOut)
fprintf(stdout, "%s", s);
} }
void TInfoSinkBase::append(int count, char c) void TInfoSinkBase::location(TSourceLoc loc) {
{ int string = loc >> SourceLocStringShift;
if (outputStream & EString) { int line = loc & SourceLocLineMask;
checkMem(count);
sink.append(count, c);
}
if (outputStream & EStdOut)
fprintf(stdout, "%c", c);
}
void TInfoSinkBase::append(const TPersistString& t) TPersistStringStream stream;
{ if (line)
if (outputStream & EString) { stream << string << ":" << line;
checkMem(t.size()); else
sink.append(t); stream << string << ":? ";
} stream << ": ";
if (outputStream & EStdOut) sink.append(stream.str());
fprintf(stdout, "%s", t.c_str());
} }
void TInfoSinkBase::append(const TString& t) void TInfoSinkBase::message(TPrefixType message, const char* s) {
{ prefix(message);
if (outputStream & EString) { sink.append(s);
checkMem(t.size()); sink.append("\n");
sink.append(t.c_str()); }
}
if (outputStream & EStdOut) void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) {
fprintf(stdout, "%s", t.c_str()); prefix(message);
location(loc);
sink.append(s);
sink.append("\n");
} }
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#define _INFOSINK_INCLUDED_ #define _INFOSINK_INCLUDED_
#include <math.h> #include <math.h>
#include "compiler/Common.h" #include "compiler/Common.h"
// Returns the fractional part of the given floating-point number. // Returns the fractional part of the given floating-point number.
...@@ -30,11 +29,6 @@ enum TPrefixType { ...@@ -30,11 +29,6 @@ enum TPrefixType {
EPrefixNote EPrefixNote
}; };
enum TOutputStream {
ENull = 0,
EStdOut = 0x01,
EString = 0x02,
};
// //
// Encapsulate info logs for all objects that have them. // Encapsulate info logs for all objects that have them.
// //
...@@ -43,72 +37,68 @@ enum TOutputStream { ...@@ -43,72 +37,68 @@ enum TOutputStream {
// //
class TInfoSinkBase { class TInfoSinkBase {
public: public:
TInfoSinkBase() : outputStream(EString) {} TInfoSinkBase() {}
void erase() { sink.erase(); }
TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } template <typename T>
TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } TInfoSinkBase& operator<<(const T& t) {
TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } TPersistStringStream stream;
TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } stream << t;
TInfoSinkBase& operator<<(const unsigned int n) { append(String(n)); return *this; } sink.append(stream.str());
TInfoSinkBase& operator<<(float n) {
char buf[40];
// Make sure that at least one decimal point is written. If a number
// does not have a fractional part, %g does not written the decimal
// portion which gets interpreted as integer by the compiler.
const char* format = fractionalPart(n) == 0.0f ? "%.1f" : "%.8g";
sprintf(buf, format, n);
append(buf);
return *this; return *this;
} }
TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } // Override << operator for specific types. It is faster to append strings
TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } // and characters directly to the sink.
TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } TInfoSinkBase& operator<<(char c) {
TInfoSinkBase& operator+(const char* s) { append(s); return *this; } sink.append(1, c);
const char* c_str() const { return sink.c_str(); } return *this;
void prefix(TPrefixType message) {
switch(message) {
case EPrefixNone: break;
case EPrefixWarning: append("WARNING: "); break;
case EPrefixError: append("ERROR: "); break;
case EPrefixInternalError: append("INTERNAL ERROR: "); break;
case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break;
case EPrefixNote: append("NOTE: "); break;
default: append("UNKOWN ERROR: "); break;
}
} }
void location(TSourceLoc loc) { TInfoSinkBase& operator<<(const char* str) {
append(FormatSourceLoc(loc).c_str()); sink.append(str);
append(": "); return *this;
} }
void message(TPrefixType message, const char* s) { TInfoSinkBase& operator<<(const TPersistString& str) {
prefix(message); sink.append(str);
append(s); return *this;
append("\n");
} }
void message(TPrefixType message, const char* s, TSourceLoc loc) { TInfoSinkBase& operator<<(const TString& str) {
prefix(message); sink.append(str.c_str());
location(loc); return *this;
append(s); }
append("\n"); // Make sure floats are written with correct precision.
TInfoSinkBase& operator<<(float f) {
// Make sure that at least one decimal point is written. If a number
// does not have a fractional part, the default precision format does
// not write the decimal portion which gets interpreted as integer by
// the compiler.
TPersistStringStream stream;
if (fractionalPart(f) == 0.0f) {
stream.precision(2);
stream << std::showpoint << f;
} else {
stream << f;
}
sink.append(stream.str());
return *this;
} }
// Write boolean values as their names instead of integral value.
void setOutputStream(int output = 4) TInfoSinkBase& operator<<(bool b) {
{ const char* str = b ? "true" : "false";
outputStream = output; sink.append(str);
return *this;
} }
protected: void erase() { sink.clear(); }
void append(const char *s);
const TPersistString& str() const { return sink; }
const char* c_str() const { return sink.c_str(); }
void append(int count, char c); void prefix(TPrefixType message);
void append(const TPersistString& t); void location(TSourceLoc loc);
void append(const TString& t); void message(TPrefixType message, const char* s);
void message(TPrefixType message, const char* s, TSourceLoc loc);
void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) private:
sink.reserve(sink.capacity() + sink.capacity() / 2); }
void appendToStream(const char* s);
TPersistString sink; TPersistString sink;
int outputStream;
}; };
class TInfoSink { class TInfoSink {
......
...@@ -477,37 +477,21 @@ void TBuiltIns::initialize() ...@@ -477,37 +477,21 @@ void TBuiltIns::initialize()
void TBuiltIns::initialize(const TBuiltInResource &resources) void TBuiltIns::initialize(const TBuiltInResource &resources)
{ {
TString builtIns; TStringStream builtIns;
// Implementation dependent constants // Implementation dependent constants
char builtInConstant[80]; builtIns << "const int gl_MaxVertexAttribs = " << resources.maxVertexAttribs << ";";
builtIns << "const int gl_MaxVertexUniformVectors = " << resources.maxVertexUniformVectors << ";";
sprintf(builtInConstant, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
builtIns.append(TString(builtInConstant)); builtIns << "const int gl_MaxVaryingVectors = " << resources.maxVaryingVectors << ";";
builtIns << "const int gl_MaxVertexTextureImageUnits = " << resources.maxVertexTextureImageUnits << ";";
sprintf(builtInConstant, "const int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors); builtIns << "const int gl_MaxCombinedTextureImageUnits = " << resources.maxCombinedTextureImageUnits << ";";
builtIns.append(TString(builtInConstant)); builtIns << "const int gl_MaxTextureImageUnits = " << resources.maxTextureImageUnits << ";";
builtIns << "const int gl_MaxFragmentUniformVectors = " << resources.maxFragmentUniformVectors << ";";
sprintf(builtInConstant, "const int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors); builtIns << "const int gl_MaxDrawBuffers = " << resources.maxDrawBuffers << ";";
builtIns.append(TString(builtInConstant));
builtInStrings[EShLangFragment].push_back(builtIns.str());
sprintf(builtInConstant, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); builtInStrings[EShLangVertex].push_back(builtIns.str());
builtIns.append(TString(builtInConstant));
sprintf(builtInConstant, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits);
builtIns.append(TString(builtInConstant));
sprintf(builtInConstant, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits);
builtIns.append(TString(builtInConstant));
sprintf(builtInConstant, "const int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
builtIns.append(TString(builtInConstant));
sprintf(builtInConstant, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers);
builtIns.append(TString(builtInConstant));
builtInStrings[EShLangFragment].push_back(builtIns);
builtInStrings[EShLangVertex].push_back(builtIns);
} }
void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable) void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable)
......
...@@ -183,12 +183,7 @@ const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type, ...@@ -183,12 +183,7 @@ const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type,
{ {
case EbtFloat: out << pConstUnion->getFConst(); break; case EbtFloat: out << pConstUnion->getFConst(); break;
case EbtInt: out << pConstUnion->getIConst(); break; case EbtInt: out << pConstUnion->getIConst(); break;
case EbtBool: case EbtBool: out << pConstUnion->getBConst(); break;
if (pConstUnion->getBConst())
out << "true";
else
out << "false";
break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
if (i != size - 1) out << ", "; if (i != size - 1) out << ", ";
......
...@@ -2085,16 +2085,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con ...@@ -2085,16 +2085,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
{ {
case EbtFloat: out << constUnion->getFConst(); break; case EbtFloat: out << constUnion->getFConst(); break;
case EbtInt: out << constUnion->getIConst(); break; case EbtInt: out << constUnion->getIConst(); break;
case EbtBool: case EbtBool: out << constUnion->getBConst(); break;
if (constUnion->getBConst())
{
out << "true";
}
else
{
out << "false";
}
break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
// are tracked in the intermediate representation, not the symbol table. // are tracked in the intermediate representation, not the symbol table.
// //
#include <assert.h>
#include "compiler/Common.h" #include "compiler/Common.h"
#include "compiler/intermediate.h" #include "compiler/intermediate.h"
#include "compiler/InfoSink.h" #include "compiler/InfoSink.h"
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#ifndef _TYPES_INCLUDED #ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED #define _TYPES_INCLUDED
#include <assert.h>
#include "compiler/Common.h" #include "compiler/Common.h"
#include "compiler/BaseTypes.h" #include "compiler/BaseTypes.h"
......
...@@ -37,22 +37,20 @@ protected: ...@@ -37,22 +37,20 @@ protected:
TString TType::getCompleteString() const TString TType::getCompleteString() const
{ {
char buf[100]; TStringStream stream;
char *p = &buf[0];
if (qualifier != EvqTemporary && qualifier != EvqGlobal) if (qualifier != EvqTemporary && qualifier != EvqGlobal)
p += sprintf(p, "%s %s ", getQualifierString(), getPrecisionString()); stream << getQualifierString() << " " << getPrecisionString() << " ";
if (array) if (array)
p += sprintf(p, "array of "); stream << "array of ";
if (matrix) if (matrix)
p += sprintf(p, "%dX%d matrix of ", size, size); stream << size << "X" << size << " matrix of ";
else if (size > 1) else if (size > 1)
p += sprintf(p, "%d-component vector of ", size); stream << size << "-component vector of ";
sprintf(p, "%s", getBasicString()); stream << getBasicString();
return stream.str();
return TString(buf); }
}
// //
// Helper functions for printing, not part of traversing. // Helper functions for printing, not part of traversing.
...@@ -62,7 +60,7 @@ void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth) ...@@ -62,7 +60,7 @@ void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth)
{ {
int i; int i;
infoSink.debug << FormatSourceLoc(node->getLine()); infoSink.debug.location(node->getLine());
for (i = 0; i < depth; ++i) for (i = 0; i < depth; ++i)
infoSink.debug << " "; infoSink.debug << " ";
...@@ -81,12 +79,8 @@ void TOutputTraverser::visitSymbol(TIntermSymbol* node) ...@@ -81,12 +79,8 @@ void TOutputTraverser::visitSymbol(TIntermSymbol* node)
{ {
OutputTreeText(infoSink, node, depth); OutputTreeText(infoSink, node, depth);
char buf[100]; infoSink.debug << "'" << node->getSymbol() << "' ";
sprintf(buf, "'%s' (%s)\n", infoSink.debug << "(" << node->getCompleteString() << ")\n";
node->getSymbol().c_str(),
node->getCompleteString().c_str());
infoSink.debug << buf;
} }
bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
...@@ -317,7 +311,6 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) ...@@ -317,7 +311,6 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
int size = node->getType().getObjectSize(); int size = node->getType().getObjectSize();
char buf[300];
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
OutputTreeText(out, node, depth); OutputTreeText(out, node, depth);
switch (node->getUnionArrayPointer()[i].getType()) { switch (node->getUnionArrayPointer()[i].getType()) {
...@@ -331,12 +324,12 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) ...@@ -331,12 +324,12 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
out.debug << "\n"; out.debug << "\n";
break; break;
case EbtFloat: case EbtFloat:
sprintf(buf, "%f (%s)", node->getUnionArrayPointer()[i].getFConst(), "const float"); out.debug << node->getUnionArrayPointer()[i].getFConst();
out.debug << buf << "\n"; out.debug << " (const float)\n";
break; break;
case EbtInt: case EbtInt:
sprintf(buf, "%d (%s)", node->getUnionArrayPointer()[i].getIConst(), "const int"); out.debug << node->getUnionArrayPointer()[i].getIConst();
out.debug << buf << "\n"; out.debug << " (const int)\n";
break; break;
default: default:
out.info.message(EPrefixInternalError, "Unknown constant", node->getLine()); out.info.message(EPrefixInternalError, "Unknown constant", node->getLine());
......
...@@ -63,9 +63,10 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) ...@@ -63,9 +63,10 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
TQualifier qualifier = node->getType().getQualifier(); TQualifier qualifier = node->getType().getQualifier();
if (qualifier != EvqConst) { if (qualifier != EvqConst) {
char buf[200]; TString buf;
sprintf(buf, "'constructor' : assigning non-constant to %s", type.getCompleteString().c_str()); buf.append("'constructor' : assigning non-constant to ");
infoSink.info.message(EPrefixError, buf, node->getLine()); buf.append(type.getCompleteString());
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
error = true; error = true;
return false; return false;
} }
...@@ -77,9 +78,10 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) ...@@ -77,9 +78,10 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
{ {
char buf[200]; TString buf;
sprintf(buf, "'constructor' : assigning non-constant to '%s'", type.getCompleteString().c_str()); buf.append("'constructor' : assigning non-constant to ");
infoSink.info.message(EPrefixError, buf, node->getLine()); buf.append(type.getCompleteString());
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
error = true; error = true;
return false; return false;
} }
...@@ -87,9 +89,10 @@ bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) ...@@ -87,9 +89,10 @@ bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
{ {
if (!node->isConstructor() && node->getOp() != EOpComma) { if (!node->isConstructor() && node->getOp() != EOpComma) {
char buf[200]; TString buf;
sprintf(buf, "'constructor' : assigning non-constant to '%s'", type.getCompleteString().c_str()); buf.append("'constructor' : assigning non-constant to ");
infoSink.info.message(EPrefixError, buf, node->getLine()); buf.append(type.getCompleteString());
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
error = true; error = true;
return false; return false;
} }
......
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