Commit dadf945f by John Kessenich

Simultaneously fix only known memory leak and take the next step in supporting…

Simultaneously fix only known memory leak and take the next step in supporting arrays of arrays. Improved several minor things along the way. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@20514 e7fa87d3-cd2b-0410-9028-fcbf551c1848
parent 6968b823
......@@ -254,6 +254,7 @@ bool CompileFile(char *fileName, ShHandle compiler, int debugOptions, const TBui
#ifdef MEASURE_MEMORY
GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters));
printf("Working set size: %d\n", counters.WorkingSetSize);
}
#endif
......
#version 130
float gu[];
float g4[4];
float g5[5];
uniform int a;
float[4] foo(float a[5])
{
return float[](a[0], a[1], a[2], a[3]);
}
void bar(float[5]) {}
void main()
{
{
float gu[2]; // okay, new scope
gu[2] = 4.0; // ERROR, overflow
}
gu[2] = 4.0; // okay
gu[3] = 3.0;
gu[a] = 5.0; // ERROR
g4 = foo(g5);
g5 = g4; // ERROR
gu = g4; // ERROR
foo(gu); // ERROR
bar(g5);
if (float[4](1.0, 2.0, 3.0, 4.0) == g4)
gu[0] = 2.0;
float u[];
u[2] = 3.0; // okay
float u[5];
u[5] = 5.0; // ERROR
foo(u); // okay
gl_FragData[1000] = vec4(1.0); // ERROR
gl_FragData[-1] = vec4(1.0); // ERROR
gl_FragData[3] = vec4(1.0);
const int ca[] = int[](3, 2);
int sum = ca[0];
sum += ca[1];
sum += ca[2]; // ERROR
const int ca3[3] = int[](3, 2); // ERROR
int ica[] = int[](3, 2);
int ica3[3] = int[](3, 2); // ERROR
}
#version 100
float gu[];
float g4[4];
float g5[5];
uniform int a;
float[4] foo(float[5] a) // ERROR // ERROR
{
return float[](a[0], a[1], a[2], a[3]); // ERROR
}
void bar(float[5]) {}
void main()
{
{
float gu[2]; // okay, new scope
gu[2] = 4.0; // ERROR, overflow
}
gu[2] = 4.0; // okay
gu[3] = 3.0;
gu[a] = 5.0; // ERROR
g4 = foo(g5);
g5 = g4; // ERROR
gu = g4; // ERROR
foo(gu); // ERROR
bar(g5);
if (float[4](1.0, 2.0, 3.0, 4.0) == g4) // ERROR
gu[0] = 2.0;
float u[];
u[2] = 3.0; // okay
float u[5];
u[5] = 5.0; // ERROR
foo(u); // okay
gl_FragData[1000] = vec4(1.0); // ERROR
gl_FragData[-1] = vec4(1.0); // ERROR
gl_FragData[3] = vec4(1.0);
}
......@@ -17,3 +17,5 @@ cppIndent.vert
cppNest.vert
cppComplexExpr.vert
pointCoord.frag
array.frag
array100.frag
\ No newline at end of file
......@@ -104,14 +104,12 @@ enum TStorageQualifier {
EvqLast,
};
//
// This is just for debug print out, carried along with the definitions above.
//
// These will show up in error messages
__inline const char* getStorageQualifierString(TStorageQualifier q)
{
switch (q) {
case EvqTemporary: return "Temporary"; break;
case EvqGlobal: return "Global"; break;
case EvqTemporary: return "temporary"; break;
case EvqGlobal: return "global"; break;
case EvqConst: return "const"; break;
case EvqConstReadOnly: return "const (read only)"; break;
case EvqAttribute: return "attribute"; break;
......@@ -121,14 +119,14 @@ __inline const char* getStorageQualifierString(TStorageQualifier q)
case EvqIn: return "in"; break;
case EvqOut: return "out"; break;
case EvqInOut: return "inout"; break;
case EvqPosition: return "Position"; break;
case EvqPointSize: return "PointSize"; break;
case EvqClipVertex: return "ClipVertex"; break;
case EvqFace: return "FrontFacing"; break;
case EvqFragCoord: return "FragCoord"; break;
case EvqPointCoord: return "PointCoord"; break;
case EvqFragColor: return "FragColor"; break;
case EvqFragDepth: return "FragDepth"; break;
case EvqPosition: return "gl_Position"; break;
case EvqPointSize: return "gl_PointSize"; break;
case EvqClipVertex: return "gl_ClipVertex"; break;
case EvqFace: return "gl_FrontFacing"; break;
case EvqFragCoord: return "gl_FragCoord"; break;
case EvqPointCoord: return "gl_PointCoord"; break;
case EvqFragColor: return "fragment out"; break;
case EvqFragDepth: return "gl_FragDepth"; break;
default: return "unknown qualifier";
}
}
......
......@@ -57,6 +57,24 @@ inline TTypeList* NewPoolTTypeList()
}
//
// TODO: TArraySizes memory: This could be replaced by something smaller.
// Almost all arrays could be handled by two sizes each fitting
// in 16 bits, needing a real vector only in the cases where there
// are more than 3 sizes or a size needing more than 16 bits.
//
// The type is a pointer, so that it can be non-allocated and zero
// for the vast majority of non-array types. Note that means if it
// is used, it will be containing at least one size.
typedef TVector<int>* TArraySizes;
inline TArraySizes NewPoolTArraySizes()
{
void* memory = GlobalPoolAllocator.allocate(sizeof(TVector<int>));
return new(memory) TVector<int>;
}
//
// This is a workaround for a problem with the yacc stack, It can't have
// types that it thinks have non-trivial constructors. It should
// just be used while recognizing the grammar, not anything else. Pointers
......@@ -79,9 +97,8 @@ public:
int vectorSize : 4;
int matrixCols : 4;
int matrixRows : 4;
bool array;
int arraySize;
TType* userDef;
TArraySizes arraySizes;
const TType* userDef;
int line;
void initType(int ln = 0)
......@@ -90,8 +107,7 @@ public:
vectorSize = 1;
matrixRows = 0;
matrixCols = 0;
array = false;
arraySize = 0;
arraySizes = 0;
userDef = 0;
line = ln;
}
......@@ -110,6 +126,8 @@ public:
void setVector(int s)
{
matrixRows = 0;
matrixCols = 0;
vectorSize = s;
}
......@@ -119,12 +137,6 @@ public:
matrixCols = c;
vectorSize = 0;
}
void setArray(bool a, int s = 0)
{
array = a;
arraySize = s;
}
};
typedef std::map<TTypeList*, TTypeList*> TStructureMap;
......@@ -136,7 +148,7 @@ class TType {
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), array(false), arraySize(0),
type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
fieldName(0), mangled(0), typeName(0)
{
......@@ -144,7 +156,7 @@ public:
qualifier.precision = EpqNone;
}
explicit TType(const TPublicType &p) :
type(p.type), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), array(p.array), arraySize(p.arraySize),
type(p.type), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
{
qualifier = p.qualifier;
......@@ -154,7 +166,7 @@ public:
}
}
explicit TType(TTypeList* userDef, const TString& n) :
type(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), array(false), arraySize(0),
type(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), arraySizes(0),
structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0)
{
qualifier.storage = EvqTemporary;
......@@ -173,9 +185,13 @@ public:
vectorSize = copyOf.vectorSize;
matrixCols = copyOf.matrixCols;
matrixRows = copyOf.matrixRows;
array = copyOf.array;
arraySize = copyOf.arraySize;
if (copyOf.arraySizes) {
arraySizes = NewPoolTArraySizes();
*arraySizes = *copyOf.arraySizes;
} else
arraySizes = 0;
TStructureMapIterator iter;
if (copyOf.structure) {
if ((iter = remapper.find(structure)) == remapper.end()) {
......@@ -220,9 +236,8 @@ public:
virtual void dereference()
{
if (array) {
array = false;
arraySize = 0;
if (arraySizes) {
arraySizes = 0;
maxArraySize = 0;
} else if (matrixCols > 0) {
vectorSize = matrixRows;
......@@ -232,7 +247,7 @@ public:
vectorSize = 1;
}
virtual void setElementType(TBasicType t, int s, int mc, int mr, TType* userDef)
virtual void setElementType(TBasicType t, int s, int mc, int mr, const TType* userDef)
{
type = t;
vectorSize = s;
......@@ -265,9 +280,15 @@ public:
virtual int getMatrixRows() const { return matrixRows; }
virtual bool isMatrix() const { return matrixCols ? true : false; }
virtual bool isArray() const { return array ? true : false; }
int getArraySize() const { return arraySize; }
void setArraySize(int s) { array = true; arraySize = s; }
virtual bool isArray() const { return arraySizes != 0; }
int getArraySize() const { return arraySizes->front(); }
void setArraySizes(TArraySizes s) {
// copy; we don't want distinct types sharing the same descriptor
if (! arraySizes)
arraySizes = NewPoolTArraySizes();
*arraySizes = *s;
}
void changeArraySize(int s) { arraySizes->front() = s; }
void setMaxArraySize (int s) { maxArraySize = s; }
int getMaxArraySize () const { return maxArraySize; }
void setArrayInformationType(TType* t) { arrayInformationType = t; }
......@@ -336,7 +357,7 @@ public:
vectorSize == right.vectorSize &&
matrixCols == right.matrixCols &&
matrixRows == right.matrixRows &&
array == right.array && (!array || arraySize == right.arraySize) &&
(arraySizes == 0 && right.arraySizes == 0 || (arraySizes && right.arraySizes && *arraySizes == *right.arraySizes)) &&
structure == right.structure;
// don't check the qualifier, it's not ever what's being sought after
}
......@@ -353,10 +374,9 @@ protected:
int vectorSize : 4;
int matrixCols : 4;
int matrixRows : 4;
unsigned int array : 1;
TQualifier qualifier;
int arraySize;
TArraySizes arraySizes;
TTypeList* structure; // 0 unless this is a struct
mutable int structureSize;
......
......@@ -713,7 +713,7 @@ void TBuiltIns::initialize()
void TBuiltIns::initialize(const TBuiltInResource &resources)
{
//
// Initialize all the built-in strings for parsing.
// Initialize the context-dependent (resource-dependent) built-in strings for parsing.
//
TString StandardUniforms;
......@@ -939,7 +939,9 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable, const TBu
case EShLangFragment: {
// Set up gl_FragData. The array size.
TType fragData(EbtFloat, EvqFragColor, 4);
fragData.setArraySize(resources.maxDrawBuffers);
TArraySizes arraySizes = NewPoolTArraySizes();
arraySizes->push_back(resources.maxDrawBuffers);
fragData.setArraySizes(arraySizes);
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
}
break;
......
......@@ -571,9 +571,14 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
if (constType)
type->getQualifier().storage = EvqConst;
if (type->isArray() && type->getArraySize() != function.getParamCount()) {
error(line, "array constructor needs one argument per array element", "constructor", "");
return true;
if (type->isArray()) {
if (type->getArraySize() == 0) {
// auto adapt the constructor type to the number of arguments
type->changeArraySize(function.getParamCount());
} else if (type->getArraySize() != function.getParamCount()) {
error(line, "array constructor needs one argument per array element", "constructor", "");
return true;
}
}
if (arrayArg && op != EOpConstructStruct) {
......@@ -653,7 +658,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
//
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
{
if (pType.type != EbtBool || pType.array || pType.matrixCols > 1 || (pType.vectorSize > 1)) {
if (pType.type != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) {
error(line, "boolean expression expected", "", "");
return true;
}
......@@ -743,7 +748,7 @@ bool TParseContext::parameterSamplerErrorCheck(int line, TStorageQualifier quali
return false;
}
bool TParseContext::containsSampler(TType& type)
bool TParseContext::containsSampler(const TType& type)
{
if (IsSampler(type.getBasicType()))
return true;
......@@ -866,9 +871,6 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
variable = new TVariable(&identifier, TType(type));
if (type.arraySize)
variable->getType().setArraySize(type.arraySize);
if (! symbolTable.insert(*variable)) {
delete variable;
error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
......@@ -897,16 +899,15 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
TType* t = variable->getArrayInformationType();
while (t != 0) {
if (t->getMaxArraySize() > type.arraySize) {
if (t->getMaxArraySize() > type.arraySizes->front()) {
error(line, "higher index value already used for the array", identifier.c_str(), "");
return true;
}
t->setArraySize(type.arraySize);
t->setArraySizes(type.arraySizes);
t = t->getArrayInformationType();
}
if (type.arraySize)
variable->getType().setArraySize(type.arraySize);
variable->getType().setArraySizes(type.arraySizes);
}
if (voidErrorCheck(line, identifier, type))
......@@ -1094,10 +1095,15 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
error(line, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
return true;
}
// Fix arrayness if variable is unsized, getting size for initializer
if (initializer->getType().isArray() && initializer->getType().getArraySize() > 0 &&
type.isArray() && type.getArraySize() == 0)
type.changeArraySize(initializer->getType().getArraySize());
//
// test for and propagate constant
//
if (qualifier == EvqConst) {
if (qualifier != initializer->getType().getQualifier().storage) {
error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
......@@ -1471,8 +1477,8 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
TType arrayElementType = node->getType();
arrayElementType.dereference();
if (index >= node->getType().getArraySize()) {
error(line, "", "[", "array index out of range '%d'", index);
if (index >= node->getType().getArraySize() || index < 0) {
error(line, "", "[", "array index '%d' out of range", index);
recover();
index = 0;
}
......
......@@ -125,7 +125,7 @@ struct TParseContext {
bool structQualifierErrorCheck(int line, const TPublicType& pType);
void setDefaultPrecision(int line, TBasicType, TPrecisionQualifier);
bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type);
bool containsSampler(TType& type);
bool containsSampler(const TType& type);
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
bool paramErrorCheck(int line, TStorageQualifier qualifier, TType* type);
......@@ -154,7 +154,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&);
void PaReservedWord();
int PaIdentOrType(TString& id, TParseContext&, TSymbol*&);
int PaParseComment(int &lineno, TParseContext&);
void setInitialState();
void ResetFlex();
typedef TParseContext* TParseContextPointer;
extern TParseContextPointer& GetGlobalParseContext();
......
......@@ -194,13 +194,11 @@ bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language
GlobalParseContext = &parseContext;
setInitialState();
assert(symbolTable->isEmpty() || symbolTable->atSharedBuiltInLevel());
//
// Parse the built-ins. This should only happen once per
// language symbol table.
// language symbol table when no 'resources' are passed in.
//
// Push the symbol table to give it an initial scope. This
// push should not have a corresponding pop, so that built-ins
......@@ -208,6 +206,7 @@ bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language
//
symbolTable->push();
//Initialize the Preprocessor
int ret = InitPreprocessor();
......@@ -215,6 +214,8 @@ bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language
infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor");
return false;
}
ResetFlex();
for (TBuiltInStrings::iterator i = BuiltInStrings[parseContext.language].begin();
i != BuiltInStrings[parseContext.language].end(); ++i) {
......@@ -229,15 +230,13 @@ bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language
return false;
}
}
FinalizePreprocessor();
if (resources) {
IdentifyBuiltIns(parseContext.language, *symbolTable, *resources);
} else {
} else {
IdentifyBuiltIns(parseContext.language, *symbolTable);
}
FinalizePreprocessor();
return true;
}
......@@ -279,6 +278,8 @@ int ShCompile(
TIntermediate intermediate(compiler->infoSink);
TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]);
// Add built-in symbols that are potentially context dependent;
// they get popped again further down.
GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage());
TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink, defaultVersion);
......@@ -286,9 +287,9 @@ int ShCompile(
GlobalParseContext = &parseContext;
setInitialState();
ResetFlex();
InitPreprocessor();
InitPreprocessor();
//
// Parse the application's shaders. All the following symbol table
// work will be throw-away, so push a new allocation scope that can
......
......@@ -87,10 +87,10 @@ void TType::buildMangledName(TString& mangledName)
mangledName += static_cast<char>('0' + getMatrixRows());
}
if (isArray()) {
if (arraySizes) {
const int maxSize = 10;
char buf[maxSize];
sprintf_s(buf, maxSize, "%d", arraySize);
sprintf_s(buf, maxSize, "%d", arraySizes->front());
mangledName += '[';
mangledName += buf;
mangledName += ']';
......
......@@ -861,7 +861,7 @@ void updateExtensionBehavior(const char* extName, const char* behavior)
} // extern "C"
void setInitialState()
void ResetFlex()
{
yy_start = 1;
}
......@@ -64,8 +64,12 @@ TString TType::getCompleteString() const
if (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal)
p += sprintf_s(p, end - p, "%s ", getStorageQualifierString());
if (array)
p += sprintf_s(p, end - p, "array of ");
if (arraySizes) {
if (arraySizes->front() == 0)
p += sprintf_s(p, end - p, "unsized array of ");
else
p += sprintf_s(p, end - p, "%d-element array of ", arraySizes->front());
}
if (qualifier.precision != EpqNone)
p += sprintf_s(p, end - p, "%s ", getPrecisionQualifierString());
if (matrixCols > 0)
......
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