From 1a334f8135d4be7b73b39ac736af0e722c864e83 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Wed, 18 Sep 2013 11:51:20 +0300 Subject: ANGLE: Update to version 2446 Update ANGLE and reapply patches. Patch changes: "Dynamically resolve functions of dwmapi.dll" Removed; ANGLE no longer uses DWM API "Make it possible to link ANGLE statically for single-thread use" Avoid name collision by using ANGLE-style getCurrent() "Fix build when SSE2 is not available." Added guard for __cpuid(), which is not available on ARM "Make DX9/DX11 mutually exclusive" Adjustments due to underlying code changes "ANGLE: Avoid memory copies on buffers when data is null" Removed; fixed upstream "Add missing intrin.h include for __cpuid" Removed; fixed upstream Change-Id: I4f3d850fc555d3194ddc05e0b51c4966d33f7eaf Reviewed-by: Oliver Wolff Reviewed-by: Joerg Bornemann Reviewed-by: Kai Koehne --- src/3rdparty/angle/src/compiler/BaseTypes.h | 8 +- src/3rdparty/angle/src/compiler/Common.h | 42 +- src/3rdparty/angle/src/compiler/Compiler.cpp | 212 +++-- src/3rdparty/angle/src/compiler/ConstantUnion.h | 2 +- .../angle/src/compiler/DetectCallDepth.cpp | 185 ++++ src/3rdparty/angle/src/compiler/DetectCallDepth.h | 80 ++ src/3rdparty/angle/src/compiler/Diagnostics.cpp | 2 +- src/3rdparty/angle/src/compiler/InfoSink.cpp | 25 +- src/3rdparty/angle/src/compiler/InfoSink.h | 8 +- src/3rdparty/angle/src/compiler/Initialize.cpp | 799 ++++++++---------- src/3rdparty/angle/src/compiler/Initialize.h | 16 +- src/3rdparty/angle/src/compiler/InitializeDll.cpp | 89 +- src/3rdparty/angle/src/compiler/InitializeDll.h | 5 +- .../angle/src/compiler/InitializeGLPosition.cpp | 61 ++ .../angle/src/compiler/InitializeGLPosition.h | 33 + .../angle/src/compiler/InitializeGlobals.h | 2 - .../angle/src/compiler/InitializeParseContext.cpp | 78 +- .../angle/src/compiler/InitializeParseContext.h | 15 +- src/3rdparty/angle/src/compiler/Intermediate.cpp | 147 ++-- src/3rdparty/angle/src/compiler/OutputGLSL.cpp | 14 + src/3rdparty/angle/src/compiler/OutputGLSL.h | 1 + src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp | 81 +- src/3rdparty/angle/src/compiler/OutputGLSLBase.h | 3 + src/3rdparty/angle/src/compiler/OutputHLSL.cpp | 324 +++---- src/3rdparty/angle/src/compiler/OutputHLSL.h | 13 +- src/3rdparty/angle/src/compiler/ParseHelper.cpp | 355 +++++--- src/3rdparty/angle/src/compiler/ParseHelper.h | 89 +- src/3rdparty/angle/src/compiler/PoolAlloc.cpp | 68 +- src/3rdparty/angle/src/compiler/PoolAlloc.h | 10 +- src/3rdparty/angle/src/compiler/ShHandle.h | 14 +- src/3rdparty/angle/src/compiler/ShaderLang.cpp | 171 ++-- src/3rdparty/angle/src/compiler/SymbolTable.cpp | 201 ++--- src/3rdparty/angle/src/compiler/SymbolTable.h | 151 ++-- src/3rdparty/angle/src/compiler/Types.h | 240 +++--- .../angle/src/compiler/ValidateLimitations.cpp | 2 +- src/3rdparty/angle/src/compiler/VariableInfo.cpp | 204 +++-- src/3rdparty/angle/src/compiler/VariableInfo.h | 24 +- src/3rdparty/angle/src/compiler/glslang.l | 310 ++++--- src/3rdparty/angle/src/compiler/glslang.y | 935 +++++++++------------ src/3rdparty/angle/src/compiler/intermOut.cpp | 17 +- src/3rdparty/angle/src/compiler/intermediate.h | 33 +- .../angle/src/compiler/localintermediate.h | 45 +- src/3rdparty/angle/src/compiler/parseConst.cpp | 42 +- .../src/compiler/preprocessor/Preprocessor.cpp | 33 +- .../angle/src/compiler/preprocessor/Preprocessor.h | 6 + .../angle/src/compiler/preprocessor/Tokenizer.h | 3 +- .../angle/src/compiler/preprocessor/Tokenizer.l | 12 +- .../compiler/timing/RestrictVertexShaderTiming.cpp | 6 +- src/3rdparty/angle/src/compiler/util.cpp | 39 +- src/3rdparty/angle/src/compiler/util.h | 17 +- 50 files changed, 2569 insertions(+), 2703 deletions(-) create mode 100644 src/3rdparty/angle/src/compiler/DetectCallDepth.cpp create mode 100644 src/3rdparty/angle/src/compiler/DetectCallDepth.h create mode 100644 src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp create mode 100644 src/3rdparty/angle/src/compiler/InitializeGLPosition.h (limited to 'src/3rdparty/angle/src/compiler') diff --git a/src/3rdparty/angle/src/compiler/BaseTypes.h b/src/3rdparty/angle/src/compiler/BaseTypes.h index af4c7e3ed9..1631f4f779 100644 --- a/src/3rdparty/angle/src/compiler/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/BaseTypes.h @@ -90,10 +90,6 @@ enum TQualifier EvqInvariantVaryingOut, // vertex shaders only read/write EvqUniform, // Readonly, vertex and fragment - // pack/unpack input and output - EvqInput, - EvqOutput, - // parameters EvqIn, EvqOut, @@ -112,6 +108,7 @@ enum TQualifier // built-ins written by fragment shader EvqFragColor, EvqFragData, + EvqFragDepth, // end of list EvqLast @@ -137,14 +134,13 @@ inline const char* getQualifierString(TQualifier q) case EvqIn: return "in"; break; case EvqOut: return "out"; break; case EvqInOut: return "inout"; break; - case EvqInput: return "input"; break; - case EvqOutput: return "output"; break; case EvqPosition: return "Position"; break; case EvqPointSize: return "PointSize"; break; case EvqFragCoord: return "FragCoord"; break; case EvqFrontFacing: return "FrontFacing"; break; case EvqFragColor: return "FragColor"; break; case EvqFragData: return "FragData"; break; + case EvqFragDepth: return "FragDepth"; break; default: return "unknown qualifier"; } } diff --git a/src/3rdparty/angle/src/compiler/Common.h b/src/3rdparty/angle/src/compiler/Common.h index 27a5598290..46f9440fff 100644 --- a/src/3rdparty/angle/src/compiler/Common.h +++ b/src/3rdparty/angle/src/compiler/Common.h @@ -14,36 +14,24 @@ #include "compiler/PoolAlloc.h" -// We need two pieces of information to report errors/warnings - string and -// line number. We encode these into a single int so that it can be easily -// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store -// line number while the rest store the string number. Since the shaders are -// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE -// can be increased to alleviate this issue. -typedef int TSourceLoc; -const unsigned int SOURCE_LOC_LINE_SIZE = 16; // in bits. -const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1; - -inline TSourceLoc EncodeSourceLoc(int string, int line) { - return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK); -} - -inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) { - if (string) *string = loc >> SOURCE_LOC_LINE_SIZE; - if (line) *line = loc & SOURCE_LOC_LINE_MASK; -} +struct TSourceLoc { + int first_file; + int first_line; + int last_file; + int last_line; +}; // // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // -#define POOL_ALLOCATOR_NEW_DELETE(A) \ - void* operator new(size_t s) { return (A).allocate(s); } \ - void* operator new(size_t, void *_Where) { return (_Where); } \ - void operator delete(void*) { } \ - void operator delete(void *, void *) { } \ - void* operator new[](size_t s) { return (A).allocate(s); } \ - void* operator new[](size_t, void *_Where) { return (_Where); } \ - void operator delete[](void*) { } \ +#define POOL_ALLOCATOR_NEW_DELETE() \ + void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ void operator delete[](void *, void *) { } // @@ -54,7 +42,7 @@ typedef std::basic_string , TStringAllocator> TStri typedef std::basic_ostringstream, TStringAllocator> TStringStream; inline TString* NewPoolTString(const char* s) { - void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString)); return new(memory) TString(s); } diff --git a/src/3rdparty/angle/src/compiler/Compiler.cpp b/src/3rdparty/angle/src/compiler/Compiler.cpp index c8c79e7147..ee64057ac4 100644 --- a/src/3rdparty/angle/src/compiler/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/Compiler.cpp @@ -1,13 +1,14 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "compiler/BuiltInFunctionEmulator.h" -#include "compiler/DetectRecursion.h" +#include "compiler/DetectCallDepth.h" #include "compiler/ForLoopUnroll.h" #include "compiler/Initialize.h" +#include "compiler/InitializeGLPosition.h" #include "compiler/InitializeParseContext.h" #include "compiler/MapLongVariableNames.h" #include "compiler/ParseHelper.h" @@ -27,66 +28,34 @@ bool isWebGLBasedSpec(ShShaderSpec spec) } namespace { -bool InitializeSymbolTable( - const TBuiltInStrings& builtInStrings, - ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources, - TInfoSink& infoSink, TSymbolTable& symbolTable) -{ - TIntermediate intermediate(infoSink); - TExtensionBehavior extBehavior; - InitExtensionBehavior(resources, extBehavior); - // The builtins deliberately don't specify precisions for the function - // arguments and return types. For that reason we don't try to check them. - TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink); - parseContext.fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; - - GlobalParseContext = &parseContext; - - assert(symbolTable.isEmpty()); - // - // Parse the built-ins. This should only happen once per - // language symbol table. - // - // Push the symbol table to give it an initial scope. This - // push should not have a corresponding pop, so that built-ins - // are preserved, and the test for an empty table fails. - // - symbolTable.push(); - - for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i) - { - const char* builtInShaders = i->c_str(); - int builtInLengths = static_cast(i->size()); - if (builtInLengths <= 0) - continue; - - if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0) - { - infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); - return false; - } - } - - IdentifyBuiltIns(type, spec, resources, symbolTable); - - return true; -} - class TScopedPoolAllocator { public: - TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop) - : mAllocator(allocator), mPushPopAllocator(pushPop) { - if (mPushPopAllocator) mAllocator->push(); + TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) { + mAllocator->push(); SetGlobalPoolAllocator(mAllocator); } ~TScopedPoolAllocator() { SetGlobalPoolAllocator(NULL); - if (mPushPopAllocator) mAllocator->pop(); + mAllocator->pop(); } private: TPoolAllocator* mAllocator; - bool mPushPopAllocator; +}; + +class TScopedSymbolTableLevel { +public: + TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) { + ASSERT(mTable->atBuiltInLevel()); + mTable->push(); + } + ~TScopedSymbolTableLevel() { + while (!mTable->atBuiltInLevel()) + mTable->pop(); + } + +private: + TSymbolTable* mTable; }; } // namespace @@ -103,6 +72,9 @@ TShHandleBase::~TShHandleBase() { TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) : shaderType(type), shaderSpec(spec), + maxUniformVectors(0), + maxExpressionComplexity(0), + maxCallStackDepth(0), fragmentPrecisionHigh(false), clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), builtInFunctionEmulator(type) @@ -121,7 +93,10 @@ bool TCompiler::Init(const ShBuiltInResources& resources) maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? resources.MaxVertexUniformVectors : resources.MaxFragmentUniformVectors; - TScopedPoolAllocator scopedAlloc(&allocator, false); + maxExpressionComplexity = resources.MaxExpressionComplexity; + maxCallStackDepth = resources.MaxCallStackDepth; + + SetGlobalPoolAllocator(&allocator); // Generate built-in symbol table. if (!InitBuiltInSymbolTable(resources)) @@ -141,7 +116,7 @@ bool TCompiler::compile(const char* const shaderStrings[], size_t numStrings, int compileOptions) { - TScopedPoolAllocator scopedAlloc(&allocator, true); + TScopedPoolAllocator scopedAlloc(&allocator); clearResults(); if (numStrings == 0) @@ -165,13 +140,11 @@ bool TCompiler::compile(const char* const shaderStrings[], shaderType, shaderSpec, compileOptions, true, sourcePath, infoSink); parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; - GlobalParseContext = &parseContext; + SetGlobalParseContext(&parseContext); // We preserve symbols at the built-in level from compile-to-compile. // Start pushing the user-defined symbols at global level. - symbolTable.push(); - if (!symbolTable.atGlobalLevel()) - infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); + TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable); // Parse shader. bool success = @@ -182,7 +155,7 @@ bool TCompiler::compile(const char* const shaderStrings[], success = intermediate.postProcess(root); if (success) - success = detectRecursion(root); + success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0); if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) success = validateLimitations(root); @@ -205,6 +178,10 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); + // Disallow expressions deemed too complex. + if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY)) + success = limitExpressionComplexity(root); + // Call mapLongVariableNames() before collectAttribsUniforms() so in // collectAttribsUniforms() we already have the mapped symbol names and // we could composite mapped and original variable names. @@ -212,12 +189,18 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL) mapLongVariableNames(root); - if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) { - collectAttribsUniforms(root); + if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) { + InitializeGLPosition initGLPosition; + root->traverse(&initGLPosition); + } + + if (success && (compileOptions & SH_VARIABLES)) { + collectVariables(root); if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) { success = enforcePackingRestrictions(); if (!success) { - infoSink.info.message(EPrefixError, "too many uniforms"); + infoSink.info.prefix(EPrefixError); + infoSink.info << "too many uniforms"; } } } @@ -231,22 +214,58 @@ bool TCompiler::compile(const char* const shaderStrings[], // Cleanup memory. intermediate.remove(parseContext.treeRoot); - // Ensure symbol table is returned to the built-in level, - // throwing away all but the built-ins. - while (!symbolTable.atBuiltInLevel()) - symbolTable.pop(); return success; } -bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources) +bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) { - TBuiltIns builtIns; - compileResources = resources; - builtIns.initialize(shaderType, shaderSpec, resources); - return InitializeSymbolTable(builtIns.getBuiltInStrings(), - shaderType, shaderSpec, resources, infoSink, symbolTable); + + assert(symbolTable.isEmpty()); + symbolTable.push(); + + TPublicType integer; + integer.type = EbtInt; + integer.size = 1; + integer.matrix = false; + integer.array = false; + + TPublicType floatingPoint; + floatingPoint.type = EbtFloat; + floatingPoint.size = 1; + floatingPoint.matrix = false; + floatingPoint.array = false; + + TPublicType sampler; + sampler.size = 1; + sampler.matrix = false; + sampler.array = false; + + switch(shaderType) + { + case SH_FRAGMENT_SHADER: + symbolTable.setDefaultPrecision(integer, EbpMedium); + break; + case SH_VERTEX_SHADER: + symbolTable.setDefaultPrecision(integer, EbpHigh); + symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); + break; + default: assert(false && "Language not supported"); + } + // We set defaults for all the sampler types, even those that are + // only available if an extension exists. + for (int samplerType = EbtGuardSamplerBegin + 1; + samplerType < EbtGuardSamplerEnd; ++samplerType) { + sampler.type = static_cast(samplerType); + symbolTable.setDefaultPrecision(sampler, EbpLow); + } + + InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable); + + IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable); + + return true; } void TCompiler::clearResults() @@ -258,24 +277,31 @@ void TCompiler::clearResults() attribs.clear(); uniforms.clear(); + varyings.clear(); builtInFunctionEmulator.Cleanup(); nameMap.clear(); } -bool TCompiler::detectRecursion(TIntermNode* root) +bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth) { - DetectRecursion detect; + DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); root->traverse(&detect); - switch (detect.detectRecursion()) { - case DetectRecursion::kErrorNone: + switch (detect.detectCallDepth()) { + case DetectCallDepth::kErrorNone: return true; - case DetectRecursion::kErrorMissingMain: - infoSink.info.message(EPrefixError, "Missing main()"); + case DetectCallDepth::kErrorMissingMain: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Missing main()"; + return false; + case DetectCallDepth::kErrorRecursion: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function recursion detected"; return false; - case DetectRecursion::kErrorRecursion: - infoSink.info.message(EPrefixError, "Function recursion detected"); + case DetectCallDepth::kErrorMaxDepthExceeded: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function call stack too deep"; return false; default: UNREACHABLE(); @@ -321,6 +347,28 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) } } +bool TCompiler::limitExpressionComplexity(TIntermNode* root) +{ + TIntermTraverser traverser; + root->traverse(&traverser); + TDependencyGraph graph(root); + + for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); + iter != graph.endUserDefinedFunctionCalls(); + ++iter) + { + TGraphFunctionCall* samplerSymbol = *iter; + TDependencyGraphTraverser graphTraverser; + samplerSymbol->traverse(&graphTraverser); + } + + if (traverser.getMaxDepth() > maxExpressionComplexity) { + infoSink.info << "Expression too complex."; + return false; + } + return true; +} + bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph) { RestrictFragmentShaderTiming restrictor(infoSink.info); @@ -335,9 +383,9 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) return restrictor.numErrors() == 0; } -void TCompiler::collectAttribsUniforms(TIntermNode* root) +void TCompiler::collectVariables(TIntermNode* root) { - CollectAttribsUniforms collect(attribs, uniforms, hashFunction); + CollectVariables collect(attribs, uniforms, varyings, hashFunction); root->traverse(&collect); } diff --git a/src/3rdparty/angle/src/compiler/ConstantUnion.h b/src/3rdparty/angle/src/compiler/ConstantUnion.h index 32af4d38b0..b1e37885f9 100644 --- a/src/3rdparty/angle/src/compiler/ConstantUnion.h +++ b/src/3rdparty/angle/src/compiler/ConstantUnion.h @@ -11,13 +11,13 @@ class ConstantUnion { public: + POOL_ALLOCATOR_NEW_DELETE(); ConstantUnion() { iConst = 0; type = EbtVoid; } - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) void setIConst(int i) {iConst = i; type = EbtInt; } void setFConst(float f) {fConst = f; type = EbtFloat; } void setBConst(bool b) {bConst = b; type = EbtBool; } diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp new file mode 100644 index 0000000000..60df52c715 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp @@ -0,0 +1,185 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/DetectCallDepth.h" +#include "compiler/InfoSink.h" + +DetectCallDepth::FunctionNode::FunctionNode(const TString& fname) + : name(fname), + visit(PreVisit) +{ +} + +const TString& DetectCallDepth::FunctionNode::getName() const +{ + return name; +} + +void DetectCallDepth::FunctionNode::addCallee( + DetectCallDepth::FunctionNode* callee) +{ + for (size_t i = 0; i < callees.size(); ++i) { + if (callees[i] == callee) + return; + } + callees.push_back(callee); +} + +int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth) +{ + ASSERT(visit == PreVisit); + ASSERT(detectCallDepth); + + int maxDepth = depth; + visit = InVisit; + for (size_t i = 0; i < callees.size(); ++i) { + switch (callees[i]->visit) { + case InVisit: + // cycle detected, i.e., recursion detected. + return kInfiniteCallDepth; + case PostVisit: + break; + case PreVisit: { + // Check before we recurse so we don't go too depth + if (detectCallDepth->checkExceedsMaxDepth(depth)) + return depth; + int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1); + // Check after we recurse so we can exit immediately and provide info. + if (detectCallDepth->checkExceedsMaxDepth(callDepth)) { + detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName(); + return callDepth; + } + maxDepth = std::max(callDepth, maxDepth); + break; + } + default: + UNREACHABLE(); + break; + } + } + visit = PostVisit; + return maxDepth; +} + +void DetectCallDepth::FunctionNode::reset() +{ + visit = PreVisit; +} + +DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth) + : TIntermTraverser(true, false, true, false), + currentFunction(NULL), + infoSink(infoSink), + maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth) +{ +} + +DetectCallDepth::~DetectCallDepth() +{ + for (size_t i = 0; i < functions.size(); ++i) + delete functions[i]; +} + +bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node) +{ + switch (node->getOp()) + { + case EOpPrototype: + // Function declaration. + // Don't add FunctionNode here because node->getName() is the + // unmangled function name. + break; + case EOpFunction: { + // Function definition. + if (visit == PreVisit) { + currentFunction = findFunctionByName(node->getName()); + if (currentFunction == NULL) { + currentFunction = new FunctionNode(node->getName()); + functions.push_back(currentFunction); + } + } else if (visit == PostVisit) { + currentFunction = NULL; + } + break; + } + case EOpFunctionCall: { + // Function call. + if (visit == PreVisit) { + FunctionNode* func = findFunctionByName(node->getName()); + if (func == NULL) { + func = new FunctionNode(node->getName()); + functions.push_back(func); + } + if (currentFunction) + currentFunction->addCallee(func); + } + break; + } + default: + break; + } + return true; +} + +bool DetectCallDepth::checkExceedsMaxDepth(int depth) +{ + return depth >= maxDepth; +} + +void DetectCallDepth::resetFunctionNodes() +{ + for (size_t i = 0; i < functions.size(); ++i) { + functions[i]->reset(); + } +} + +DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func) +{ + currentFunction = NULL; + resetFunctionNodes(); + + int maxCallDepth = func->detectCallDepth(this, 1); + + if (maxCallDepth == FunctionNode::kInfiniteCallDepth) + return kErrorRecursion; + + if (maxCallDepth >= maxDepth) + return kErrorMaxDepthExceeded; + + return kErrorNone; +} + +DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth() +{ + if (maxDepth != FunctionNode::kInfiniteCallDepth) { + // Check all functions because the driver may fail on them + // TODO: Before detectingRecursion, strip unused functions. + for (size_t i = 0; i < functions.size(); ++i) { + ErrorCode error = detectCallDepthForFunction(functions[i]); + if (error != kErrorNone) + return error; + } + } else { + FunctionNode* main = findFunctionByName("main("); + if (main == NULL) + return kErrorMissingMain; + + return detectCallDepthForFunction(main); + } + + return kErrorNone; +} + +DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName( + const TString& name) +{ + for (size_t i = 0; i < functions.size(); ++i) { + if (functions[i]->getName() == name) + return functions[i]; + } + return NULL; +} + diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/DetectCallDepth.h new file mode 100644 index 0000000000..89e85f88f6 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/DetectCallDepth.h @@ -0,0 +1,80 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_DETECT_RECURSION_H_ +#define COMPILER_DETECT_RECURSION_H_ + +#include "GLSLANG/ShaderLang.h" + +#include +#include "compiler/intermediate.h" +#include "compiler/VariableInfo.h" + +class TInfoSink; + +// Traverses intermediate tree to detect function recursion. +class DetectCallDepth : public TIntermTraverser { +public: + enum ErrorCode { + kErrorMissingMain, + kErrorRecursion, + kErrorMaxDepthExceeded, + kErrorNone + }; + + DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth); + ~DetectCallDepth(); + + virtual bool visitAggregate(Visit, TIntermAggregate*); + + bool checkExceedsMaxDepth(int depth); + + ErrorCode detectCallDepth(); + +private: + class FunctionNode { + public: + static const int kInfiniteCallDepth = INT_MAX; + + FunctionNode(const TString& fname); + + const TString& getName() const; + + // If a function is already in the callee list, this becomes a no-op. + void addCallee(FunctionNode* callee); + + // Returns kInifinityCallDepth if recursive function calls are detected. + int detectCallDepth(DetectCallDepth* detectCallDepth, int depth); + + // Reset state. + void reset(); + + private: + // mangled function name is unique. + TString name; + + // functions that are directly called by this function. + TVector callees; + + Visit visit; + }; + + ErrorCode detectCallDepthForFunction(FunctionNode* func); + FunctionNode* findFunctionByName(const TString& name); + void resetFunctionNodes(); + + TInfoSink& getInfoSink() { return infoSink; } + + TVector functions; + FunctionNode* currentFunction; + TInfoSink& infoSink; + int maxDepth; + + DetectCallDepth(const DetectCallDepth&); + void operator=(const DetectCallDepth&); +}; + +#endif // COMPILER_DETECT_RECURSION_H_ diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/Diagnostics.cpp index 06f370dbe5..8a38c41a65 100644 --- a/src/3rdparty/angle/src/compiler/Diagnostics.cpp +++ b/src/3rdparty/angle/src/compiler/Diagnostics.cpp @@ -46,7 +46,7 @@ void TDiagnostics::writeInfo(Severity severity, TInfoSinkBase& sink = mInfoSink.info; /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ sink.prefix(prefix); - sink.location(EncodeSourceLoc(loc.file, loc.line)); + sink.location(loc.file, loc.line); sink << "'" << token << "' : " << reason << " " << extra << "\n"; } diff --git a/src/3rdparty/angle/src/compiler/InfoSink.cpp b/src/3rdparty/angle/src/compiler/InfoSink.cpp index ba32f781f5..d20a6c0175 100644 --- a/src/3rdparty/angle/src/compiler/InfoSink.cpp +++ b/src/3rdparty/angle/src/compiler/InfoSink.cpp @@ -6,8 +6,8 @@ #include "compiler/InfoSink.h" -void TInfoSinkBase::prefix(TPrefixType message) { - switch(message) { +void TInfoSinkBase::prefix(TPrefixType p) { + switch(p) { case EPrefixNone: break; case EPrefixWarning: @@ -31,29 +31,24 @@ void TInfoSinkBase::prefix(TPrefixType message) { } } -void TInfoSinkBase::location(TSourceLoc loc) { - int string = 0, line = 0; - DecodeSourceLoc(loc, &string, &line); - +void TInfoSinkBase::location(int file, int line) { TPersistStringStream stream; if (line) - stream << string << ":" << line; + stream << file << ":" << line; else - stream << string << ":? "; + stream << file << ":? "; stream << ": "; sink.append(stream.str()); } -void TInfoSinkBase::message(TPrefixType message, const char* s) { - prefix(message); - sink.append(s); - sink.append("\n"); +void TInfoSinkBase::location(const TSourceLoc& loc) { + location(loc.first_file, loc.first_line); } -void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) { - prefix(message); +void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) { + prefix(p); location(loc); - sink.append(s); + sink.append(m); sink.append("\n"); } diff --git a/src/3rdparty/angle/src/compiler/InfoSink.h b/src/3rdparty/angle/src/compiler/InfoSink.h index e2224e918d..6888838142 100644 --- a/src/3rdparty/angle/src/compiler/InfoSink.h +++ b/src/3rdparty/angle/src/compiler/InfoSink.h @@ -96,10 +96,10 @@ public: const TPersistString& str() const { return sink; } const char* c_str() const { return sink.c_str(); } - void prefix(TPrefixType message); - void location(TSourceLoc loc); - void message(TPrefixType message, const char* s); - void message(TPrefixType message, const char* s, TSourceLoc loc); + void prefix(TPrefixType p); + void location(int file, int line); + void location(const TSourceLoc& loc); + void message(TPrefixType p, const TSourceLoc& loc, const char* m); private: TPersistString sink; diff --git a/src/3rdparty/angle/src/compiler/Initialize.cpp b/src/3rdparty/angle/src/compiler/Initialize.cpp index 97b46f898e..236383d874 100644 --- a/src/3rdparty/angle/src/compiler/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/Initialize.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -14,513 +14,413 @@ #include "compiler/intermediate.h" -//============================================================================ -// -// Prototypes for built-in functions seen by both vertex and fragment shaders. -// -//============================================================================ -static TString BuiltInFunctionsCommon(const ShBuiltInResources& resources) +void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { - TString s; + TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1); + TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2); + TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3); + TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4); + + TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2); + TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3); + TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4); // // Angle and Trigonometric Functions. // - s.append(TString("float radians(float degrees);")); - s.append(TString("vec2 radians(vec2 degrees);")); - s.append(TString("vec3 radians(vec3 degrees);")); - s.append(TString("vec4 radians(vec4 degrees);")); - - s.append(TString("float degrees(float radians);")); - s.append(TString("vec2 degrees(vec2 radians);")); - s.append(TString("vec3 degrees(vec3 radians);")); - s.append(TString("vec4 degrees(vec4 radians);")); - - s.append(TString("float sin(float angle);")); - s.append(TString("vec2 sin(vec2 angle);")); - s.append(TString("vec3 sin(vec3 angle);")); - s.append(TString("vec4 sin(vec4 angle);")); - - s.append(TString("float cos(float angle);")); - s.append(TString("vec2 cos(vec2 angle);")); - s.append(TString("vec3 cos(vec3 angle);")); - s.append(TString("vec4 cos(vec4 angle);")); - - s.append(TString("float tan(float angle);")); - s.append(TString("vec2 tan(vec2 angle);")); - s.append(TString("vec3 tan(vec3 angle);")); - s.append(TString("vec4 tan(vec4 angle);")); - - s.append(TString("float asin(float x);")); - s.append(TString("vec2 asin(vec2 x);")); - s.append(TString("vec3 asin(vec3 x);")); - s.append(TString("vec4 asin(vec4 x);")); - - s.append(TString("float acos(float x);")); - s.append(TString("vec2 acos(vec2 x);")); - s.append(TString("vec3 acos(vec3 x);")); - s.append(TString("vec4 acos(vec4 x);")); - - s.append(TString("float atan(float y, float x);")); - s.append(TString("vec2 atan(vec2 y, vec2 x);")); - s.append(TString("vec3 atan(vec3 y, vec3 x);")); - s.append(TString("vec4 atan(vec4 y, vec4 x);")); - - s.append(TString("float atan(float y_over_x);")); - s.append(TString("vec2 atan(vec2 y_over_x);")); - s.append(TString("vec3 atan(vec3 y_over_x);")); - s.append(TString("vec4 atan(vec4 y_over_x);")); + symbolTable.insertBuiltIn(float1, "radians", float1); + symbolTable.insertBuiltIn(float2, "radians", float2); + symbolTable.insertBuiltIn(float3, "radians", float3); + symbolTable.insertBuiltIn(float4, "radians", float4); + + symbolTable.insertBuiltIn(float1, "degrees", float1); + symbolTable.insertBuiltIn(float2, "degrees", float2); + symbolTable.insertBuiltIn(float3, "degrees", float3); + symbolTable.insertBuiltIn(float4, "degrees", float4); + + symbolTable.insertBuiltIn(float1, "sin", float1); + symbolTable.insertBuiltIn(float2, "sin", float2); + symbolTable.insertBuiltIn(float3, "sin", float3); + symbolTable.insertBuiltIn(float4, "sin", float4); + + symbolTable.insertBuiltIn(float1, "cos", float1); + symbolTable.insertBuiltIn(float2, "cos", float2); + symbolTable.insertBuiltIn(float3, "cos", float3); + symbolTable.insertBuiltIn(float4, "cos", float4); + + symbolTable.insertBuiltIn(float1, "tan", float1); + symbolTable.insertBuiltIn(float2, "tan", float2); + symbolTable.insertBuiltIn(float3, "tan", float3); + symbolTable.insertBuiltIn(float4, "tan", float4); + + symbolTable.insertBuiltIn(float1, "asin", float1); + symbolTable.insertBuiltIn(float2, "asin", float2); + symbolTable.insertBuiltIn(float3, "asin", float3); + symbolTable.insertBuiltIn(float4, "asin", float4); + + symbolTable.insertBuiltIn(float1, "acos", float1); + symbolTable.insertBuiltIn(float2, "acos", float2); + symbolTable.insertBuiltIn(float3, "acos", float3); + symbolTable.insertBuiltIn(float4, "acos", float4); + + symbolTable.insertBuiltIn(float1, "atan", float1, float1); + symbolTable.insertBuiltIn(float2, "atan", float2, float2); + symbolTable.insertBuiltIn(float3, "atan", float3, float3); + symbolTable.insertBuiltIn(float4, "atan", float4, float4); + + symbolTable.insertBuiltIn(float1, "atan", float1); + symbolTable.insertBuiltIn(float2, "atan", float2); + symbolTable.insertBuiltIn(float3, "atan", float3); + symbolTable.insertBuiltIn(float4, "atan", float4); // // Exponential Functions. // - s.append(TString("float pow(float x, float y);")); - s.append(TString("vec2 pow(vec2 x, vec2 y);")); - s.append(TString("vec3 pow(vec3 x, vec3 y);")); - s.append(TString("vec4 pow(vec4 x, vec4 y);")); - - s.append(TString("float exp(float x);")); - s.append(TString("vec2 exp(vec2 x);")); - s.append(TString("vec3 exp(vec3 x);")); - s.append(TString("vec4 exp(vec4 x);")); - - s.append(TString("float log(float x);")); - s.append(TString("vec2 log(vec2 x);")); - s.append(TString("vec3 log(vec3 x);")); - s.append(TString("vec4 log(vec4 x);")); - - s.append(TString("float exp2(float x);")); - s.append(TString("vec2 exp2(vec2 x);")); - s.append(TString("vec3 exp2(vec3 x);")); - s.append(TString("vec4 exp2(vec4 x);")); - - s.append(TString("float log2(float x);")); - s.append(TString("vec2 log2(vec2 x);")); - s.append(TString("vec3 log2(vec3 x);")); - s.append(TString("vec4 log2(vec4 x);")); - - s.append(TString("float sqrt(float x);")); - s.append(TString("vec2 sqrt(vec2 x);")); - s.append(TString("vec3 sqrt(vec3 x);")); - s.append(TString("vec4 sqrt(vec4 x);")); - - s.append(TString("float inversesqrt(float x);")); - s.append(TString("vec2 inversesqrt(vec2 x);")); - s.append(TString("vec3 inversesqrt(vec3 x);")); - s.append(TString("vec4 inversesqrt(vec4 x);")); + symbolTable.insertBuiltIn(float1, "pow", float1, float1); + symbolTable.insertBuiltIn(float2, "pow", float2, float2); + symbolTable.insertBuiltIn(float3, "pow", float3, float3); + symbolTable.insertBuiltIn(float4, "pow", float4, float4); + + symbolTable.insertBuiltIn(float1, "exp", float1); + symbolTable.insertBuiltIn(float2, "exp", float2); + symbolTable.insertBuiltIn(float3, "exp", float3); + symbolTable.insertBuiltIn(float4, "exp", float4); + + symbolTable.insertBuiltIn(float1, "log", float1); + symbolTable.insertBuiltIn(float2, "log", float2); + symbolTable.insertBuiltIn(float3, "log", float3); + symbolTable.insertBuiltIn(float4, "log", float4); + + symbolTable.insertBuiltIn(float1, "exp2", float1); + symbolTable.insertBuiltIn(float2, "exp2", float2); + symbolTable.insertBuiltIn(float3, "exp2", float3); + symbolTable.insertBuiltIn(float4, "exp2", float4); + + symbolTable.insertBuiltIn(float1, "log2", float1); + symbolTable.insertBuiltIn(float2, "log2", float2); + symbolTable.insertBuiltIn(float3, "log2", float3); + symbolTable.insertBuiltIn(float4, "log2", float4); + + symbolTable.insertBuiltIn(float1, "sqrt", float1); + symbolTable.insertBuiltIn(float2, "sqrt", float2); + symbolTable.insertBuiltIn(float3, "sqrt", float3); + symbolTable.insertBuiltIn(float4, "sqrt", float4); + + symbolTable.insertBuiltIn(float1, "inversesqrt", float1); + symbolTable.insertBuiltIn(float2, "inversesqrt", float2); + symbolTable.insertBuiltIn(float3, "inversesqrt", float3); + symbolTable.insertBuiltIn(float4, "inversesqrt", float4); // // Common Functions. // - s.append(TString("float abs(float x);")); - s.append(TString("vec2 abs(vec2 x);")); - s.append(TString("vec3 abs(vec3 x);")); - s.append(TString("vec4 abs(vec4 x);")); - - s.append(TString("float sign(float x);")); - s.append(TString("vec2 sign(vec2 x);")); - s.append(TString("vec3 sign(vec3 x);")); - s.append(TString("vec4 sign(vec4 x);")); - - s.append(TString("float floor(float x);")); - s.append(TString("vec2 floor(vec2 x);")); - s.append(TString("vec3 floor(vec3 x);")); - s.append(TString("vec4 floor(vec4 x);")); - - s.append(TString("float ceil(float x);")); - s.append(TString("vec2 ceil(vec2 x);")); - s.append(TString("vec3 ceil(vec3 x);")); - s.append(TString("vec4 ceil(vec4 x);")); - - s.append(TString("float fract(float x);")); - s.append(TString("vec2 fract(vec2 x);")); - s.append(TString("vec3 fract(vec3 x);")); - s.append(TString("vec4 fract(vec4 x);")); - - s.append(TString("float mod(float x, float y);")); - s.append(TString("vec2 mod(vec2 x, float y);")); - s.append(TString("vec3 mod(vec3 x, float y);")); - s.append(TString("vec4 mod(vec4 x, float y);")); - s.append(TString("vec2 mod(vec2 x, vec2 y);")); - s.append(TString("vec3 mod(vec3 x, vec3 y);")); - s.append(TString("vec4 mod(vec4 x, vec4 y);")); - - s.append(TString("float min(float x, float y);")); - s.append(TString("vec2 min(vec2 x, float y);")); - s.append(TString("vec3 min(vec3 x, float y);")); - s.append(TString("vec4 min(vec4 x, float y);")); - s.append(TString("vec2 min(vec2 x, vec2 y);")); - s.append(TString("vec3 min(vec3 x, vec3 y);")); - s.append(TString("vec4 min(vec4 x, vec4 y);")); - - s.append(TString("float max(float x, float y);")); - s.append(TString("vec2 max(vec2 x, float y);")); - s.append(TString("vec3 max(vec3 x, float y);")); - s.append(TString("vec4 max(vec4 x, float y);")); - s.append(TString("vec2 max(vec2 x, vec2 y);")); - s.append(TString("vec3 max(vec3 x, vec3 y);")); - s.append(TString("vec4 max(vec4 x, vec4 y);")); - - s.append(TString("float clamp(float x, float minVal, float maxVal);")); - s.append(TString("vec2 clamp(vec2 x, float minVal, float maxVal);")); - s.append(TString("vec3 clamp(vec3 x, float minVal, float maxVal);")); - s.append(TString("vec4 clamp(vec4 x, float minVal, float maxVal);")); - s.append(TString("vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);")); - s.append(TString("vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);")); - s.append(TString("vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);")); - - s.append(TString("float mix(float x, float y, float a);")); - s.append(TString("vec2 mix(vec2 x, vec2 y, float a);")); - s.append(TString("vec3 mix(vec3 x, vec3 y, float a);")); - s.append(TString("vec4 mix(vec4 x, vec4 y, float a);")); - s.append(TString("vec2 mix(vec2 x, vec2 y, vec2 a);")); - s.append(TString("vec3 mix(vec3 x, vec3 y, vec3 a);")); - s.append(TString("vec4 mix(vec4 x, vec4 y, vec4 a);")); - - s.append(TString("float step(float edge, float x);")); - s.append(TString("vec2 step(vec2 edge, vec2 x);")); - s.append(TString("vec3 step(vec3 edge, vec3 x);")); - s.append(TString("vec4 step(vec4 edge, vec4 x);")); - s.append(TString("vec2 step(float edge, vec2 x);")); - s.append(TString("vec3 step(float edge, vec3 x);")); - s.append(TString("vec4 step(float edge, vec4 x);")); - - s.append(TString("float smoothstep(float edge0, float edge1, float x);")); - s.append(TString("vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);")); - s.append(TString("vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);")); - s.append(TString("vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);")); - s.append(TString("vec2 smoothstep(float edge0, float edge1, vec2 x);")); - s.append(TString("vec3 smoothstep(float edge0, float edge1, vec3 x);")); - s.append(TString("vec4 smoothstep(float edge0, float edge1, vec4 x);")); + symbolTable.insertBuiltIn(float1, "abs", float1); + symbolTable.insertBuiltIn(float2, "abs", float2); + symbolTable.insertBuiltIn(float3, "abs", float3); + symbolTable.insertBuiltIn(float4, "abs", float4); + + symbolTable.insertBuiltIn(float1, "sign", float1); + symbolTable.insertBuiltIn(float2, "sign", float2); + symbolTable.insertBuiltIn(float3, "sign", float3); + symbolTable.insertBuiltIn(float4, "sign", float4); + + symbolTable.insertBuiltIn(float1, "floor", float1); + symbolTable.insertBuiltIn(float2, "floor", float2); + symbolTable.insertBuiltIn(float3, "floor", float3); + symbolTable.insertBuiltIn(float4, "floor", float4); + + symbolTable.insertBuiltIn(float1, "ceil", float1); + symbolTable.insertBuiltIn(float2, "ceil", float2); + symbolTable.insertBuiltIn(float3, "ceil", float3); + symbolTable.insertBuiltIn(float4, "ceil", float4); + + symbolTable.insertBuiltIn(float1, "fract", float1); + symbolTable.insertBuiltIn(float2, "fract", float2); + symbolTable.insertBuiltIn(float3, "fract", float3); + symbolTable.insertBuiltIn(float4, "fract", float4); + + symbolTable.insertBuiltIn(float1, "mod", float1, float1); + symbolTable.insertBuiltIn(float2, "mod", float2, float1); + symbolTable.insertBuiltIn(float3, "mod", float3, float1); + symbolTable.insertBuiltIn(float4, "mod", float4, float1); + symbolTable.insertBuiltIn(float2, "mod", float2, float2); + symbolTable.insertBuiltIn(float3, "mod", float3, float3); + symbolTable.insertBuiltIn(float4, "mod", float4, float4); + + symbolTable.insertBuiltIn(float1, "min", float1, float1); + symbolTable.insertBuiltIn(float2, "min", float2, float1); + symbolTable.insertBuiltIn(float3, "min", float3, float1); + symbolTable.insertBuiltIn(float4, "min", float4, float1); + symbolTable.insertBuiltIn(float2, "min", float2, float2); + symbolTable.insertBuiltIn(float3, "min", float3, float3); + symbolTable.insertBuiltIn(float4, "min", float4, float4); + + symbolTable.insertBuiltIn(float1, "max", float1, float1); + symbolTable.insertBuiltIn(float2, "max", float2, float1); + symbolTable.insertBuiltIn(float3, "max", float3, float1); + symbolTable.insertBuiltIn(float4, "max", float4, float1); + symbolTable.insertBuiltIn(float2, "max", float2, float2); + symbolTable.insertBuiltIn(float3, "max", float3, float3); + symbolTable.insertBuiltIn(float4, "max", float4, float4); + + symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1); + symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1); + symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1); + symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4); + + symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1); + symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1); + symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1); + symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4); + + symbolTable.insertBuiltIn(float1, "step", float1, float1); + symbolTable.insertBuiltIn(float2, "step", float2, float2); + symbolTable.insertBuiltIn(float3, "step", float3, float3); + symbolTable.insertBuiltIn(float4, "step", float4, float4); + symbolTable.insertBuiltIn(float2, "step", float1, float2); + symbolTable.insertBuiltIn(float3, "step", float1, float3); + symbolTable.insertBuiltIn(float4, "step", float1, float4); + + symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4); + symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2); + symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3); + symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4); // // Geometric Functions. // - s.append(TString("float length(float x);")); - s.append(TString("float length(vec2 x);")); - s.append(TString("float length(vec3 x);")); - s.append(TString("float length(vec4 x);")); - - s.append(TString("float distance(float p0, float p1);")); - s.append(TString("float distance(vec2 p0, vec2 p1);")); - s.append(TString("float distance(vec3 p0, vec3 p1);")); - s.append(TString("float distance(vec4 p0, vec4 p1);")); - - s.append(TString("float dot(float x, float y);")); - s.append(TString("float dot(vec2 x, vec2 y);")); - s.append(TString("float dot(vec3 x, vec3 y);")); - s.append(TString("float dot(vec4 x, vec4 y);")); - - s.append(TString("vec3 cross(vec3 x, vec3 y);")); - s.append(TString("float normalize(float x);")); - s.append(TString("vec2 normalize(vec2 x);")); - s.append(TString("vec3 normalize(vec3 x);")); - s.append(TString("vec4 normalize(vec4 x);")); - - s.append(TString("float faceforward(float N, float I, float Nref);")); - s.append(TString("vec2 faceforward(vec2 N, vec2 I, vec2 Nref);")); - s.append(TString("vec3 faceforward(vec3 N, vec3 I, vec3 Nref);")); - s.append(TString("vec4 faceforward(vec4 N, vec4 I, vec4 Nref);")); - - s.append(TString("float reflect(float I, float N);")); - s.append(TString("vec2 reflect(vec2 I, vec2 N);")); - s.append(TString("vec3 reflect(vec3 I, vec3 N);")); - s.append(TString("vec4 reflect(vec4 I, vec4 N);")); - - s.append(TString("float refract(float I, float N, float eta);")); - s.append(TString("vec2 refract(vec2 I, vec2 N, float eta);")); - s.append(TString("vec3 refract(vec3 I, vec3 N, float eta);")); - s.append(TString("vec4 refract(vec4 I, vec4 N, float eta);")); + symbolTable.insertBuiltIn(float1, "length", float1); + symbolTable.insertBuiltIn(float1, "length", float2); + symbolTable.insertBuiltIn(float1, "length", float3); + symbolTable.insertBuiltIn(float1, "length", float4); + + symbolTable.insertBuiltIn(float1, "distance", float1, float1); + symbolTable.insertBuiltIn(float1, "distance", float2, float2); + symbolTable.insertBuiltIn(float1, "distance", float3, float3); + symbolTable.insertBuiltIn(float1, "distance", float4, float4); + + symbolTable.insertBuiltIn(float1, "dot", float1, float1); + symbolTable.insertBuiltIn(float1, "dot", float2, float2); + symbolTable.insertBuiltIn(float1, "dot", float3, float3); + symbolTable.insertBuiltIn(float1, "dot", float4, float4); + + symbolTable.insertBuiltIn(float3, "cross", float3, float3); + symbolTable.insertBuiltIn(float1, "normalize", float1); + symbolTable.insertBuiltIn(float2, "normalize", float2); + symbolTable.insertBuiltIn(float3, "normalize", float3); + symbolTable.insertBuiltIn(float4, "normalize", float4); + + symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2); + symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3); + symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4); + + symbolTable.insertBuiltIn(float1, "reflect", float1, float1); + symbolTable.insertBuiltIn(float2, "reflect", float2, float2); + symbolTable.insertBuiltIn(float3, "reflect", float3, float3); + symbolTable.insertBuiltIn(float4, "reflect", float4, float4); + + symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1); + symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1); + symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1); + symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1); + + TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true); + TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true); + TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true); // // Matrix Functions. // - s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);")); - s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);")); - s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);")); + symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2); + symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3); + symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4); + + TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1); + TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2); + TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3); + TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4); // // Vector relational functions. // - s.append(TString("bvec2 lessThan(vec2 x, vec2 y);")); - s.append(TString("bvec3 lessThan(vec3 x, vec3 y);")); - s.append(TString("bvec4 lessThan(vec4 x, vec4 y);")); - - s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2); + symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3); + symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4); - s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);")); - s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);")); - s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2); + symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3); + symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4); - s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4); - s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);")); - s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);")); - s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4); - s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2); + symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3); + symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4); - s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);")); - s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);")); - s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2); + symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3); + symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4); - s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4); - s.append(TString("bvec2 equal(vec2 x, vec2 y);")); - s.append(TString("bvec3 equal(vec3 x, vec3 y);")); - s.append(TString("bvec4 equal(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4); - s.append(TString("bvec2 equal(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 equal(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 equal(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "equal", float2, float2); + symbolTable.insertBuiltIn(bool3, "equal", float3, float3); + symbolTable.insertBuiltIn(bool4, "equal", float4, float4); - s.append(TString("bvec2 equal(bvec2 x, bvec2 y);")); - s.append(TString("bvec3 equal(bvec3 x, bvec3 y);")); - s.append(TString("bvec4 equal(bvec4 x, bvec4 y);")); + symbolTable.insertBuiltIn(bool2, "equal", int2, int2); + symbolTable.insertBuiltIn(bool3, "equal", int3, int3); + symbolTable.insertBuiltIn(bool4, "equal", int4, int4); - s.append(TString("bvec2 notEqual(vec2 x, vec2 y);")); - s.append(TString("bvec3 notEqual(vec3 x, vec3 y);")); - s.append(TString("bvec4 notEqual(vec4 x, vec4 y);")); + symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2); + symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3); + symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4); - s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);")); - s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);")); - s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);")); + symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2); + symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4); - s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);")); - s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);")); - s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);")); + symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4); - s.append(TString("bool any(bvec2 x);")); - s.append(TString("bool any(bvec3 x);")); - s.append(TString("bool any(bvec4 x);")); + symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2); + symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3); + symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4); - s.append(TString("bool all(bvec2 x);")); - s.append(TString("bool all(bvec3 x);")); - s.append(TString("bool all(bvec4 x);")); - - s.append(TString("bvec2 not(bvec2 x);")); - s.append(TString("bvec3 not(bvec3 x);")); - s.append(TString("bvec4 not(bvec4 x);")); - - // - // Texture Functions. - // - s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);")); - s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);")); - - if (resources.OES_EGL_image_external) { - s.append(TString("vec4 texture2D(samplerExternalOES sampler, vec2 coord);")); - s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec3 coord);")); - s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec4 coord);")); - } + symbolTable.insertBuiltIn(bool1, "any", bool2); + symbolTable.insertBuiltIn(bool1, "any", bool3); + symbolTable.insertBuiltIn(bool1, "any", bool4); - if (resources.ARB_texture_rectangle) { - s.append(TString("vec4 texture2DRect(sampler2DRect sampler, vec2 coord);")); - s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);")); - s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);")); - } + symbolTable.insertBuiltIn(bool1, "all", bool2); + symbolTable.insertBuiltIn(bool1, "all", bool3); + symbolTable.insertBuiltIn(bool1, "all", bool4); - // - // Noise functions. - // - //s.append(TString("float noise1(float x);")); - //s.append(TString("float noise1(vec2 x);")); - //s.append(TString("float noise1(vec3 x);")); - //s.append(TString("float noise1(vec4 x);")); - - //s.append(TString("vec2 noise2(float x);")); - //s.append(TString("vec2 noise2(vec2 x);")); - //s.append(TString("vec2 noise2(vec3 x);")); - //s.append(TString("vec2 noise2(vec4 x);")); - - //s.append(TString("vec3 noise3(float x);")); - //s.append(TString("vec3 noise3(vec2 x);")); - //s.append(TString("vec3 noise3(vec3 x);")); - //s.append(TString("vec3 noise3(vec4 x);")); - - //s.append(TString("vec4 noise4(float x);")); - //s.append(TString("vec4 noise4(vec2 x);")); - //s.append(TString("vec4 noise4(vec3 x);")); - //s.append(TString("vec4 noise4(vec4 x);")); - - return s; -} + symbolTable.insertBuiltIn(bool2, "not", bool2); + symbolTable.insertBuiltIn(bool3, "not", bool3); + symbolTable.insertBuiltIn(bool4, "not", bool4); -//============================================================================ -// -// Prototypes for built-in functions seen by vertex shaders only. -// -//============================================================================ -static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources) -{ - TString s; + TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1); + TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1); // - // Geometric Functions. + // Texture Functions for GLSL ES 1.0 // - //s.append(TString("vec4 ftransform();")); + symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4); + symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3); - // - // Texture Functions. - // - s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);")); - s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);")); - s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);")); - s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);")); + if (resources.OES_EGL_image_external) + { + TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1); - return s; -} + symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2); + symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3); + symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4); + } -//============================================================================ -// -// Prototypes for built-in functions seen by fragment shaders only. -// -//============================================================================ -static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources) -{ - TString s; + if (resources.ARB_texture_rectangle) + { + TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1); - // - // Texture Functions. - // - s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);")); - s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);")); - s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);")); - - if (resources.OES_standard_derivatives) { - s.append(TString("float dFdx(float p);")); - s.append(TString("vec2 dFdx(vec2 p);")); - s.append(TString("vec3 dFdx(vec3 p);")); - s.append(TString("vec4 dFdx(vec4 p);")); - - s.append(TString("float dFdy(float p);")); - s.append(TString("vec2 dFdy(vec2 p);")); - s.append(TString("vec3 dFdy(vec3 p);")); - s.append(TString("vec4 dFdy(vec4 p);")); - - s.append(TString("float fwidth(float p);")); - s.append(TString("vec2 fwidth(vec2 p);")); - s.append(TString("vec3 fwidth(vec3 p);")); - s.append(TString("vec4 fwidth(vec4 p);")); + symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2); + symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3); + symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4); } - return s; -} + if (type == SH_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1); + symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1); + + if (resources.OES_standard_derivatives) + { + symbolTable.insertBuiltIn(float1, "dFdx", float1); + symbolTable.insertBuiltIn(float2, "dFdx", float2); + symbolTable.insertBuiltIn(float3, "dFdx", float3); + symbolTable.insertBuiltIn(float4, "dFdx", float4); + + symbolTable.insertBuiltIn(float1, "dFdy", float1); + symbolTable.insertBuiltIn(float2, "dFdy", float2); + symbolTable.insertBuiltIn(float3, "dFdy", float3); + symbolTable.insertBuiltIn(float4, "dFdy", float4); + + symbolTable.insertBuiltIn(float1, "fwidth", float1); + symbolTable.insertBuiltIn(float2, "fwidth", float2); + symbolTable.insertBuiltIn(float3, "fwidth", float3); + symbolTable.insertBuiltIn(float4, "fwidth", float4); + } + } -//============================================================================ -// -// Standard uniforms. -// -//============================================================================ -static TString StandardUniforms() -{ - TString s; + if(type == SH_VERTEX_SHADER) + { + symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1); + symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1); + symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1); + symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1); + } // // Depth range in window coordinates // - s.append(TString("struct gl_DepthRangeParameters {")); - s.append(TString(" highp float near;")); // n - s.append(TString(" highp float far;")); // f - s.append(TString(" highp float diff;")); // f - n - s.append(TString("};")); - s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;")); - - return s; -} - -//============================================================================ -// -// Default precision for vertex shaders. -// -//============================================================================ -static TString DefaultPrecisionVertex() -{ - TString s; - - s.append(TString("precision highp int;")); - s.append(TString("precision highp float;")); - - return s; -} - -//============================================================================ -// -// Default precision for fragment shaders. -// -//============================================================================ -static TString DefaultPrecisionFragment() -{ - TString s; + TFieldList *fields = NewPoolTFieldList(); + TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near")); + TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far")); + TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff")); + fields->push_back(near); + fields->push_back(far); + fields->push_back(diff); + TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields); + TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true); + symbolTable.insert(*depthRangeParameters); + TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct)); + depthRange->setQualifier(EvqUniform); + symbolTable.insert(*depthRange); - s.append(TString("precision mediump int;")); - // No default precision for float in fragment shaders - - return s; -} - -//============================================================================ -// -// Implementation dependent built-in constants. -// -//============================================================================ -static TString BuiltInConstants(ShShaderSpec spec, const ShBuiltInResources &resources) -{ - TStringStream s; - - s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";"; - s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";"; - - s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";"; - s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";"; - s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";"; - s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";"; - s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";"; + // + // Implementation dependent built-in constants. + // + symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs); + symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors); + symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors); + symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits); + symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits); + symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits); + symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors); if (spec != SH_CSS_SHADERS_SPEC) - s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";"; - - return s.str(); -} - -void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources& resources) -{ - switch (type) { - case SH_FRAGMENT_SHADER: - builtInStrings.push_back(DefaultPrecisionFragment()); - builtInStrings.push_back(BuiltInFunctionsCommon(resources)); - builtInStrings.push_back(BuiltInFunctionsFragment(resources)); - builtInStrings.push_back(StandardUniforms()); - break; - - case SH_VERTEX_SHADER: - builtInStrings.push_back(DefaultPrecisionVertex()); - builtInStrings.push_back(BuiltInFunctionsCommon(resources)); - builtInStrings.push_back(BuiltInFunctionsVertex(resources)); - builtInStrings.push_back(StandardUniforms()); - break; - - default: assert(false && "Language not supported"); + { + symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers); } - - builtInStrings.push_back(BuiltInConstants(spec, resources)); } void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources& resources, - TSymbolTable& symbolTable) + const ShBuiltInResources &resources, + TSymbolTable &symbolTable) { // // First, insert some special built-in variables that are not in @@ -539,6 +439,10 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, if (spec != SH_CSS_SHADERS_SPEC) { symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); + if (resources.EXT_frag_depth) { + symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); + symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth"); + } } else { symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true))); @@ -560,8 +464,6 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, // expected to be resolved through a library of functions, versus as // operations. // - symbolTable.relateToOperator("not", EOpVectorLogicalNot); - symbolTable.relateToOperator("matrixCompMult", EOpMul); symbolTable.relateToOperator("equal", EOpVectorEqual); @@ -612,6 +514,7 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, symbolTable.relateToOperator("any", EOpAny); symbolTable.relateToOperator("all", EOpAll); + symbolTable.relateToOperator("not", EOpVectorLogicalNot); // Map language-specific operators. switch(type) { @@ -656,4 +559,6 @@ void InitExtensionBehavior(const ShBuiltInResources& resources, extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined; if (resources.EXT_draw_buffers) extBehavior["GL_EXT_draw_buffers"] = EBhUndefined; + if (resources.EXT_frag_depth) + extBehavior["GL_EXT_frag_depth"] = EBhUndefined; } diff --git a/src/3rdparty/angle/src/compiler/Initialize.h b/src/3rdparty/angle/src/compiler/Initialize.h index 8b0adc6b4c..4aa13466ac 100644 --- a/src/3rdparty/angle/src/compiler/Initialize.h +++ b/src/3rdparty/angle/src/compiler/Initialize.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -11,19 +11,7 @@ #include "compiler/ShHandle.h" #include "compiler/SymbolTable.h" -typedef TVector TBuiltInStrings; - -class TBuiltIns { -public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - - void initialize(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources& resources); - const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; } - -protected: - TBuiltInStrings builtInStrings; -}; +void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources, diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/InitializeDll.cpp index 8763cfeea8..6c7f27fced 100644 --- a/src/3rdparty/angle/src/compiler/InitializeDll.cpp +++ b/src/3rdparty/angle/src/compiler/InitializeDll.cpp @@ -10,25 +10,8 @@ #include "compiler/InitializeParseContext.h" #include "compiler/osinclude.h" -OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX; - bool InitProcess() { - if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) { - // - // Function is re-entrant. - // - return true; - } - - ThreadInitializeIndex = OS_AllocTLSIndex(); - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitProcess(): Failed to allocate TLS area for init flag"); - return false; - } - - if (!InitializePoolIndex()) { assert(0 && "InitProcess(): Failed to initalize global pool"); return false; @@ -39,77 +22,11 @@ bool InitProcess() return false; } - return InitThread(); -} - -bool DetachProcess() -{ - bool success = true; - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) - return true; - - success = DetachThread(); - - if (!FreeParseContextIndex()) - success = false; - - FreePoolIndex(); - - OS_FreeTLSIndex(ThreadInitializeIndex); - ThreadInitializeIndex = OS_INVALID_TLS_INDEX; - - return success; -} - -bool InitThread() -{ - // - // This function is re-entrant - // - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitThread(): Process hasn't been initalised."); - return false; - } - - if (OS_GetTLSValue(ThreadInitializeIndex) != 0) - return true; - - InitializeGlobalPools(); - - if (!InitializeGlobalParseContext()) - return false; - - if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) { - assert(0 && "InitThread(): Unable to set init flag."); - return false; - } - return true; } -bool DetachThread() +void DetachProcess() { - bool success = true; - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) - return true; - - // - // Function is re-entrant and this thread may not have been initalised. - // - if (OS_GetTLSValue(ThreadInitializeIndex) != 0) { - if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) { - assert(0 && "DetachThread(): Unable to clear init flag."); - success = false; - } - - if (!FreeParseContext()) - success = false; - - FreeGlobalPools(); - } - - return success; + FreeParseContextIndex(); + FreePoolIndex(); } - diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.h b/src/3rdparty/angle/src/compiler/InitializeDll.h index 857238eeae..43070cc3ff 100644 --- a/src/3rdparty/angle/src/compiler/InitializeDll.h +++ b/src/3rdparty/angle/src/compiler/InitializeDll.h @@ -7,10 +7,7 @@ #define __INITIALIZEDLL_H bool InitProcess(); -bool DetachProcess(); - -bool InitThread(); -bool DetachThread(); +void DetachProcess(); #endif // __INITIALIZEDLL_H diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp b/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp new file mode 100644 index 0000000000..e0193e39d2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/InitializeGLPosition.h" +#include "compiler/debug.h" + +bool InitializeGLPosition::visitAggregate(Visit visit, TIntermAggregate* node) +{ + bool visitChildren = !mCodeInserted; + switch (node->getOp()) + { + case EOpSequence: break; + case EOpFunction: + { + // Function definition. + ASSERT(visit == PreVisit); + if (node->getName() == "main(") + { + TIntermSequence &sequence = node->getSequence(); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermAggregate *body = NULL; + if (sequence.size() == 1) + { + body = new TIntermAggregate(EOpSequence); + sequence.push_back(body); + } + else + { + body = sequence[1]->getAsAggregate(); + } + ASSERT(body); + insertCode(body->getSequence()); + mCodeInserted = true; + } + break; + } + default: visitChildren = false; break; + } + return visitChildren; +} + +void InitializeGLPosition::insertCode(TIntermSequence& sequence) +{ + TIntermBinary *binary = new TIntermBinary(EOpAssign); + sequence.insert(sequence.begin(), binary); + + TIntermSymbol *left = new TIntermSymbol( + 0, "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4)); + binary->setLeft(left); + + ConstantUnion *u = new ConstantUnion[4]; + for (int ii = 0; ii < 3; ++ii) + u[ii].setFConst(0.0f); + u[3].setFConst(1.0f); + TIntermConstantUnion *right = new TIntermConstantUnion( + u, TType(EbtFloat, EbpUndefined, EvqConst, 4)); + binary->setRight(right); +} diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.h b/src/3rdparty/angle/src/compiler/InitializeGLPosition.h new file mode 100644 index 0000000000..1b11075a13 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/InitializeGLPosition.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_INITIALIZE_GL_POSITION_H_ +#define COMPILER_INITIALIZE_GL_POSITION_H_ + +#include "compiler/intermediate.h" + +class InitializeGLPosition : public TIntermTraverser +{ +public: + InitializeGLPosition() : mCodeInserted(false) { } + +protected: + virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; } + virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; } + virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; } + virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; } + virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; } + + virtual bool visitAggregate(Visit visit, TIntermAggregate* node); + +private: + // Insert AST node in the beginning of main() for "gl_Position = vec4(0.0, 0.0, 0.0, 1.0);". + void insertCode(TIntermSequence& sequence); + + bool mCodeInserted; +}; + +#endif // COMPILER_INITIALIZE_GL_POSITION_H_ diff --git a/src/3rdparty/angle/src/compiler/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/InitializeGlobals.h index 842a45281d..0715941424 100644 --- a/src/3rdparty/angle/src/compiler/InitializeGlobals.h +++ b/src/3rdparty/angle/src/compiler/InitializeGlobals.h @@ -7,8 +7,6 @@ #ifndef __INITIALIZE_GLOBALS_INCLUDED_ #define __INITIALIZE_GLOBALS_INCLUDED_ -void InitializeGlobalPools(); -void FreeGlobalPools(); bool InitializePoolIndex(); void FreePoolIndex(); diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp index 1f40cf5800..dfab027330 100644 --- a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp @@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; bool InitializeParseContextIndex() { - if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } + assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); - // - // Allocate a TLS index. - // GlobalParseContextIndex = OS_AllocTLSIndex(); - - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } - - return true; + return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; } -bool FreeParseContextIndex() +void FreeParseContextIndex() { - OS_TLSIndex tlsiIndex = GlobalParseContextIndex; - - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "FreeParseContextIndex(): Parse Context index not initalized"); - return false; - } + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + OS_FreeTLSIndex(GlobalParseContextIndex); GlobalParseContextIndex = OS_INVALID_TLS_INDEX; - - return OS_FreeTLSIndex(tlsiIndex); -} - -bool InitializeGlobalParseContext() -{ - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized"); - return false; - } - - TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext != 0) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } - - TThreadParseContext *lpThreadData = new TThreadParseContext(); - if (lpThreadData == 0) { - assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context"); - return false; - } - - lpThreadData->lpGlobalParseContext = 0; - OS_SetTLSValue(GlobalParseContextIndex, lpThreadData); - - return true; } -bool FreeParseContext() +void SetGlobalParseContext(TParseContext* context) { - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "FreeParseContext(): Parse Context index not initalized"); - return false; - } - - TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext) - delete lpParseContext; - - return true; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(GlobalParseContextIndex, context); } -TParseContextPointer& GetGlobalParseContext() +TParseContext* GetGlobalParseContext() { - // - // Minimal error checking for speed - // - - TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); - - return lpParseContext->lpGlobalParseContext; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + return static_cast(OS_GetTLSValue(GlobalParseContextIndex)); } diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/InitializeParseContext.h index aa53b735d4..bffbab87d0 100644 --- a/src/3rdparty/angle/src/compiler/InitializeParseContext.h +++ b/src/3rdparty/angle/src/compiler/InitializeParseContext.h @@ -8,19 +8,10 @@ #define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ bool InitializeParseContextIndex(); -bool FreeParseContextIndex(); - -bool InitializeGlobalParseContext(); -bool FreeParseContext(); +void FreeParseContextIndex(); struct TParseContext; -typedef TParseContext* TParseContextPointer; -extern TParseContextPointer& GetGlobalParseContext(); -#define GlobalParseContext GetGlobalParseContext() - -typedef struct TThreadParseContextRec -{ - TParseContext *lpGlobalParseContext; -} TThreadParseContext; +extern void SetGlobalParseContext(TParseContext* context); +extern TParseContext* GetGlobalParseContext(); #endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/Intermediate.cpp b/src/3rdparty/angle/src/compiler/Intermediate.cpp index edf279ef67..3b6622185d 100644 --- a/src/3rdparty/angle/src/compiler/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/Intermediate.cpp @@ -131,7 +131,7 @@ const char* getOperatorString(TOperator op) { // // Returns the added node. // -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line) +TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line) { TIntermSymbol* node = new TIntermSymbol(id, name, type); node->setLine(line); @@ -144,7 +144,7 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType // // Returns the added node. // -TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable) +TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable) { switch (op) { case EOpEqual: @@ -200,8 +200,6 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // one and promote it to the right type. // TIntermBinary* node = new TIntermBinary(op); - if (line == 0) - line = right->getLine(); node->setLine(line); node->setLeft(left); @@ -230,15 +228,13 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // // Returns the added node. // -TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line) +TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) { // // Like adding binary math, except the conversion can only go // from right to left. // TIntermBinary* node = new TIntermBinary(op); - if (line == 0) - line = left->getLine(); node->setLine(line); TIntermTyped* child = addConversion(op, left->getType(), right); @@ -260,11 +256,9 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm // Returns the added node. // The caller should set the type of the returned node. // -TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line) +TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line) { TIntermBinary* node = new TIntermBinary(op); - if (line == 0) - line = index->getLine(); node->setLine(line); node->setLeft(base); node->setRight(index); @@ -279,13 +273,13 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT // // Returns the added node. // -TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable) +TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable) { TIntermUnary* node; TIntermTyped* child = childNode->getAsTyped(); if (child == 0) { - infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); + infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath"); return 0; } @@ -348,8 +342,6 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, // Make a new node for the operator. // node = new TIntermUnary(op); - if (line == 0) - line = child->getLine(); node->setLine(line); node->setOperand(child); @@ -376,7 +368,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, // Returns an aggregate node, which could be the one passed in if // it was already an aggregate but no operator was set. // -TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line) +TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line) { TIntermAggregate* aggNode; @@ -391,8 +383,6 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat // aggNode = new TIntermAggregate(); aggNode->getSequence().push_back(node); - if (line == 0) - line = node->getLine(); } } else aggNode = new TIntermAggregate(); @@ -401,8 +391,7 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat // Set the operator. // aggNode->setOp(op); - if (line != 0) - aggNode->setLine(line); + aggNode->setLine(line); return aggNode; } @@ -491,7 +480,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EbtInt: newOp = EOpConvIntToFloat; break; case EbtBool: newOp = EOpConvBoolToFloat; break; default: - infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); return 0; } break; @@ -500,7 +489,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EbtInt: newOp = EOpConvIntToBool; break; case EbtFloat: newOp = EOpConvFloatToBool; break; default: - infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); return 0; } break; @@ -509,12 +498,12 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt case EbtBool: newOp = EOpConvBoolToInt; break; case EbtFloat: newOp = EOpConvFloatToInt; break; default: - infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); return 0; } break; default: - infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type"); return 0; } @@ -534,7 +523,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt // Returns the resulting aggregate, unless 0 was passed in for // both existing nodes. // -TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line) +TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line) { if (left == 0 && right == 0) return 0; @@ -551,8 +540,7 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r if (right) aggNode->getSequence().push_back(right); - if (line != 0) - aggNode->setLine(line); + aggNode->setLine(line); return aggNode; } @@ -562,18 +550,14 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r // // Returns an aggregate, unless 0 was passed in for the existing node. // -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line) +TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line) { if (node == 0) return 0; TIntermAggregate* aggNode = new TIntermAggregate; aggNode->getSequence().push_back(node); - - if (line != 0) - aggNode->setLine(line); - else - aggNode->setLine(node->getLine()); + aggNode->setLine(line); return aggNode; } @@ -585,7 +569,7 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc lin // // Returns the selection node created. // -TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line) +TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line) { // // For compile time constant selections, prune the code and @@ -606,7 +590,7 @@ TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nod } -TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line) +TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) { if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { return right; @@ -626,7 +610,7 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T // // Returns the selection node created, or 0 if one could not be. // -TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line) +TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line) { // // Get compatible types. @@ -669,7 +653,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // Returns the constant union node created. // -TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line) +TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line) { TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); node->setLine(line); @@ -677,7 +661,7 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayP return node; } -TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line) +TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line) { TIntermAggregate* node = new TIntermAggregate(EOpSequence); @@ -700,7 +684,7 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line) // // Create loop nodes. // -TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line) +TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line) { TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); node->setLine(line); @@ -711,12 +695,12 @@ TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTy // // Add branches. // -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line) +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line) { return addBranch(branchOp, 0, line); } -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line) +TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line) { TIntermBranch* node = new TIntermBranch(branchOp, expression); node->setLine(line); @@ -861,7 +845,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) { // This function only handles scalars, vectors, and matrices. if (left->isArray() || right->isArray()) { - infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays"); return false; } @@ -966,7 +950,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); } } else { - infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); return false; } break; @@ -995,7 +979,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); } } else { - infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); return false; } break; @@ -1035,23 +1019,22 @@ bool TIntermBinary::promote(TInfoSink& infoSink) bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) { - const TTypeList* fields = leftNodeType.getStruct(); + const TFieldList& fields = leftNodeType.getStruct()->fields(); - size_t structSize = fields->size(); - int index = 0; + size_t structSize = fields.size(); + size_t index = 0; for (size_t j = 0; j < structSize; j++) { - int size = (*fields)[j].type->getObjectSize(); - for (int i = 0; i < size; i++) { - if ((*fields)[j].type->getBasicType() == EbtStruct) { - if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index])) + size_t size = fields[j]->type()->getObjectSize(); + for (size_t i = 0; i < size; i++) { + if (fields[j]->type()->getBasicType() == EbtStruct) { + if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index])) return false; } else { if (leftUnionArray[index] != rightUnionArray[index]) return false; index++; } - } } return true; @@ -1063,10 +1046,10 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, TType typeWithoutArrayness = leftNodeType; typeWithoutArrayness.clearArrayness(); - int arraySize = leftNodeType.getArraySize(); + size_t arraySize = leftNodeType.getArraySize(); - for (int i = 0; i < arraySize; ++i) { - int offset = typeWithoutArrayness.getObjectSize() * i; + for (size_t i = 0; i < arraySize; ++i) { + size_t offset = typeWithoutArrayness.getObjectSize() * i; if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) return false; } @@ -1086,7 +1069,7 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) { ConstantUnion *unionArray = getUnionArrayPointer(); - int objectSize = getType().getObjectSize(); + size_t objectSize = getType().getObjectSize(); if (constantNode) { // binary operations TIntermConstantUnion *node = constantNode->getAsConstantUnion(); @@ -1096,13 +1079,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod // for a case like float f = 1.2 + vec4(2,3,4,5); if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) { rightUnionArray = new ConstantUnion[objectSize]; - for (int i = 0; i < objectSize; ++i) + for (size_t i = 0; i < objectSize; ++i) rightUnionArray[i] = *node->getUnionArrayPointer(); returnType = getType(); } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) { // for a case like float f = vec4(2,3,4,5) + 1.2; unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; - for (int i = 0; i < constantNode->getType().getObjectSize(); ++i) + for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) unionArray[i] = *getUnionArrayPointer(); returnType = node->getType(); objectSize = constantNode->getType().getObjectSize(); @@ -1116,14 +1099,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpAdd: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] + rightUnionArray[i]; } break; case EOpSub: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] - rightUnionArray[i]; } break; @@ -1133,13 +1116,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpMatrixTimesScalar: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] * rightUnionArray[i]; } break; case EOpMatrixTimesMatrix: if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply"); return 0; } {// support MSVC++6.0 @@ -1158,11 +1141,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpDiv: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) { + for (size_t i = 0; i < objectSize; i++) { switch (getType().getBasicType()) { case EbtFloat: if (rightUnionArray[i] == 0.0f) { - infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); } else tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); @@ -1170,13 +1153,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EbtInt: if (rightUnionArray[i] == 0) { - infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); tempConstArray[i].setIConst(INT_MAX); } else tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); break; default: - infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\""); return 0; } } @@ -1185,7 +1168,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpMatrixTimesVector: if (node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector"); return 0; } tempConstArray = new ConstantUnion[getNominalSize()]; @@ -1206,7 +1189,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpVectorTimesMatrix: if (getType().getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix"); return 0; } @@ -1224,7 +1207,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] && rightUnionArray[i]; } break; @@ -1232,7 +1215,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpLogicalOr: // this code is written for possible future use, will not get executed currently tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) tempConstArray[i] = unionArray[i] || rightUnionArray[i]; } break; @@ -1240,7 +1223,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EOpLogicalXor: tempConstArray = new ConstantUnion[objectSize]; {// support MSVC++6.0 - for (int i = 0; i < objectSize; i++) + for (size_t i = 0; i < objectSize; i++) switch (getType().getBasicType()) { case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break; default: assert(false && "Default missing"); @@ -1286,7 +1269,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) boolNodeFlag = true; } else { - for (int i = 0; i < objectSize; i++) { + for (size_t i = 0; i < objectSize; i++) { if (unionArray[i] != rightUnionArray[i]) { boolNodeFlag = true; break; // break out of for loop @@ -1312,7 +1295,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) boolNodeFlag = true; } else { - for (int i = 0; i < objectSize; i++) { + for (size_t i = 0; i < objectSize; i++) { if (unionArray[i] == rightUnionArray[i]) { boolNodeFlag = true; break; // break out of for loop @@ -1334,7 +1317,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod return tempNode; default: - infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding"); return 0; } tempNode = new TIntermConstantUnion(tempConstArray, returnType); @@ -1347,14 +1330,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod // TIntermConstantUnion *newNode = 0; ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - for (int i = 0; i < objectSize; i++) { + for (size_t i = 0; i < objectSize; i++) { switch(op) { case EOpNegative: switch (getType().getBasicType()) { case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; default: - infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); return 0; } break; @@ -1362,7 +1345,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod switch (getType().getBasicType()) { case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; default: - infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); return 0; } break; @@ -1378,11 +1361,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) { - int size = node->getType().getObjectSize(); + size_t size = node->getType().getObjectSize(); ConstantUnion *leftUnionArray = new ConstantUnion[size]; - for (int i=0; i < size; i++) { + for (size_t i = 0; i < size; i++) { switch (promoteTo) { case EbtFloat: @@ -1397,7 +1380,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC leftUnionArray[i].setFConst(static_cast(node->getFConst(i))); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; @@ -1413,7 +1396,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC leftUnionArray[i].setIConst(static_cast(node->getFConst(i))); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; @@ -1429,13 +1412,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; default: - infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); return 0; } diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp index 206f403408..10a451c0d7 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp @@ -19,3 +19,17 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision) { return false; } + +void TOutputGLSL::visitSymbol(TIntermSymbol* node) +{ + TInfoSinkBase& out = objSink(); + + if (node->getSymbol() == "gl_FragDepthEXT") + { + out << "gl_FragDepth"; + } + else + { + TOutputGLSLBase::visitSymbol(node); + } +} diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.h b/src/3rdparty/angle/src/compiler/OutputGLSL.h index 199b6f3e46..fa68ac8103 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.h +++ b/src/3rdparty/angle/src/compiler/OutputGLSL.h @@ -20,6 +20,7 @@ public: protected: virtual bool writeVariablePrecision(TPrecision); + virtual void visitSymbol(TIntermSymbol* node); }; #endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp index 1b9a10deaa..d677c75633 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp @@ -79,25 +79,9 @@ void TOutputGLSLBase::writeVariableType(const TType& type) if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal)) out << type.getQualifierString() << " "; // Declare the struct if we have not done so already. - if ((type.getBasicType() == EbtStruct) && - (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end())) + if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct())) { - out << "struct " << hashName(type.getTypeName()) << "{\n"; - const TTypeList* structure = type.getStruct(); - ASSERT(structure != NULL); - for (size_t i = 0; i < structure->size(); ++i) - { - const TType* fieldType = (*structure)[i].type; - ASSERT(fieldType != NULL); - if (writeVariablePrecision(fieldType->getPrecision())) - out << " "; - out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName()); - if (fieldType->isArray()) - out << arrayBrackets(*fieldType); - out << ";\n"; - } - out << "}"; - mDeclaredStructs.insert(type.getTypeName()); + declareStruct(type.getStruct()); } else { @@ -138,24 +122,25 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, if (type.getBasicType() == EbtStruct) { - out << hashName(type.getTypeName()) << "("; - const TTypeList* structure = type.getStruct(); - ASSERT(structure != NULL); - for (size_t i = 0; i < structure->size(); ++i) + const TStructure* structure = type.getStruct(); + out << hashName(structure->name()) << "("; + + const TFieldList& fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) { - const TType* fieldType = (*structure)[i].type; + const TType* fieldType = fields[i]->type(); ASSERT(fieldType != NULL); pConstUnion = writeConstantUnion(*fieldType, pConstUnion); - if (i != structure->size() - 1) out << ", "; + if (i != fields.size() - 1) out << ", "; } out << ")"; } else { - int size = type.getObjectSize(); + size_t size = type.getObjectSize(); bool writeType = size > 1; if (writeType) out << getTypeName(type) << "("; - for (int i = 0; i < size; ++i, ++pConstUnion) + for (size_t i = 0; i < size; ++i, ++pConstUnion) { switch (pConstUnion->getType()) { @@ -260,12 +245,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) case EOpIndexDirectStruct: if (visit == InVisit) { + // Here we are writing out "foo.bar", where "foo" is struct + // and "bar" is field. In AST, it is represented as a binary + // node, where left child represents "foo" and right child "bar". + // The node itself represents ".". The struct field "bar" is + // actually stored as an index into TStructure::fields. out << "."; - // TODO(alokp): ASSERT - TString fieldName = node->getType().getFieldName(); + const TStructure* structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); + const TField* field = structure->fields()[index->getIConst(0)]; - const TType& structType = node->getLeft()->getType(); - if (!mSymbolTable.findBuiltIn(structType.getTypeName())) + TString fieldName = field->name(); + if (!mSymbolTable.findBuiltIn(structure->name())) fieldName = hashName(fieldName); out << fieldName; @@ -596,7 +587,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) { const TType& type = node->getType(); ASSERT(type.getBasicType() == EbtStruct); - out << hashName(type.getTypeName()) << "("; + out << hashName(type.getStruct()->name()) << "("; } else if (visit == InVisit) { @@ -765,7 +756,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type) else { if (type.getBasicType() == EbtStruct) - out << hashName(type.getTypeName()); + out << hashName(type.getStruct()->name()); else out << type.getBasicString(); } @@ -798,3 +789,29 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name) return name; return hashName(name); } + +bool TOutputGLSLBase::structDeclared(const TStructure* structure) const +{ + return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end(); +} + +void TOutputGLSLBase::declareStruct(const TStructure* structure) +{ + TInfoSinkBase& out = objSink(); + + out << "struct " << hashName(structure->name()) << "{\n"; + const TFieldList& fields = structure->fields(); + for (size_t i = 0; i < fields.size(); ++i) + { + const TField* field = fields[i]; + if (writeVariablePrecision(field->type()->getPrecision())) + out << " "; + out << getTypeName(*field->type()) << " " << hashName(field->name()); + if (field->type()->isArray()) + out << arrayBrackets(*field->type()); + out << ";\n"; + } + out << "}"; + + mDeclaredStructs.insert(structure->name()); +} diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h index c9f72d5631..df4ad68c2c 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h @@ -52,6 +52,9 @@ protected: TString hashFunctionName(const TString& mangled_name); private: + bool structDeclared(const TStructure* structure) const; + void declareStruct(const TStructure* structure); + TInfoSinkBase& mObjSink; bool mDeclaringVariables; diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp index f6a984148b..79a373ebab 100644 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp @@ -55,6 +55,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mUsesPointCoord = false; mUsesFrontFacing = false; mUsesPointSize = false; + mUsesFragDepth = false; mUsesXor = false; mUsesMod1 = false; mUsesMod2v = false; @@ -67,18 +68,6 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mUsesFaceforward2 = false; mUsesFaceforward3 = false; mUsesFaceforward4 = false; - mUsesEqualMat2 = false; - mUsesEqualMat3 = false; - mUsesEqualMat4 = false; - mUsesEqualVec2 = false; - mUsesEqualVec3 = false; - mUsesEqualVec4 = false; - mUsesEqualIVec2 = false; - mUsesEqualIVec3 = false; - mUsesEqualIVec4 = false; - mUsesEqualBVec2 = false; - mUsesEqualBVec3 = false; - mUsesEqualBVec4 = false; mUsesAtan2_1 = false; mUsesAtan2_2 = false; mUsesAtan2_3 = false; @@ -210,9 +199,9 @@ void OutputHLSL::header() if (shaderType == SH_FRAGMENT_SHADER) { TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); - bool usingMRTExtension = iter != mContext.extensionBehavior().end() && iter->second == EBhEnable; + const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); - unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; + const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; out << "// Varyings\n"; out << varyings; @@ -230,6 +219,11 @@ void OutputHLSL::header() } out << "};\n"; + if (mUsesFragDepth) + { + out << "static float gl_Depth = 0.0;\n"; + } + if (mUsesFragCoord) { out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n"; @@ -844,6 +838,16 @@ void OutputHLSL::header() out << "#define GL_USES_POINT_SIZE\n"; } + if (mUsesFragDepth) + { + out << "#define GL_USES_FRAG_DEPTH\n"; + } + + if (mUsesDepthRange) + { + out << "#define GL_USES_DEPTH_RANGE\n"; + } + if (mUsesXor) { out << "bool xor(bool p, bool q)\n" @@ -980,108 +984,6 @@ void OutputHLSL::header() "\n"; } - if (mUsesEqualMat2) - { - out << "bool equal(float2x2 m, float2x2 n)\n" - "{\n" - " return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n" - " m[1][0] == n[1][0] && m[1][1] == n[1][1];\n" - "}\n"; - } - - if (mUsesEqualMat3) - { - out << "bool equal(float3x3 m, float3x3 n)\n" - "{\n" - " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n" - " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n" - " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n" - "}\n"; - } - - if (mUsesEqualMat4) - { - out << "bool equal(float4x4 m, float4x4 n)\n" - "{\n" - " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n" - " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n" - " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n" - " m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n" - "}\n"; - } - - if (mUsesEqualVec2) - { - out << "bool equal(float2 v, float2 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y;\n" - "}\n"; - } - - if (mUsesEqualVec3) - { - out << "bool equal(float3 v, float3 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z;\n" - "}\n"; - } - - if (mUsesEqualVec4) - { - out << "bool equal(float4 v, float4 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" - "}\n"; - } - - if (mUsesEqualIVec2) - { - out << "bool equal(int2 v, int2 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y;\n" - "}\n"; - } - - if (mUsesEqualIVec3) - { - out << "bool equal(int3 v, int3 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z;\n" - "}\n"; - } - - if (mUsesEqualIVec4) - { - out << "bool equal(int4 v, int4 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" - "}\n"; - } - - if (mUsesEqualBVec2) - { - out << "bool equal(bool2 v, bool2 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y;\n" - "}\n"; - } - - if (mUsesEqualBVec3) - { - out << "bool equal(bool3 v, bool3 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z;\n" - "}\n"; - } - - if (mUsesEqualBVec4) - { - out << "bool equal(bool4 v, bool4 u)\n" - "{\n" - " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n" - "}\n"; - } - if (mUsesAtan2_1) { out << "float atanyx(float y, float x)\n" @@ -1166,6 +1068,11 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mUsesPointSize = true; out << name; } + else if (name == "gl_FragDepthEXT") + { + mUsesFragDepth = true; + out << "gl_Depth"; + } else { TQualifier qualifier = node->getQualifier(); @@ -1275,7 +1182,10 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) case EOpIndexDirectStruct: if (visit == InVisit) { - out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType()); + const TStructure* structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); + const TField* field = structure->fields()[index->getIConst(0)]; + out << "." + decorateField(field->name(), node->getLeft()->getType()); return false; } @@ -1344,18 +1254,18 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) out << "!("; } - const TTypeList *fields = node->getLeft()->getType().getStruct(); + const TFieldList &fields = node->getLeft()->getType().getStruct()->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 TField *field = fields[i]; node->getLeft()->traverse(this); - out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == "; + out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == "; node->getRight()->traverse(this); - out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()); + out << "." + decorateField(field->name(), node->getLeft()->getType()); - if (i < fields->size() - 1) + if (i < fields.size() - 1) { out << " && "; } @@ -1367,59 +1277,15 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) } else { - if (node->getLeft()->isMatrix()) - { - switch (node->getLeft()->getNominalSize()) - { - case 2: mUsesEqualMat2 = true; break; - case 3: mUsesEqualMat3 = true; break; - case 4: mUsesEqualMat4 = true; break; - default: UNREACHABLE(); - } - } - else if (node->getLeft()->isVector()) - { - switch (node->getLeft()->getBasicType()) - { - case EbtFloat: - switch (node->getLeft()->getNominalSize()) - { - case 2: mUsesEqualVec2 = true; break; - case 3: mUsesEqualVec3 = true; break; - case 4: mUsesEqualVec4 = true; break; - default: UNREACHABLE(); - } - break; - case EbtInt: - switch (node->getLeft()->getNominalSize()) - { - case 2: mUsesEqualIVec2 = true; break; - case 3: mUsesEqualIVec3 = true; break; - case 4: mUsesEqualIVec4 = true; break; - default: UNREACHABLE(); - } - break; - case EbtBool: - switch (node->getLeft()->getNominalSize()) - { - case 2: mUsesEqualBVec2 = true; break; - case 3: mUsesEqualBVec3 = true; break; - case 4: mUsesEqualBVec4 = true; break; - default: UNREACHABLE(); - } - break; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); + ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector()); if (node->getOp() == EOpEqual) { - outputTriplet(visit, "equal(", ", ", ")"); + outputTriplet(visit, "all(", " == ", ")"); } else { - outputTriplet(visit, "!equal(", ", ", ")"); + outputTriplet(visit, "!all(", " == ", ")"); } } break; @@ -1561,7 +1427,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { if (mInsideFunction) { - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; mScopeDepth++; @@ -1578,7 +1444,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) { - outputLineDirective((*sit)->getLine()); + outputLineDirective((*sit)->getLine().first_line); traverseStatements(*sit); @@ -1587,7 +1453,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (mInsideFunction) { - outputLineDirective(node->getEndLine()); + outputLineDirective(node->getLine().last_line); out << "}\n"; mScopeDepth--; @@ -1605,7 +1471,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { if (variable->getType().getStruct()) { - addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL); + addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL); } if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration @@ -1732,7 +1598,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { if (symbol->getType().getStruct()) { - addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL); + addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL); } out << argumentString(symbol); @@ -1993,8 +1859,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) outputTriplet(visit, "mat4(", ", ", ")"); break; case EOpConstructStruct: - addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence()); - outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")"); + addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence()); + outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")"); break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; @@ -2084,7 +1950,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) out << ")\n"; - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; if (node->getTrueBlock()) @@ -2092,20 +1958,20 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) traverseStatements(node->getTrueBlock()); } - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << ";\n}\n"; if (node->getFalseBlock()) { out << "else\n"; - outputLineDirective(node->getFalseBlock()->getLine()); + outputLineDirective(node->getFalseBlock()->getLine().first_line); out << "{\n"; - outputLineDirective(node->getFalseBlock()->getLine()); + outputLineDirective(node->getFalseBlock()->getLine().first_line); traverseStatements(node->getFalseBlock()); - outputLineDirective(node->getFalseBlock()->getLine()); + outputLineDirective(node->getFalseBlock()->getLine().first_line); out << ";\n}\n"; } } @@ -2141,7 +2007,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) { out << "{do\n"; - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; } else @@ -2169,7 +2035,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) out << ")\n"; - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; } @@ -2178,12 +2044,12 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) traverseStatements(node->getBody()); } - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << ";}\n"; if (node->getType() == ELoopDoWhile) { - outputLineDirective(node->getCondition()->getLine()); + outputLineDirective(node->getCondition()->getLine().first_line); out << "while(\n"; node->getCondition()->traverse(this); @@ -2455,7 +2321,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) out << increment; out << ")\n"; - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << "{\n"; if (node->getBody()) @@ -2463,7 +2329,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) node->getBody()->traverse(this); } - outputLineDirective(node->getLine()); + outputLineDirective(node->getLine().first_line); out << ";}\n"; if (!firstLoopFragment) @@ -2565,22 +2431,23 @@ TString OutputHLSL::typeString(const TType &type) { if (type.getBasicType() == EbtStruct) { - if (type.getTypeName() != "") + const TString& typeName = type.getStruct()->name(); + if (typeName != "") { - return structLookup(type.getTypeName()); + return structLookup(typeName); } else // Nameless structure, define in place { - const TTypeList &fields = *type.getStruct(); + const TFieldList &fields = type.getStruct()->fields(); TString string = "struct\n" "{\n"; for (unsigned int i = 0; i < fields.size(); i++) { - const TType &field = *fields[i].type; + const TField *field = fields[i]; - string += " " + typeString(field) + " " + decorate(field.getFieldName()) + arrayString(field) + ";\n"; + string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n"; } string += "} "; @@ -2674,11 +2541,12 @@ TString OutputHLSL::initializer(const TType &type) { TString string; - for (int component = 0; component < type.getObjectSize(); component++) + size_t size = type.getObjectSize(); + for (size_t component = 0; component < size; component++) { string += "0"; - if (component < type.getObjectSize() - 1) + if (component + 1 < size) { string += ", "; } @@ -2717,13 +2585,13 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI structure += "struct " + decorate(name) + "\n" "{\n"; - const TTypeList &fields = *type.getStruct(); + const TFieldList &fields = type.getStruct()->fields(); for (unsigned int i = 0; i < fields.size(); i++) { - const TType &field = *fields[i].type; + const TField *field = fields[i]; - structure += " " + typeString(field) + " " + decorateField(field.getFieldName(), type) + arrayString(field) + ";\n"; + structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n"; } structure += "};\n"; @@ -2735,7 +2603,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI for (unsigned int i = 0; i < fields.size(); i++) { - ctorParameters.push_back(*fields[i].type); + ctorParameters.push_back(*fields[i]->type()); } } else if (parameters) @@ -2828,27 +2696,30 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI } else { - int remainingComponents = ctorType.getObjectSize(); - int parameterIndex = 0; + size_t remainingComponents = ctorType.getObjectSize(); + size_t parameterIndex = 0; while (remainingComponents > 0) { const TType ¶meter = ctorParameters[parameterIndex]; - bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1; + const size_t parameterSize = parameter.getObjectSize(); + bool moreParameters = parameterIndex + 1 < ctorParameters.size(); constructor += "x" + str(parameterIndex); if (parameter.isScalar()) { - remainingComponents -= parameter.getObjectSize(); + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; } else if (parameter.isVector()) { - if (remainingComponents == parameter.getObjectSize() || moreParameters) + if (remainingComponents == parameterSize || moreParameters) { - remainingComponents -= parameter.getObjectSize(); + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; } - else if (remainingComponents < parameter.getNominalSize()) + else if (remainingComponents < static_cast(parameter.getNominalSize())) { switch (remainingComponents) { @@ -2865,9 +2736,10 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI } else if (parameter.isMatrix() || parameter.getStruct()) { - ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters); + ASSERT(remainingComponents == parameterSize || moreParameters); + ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameter.getObjectSize(); + remainingComponents -= parameterSize; } else UNREACHABLE(); @@ -2904,17 +2776,17 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con if (type.getBasicType() == EbtStruct) { - out << structLookup(type.getTypeName()) + "_ctor("; + out << structLookup(type.getStruct()->name()) + "_ctor("; - const TTypeList *structure = type.getStruct(); + const TFieldList &fields = type.getStruct()->fields(); - for (size_t i = 0; i < structure->size(); i++) + for (size_t i = 0; i < fields.size(); i++) { - const TType *fieldType = (*structure)[i].type; + const TType *fieldType = fields[i]->type(); constUnion = writeConstantUnion(*fieldType, constUnion); - if (i != structure->size() - 1) + if (i != fields.size() - 1) { out << ", "; } @@ -2924,7 +2796,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con } else { - int size = type.getObjectSize(); + size_t size = type.getObjectSize(); bool writeType = size > 1; if (writeType) @@ -2932,7 +2804,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con out << typeString(type) << "("; } - for (int i = 0; i < size; i++, constUnion++) + for (size_t i = 0; i < size; i++, constUnion++) { switch (constUnion->getType()) { @@ -3021,7 +2893,7 @@ TString OutputHLSL::decorateUniform(const TString &string, const TType &type) TString OutputHLSL::decorateField(const TString &string, const TType &structure) { - if (structure.getTypeName().compare(0, 3, "gl_") != 0) + if (structure.getStruct()->name().compare(0, 3, "gl_") != 0) { return decorate(string); } @@ -3069,7 +2941,7 @@ int OutputHLSL::uniformRegister(TIntermSymbol *uniform) void OutputHLSL::declareUniform(const TType &type, const TString &name, int index) { - const TTypeList *structure = type.getStruct(); + TStructure *structure = type.getStruct(); if (!structure) { @@ -3077,18 +2949,18 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde } else { + const TFieldList &fields = structure->fields(); + if (type.isArray()) { int elementIndex = index; for (int i = 0; i < type.getArraySize(); i++) { - for (size_t j = 0; j < structure->size(); j++) + for (size_t j = 0; j < fields.size(); j++) { - const TType &fieldType = *(*structure)[j].type; - const TString &fieldName = fieldType.getFieldName(); - - const TString uniformName = name + "[" + str(i) + "]." + fieldName; + const TType &fieldType = *fields[j]->type(); + const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name(); declareUniform(fieldType, uniformName, elementIndex); elementIndex += fieldType.totalRegisterCount(); } @@ -3098,12 +2970,10 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde { int fieldIndex = index; - for (size_t i = 0; i < structure->size(); i++) + for (size_t i = 0; i < fields.size(); i++) { - const TType &fieldType = *(*structure)[i].type; - const TString &fieldName = fieldType.getFieldName(); - - const TString uniformName = name + "." + fieldName; + const TType &fieldType = *fields[i]->type(); + const TString uniformName = name + "." + fields[i]->name(); declareUniform(fieldType, uniformName, fieldIndex); fieldIndex += fieldType.totalRegisterCount(); } diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.h b/src/3rdparty/angle/src/compiler/OutputHLSL.h index 749a3461b3..cde4120718 100644 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/OutputHLSL.h @@ -108,6 +108,7 @@ class OutputHLSL : public TIntermTraverser bool mUsesPointCoord; bool mUsesFrontFacing; bool mUsesPointSize; + bool mUsesFragDepth; bool mUsesXor; bool mUsesMod1; bool mUsesMod2v; @@ -120,18 +121,6 @@ class OutputHLSL : public TIntermTraverser bool mUsesFaceforward2; bool mUsesFaceforward3; bool mUsesFaceforward4; - bool mUsesEqualMat2; - bool mUsesEqualMat3; - bool mUsesEqualMat4; - bool mUsesEqualVec2; - bool mUsesEqualVec3; - bool mUsesEqualVec4; - bool mUsesEqualIVec2; - bool mUsesEqualIVec3; - bool mUsesEqualIVec4; - bool mUsesEqualBVec2; - bool mUsesEqualBVec3; - bool mUsesEqualBVec4; bool mUsesAtan2_1; bool mUsesAtan2_2; bool mUsesAtan2_3; diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.cpp b/src/3rdparty/angle/src/compiler/ParseHelper.cpp index 441ff35e00..1f8538e6a4 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.cpp +++ b/src/3rdparty/angle/src/compiler/ParseHelper.cpp @@ -22,7 +22,7 @@ // Look at a '.' field selector string and change it into offsets // for a vector. // -bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line) +bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line) { fields.num = (int) compString.size(); if (fields.num > 4) { @@ -115,7 +115,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV // Look at a '.' field selector string and change it into offsets // for a matrix. // -bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line) +bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line) { fields.wholeRow = false; fields.wholeCol = false; @@ -175,22 +175,24 @@ void TParseContext::recover() // // Used by flex/bison to output all syntax and parsing errors. // -void TParseContext::error(TSourceLoc loc, +void TParseContext::error(const TSourceLoc& loc, const char* reason, const char* token, const char* extraInfo) { pp::SourceLocation srcLoc; - DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line); + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; diagnostics.writeInfo(pp::Diagnostics::ERROR, srcLoc, reason, token, extraInfo); } -void TParseContext::warning(TSourceLoc loc, +void TParseContext::warning(const TSourceLoc& loc, const char* reason, const char* token, const char* extraInfo) { pp::SourceLocation srcLoc; - DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line); + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; diagnostics.writeInfo(pp::Diagnostics::WARNING, srcLoc, reason, token, extraInfo); } @@ -203,7 +205,7 @@ void TParseContext::trace(const char* str) // // Same error message for all places assignments don't work. // -void TParseContext::assignError(int line, const char* op, TString left, TString right) +void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right) { std::stringstream extraInfoStream; extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'"; @@ -214,7 +216,7 @@ void TParseContext::assignError(int line, const char* op, TString left, TString // // Same error message for all places unary operations don't work. // -void TParseContext::unaryOpError(int line, const char* op, TString operand) +void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand) { std::stringstream extraInfoStream; extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand @@ -226,7 +228,7 @@ void TParseContext::unaryOpError(int line, const char* op, TString operand) // // Same error message for all binary operations don't work. // -void TParseContext::binaryOpError(int line, const char* op, TString left, TString right) +void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right) { std::stringstream extraInfoStream; extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left @@ -235,7 +237,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin error(line, " wrong operand types ", op, extraInfo.c_str()); } -bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){ +bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){ if (!checksPrecisionErrors) return false; switch( type ){ @@ -263,7 +265,7 @@ bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicTy // // Returns true if the was an error. // -bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node) +bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node) { TIntermSymbol* symNode = node->getAsSymbolNode(); TIntermBinary* binaryNode = node->getAsBinaryNode(); @@ -317,7 +319,6 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod case EvqAttribute: message = "can't modify an attribute"; break; case EvqUniform: message = "can't modify a uniform"; break; case EvqVaryingIn: message = "can't modify a varying"; break; - case EvqInput: message = "can't modify an input"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break; case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; case EvqPointCoord: message = "can't modify gl_PointCoord"; break; @@ -409,7 +410,7 @@ bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) // // Returns true if the was an error. // -bool TParseContext::globalErrorCheck(int line, bool global, const char* token) +bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token) { if (global) return false; @@ -428,7 +429,7 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token) // // Returns true if there was an error. // -bool TParseContext::reservedErrorCheck(int line, const TString& identifier) +bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier) { static const char* reservedErrMsg = "reserved built-in name"; if (!symbolTable.atBuiltInLevel()) { @@ -466,7 +467,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier) // // Returns true if there was an error in construction. // -bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type) +bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type) { *type = function.getReturnType(); @@ -487,7 +488,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction // again, there is an extra argument, so 'overfull' will become true. // - int size = 0; + size_t size = 0; bool constType = true; bool full = false; bool overFull = false; @@ -534,7 +535,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction return true; } - if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) { + if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) { error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); return true; } @@ -568,7 +569,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction // // returns true in case of an error // -bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType) +bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType) { if (pubType.type == EbtVoid) { error(line, "illegal use of type 'void'", identifier.c_str()); @@ -582,7 +583,7 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP // // returns true in case of an error // -bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) +bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type) { if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { error(line, "boolean expression expected", ""); @@ -596,7 +597,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) // // returns true in case of an error // -bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) +bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType) { if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { error(line, "boolean expression expected", ""); @@ -606,7 +607,7 @@ bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) return false; } -bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason) +bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason) { if (pType.type == EbtStruct) { if (containsSampler(*pType.userDef)) { @@ -625,7 +626,7 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const return false; } -bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType) +bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType) { if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && pType.type == EbtStruct) { @@ -640,7 +641,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType return false; } -bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type) +bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type) { if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { @@ -657,9 +658,9 @@ bool TParseContext::containsSampler(TType& type) return true; if (type.getBasicType() == EbtStruct) { - TTypeList& structure = *type.getStruct(); - for (unsigned int i = 0; i < structure.size(); ++i) { - if (containsSampler(*structure[i].type)) + const TFieldList& fields = type.getStruct()->fields(); + for (unsigned int i = 0; i < fields.size(); ++i) { + if (containsSampler(*fields[i]->type())) return true; } } @@ -672,7 +673,7 @@ bool TParseContext::containsSampler(TType& type) // // Returns true if there was an error. // -bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) +bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size) { TIntermConstantUnion* constant = expr->getAsConstantUnion(); if (constant == 0 || constant->getBasicType() != EbtInt) { @@ -696,7 +697,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) // // Returns true if there is an error. // -bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) +bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) { if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); @@ -711,7 +712,7 @@ bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) // // Returns true if there is an error. // -bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) +bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type) { // // Can the type be an array? @@ -732,7 +733,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) // // Returns true if there was an error. // -bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable) +bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable) { // // Don't check for reserved word use until after we know it's not in the symbol table, @@ -777,16 +778,6 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t return true; } - TType* t = variable->getArrayInformationType(); - while (t != 0) { - if (t->getMaxArraySize() > type.arraySize) { - error(line, "higher index value already used for the array", identifier.c_str()); - return true; - } - t->setArraySize(type.arraySize); - t = t->getArrayInformationType(); - } - if (type.arraySize) variable->getType().setArraySize(type.arraySize); } @@ -797,56 +788,12 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t return false; } -bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line) -{ - bool builtIn = false; - TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn); - if (symbol == 0) { - error(line, " undeclared identifier", node->getSymbol().c_str()); - return true; - } - TVariable* variable = static_cast(symbol); - - type->setArrayInformationType(variable->getArrayInformationType()); - variable->updateArrayInformationType(type); - - // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers - // its an error - if (node->getSymbol() == "gl_FragData") { - TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn); - ASSERT(fragData); - - int fragDataValue = static_cast(fragData)->getConstPointer()[0].getIConst(); - if (fragDataValue <= size) { - error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers"); - return true; - } - } - - // we dont want to update the maxArraySize when this flag is not set, we just want to include this - // node type in the chain of node types so that its updated when a higher maxArraySize comes in. - if (!updateFlag) - return false; - - size++; - variable->getType().setMaxArraySize(size); - type->setMaxArraySize(size); - TType* tt = type; - - while(tt->getArrayInformationType() != 0) { - tt = tt->getArrayInformationType(); - tt->setMaxArraySize(size); - } - - return false; -} - // // Enforce non-initializer type/qualifier rules. // // Returns true if there was an error. // -bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array) +bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array) { if (type.qualifier == EvqConst) { @@ -878,7 +825,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli // // Returns true if there was an error. // -bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable) +bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable) { if (reservedErrorCheck(line, identifier)) recover(); @@ -898,7 +845,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType return false; } -bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type) +bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type) { if (qualifier != EvqConst && qualifier != EvqTemporary) { error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); @@ -917,7 +864,7 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier p return false; } -bool TParseContext::extensionErrorCheck(int line, const TString& extension) +bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension) { const TExtensionBehavior& extBehavior = extensionBehavior(); TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); @@ -945,18 +892,17 @@ bool TParseContext::supportsExtension(const char* extension) return (iter != extbehavior.end()); } -void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior) +bool TParseContext::isExtensionEnabled(const char* extension) const { - pp::SourceLocation loc; - DecodeSourceLoc(line, &loc.file, &loc.line); - directiveHandler.handleExtension(loc, extName, behavior); -} + const TExtensionBehavior& extbehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extbehavior.find(extension); -void TParseContext::handlePragmaDirective(int line, const char* name, const char* value) -{ - pp::SourceLocation loc; - DecodeSourceLoc(line, &loc.file, &loc.line); - directiveHandler.handlePragma(loc, name, value); + if (iter == extbehavior.end()) + { + return false; + } + + return (iter->second == EBhEnable || iter->second == EBhRequire); } ///////////////////////////////////////////////////////////////////////////////// @@ -970,12 +916,13 @@ void TParseContext::handlePragmaDirective(int line, const char* name, const char // // Return the function symbol if found, otherwise 0. // -const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn) +const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn) { // First find by unmangled name to check whether the function name has been // hidden by a variable name or struct typename. + // If a function is found, check for one with a matching argument list. const TSymbol* symbol = symbolTable.find(call->getName(), builtIn); - if (symbol == 0) { + if (symbol == 0 || symbol->isFunction()) { symbol = symbolTable.find(call->getMangledName(), builtIn); } @@ -996,7 +943,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu // Initializers show up in several places in the grammar. Have one set of // code to handle them here. // -bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, +bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { TType type = TType(pType); @@ -1048,13 +995,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu return true; } if (initializer->getAsConstantUnion()) { - ConstantUnion* unionArray = variable->getConstPointer(); - - if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) { - *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0]; - } else { - variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - } + variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); } else if (initializer->getAsSymbolNode()) { const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); const TVariable* tVar = static_cast(symbol); @@ -1108,16 +1049,16 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) // // Returns 0 for an error or the constructed node (aggregate or typed) for no error. // -TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line) +TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) { if (node == 0) return 0; TIntermAggregate* aggrNode = node->getAsAggregate(); - TTypeList::const_iterator memberTypes; + TFieldList::const_iterator memberFields; if (op == EOpConstructStruct) - memberTypes = type->getStruct()->begin(); + memberFields = type->getStruct()->fields().begin(); TType elementType = *type; if (type->isArray()) @@ -1139,7 +1080,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type if (type->isArray()) newNode = constructStruct(node, &elementType, 1, node->getLine(), false); else if (op == EOpConstructStruct) - newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false); + newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false); else newNode = constructBuiltIn(type, op, node, node->getLine(), false); @@ -1170,7 +1111,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type if (type->isArray()) newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); else if (op == EOpConstructStruct) - newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true); + newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true); else newNode = constructBuiltIn(type, op, *p, node->getLine(), true); @@ -1216,7 +1157,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co // // Returns 0 for an error or the constructed node. // -TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset) +TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) { TIntermTyped* newNode; TOperator basicOp; @@ -1278,7 +1219,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T // // Returns 0 for an error or the input node itself if the expected and the given parameter types match. // -TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset) +TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) { if (*type == node->getAsTyped()->getType()) { if (subset) @@ -1305,7 +1246,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of // a constant matrix. // -TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1327,7 +1268,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy ConstantUnion* constArray = new ConstantUnion[fields.num]; for (int i = 0; i < fields.num; i++) { - if (fields.offsets[i] >= node->getType().getObjectSize()) { + if (fields.offsets[i] >= node->getType().getNominalSize()) { std::stringstream extraInfoStream; extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; std::string extraInfo = extraInfoStream.str(); @@ -1349,7 +1290,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) // -TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1384,7 +1325,7 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T // to the function could either be a symbol node (a[0] where a is a constant array)that represents a // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) // -TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1400,9 +1341,8 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS index = 0; } - int arrayElementSize = arrayElementType.getObjectSize(); - if (tempConstantNode) { + size_t arrayElementSize = arrayElementType.getObjectSize(); ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); } else { @@ -1421,22 +1361,21 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr // function and returns the parse-tree with the values of the embedded/nested struct. // -TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line) { - const TTypeList* fields = node->getType().getStruct(); - TIntermTyped *typedNode; - int instanceSize = 0; - unsigned int index = 0; - TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); - - for ( index = 0; index < fields->size(); ++index) { - if ((*fields)[index].type->getFieldName() == identifier) { + const TFieldList& fields = node->getType().getStruct()->fields(); + + size_t instanceSize = 0; + for (size_t index = 0; index < fields.size(); ++index) { + if (fields[index]->name() == identifier) { break; } else { - instanceSize += (*fields)[index].type->getObjectSize(); + instanceSize += fields[index]->type()->getObjectSize(); } } + TIntermTyped* typedNode = 0; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); if (tempConstantNode) { ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); @@ -1451,7 +1390,7 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n return typedNode; } -bool TParseContext::enterStructDeclaration(int line, const TString& identifier) +bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) { ++structNestingLevel; @@ -1477,30 +1416,166 @@ const int kWebGLMaxStructNesting = 4; } // namespace -bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType) +bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) { if (!isWebGLBasedSpec(shaderSpec)) { return false; } - if (fieldType.getBasicType() != EbtStruct) { + if (field.type()->getBasicType() != EbtStruct) { return false; } // We're already inside a structure definition at this point, so add // one to the field's struct nesting. - if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) { - std::stringstream extraInfoStream; - extraInfoStream << "Reference of struct type " << fieldType.getTypeName() - << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "", extraInfo.c_str()); + if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) { + std::stringstream reasonStream; + reasonStream << "Reference of struct type " + << field.type()->getStruct()->name().c_str() + << " exceeds maximum allowed nesting level of " + << kWebGLMaxStructNesting; + std::string reason = reasonStream.str(); + error(line, reason.c_str(), field.name().c_str(), ""); return true; } return false; } +// +// Parse an array index expression +// +TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression) +{ + TIntermTyped *indexedExpression = NULL; + + if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) + { + if (baseExpression->getAsSymbolNode()) + { + error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str()); + } + else + { + error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); + } + recover(); + } + + if (indexExpression->getQualifier() == EvqConst) + { + int index = indexExpression->getAsConstantUnion()->getIConst(0); + if (index < 0) + { + std::stringstream infoStream; + infoStream << index; + std::string info = infoStream.str(); + error(location, "negative index", info.c_str()); + recover(); + index = 0; + } + if (baseExpression->getType().getQualifier() == EvqConst) + { + if (baseExpression->isArray()) + { + // constant folding for arrays + indexedExpression = addConstArrayNode(index, baseExpression, location); + } + else if (baseExpression->isVector()) + { + // constant folding for vectors + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array + indexedExpression = addConstVectorNode(fields, baseExpression, location); + } + else if (baseExpression->isMatrix()) + { + // constant folding for matrices + indexedExpression = addConstMatrixNode(index, baseExpression, location); + } + } + else + { + if (baseExpression->isArray()) + { + if (index >= baseExpression->getType().getArraySize()) + { + std::stringstream extraInfoStream; + extraInfoStream << "array index out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(location, "", "[", extraInfo.c_str()); + recover(); + index = baseExpression->getType().getArraySize() - 1; + } + else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers")) + { + error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled"); + recover(); + index = 0; + } + } + else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index) + { + std::stringstream extraInfoStream; + extraInfoStream << "field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(location, "", "[", extraInfo.c_str()); + recover(); + index = baseExpression->getType().getNominalSize() - 1; + } + + indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); + indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); + } + } + else + { + indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); + } + + if (indexedExpression == 0) + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); + } + else if (baseExpression->isArray()) + { + const TType &baseType = baseExpression->getType(); + if (baseType.getStruct()) + { + TType copyOfType(baseType.getStruct()); + indexedExpression->setType(copyOfType); + } + else + { + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix())); + } + + if (baseExpression->getType().getQualifier() == EvqConst) + { + indexedExpression->getTypePointer()->setQualifier(EvqConst); + } + } + else if (baseExpression->isMatrix()) + { + TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize())); + } + else if (baseExpression->isVector()) + { + TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier)); + } + else + { + indexedExpression->setType(baseExpression->getType()); + } + + return indexedExpression; +} + // // Parse an array of strings using yyparse. // diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.h b/src/3rdparty/angle/src/compiler/ParseHelper.h index 26a3ea1308..c2b3c3f7ec 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.h +++ b/src/3rdparty/angle/src/compiler/ParseHelper.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -33,10 +33,8 @@ struct TParseContext { compileOptions(options), sourcePath(sourcePath), treeRoot(0), - lexAfterType(false), loopNestingLevel(0), structNestingLevel(0), - inTypeParen(false), currentFunctionType(NULL), functionReturnsValue(false), checksPrecisionErrors(checksPrecErrors), @@ -51,16 +49,13 @@ struct TParseContext { int compileOptions; const char* sourcePath; // Path of source file or NULL. TIntermNode* treeRoot; // root of parse tree being created - bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier int loopNestingLevel; // 0 if outside all loops int structNestingLevel; // incremented while parsing a struct declaration - bool inTypeParen; // true if in parentheses, looking only for an identifier const TType* currentFunctionType; // the return type of the function that's currently being parsed bool functionReturnsValue; // true if a non-void function has a return bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language. TString HashErrMsg; - bool AfterEOF; TDiagnostics diagnostics; TDirectiveHandler directiveHandler; pp::Preprocessor preprocessor; @@ -68,71 +63,69 @@ struct TParseContext { int numErrors() const { return diagnostics.numErrors(); } TInfoSink& infoSink() { return diagnostics.infoSink(); } - void error(TSourceLoc loc, const char *reason, const char* token, + void error(const TSourceLoc& loc, const char *reason, const char* token, const char* extraInfo=""); - void warning(TSourceLoc loc, const char* reason, const char* token, + void warning(const TSourceLoc& loc, const char* reason, const char* token, const char* extraInfo=""); void trace(const char* str); void recover(); - bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line); - bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line); + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); + bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line); - bool reservedErrorCheck(int line, const TString& identifier); - void assignError(int line, const char* op, TString left, TString right); - void unaryOpError(int line, const char* op, TString operand); - void binaryOpError(int line, const char* op, TString left, TString right); - bool precisionErrorCheck(int line, TPrecision precision, TBasicType type); - bool lValueErrorCheck(int line, const char* op, TIntermTyped*); + bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier); + void assignError(const TSourceLoc& line, const char* op, TString left, TString right); + void unaryOpError(const TSourceLoc& line, const char* op, TString operand); + void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right); + bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type); + bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*); bool constErrorCheck(TIntermTyped* node); bool integerErrorCheck(TIntermTyped* node, const char* token); - bool globalErrorCheck(int line, bool global, const char* token); - bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*); - bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size); - bool arrayQualifierErrorCheck(int line, TPublicType type); - bool arrayTypeErrorCheck(int line, TPublicType type); - bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable); - bool voidErrorCheck(int, const TString&, const TPublicType&); - bool boolErrorCheck(int, const TIntermTyped*); - bool boolErrorCheck(int, const TPublicType&); - bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason); - bool structQualifierErrorCheck(int line, const TPublicType& pType); - bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type); - bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array); - bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable); - bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type); - bool extensionErrorCheck(int line, const TString&); + bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token); + bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*); + bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size); + bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type); + bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type); + bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable); + bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&); + bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); + bool boolErrorCheck(const TSourceLoc&, const TPublicType&); + bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason); + bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType); + bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type); + bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array); + bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable); + bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type); + bool extensionErrorCheck(const TSourceLoc& line, const TString&); + const TPragma& pragma() const { return directiveHandler.pragma(); } const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } bool supportsExtension(const char* extension); - void handleExtensionDirective(int line, const char* extName, const char* behavior); - - const TPragma& pragma() const { return directiveHandler.pragma(); } - void handlePragmaDirective(int line, const char* name, const char* value); + bool isExtensionEnabled(const char* extension) const; bool containsSampler(TType& type); bool areAllChildConst(TIntermAggregate* aggrNode); - const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0); - bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, + const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0); + bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); - bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc); - TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc); + TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); - TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset); - TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset); - TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc); - TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc); - TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line); - TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc); + TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset); + TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset); + TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line); + TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&); + TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); // Performs an error check for embedded struct declarations. // Returns true if an error was raised due to the declaration of // this struct. - bool enterStructDeclaration(TSourceLoc line, const TString& identifier); + bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier); void exitStructDeclaration(); - bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType); + bool structNestingErrorCheck(const TSourceLoc& line, const TField& field); }; int PaParseStrings(size_t count, const char* const string[], const int length[], diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/PoolAlloc.cpp index 9ef4f59f5c..eb993567b3 100644 --- a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp +++ b/src/3rdparty/angle/src/compiler/PoolAlloc.cpp @@ -17,55 +17,32 @@ OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; -void InitializeGlobalPools() -{ - TThreadGlobalPools* globalPools= static_cast(OS_GetTLSValue(PoolIndex)); - if (globalPools) - return; - - TThreadGlobalPools* threadData = new TThreadGlobalPools(); - threadData->globalPoolAllocator = 0; - - OS_SetTLSValue(PoolIndex, threadData); -} - -void FreeGlobalPools() -{ - // Release the allocated memory for this thread. - TThreadGlobalPools* globalPools= static_cast(OS_GetTLSValue(PoolIndex)); - if (!globalPools) - return; - - delete globalPools; -} - bool InitializePoolIndex() { - // Allocate a TLS index. - if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX) - return false; + assert(PoolIndex == OS_INVALID_TLS_INDEX); - return true; + PoolIndex = OS_AllocTLSIndex(); + return PoolIndex != OS_INVALID_TLS_INDEX; } void FreePoolIndex() { - // Release the TLS index. + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_FreeTLSIndex(PoolIndex); + PoolIndex = OS_INVALID_TLS_INDEX; } -TPoolAllocator& GetGlobalPoolAllocator() +TPoolAllocator* GetGlobalPoolAllocator() { - TThreadGlobalPools* threadData = static_cast(OS_GetTLSValue(PoolIndex)); - - return *threadData->globalPoolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + return static_cast(OS_GetTLSValue(PoolIndex)); } void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { - TThreadGlobalPools* threadData = static_cast(OS_GetTLSValue(PoolIndex)); - - threadData->globalPoolAllocator = poolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(PoolIndex, poolAllocator); } // @@ -228,24 +205,27 @@ void TPoolAllocator::popAll() void* TPoolAllocator::allocate(size_t numBytes) { + // + // Just keep some interesting statistics. + // + ++numCalls; + totalBytes += numBytes; + // If we are using guard blocks, all allocations are bracketed by // them: [guardblock][allocation][guardblock]. numBytes is how // much memory the caller asked for. allocationSize is the total // size including guard blocks. In release build, // guardBlockSize=0 and this all gets optimized away. size_t allocationSize = TAllocation::allocationSize(numBytes); - - // - // Just keep some interesting statistics. - // - ++numCalls; - totalBytes += numBytes; + // Detect integer overflow. + if (allocationSize < numBytes) + return 0; // // Do the allocation, most likely case first, for efficiency. // This step could be moved to be inline sometime. // - if (currentPageOffset + allocationSize <= pageSize) { + if (allocationSize <= pageSize - currentPageOffset) { // // Safe to allocate from currentPageOffset. // @@ -256,12 +236,16 @@ void* TPoolAllocator::allocate(size_t numBytes) return initializeAllocation(inUseList, memory, numBytes); } - if (allocationSize + headerSkip > pageSize) { + if (allocationSize > pageSize - headerSkip) { // // Do a multi-page allocation. Don't mix these with the others. // The OS is efficient and allocating and free-ing multiple pages. // size_t numBytesToAlloc = allocationSize + headerSkip; + // Detect integer overflow. + if (numBytesToAlloc < allocationSize) + return 0; + tHeader* memory = reinterpret_cast(::new char[numBytesToAlloc]); if (memory == 0) return 0; diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.h b/src/3rdparty/angle/src/compiler/PoolAlloc.h index a8a59c69ac..edd249c4d3 100644 --- a/src/3rdparty/angle/src/compiler/PoolAlloc.h +++ b/src/3rdparty/angle/src/compiler/PoolAlloc.h @@ -219,14 +219,8 @@ private: // different times. But a simple use is to have a global pop // with everyone using the same global allocator. // -extern TPoolAllocator& GetGlobalPoolAllocator(); +extern TPoolAllocator* GetGlobalPoolAllocator(); extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); -#define GlobalPoolAllocator GetGlobalPoolAllocator() - -struct TThreadGlobalPools -{ - TPoolAllocator* globalPoolAllocator; -}; // // This STL compatible allocator is intended to be used as the allocator @@ -253,7 +247,7 @@ public: pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } - pool_allocator() : allocator(&GlobalPoolAllocator) { } + pool_allocator() : allocator(GetGlobalPoolAllocator()) { } pool_allocator(TPoolAllocator& a) : allocator(&a) { } pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } diff --git a/src/3rdparty/angle/src/compiler/ShHandle.h b/src/3rdparty/angle/src/compiler/ShHandle.h index 28049305e0..873580a99c 100644 --- a/src/3rdparty/angle/src/compiler/ShHandle.h +++ b/src/3rdparty/angle/src/compiler/ShHandle.h @@ -70,6 +70,7 @@ public: TInfoSink& getInfoSink() { return infoSink; } const TVariableInfoList& getAttribs() const { return attribs; } const TVariableInfoList& getUniforms() const { return uniforms; } + const TVariableInfoList& getVaryings() const { return varyings; } int getMappedNameMaxLength() const; ShHashFunction64 getHashFunction() const { return hashFunction; } @@ -83,15 +84,15 @@ protected: bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); // Clears the results from the previous compilation. void clearResults(); - // Return true if function recursion is detected. - bool detectRecursion(TIntermNode* root); + // Return true if function recursion is detected or call depth exceeded. + bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth); // Rewrites a shader's intermediate tree according to the CSS Shaders spec. void rewriteCSSShader(TIntermNode* root); // Returns true if the given shader does not exceed the minimum // functionality mandated in GLSL 1.0 spec Appendix A. bool validateLimitations(TIntermNode* root); - // Collect info for all attribs and uniforms. - void collectAttribsUniforms(TIntermNode* root); + // Collect info for all attribs, uniforms, varyings. + void collectVariables(TIntermNode* root); // Map long variable names into shorter ones. void mapLongVariableNames(TIntermNode* root); // Translate to object code. @@ -106,6 +107,8 @@ protected: // Returns true if the shader does not use sampler dependent values to affect control // flow or in operations whose time can depend on the input values. bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); + // Return true if the maximum expression complexity below the limit. + bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; // Get the resources set by InitBuiltInSymbolTable @@ -120,6 +123,8 @@ private: ShShaderSpec shaderSpec; int maxUniformVectors; + int maxExpressionComplexity; + int maxCallStackDepth; ShBuiltInResources compileResources; @@ -138,6 +143,7 @@ private: TInfoSink infoSink; // Output sink. TVariableInfoList attribs; // Active attributes in the compiled shader. TVariableInfoList uniforms; // Active uniforms in the compiled shader. + TVariableInfoList varyings; // Varyings in the compiled shader. // Cached copy of the ref-counted singleton. LongNameMap* longNameMap; diff --git a/src/3rdparty/angle/src/compiler/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/ShaderLang.cpp index 92f39311c2..42cd5cc5c1 100644 --- a/src/3rdparty/angle/src/compiler/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/ShaderLang.cpp @@ -15,20 +15,25 @@ #include "compiler/preprocessor/length_limits.h" #include "compiler/ShHandle.h" #include "compiler/TranslatorHLSL.h" +#include "compiler/VariablePacker.h" // // This is the platform independent interface between an OGL driver // and the shading language compiler. // -static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle, - size_t expectedValue) +static bool checkVariableMaxLengths(const ShHandle handle, + size_t expectedValue) { size_t activeUniformLimit = 0; ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); size_t activeAttribLimit = 0; ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); - return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit); + size_t varyingLimit = 0; + ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit); + return (expectedValue == activeUniformLimit && + expectedValue == activeAttribLimit && + expectedValue == varyingLimit); } static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) @@ -38,62 +43,14 @@ static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue return (expectedValue == mappedNameMaxLength); } -static void getVariableInfo(ShShaderInfo varType, - const ShHandle handle, - int index, - size_t* length, - int* size, - ShDataType* type, - char* name, - char* mappedName) -{ - if (!handle || !size || !type || !name) - return; - ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || - (varType == SH_ACTIVE_UNIFORMS)); - - TShHandleBase* base = reinterpret_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return; - - const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ? - compiler->getAttribs() : compiler->getUniforms(); - if (index < 0 || index >= static_cast(varList.size())) - return; - - const TVariableInfo& varInfo = varList[index]; - if (length) *length = varInfo.name.size(); - *size = varInfo.size; - *type = varInfo.type; - - // This size must match that queried by - // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH - // in ShGetInfo, below. - size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN; - ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength)); - strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength); - name[activeUniformAndAttribLength - 1] = 0; - if (mappedName) { - // This size must match that queried by - // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. - size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; - ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); - strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); - mappedName[maxMappedNameLength - 1] = 0; - } -} - // -// Driver must call this first, once, before doing any other -// compiler operations. +// Driver must call this first, once, before doing any other compiler operations. +// Subsequent calls to this function are no-op. // int ShInitialize() { - if (!InitProcess()) - return 0; - - return 1; + static const bool kInitialized = InitProcess(); + return kInitialized ? 1 : 0; } // @@ -101,9 +58,7 @@ int ShInitialize() // int ShFinalize() { - if (!DetachProcess()) - return 0; - + DetachProcess(); return 1; } @@ -127,6 +82,7 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->OES_EGL_image_external = 0; resources->ARB_texture_rectangle = 0; resources->EXT_draw_buffers = 0; + resources->EXT_frag_depth = 0; // Disable highp precision in fragment shader by default. resources->FragmentPrecisionHigh = 0; @@ -144,9 +100,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources) { - if (!InitThread()) - return 0; - TShHandleBase* base = static_cast(ConstructCompiler(type, spec, output)); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) @@ -185,9 +138,6 @@ int ShCompile( size_t numStrings, int compileOptions) { - if (!InitThread()) - return 0; - if (handle == 0) return 0; @@ -229,6 +179,12 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: *params = 1 + MAX_SYMBOL_NAME_LEN; break; + case SH_VARYINGS: + *params = compiler->getVaryings().size(); + break; + case SH_VARYING_MAX_LENGTH: + *params = 1 + MAX_SYMBOL_NAME_LEN; + break; case SH_MAPPED_NAME_MAX_LENGTH: // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to // handle array and struct dereferences. @@ -286,28 +242,71 @@ void ShGetObjectCode(const ShHandle handle, char* objCode) strcpy(objCode, infoSink.obj.c_str()); } -void ShGetActiveAttrib(const ShHandle handle, +void ShGetVariableInfo(const ShHandle handle, + ShShaderInfo varType, int index, size_t* length, int* size, ShDataType* type, + ShPrecisionType* precision, + int* staticUse, char* name, char* mappedName) { - getVariableInfo(SH_ACTIVE_ATTRIBUTES, - handle, index, length, size, type, name, mappedName); -} + if (!handle || !size || !type || !precision || !staticUse || !name) + return; + ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || + (varType == SH_ACTIVE_UNIFORMS) || + (varType == SH_VARYINGS)); -void ShGetActiveUniform(const ShHandle handle, - int index, - size_t* length, - int* size, - ShDataType* type, - char* name, - char* mappedName) -{ - getVariableInfo(SH_ACTIVE_UNIFORMS, - handle, index, length, size, type, name, mappedName); + TShHandleBase* base = reinterpret_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return; + + const TVariableInfoList& varList = + varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : + (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() : + compiler->getVaryings()); + if (index < 0 || index >= static_cast(varList.size())) + return; + + const TVariableInfo& varInfo = varList[index]; + if (length) *length = varInfo.name.size(); + *size = varInfo.size; + *type = varInfo.type; + switch (varInfo.precision) { + case EbpLow: + *precision = SH_PRECISION_LOWP; + break; + case EbpMedium: + *precision = SH_PRECISION_MEDIUMP; + break; + case EbpHigh: + *precision = SH_PRECISION_HIGHP; + break; + default: + // Some types does not support precision, for example, boolean. + *precision = SH_PRECISION_UNDEFINED; + break; + } + *staticUse = varInfo.staticUse ? 1 : 0; + + // This size must match that queried by + // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH + // in ShGetInfo, below. + size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN; + ASSERT(checkVariableMaxLengths(handle, variableLength)); + strncpy(name, varInfo.name.c_str(), variableLength); + name[variableLength - 1] = 0; + if (mappedName) { + // This size must match that queried by + // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. + size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; + ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); + strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); + mappedName[maxMappedNameLength - 1] = 0; + } } void ShGetNameHashingEntry(const ShHandle handle, @@ -370,3 +369,19 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) default: UNREACHABLE(); } } + +int ShCheckVariablesWithinPackingLimits( + int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize) +{ + if (varInfoArraySize == 0) + return 1; + ASSERT(varInfoArray); + TVariableInfoList variables; + for (size_t ii = 0; ii < varInfoArraySize; ++ii) + { + TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size); + variables.push_back(var); + } + VariablePacker packer; + return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; +} diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/SymbolTable.cpp index 847c1e4085..a7ce21680f 100644 --- a/src/3rdparty/angle/src/compiler/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/SymbolTable.cpp @@ -17,48 +17,34 @@ #include #include - -#include "common/angleutils.h" +#include TType::TType(const TPublicType &p) : - type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), - maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) + type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0) { - if (p.userDef) { + if (p.userDef) structure = p.userDef->getStruct(); - typeName = NewPoolTString(p.userDef->getTypeName().c_str()); - computeDeepestStructNesting(); - } } // // Recursively generate mangled names. // -void TType::buildMangledName(TString& mangledName) +TString TType::buildMangledName() const { + TString mangledName; if (isMatrix()) mangledName += 'm'; else if (isVector()) mangledName += 'v'; switch (type) { - case EbtFloat: mangledName += 'f'; break; - case EbtInt: mangledName += 'i'; break; - case EbtBool: mangledName += 'b'; break; - case EbtSampler2D: mangledName += "s2"; break; - case EbtSamplerCube: mangledName += "sC"; break; - case EbtStruct: - mangledName += "struct-"; - if (typeName) - mangledName += *typeName; - {// support MSVC++6.0 - for (unsigned int i = 0; i < structure->size(); ++i) { - mangledName += '-'; - (*structure)[i].type->buildMangledName(mangledName); - } - } - default: - break; + case EbtFloat: mangledName += 'f'; break; + case EbtInt: mangledName += 'i'; break; + case EbtBool: mangledName += 'b'; break; + case EbtSampler2D: mangledName += "s2"; break; + case EbtSamplerCube: mangledName += "sC"; break; + case EbtStruct: mangledName += structure->mangledName(); break; + default: break; } mangledName += static_cast('0' + getNominalSize()); @@ -69,53 +55,72 @@ void TType::buildMangledName(TString& mangledName) mangledName += buf; mangledName += ']'; } + return mangledName; } -int TType::getStructSize() const +size_t TType::getObjectSize() const { - if (!getStruct()) { - assert(false && "Not a struct"); - return 0; - } + size_t totalSize = 0; - if (structureSize == 0) - for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) - structureSize += ((*tl).type)->getObjectSize(); + if (getBasicType() == EbtStruct) + totalSize = structure->objectSize(); + else if (matrix) + totalSize = size * size; + else + totalSize = size; + + if (isArray()) { + size_t arraySize = getArraySize(); + if (arraySize > INT_MAX / totalSize) + totalSize = INT_MAX; + else + totalSize *= arraySize; + } - return structureSize; + return totalSize; } -void TType::computeDeepestStructNesting() +bool TStructure::containsArrays() const { - if (!getStruct()) { - return; + for (size_t i = 0; i < mFields->size(); ++i) { + const TType* fieldType = (*mFields)[i]->type(); + if (fieldType->isArray() || fieldType->isStructureContainingArrays()) + return true; } + return false; +} - int maxNesting = 0; - for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) { - maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting()); +TString TStructure::buildMangledName() const +{ + TString mangledName("struct-"); + mangledName += *mName; + for (size_t i = 0; i < mFields->size(); ++i) { + mangledName += '-'; + mangledName += (*mFields)[i]->type()->getMangledName(); } - - deepestStructNesting = 1 + maxNesting; + return mangledName; } -bool TType::isStructureContainingArrays() const +size_t TStructure::calculateObjectSize() const { - if (!structure) - { - return false; + size_t size = 0; + for (size_t i = 0; i < mFields->size(); ++i) { + size_t fieldSize = (*mFields)[i]->type()->getObjectSize(); + if (fieldSize > INT_MAX - size) + size = INT_MAX; + else + size += fieldSize; } + return size; +} - for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++) - { - if (member->type->isArray() || - member->type->isStructureContainingArrays()) - { - return true; - } +int TStructure::calculateDeepestNesting() const +{ + int maxNesting = 0; + for (size_t i = 0; i < mFields->size(); ++i) { + maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); } - - return false; + return 1 + maxNesting; } // @@ -196,84 +201,16 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) { for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { - if (it->second->isFunction()) { - TFunction* function = static_cast(it->second); - if (function->getName() == name) - function->relateToExtension(ext); - } + TSymbol* symbol = it->second; + if (symbol->getName() == name) + symbol->relateToExtension(ext); } } -TSymbol::TSymbol(const TSymbol& copyOf) -{ - name = NewPoolTString(copyOf.name->c_str()); - uniqueId = copyOf.uniqueId; -} - -TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf) +TSymbolTable::~TSymbolTable() { - type.copyType(copyOf.type, remapper); - userType = copyOf.userType; - // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL - assert(copyOf.arrayInformationType == 0); - arrayInformationType = 0; - - if (copyOf.unionArray) { - assert(!copyOf.type.getStruct()); - assert(copyOf.type.getObjectSize() == 1); - unionArray = new ConstantUnion[1]; - unionArray[0] = copyOf.unionArray[0]; - } else - unionArray = 0; -} - -TVariable* TVariable::clone(TStructureMap& remapper) -{ - TVariable *variable = new TVariable(*this, remapper); - - return variable; -} - -TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf) -{ - for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) { - TParameter param; - parameters.push_back(param); - parameters.back().copyParam(copyOf.parameters[i], remapper); - } - - returnType.copyType(copyOf.returnType, remapper); - mangledName = copyOf.mangledName; - op = copyOf.op; - defined = copyOf.defined; -} - -TFunction* TFunction::clone(TStructureMap& remapper) -{ - TFunction *function = new TFunction(*this, remapper); - - return function; -} - -TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper) -{ - TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); - tLevel::iterator iter; - for (iter = level.begin(); iter != level.end(); ++iter) { - symTableLevel->insert(*iter->second->clone(remapper)); - } - - return symTableLevel; -} - -void TSymbolTable::copyTable(const TSymbolTable& copyOf) -{ - TStructureMap remapper; - uniqueId = copyOf.uniqueId; - for (unsigned int i = 0; i < copyOf.table.size(); ++i) { - table.push_back(copyOf.table[i]->clone(remapper)); - } - for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) { - precisionStack.push_back( copyOf.precisionStack[i] ); - } + for (size_t i = 0; i < table.size(); ++i) + delete table[i]; + for (size_t i = 0; i < precisionStack.size(); ++i) + delete precisionStack[i]; } diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.h b/src/3rdparty/angle/src/compiler/SymbolTable.h index d27aa332b7..bebad4b92e 100644 --- a/src/3rdparty/angle/src/compiler/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/SymbolTable.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -32,6 +32,7 @@ #include +#include "common/angleutils.h" #include "compiler/InfoSink.h" #include "compiler/intermediate.h" @@ -40,22 +41,26 @@ // class TSymbol { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - TSymbol(const TString *n) : name(n) { } + POOL_ALLOCATOR_NEW_DELETE(); + TSymbol(const TString* n) : uniqueId(0), name(n) { } virtual ~TSymbol() { /* don't delete name, it's from the pool */ } + const TString& getName() const { 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; } - virtual void dump(TInfoSink &infoSink) const = 0; - TSymbol(const TSymbol&); - virtual TSymbol* clone(TStructureMap& remapper) = 0; + virtual void dump(TInfoSink &infoSink) const = 0; + void relateToExtension(const TString& ext) { extension = ext; } + const TString& getExtension() const { return extension; } -protected: +private: + DISALLOW_COPY_AND_ASSIGN(TSymbol); + + int uniqueId; // For real comparing during code generation const TString *name; - unsigned int uniqueId; // For real comparing during code generation + TString extension; }; // @@ -70,15 +75,13 @@ protected: // class TVariable : public TSymbol { public: - TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { } + TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { } virtual ~TVariable() { } 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); } - void updateArrayInformationType(TType *t) { arrayInformationType = t; } - TType* getArrayInformationType() { return arrayInformationType; } virtual void dump(TInfoSink &infoSink) const; @@ -100,16 +103,15 @@ public: delete[] unionArray; unionArray = constArray; } - TVariable(const TVariable&, TStructureMap& remapper); // copy constructor - virtual TVariable* clone(TStructureMap& remapper); -protected: +private: + DISALLOW_COPY_AND_ASSIGN(TVariable); + TType type; bool userType; // we are assuming that Pool Allocator will free the memory allocated to unionArray // when this object is destroyed ConstantUnion *unionArray; - TType *arrayInformationType; // this is used for updating maxArraySize in all the references to a given symbol }; // @@ -119,11 +121,6 @@ protected: struct TParameter { TString *name; TType* type; - void copyParam(const TParameter& param, TStructureMap& remapper) - { - name = NewPoolTString(param.name->c_str()); - type = param.type->clone(remapper); - } }; // @@ -163,9 +160,6 @@ public: void relateToOperator(TOperator o) { op = o; } TOperator getBuiltInOp() const { return op; } - void relateToExtension(const TString& ext) { extension = ext; } - const TString& getExtension() const { return extension; } - void setDefined() { defined = true; } bool isDefined() { return defined; } @@ -173,16 +167,15 @@ public: const TParameter& getParam(size_t i) const { return parameters[i]; } virtual void dump(TInfoSink &infoSink) const; - TFunction(const TFunction&, TStructureMap& remapper); - virtual TFunction* clone(TStructureMap& remapper); -protected: +private: + DISALLOW_COPY_AND_ASSIGN(TFunction); + typedef TVector TParamList; TParamList parameters; TType returnType; TString mangledName; TOperator op; - TString extension; bool defined; }; @@ -194,21 +187,24 @@ public: typedef const tLevel::value_type tLevelPair; typedef std::pair tInsertResult; - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) TSymbolTableLevel() { } ~TSymbolTableLevel(); - bool insert(TSymbol& symbol) + bool insert(const TString &name, TSymbol &symbol) { // // returning true means symbol was added to the table // - tInsertResult result; - result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); + tInsertResult result = level.insert(tLevelPair(name, &symbol)); return result.second; } + bool insert(TSymbol &symbol) + { + return insert(symbol.getMangledName(), symbol); + } + TSymbol* find(const TString& name) const { tLevel::const_iterator it = level.find(name); @@ -231,7 +227,6 @@ public: void relateToOperator(const char* name, TOperator op); void relateToExtension(const char* name, const TString& ext); void dump(TInfoSink &infoSink) const; - TSymbolTableLevel* clone(TStructureMap& remapper); protected: tLevel level; @@ -247,13 +242,7 @@ public: // that the symbol table has not been preloaded with built-ins. // } - - ~TSymbolTable() - { - // level 0 is always built In symbols, so we never pop that out - while (table.size() > 1) - pop(); - } + ~TSymbolTable(); // // When the symbol table is initialized with the built-ins, there should @@ -266,13 +255,15 @@ public: void push() { table.push_back(new TSymbolTableLevel); - precisionStack.push_back( PrecisionStackLevel() ); + precisionStack.push_back(new PrecisionStackLevel); } void pop() - { - delete table[currentLevel()]; - table.pop_back(); + { + delete table.back(); + table.pop_back(); + + delete precisionStack.back(); precisionStack.pop_back(); } @@ -282,6 +273,35 @@ public: return table[currentLevel()]->insert(symbol); } + bool insertConstInt(const char *name, int value) + { + TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); + constant->getConstPointer()->setIConst(value); + return insert(*constant); + } + + bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0) + { + TFunction *function = new TFunction(NewPoolTString(name), *rvalue); + + TParameter param1 = {NULL, ptype1}; + function->addParameter(param1); + + if(ptype2) + { + TParameter param2 = {NULL, ptype2}; + function->addParameter(param2); + } + + if(ptype3) + { + TParameter param3 = {NULL, ptype3}; + function->addParameter(param3); + } + + return insert(*function); + } + TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) { int level = currentLevel(); @@ -298,16 +318,11 @@ public: return symbol; } - TSymbol *findBuiltIn(const TString &name) + TSymbol* findBuiltIn(const TString &name) { return table[0]->find(name); } - TSymbolTableLevel* getGlobalLevel() { - assert(table.size() >= 2); - return table[1]; - } - TSymbolTableLevel* getOuterLevel() { assert(table.size() >= 2); return table[currentLevel() - 1]; @@ -319,32 +334,29 @@ public: void relateToExtension(const char* name, const TString& ext) { table[0]->relateToExtension(name, ext); } - int getMaxSymbolId() { return uniqueId; } void dump(TInfoSink &infoSink) const; - void copyTable(const TSymbolTable& copyOf); - bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){ - if (IsSampler(type.type)) - return true; // Skip sampler types for the time being - if (type.type != EbtFloat && type.type != EbtInt) - return false; // Only set default precision for int/float + bool setDefaultPrecision(const TPublicType& type, TPrecision prec) { + if (!supportsPrecision(type.type)) + return false; if (type.size != 1 || type.matrix || type.array) return false; // Not allowed to set for aggregate types int indexOfLastElement = static_cast(precisionStack.size()) - 1; - precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value + (*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value return true; } // Searches down the precisionStack for a precision qualifier for the specified TBasicType - TPrecision getDefaultPrecision( TBasicType type){ - if( type != EbtFloat && type != EbtInt ) return EbpUndefined; + TPrecision getDefaultPrecision(TBasicType type) { + if (!supportsPrecision(type)) + return EbpUndefined; int level = static_cast(precisionStack.size()) - 1; - assert( level >= 0); // Just to be safe. Should not happen. + assert(level >= 0); // Just to be safe. Should not happen. PrecisionStackLevel::iterator it; TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this? - while( level >= 0 ){ - it = precisionStack[level].find( type ); - if( it != precisionStack[level].end() ){ + while (level >= 0) { + it = precisionStack[level]->find(type); + if (it != precisionStack[level]->end()) { prec = (*it).second; break; } @@ -353,13 +365,18 @@ public: return prec; } -protected: +private: int currentLevel() const { return static_cast(table.size()) - 1; } - std::vector table; - typedef std::map< TBasicType, TPrecision > PrecisionStackLevel; - std::vector< PrecisionStackLevel > precisionStack; + bool supportsPrecision(TBasicType type) { + // Only supports precision for int, float, and sampler types. + return type == EbtFloat || type == EbtInt || IsSampler(type); + } + int uniqueId; // for unique identification in code generation + std::vector table; + typedef TMap PrecisionStackLevel; + std::vector precisionStack; }; #endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/Types.h b/src/3rdparty/angle/src/compiler/Types.h index 854bb44c07..505fa8e3bf 100644 --- a/src/3rdparty/angle/src/compiler/Types.h +++ b/src/3rdparty/angle/src/compiler/Types.h @@ -7,30 +7,85 @@ #ifndef _TYPES_INCLUDED #define _TYPES_INCLUDED +#include "common/angleutils.h" + #include "compiler/BaseTypes.h" #include "compiler/Common.h" #include "compiler/debug.h" -class TType; struct TPublicType; +class TType; -// -// Need to have association of line numbers to types in a list for building structs. -// -struct TTypeLine { - TType* type; - int line; +class TField +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TField(TType* type, TString* name) : mType(type), mName(name) {} + + // TODO(alokp): We should only return const type. + // Fix it by tweaking grammar. + TType* type() { return mType; } + const TType* type() const { return mType; } + + const TString& name() const { return *mName; } + +private: + DISALLOW_COPY_AND_ASSIGN(TField); + TType* mType; + TString* mName; }; -typedef TVector TTypeList; -inline TTypeList* NewPoolTTypeList() +typedef TVector TFieldList; +inline TFieldList* NewPoolTFieldList() { - void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList)); - return new(memory) TTypeList; + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); + return new(memory) TFieldList; } -typedef TMap TStructureMap; -typedef TMap::iterator TStructureMapIterator; +class TStructure +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TStructure(TString* name, TFieldList* fields) + : mName(name), + mFields(fields), + mObjectSize(0), + mDeepestNesting(0) { + } + + const TString& name() const { return *mName; } + const TFieldList& fields() const { return *mFields; } + + const TString& mangledName() const { + if (mMangledName.empty()) + mMangledName = buildMangledName(); + return mMangledName; + } + size_t objectSize() const { + if (mObjectSize == 0) + mObjectSize = calculateObjectSize(); + return mObjectSize; + }; + int deepestNesting() const { + if (mDeepestNesting == 0) + mDeepestNesting = calculateDeepestNesting(); + return mDeepestNesting; + } + bool containsArrays() const; + +private: + DISALLOW_COPY_AND_ASSIGN(TStructure); + TString buildMangledName() const; + size_t calculateObjectSize() const; + int calculateDeepestNesting() const; + + TString* mName; + TFieldList* mFields; + + mutable TString mMangledName; + mutable size_t mObjectSize; + mutable int mDeepestNesting; +}; // // Base class for things that have a type. @@ -38,72 +93,16 @@ typedef TMap::iterator TStructureMapIterator; class TType { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TType() {} TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : - type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), - maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) + type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0) { } explicit TType(const TPublicType &p); - TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : - type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), - maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) - { - typeName = NewPoolTString(n.c_str()); - } - - void copyType(const TType& copyOf, TStructureMap& remapper) + TType(TStructure* userDef, TPrecision p = EbpUndefined) : + type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef) { - type = copyOf.type; - precision = copyOf.precision; - qualifier = copyOf.qualifier; - size = copyOf.size; - matrix = copyOf.matrix; - array = copyOf.array; - arraySize = copyOf.arraySize; - - TStructureMapIterator iter; - if (copyOf.structure) { - if ((iter = remapper.find(structure)) == remapper.end()) { - // create the new structure here - structure = NewPoolTTypeList(); - for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { - TTypeLine typeLine; - typeLine.line = (*copyOf.structure)[i].line; - typeLine.type = (*copyOf.structure)[i].type->clone(remapper); - structure->push_back(typeLine); - } - } else { - structure = iter->second; - } - } else - structure = 0; - - fieldName = 0; - if (copyOf.fieldName) - fieldName = NewPoolTString(copyOf.fieldName->c_str()); - typeName = 0; - if (copyOf.typeName) - typeName = NewPoolTString(copyOf.typeName->c_str()); - - mangled = 0; - if (copyOf.mangled) - mangled = NewPoolTString(copyOf.mangled->c_str()); - - structureSize = copyOf.structureSize; - maxArraySize = copyOf.maxArraySize; - deepestStructNesting = copyOf.deepestStructNesting; - assert(copyOf.arrayInformationType == 0); - arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level - } - - TType* clone(TStructureMap& remapper) - { - TType *newType = new TType(); - newType->copyType(*this, remapper); - - return newType; } TBasicType getBasicType() const { return type; } @@ -119,34 +118,18 @@ public: int getNominalSize() const { return size; } void setNominalSize(int s) { size = s; } // Full size of single instance of type - int getObjectSize() const - { - int totalSize; - - if (getBasicType() == EbtStruct) - totalSize = getStructSize(); - else if (matrix) - totalSize = size * size; - else - totalSize = size; - - if (isArray()) - totalSize *= std::max(getArraySize(), getMaxArraySize()); - - return totalSize; - } + size_t getObjectSize() const; int elementRegisterCount() const { - TTypeList *structure = getStruct(); - if (structure) { + const TFieldList &fields = getStruct()->fields(); int registerCount = 0; - for (size_t i = 0; i < structure->size(); i++) + for (size_t i = 0; i < fields.size(); i++) { - registerCount += (*structure)[i].type->totalRegisterCount(); + registerCount += fields[i]->type()->totalRegisterCount(); } return registerCount; @@ -179,47 +162,20 @@ public: bool isArray() const { return array ? true : false; } int getArraySize() const { return arraySize; } void setArraySize(int s) { array = true; arraySize = s; } - int getMaxArraySize () const { return maxArraySize; } - void setMaxArraySize (int s) { maxArraySize = s; } - void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } - void setArrayInformationType(TType* t) { arrayInformationType = t; } - TType* getArrayInformationType() const { return arrayInformationType; } + void clearArrayness() { array = false; arraySize = 0; } bool isVector() const { return size > 1 && !matrix; } bool isScalar() const { return size == 1 && !matrix && !structure; } - TTypeList* getStruct() const { return structure; } - void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); } - - const TString& getTypeName() const - { - assert(typeName); - return *typeName; - } - void setTypeName(const TString& n) - { - typeName = NewPoolTString(n.c_str()); - } - - bool isField() const { return fieldName != 0; } - const TString& getFieldName() const - { - assert(fieldName); - return *fieldName; - } - void setFieldName(const TString& n) - { - fieldName = NewPoolTString(n.c_str()); - } + TStructure* getStruct() const { return structure; } + void setStruct(TStructure* s) { structure = s; } - TString& getMangledName() { - if (!mangled) { - mangled = NewPoolTString(""); - buildMangledName(*mangled); - *mangled += ';' ; + const TString& getMangledName() const { + if (mangled.empty()) { + mangled = buildMangledName(); + mangled += ';'; } - - return *mangled; + return mangled; } bool sameElementType(const TType& right) const { @@ -267,14 +223,16 @@ public: // For type "nesting2", this method would return 2 -- the number // of structures through which indirection must occur to reach the // deepest field (nesting2.field1.position). - int getDeepestStructNesting() const { return deepestStructNesting; } + int getDeepestStructNesting() const { + return structure ? structure->deepestNesting() : 0; + } - bool isStructureContainingArrays() const; + bool isStructureContainingArrays() const { + return structure ? structure->containsArrays() : false; + } -protected: - void buildMangledName(TString&); - int getStructSize() const; - void computeDeepestStructNesting(); +private: + TString buildMangledName() const; TBasicType type : 6; TPrecision precision; @@ -283,16 +241,10 @@ protected: unsigned int matrix : 1; unsigned int array : 1; int arraySize; - int maxArraySize; - TType* arrayInformationType; - TTypeList* structure; // 0 unless this is a struct - mutable int structureSize; - int deepestStructNesting; + TStructure* structure; // 0 unless this is a struct - TString *fieldName; // for structure field names - TString *mangled; - TString *typeName; // for structure field type name + mutable TString mangled; }; // @@ -314,9 +266,9 @@ struct TPublicType bool array; int arraySize; TType* userDef; - int line; + TSourceLoc line; - void setBasic(TBasicType bt, TQualifier q, int ln = 0) + void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln) { type = bt; qualifier = q; diff --git a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp index a5562d09a4..736ceeaefc 100644 --- a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp @@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) return true; bool valid = true; - TSymbolTable& symbolTable = GlobalParseContext->symbolTable; + TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable; TSymbol* symbol = symbolTable.find(node->getName()); ASSERT(symbol && symbol->isFunction()); TFunction* function = static_cast(symbol); diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/VariableInfo.cpp index eb6bea9b0f..f3f7b1ef35 100644 --- a/src/3rdparty/angle/src/compiler/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/VariableInfo.cpp @@ -6,15 +6,17 @@ #include "compiler/VariableInfo.h" -static TString arrayBrackets(int index) +namespace { + +TString arrayBrackets(int index) { TStringStream stream; stream << "[" << index << "]"; return stream.str(); } -// Returns the data type for an attribute or uniform. -static ShDataType getVariableDataType(const TType& type) +// Returns the data type for an attribute, uniform, or varying. +ShDataType getVariableDataType(const TType& type) { switch (type.getBasicType()) { case EbtFloat: @@ -70,22 +72,22 @@ static ShDataType getVariableDataType(const TType& type) return SH_NONE; } -static void getBuiltInVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList); -static void getUserDefinedVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction); - -// Returns info for an attribute or uniform. -static void getVariableInfo(const TType& type, +void getBuiltInVariableInfo(const TType& type, const TString& name, const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction) + TVariableInfoList& infoList); +void getUserDefinedVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList, + ShHashFunction64 hashFunction); + +// Returns info for an attribute, uniform, or varying. +void getVariableInfo(const TType& type, + const TString& name, + const TString& mappedName, + TVariableInfoList& infoList, + ShHashFunction64 hashFunction) { if (type.getBasicType() == EbtStruct) { if (type.isArray()) { @@ -119,6 +121,7 @@ void getBuiltInVariableInfo(const TType& type, varInfo.mappedName = mappedName.c_str(); varInfo.size = 1; } + varInfo.precision = type.getPrecision(); varInfo.type = getVariableDataType(type); infoList.push_back(varInfo); } @@ -131,86 +134,156 @@ void getUserDefinedVariableInfo(const TType& type, { ASSERT(type.getBasicType() == EbtStruct); - const TTypeList* structure = type.getStruct(); - for (size_t i = 0; i < structure->size(); ++i) { - const TType* fieldType = (*structure)[i].type; - getVariableInfo(*fieldType, - name + "." + fieldType->getFieldName(), - mappedName + "." + TIntermTraverser::hash(fieldType->getFieldName(), hashFunction), + const TFieldList& fields = type.getStruct()->fields(); + for (size_t i = 0; i < fields.size(); ++i) { + const TType& fieldType = *(fields[i]->type()); + const TString& fieldName = fields[i]->name(); + getVariableInfo(fieldType, + name + "." + fieldName, + mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction), infoList, hashFunction); } } +TVariableInfo* findVariable(const TType& type, + const TString& name, + TVariableInfoList& infoList) +{ + // TODO(zmo): optimize this function. + TString myName = name; + if (type.isArray()) + myName += "[0]"; + for (size_t ii = 0; ii < infoList.size(); ++ii) + { + if (infoList[ii].name.c_str() == myName) + return &(infoList[ii]); + } + return NULL; +} + +} // namespace anonymous + TVariableInfo::TVariableInfo() + : type(SH_NONE), + size(0), + precision(EbpUndefined), + staticUse(false) { } TVariableInfo::TVariableInfo(ShDataType type, int size) : type(type), - size(size) + size(size), + precision(EbpUndefined), + staticUse(false) { } -CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - ShHashFunction64 hashFunction) +CollectVariables::CollectVariables(TVariableInfoList& attribs, + TVariableInfoList& uniforms, + TVariableInfoList& varyings, + ShHashFunction64 hashFunction) : mAttribs(attribs), mUniforms(uniforms), + mVaryings(varyings), + mPointCoordAdded(false), + mFrontFacingAdded(false), + mFragCoordAdded(false), mHashFunction(hashFunction) { } -// We are only interested in attribute and uniform variable declaration. -void CollectAttribsUniforms::visitSymbol(TIntermSymbol*) -{ -} - -void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*) -{ -} - -bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*) +// We want to check whether a uniform/varying is statically used +// because we only count the used ones in packing computing. +// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count +// toward varying counting if they are statically used in a fragment +// shader. +void CollectVariables::visitSymbol(TIntermSymbol* symbol) { - return false; -} - -bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*) -{ - return false; -} - -bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*) -{ - return false; + ASSERT(symbol != NULL); + TVariableInfo* var = NULL; + switch (symbol->getQualifier()) + { + case EvqVaryingOut: + case EvqInvariantVaryingOut: + case EvqVaryingIn: + case EvqInvariantVaryingIn: + var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings); + break; + case EvqUniform: + var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms); + break; + case EvqFragCoord: + if (!mFragCoordAdded) { + TVariableInfo info; + info.name = "gl_FragCoord"; + info.mappedName = "gl_FragCoord"; + info.type = SH_FLOAT_VEC4; + info.size = 1; + info.precision = EbpMedium; // Use mediump as it doesn't really matter. + info.staticUse = true; + mVaryings.push_back(info); + mFragCoordAdded = true; + } + return; + case EvqFrontFacing: + if (!mFrontFacingAdded) { + TVariableInfo info; + info.name = "gl_FrontFacing"; + info.mappedName = "gl_FrontFacing"; + info.type = SH_BOOL; + info.size = 1; + info.precision = EbpUndefined; + info.staticUse = true; + mVaryings.push_back(info); + mFrontFacingAdded = true; + } + return; + case EvqPointCoord: + if (!mPointCoordAdded) { + TVariableInfo info; + info.name = "gl_PointCoord"; + info.mappedName = "gl_PointCoord"; + info.type = SH_FLOAT_VEC2; + info.size = 1; + info.precision = EbpMedium; // Use mediump as it doesn't really matter. + info.staticUse = true; + mVaryings.push_back(info); + mPointCoordAdded = true; + } + return; + default: + break; + } + if (var) + var->staticUse = true; } -bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node) +bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node) { - bool visitChildren = false; + bool visitChildren = true; switch (node->getOp()) { - case EOpSequence: - // We need to visit sequence children to get to variable declarations. - visitChildren = true; - break; case EOpDeclaration: { const TIntermSequence& sequence = node->getSequence(); TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); - if (qualifier == EvqAttribute || qualifier == EvqUniform) + if (qualifier == EvqAttribute || qualifier == EvqUniform || + qualifier == EvqVaryingIn || qualifier == EvqVaryingOut || + qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut) { - TVariableInfoList& infoList = qualifier == EvqAttribute ? - mAttribs : mUniforms; + TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs : + (qualifier == EvqUniform ? mUniforms : mVaryings); for (TIntermSequence::const_iterator i = sequence.begin(); i != sequence.end(); ++i) { const TIntermSymbol* variable = (*i)->getAsSymbolNode(); // The only case in which the sequence will not contain a // TIntermSymbol node is initialization. It will contain a - // TInterBinary node in that case. Since attributes and unifroms - // cannot be initialized in a shader, we must have only - // TIntermSymbol nodes in the sequence. + // TInterBinary node in that case. Since attributes, uniforms, + // and varyings cannot be initialized in a shader, we must have + // only TIntermSymbol nodes in the sequence. ASSERT(variable != NULL); TString processedSymbol; if (mHashFunction == NULL) @@ -222,6 +295,7 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node) processedSymbol, infoList, mHashFunction); + visitChildren = false; } } break; @@ -232,13 +306,3 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node) return visitChildren; } -bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*) -{ - return false; -} - -bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*) -{ - return false; -} - diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.h b/src/3rdparty/angle/src/compiler/VariableInfo.h index 4130a589f5..3c7f2a5f84 100644 --- a/src/3rdparty/angle/src/compiler/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/VariableInfo.h @@ -20,28 +20,30 @@ struct TVariableInfo { TPersistString mappedName; ShDataType type; int size; + TPrecision precision; + bool staticUse; }; typedef std::vector TVariableInfoList; -// Traverses intermediate tree to collect all attributes and uniforms. -class CollectAttribsUniforms : public TIntermTraverser { +// Traverses intermediate tree to collect all attributes, uniforms, varyings. +class CollectVariables : public TIntermTraverser { public: - CollectAttribsUniforms(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - ShHashFunction64 hashFunction); + CollectVariables(TVariableInfoList& attribs, + TVariableInfoList& uniforms, + TVariableInfoList& varyings, + ShHashFunction64 hashFunction); virtual void visitSymbol(TIntermSymbol*); - virtual void visitConstantUnion(TIntermConstantUnion*); - virtual bool visitBinary(Visit, TIntermBinary*); - virtual bool visitUnary(Visit, TIntermUnary*); - virtual bool visitSelection(Visit, TIntermSelection*); virtual bool visitAggregate(Visit, TIntermAggregate*); - virtual bool visitLoop(Visit, TIntermLoop*); - virtual bool visitBranch(Visit, TIntermBranch*); private: TVariableInfoList& mAttribs; TVariableInfoList& mUniforms; + TVariableInfoList& mVaryings; + + bool mPointCoordAdded; + bool mFrontFacingAdded; + bool mFragCoordAdded; ShHashFunction64 mHashFunction; }; diff --git a/src/3rdparty/angle/src/compiler/glslang.l b/src/3rdparty/angle/src/compiler/glslang.l index 140a9aeb2d..60663f9a6b 100644 --- a/src/3rdparty/angle/src/compiler/glslang.l +++ b/src/3rdparty/angle/src/compiler/glslang.l @@ -47,20 +47,23 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #pragma warning(disable : 4102) #endif -#define YY_USER_ACTION yylval->lex.line = yylineno; +#define YY_USER_ACTION \ + yylloc->first_file = yylloc->last_file = yycolumn; \ + yylloc->first_line = yylloc->last_line = yylineno; + #define YY_INPUT(buf, result, max_size) \ result = string_input(buf, max_size, yyscanner); static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); static int check_type(yyscan_t yyscanner); static int reserved_word(yyscan_t yyscanner); +static int int_constant(yyscan_t yyscanner); +static int float_constant(yyscan_t yyscanner); %} %option noyywrap nounput never-interactive -%option yylineno reentrant bison-bridge -%option stack +%option yylineno reentrant bison-bridge bison-locations %option extra-type="TParseContext*" -%x COMMENT FIELDS D [0-9] L [a-zA-Z_] @@ -70,73 +73,60 @@ O [0-7] %% -%{ - TParseContext* context = yyextra; -%} - - /* Single-line comments */ -"//"[^\n]* ; - - /* Multi-line comments */ -"/*" { yy_push_state(COMMENT, yyscanner); } -. | -\n ; -"*/" { yy_pop_state(yyscanner); } - -"invariant" { return(INVARIANT); } -"highp" { return(HIGH_PRECISION); } -"mediump" { return(MEDIUM_PRECISION); } -"lowp" { return(LOW_PRECISION); } -"precision" { return(PRECISION); } - -"attribute" { return(ATTRIBUTE); } -"const" { return(CONST_QUAL); } -"uniform" { return(UNIFORM); } -"varying" { return(VARYING); } - -"break" { return(BREAK); } -"continue" { return(CONTINUE); } -"do" { return(DO); } -"for" { return(FOR); } -"while" { return(WHILE); } - -"if" { return(IF); } -"else" { return(ELSE); } - -"in" { return(IN_QUAL); } -"out" { return(OUT_QUAL); } -"inout" { return(INOUT_QUAL); } - -"float" { context->lexAfterType = true; return(FLOAT_TYPE); } -"int" { context->lexAfterType = true; return(INT_TYPE); } -"void" { context->lexAfterType = true; return(VOID_TYPE); } -"bool" { context->lexAfterType = true; return(BOOL_TYPE); } -"true" { yylval->lex.b = true; return(BOOLCONSTANT); } -"false" { yylval->lex.b = false; return(BOOLCONSTANT); } - -"discard" { return(DISCARD); } -"return" { return(RETURN); } - -"mat2" { context->lexAfterType = true; return(MATRIX2); } -"mat3" { context->lexAfterType = true; return(MATRIX3); } -"mat4" { context->lexAfterType = true; return(MATRIX4); } - -"vec2" { context->lexAfterType = true; return (VEC2); } -"vec3" { context->lexAfterType = true; return (VEC3); } -"vec4" { context->lexAfterType = true; return (VEC4); } -"ivec2" { context->lexAfterType = true; return (IVEC2); } -"ivec3" { context->lexAfterType = true; return (IVEC3); } -"ivec4" { context->lexAfterType = true; return (IVEC4); } -"bvec2" { context->lexAfterType = true; return (BVEC2); } -"bvec3" { context->lexAfterType = true; return (BVEC3); } -"bvec4" { context->lexAfterType = true; return (BVEC4); } - -"sampler2D" { context->lexAfterType = true; return SAMPLER2D; } -"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; } -"samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; } -"sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; } - -"struct" { context->lexAfterType = true; return(STRUCT); } +"invariant" { return INVARIANT; } +"highp" { return HIGH_PRECISION; } +"mediump" { return MEDIUM_PRECISION; } +"lowp" { return LOW_PRECISION; } +"precision" { return PRECISION; } + +"attribute" { return ATTRIBUTE; } +"const" { return CONST_QUAL; } +"uniform" { return UNIFORM; } +"varying" { return VARYING; } + +"break" { return BREAK; } +"continue" { return CONTINUE; } +"do" { return DO; } +"for" { return FOR; } +"while" { return WHILE; } + +"if" { return IF; } +"else" { return ELSE; } + +"in" { return IN_QUAL; } +"out" { return OUT_QUAL; } +"inout" { return INOUT_QUAL; } + +"float" { return FLOAT_TYPE; } +"int" { return INT_TYPE; } +"void" { return VOID_TYPE; } +"bool" { return BOOL_TYPE; } +"true" { yylval->lex.b = true; return BOOLCONSTANT; } +"false" { yylval->lex.b = false; return BOOLCONSTANT; } + +"discard" { return DISCARD; } +"return" { return RETURN; } + +"mat2" { return MATRIX2; } +"mat3" { return MATRIX3; } +"mat4" { return MATRIX4; } + +"vec2" { return VEC2; } +"vec3" { return VEC3; } +"vec4" { return VEC4; } +"ivec2" { return IVEC2; } +"ivec3" { return IVEC3; } +"ivec4" { return IVEC4; } +"bvec2" { return BVEC2; } +"bvec3" { return BVEC3; } +"bvec4" { return BVEC4; } + +"sampler2D" { return SAMPLER2D; } +"samplerCube" { return SAMPLERCUBE; } +"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } +"sampler2DRect" { return SAMPLER2DRECT; } + +"struct" { return STRUCT; } "asm" { return reserved_word(yyscanner); } @@ -183,13 +173,11 @@ O [0-7] "fvec3" { return reserved_word(yyscanner); } "fvec4" { return reserved_word(yyscanner); } -"sampler1D" { return reserved_word(yyscanner); } -"sampler3D" { return reserved_word(yyscanner); } - -"sampler1DShadow" { return reserved_word(yyscanner); } -"sampler2DShadow" { return reserved_word(yyscanner); } - -"sampler3DRect" { return reserved_word(yyscanner); } +"sampler1D" { return reserved_word(yyscanner); } +"sampler3D" { return reserved_word(yyscanner); } +"sampler1DShadow" { return reserved_word(yyscanner); } +"sampler2DShadow" { return reserved_word(yyscanner); } +"sampler3DRect" { return reserved_word(yyscanner); } "sampler2DRectShadow" { return reserved_word(yyscanner); } "sizeof" { return reserved_word(yyscanner); } @@ -203,72 +191,64 @@ O [0-7] return check_type(yyscanner); } -0[xX]{H}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } -0{O}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } -0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;} -{D}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } - -{D}+{E} { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } -{D}+"."{D}*({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } -"."{D}+({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } - -"+=" { return(ADD_ASSIGN); } -"-=" { return(SUB_ASSIGN); } -"*=" { return(MUL_ASSIGN); } -"/=" { return(DIV_ASSIGN); } -"%=" { return(MOD_ASSIGN); } -"<<=" { return(LEFT_ASSIGN); } -">>=" { return(RIGHT_ASSIGN); } -"&=" { return(AND_ASSIGN); } -"^=" { return(XOR_ASSIGN); } -"|=" { return(OR_ASSIGN); } - -"++" { return(INC_OP); } -"--" { return(DEC_OP); } -"&&" { return(AND_OP); } -"||" { return(OR_OP); } -"^^" { return(XOR_OP); } -"<=" { return(LE_OP); } -">=" { return(GE_OP); } -"==" { return(EQ_OP); } -"!=" { return(NE_OP); } -"<<" { return(LEFT_OP); } -">>" { return(RIGHT_OP); } -";" { context->lexAfterType = false; return(SEMICOLON); } -("{"|"<%") { context->lexAfterType = false; return(LEFT_BRACE); } -("}"|"%>") { return(RIGHT_BRACE); } -"," { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); } -":" { return(COLON); } -"=" { context->lexAfterType = false; return(EQUAL); } -"(" { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); } -")" { context->inTypeParen = false; return(RIGHT_PAREN); } -("["|"<:") { return(LEFT_BRACKET); } -("]"|":>") { return(RIGHT_BRACKET); } -"." { BEGIN(FIELDS); return(DOT); } -"!" { return(BANG); } -"-" { return(DASH); } -"~" { return(TILDE); } -"+" { return(PLUS); } -"*" { return(STAR); } -"/" { return(SLASH); } -"%" { return(PERCENT); } -"<" { return(LEFT_ANGLE); } -">" { return(RIGHT_ANGLE); } -"|" { return(VERTICAL_BAR); } -"^" { return(CARET); } -"&" { return(AMPERSAND); } -"?" { return(QUESTION); } - -{L}({L}|{D})* { - BEGIN(INITIAL); - yylval->lex.string = NewPoolTString(yytext); - return FIELD_SELECTION; -} -[ \t\v\f\r] {} - -[ \t\v\n\f\r] { } -<*><> { context->AfterEOF = true; yyterminate(); } -<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; } +0[xX]{H}+ { return int_constant(yyscanner); } +0{O}+ { return int_constant(yyscanner); } +{D}+ { return int_constant(yyscanner); } + +{D}+{E} { return float_constant(yyscanner); } +{D}+"."{D}*({E})? { return float_constant(yyscanner); } +"."{D}+({E})? { return float_constant(yyscanner); } + +"+=" { return ADD_ASSIGN; } +"-=" { return SUB_ASSIGN; } +"*=" { return MUL_ASSIGN; } +"/=" { return DIV_ASSIGN; } +"%=" { return MOD_ASSIGN; } +"<<=" { return LEFT_ASSIGN; } +">>=" { return RIGHT_ASSIGN; } +"&=" { return AND_ASSIGN; } +"^=" { return XOR_ASSIGN; } +"|=" { return OR_ASSIGN; } + +"++" { return INC_OP; } +"--" { return DEC_OP; } +"&&" { return AND_OP; } +"||" { return OR_OP; } +"^^" { return XOR_OP; } +"<=" { return LE_OP; } +">=" { return GE_OP; } +"==" { return EQ_OP; } +"!=" { return NE_OP; } +"<<" { return LEFT_OP; } +">>" { return RIGHT_OP; } +";" { return SEMICOLON; } +("{"|"<%") { return LEFT_BRACE; } +("}"|"%>") { return RIGHT_BRACE; } +"," { return COMMA; } +":" { return COLON; } +"=" { return EQUAL; } +"(" { return LEFT_PAREN; } +")" { return RIGHT_PAREN; } +("["|"<:") { return LEFT_BRACKET; } +("]"|":>") { return RIGHT_BRACKET; } +"." { return DOT; } +"!" { return BANG; } +"-" { return DASH; } +"~" { return TILDE; } +"+" { return PLUS; } +"*" { return STAR; } +"/" { return SLASH; } +"%" { return PERCENT; } +"<" { return LEFT_ANGLE; } +">" { return RIGHT_ANGLE; } +"|" { return VERTICAL_BAR; } +"^" { return CARET; } +"&" { return AMPERSAND; } +"?" { return QUESTION; } + +[ \t\v\n\f\r] { } +<> { yyterminate(); } +. { assert(false); return 0; } %% @@ -278,7 +258,8 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); if (len < max_size) memcpy(buf, token.text.c_str(), len); - yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner); + yyset_column(token.location.file, yyscanner); + yyset_lineno(token.location.line, yyscanner); if (len >= max_size) YY_FATAL_ERROR("Input buffer overflow"); @@ -292,12 +273,10 @@ int check_type(yyscan_t yyscanner) { int token = IDENTIFIER; TSymbol* symbol = yyextra->symbolTable.find(yytext); - if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) { + if (symbol && symbol->isVariable()) { TVariable* variable = static_cast(symbol); - if (variable->isUserType()) { - yyextra->lexAfterType = true; + if (variable->isUserType()) token = TYPE_NAME; - } } yylval->lex.symbol = symbol; return token; @@ -306,22 +285,32 @@ int check_type(yyscan_t yyscanner) { int reserved_word(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - yyextra->error(yylineno, "Illegal use of reserved word", yytext, ""); + yyextra->error(*yylloc, "Illegal use of reserved word", yytext, ""); yyextra->recover(); return 0; } -void yyerror(TParseContext* context, const char* reason) { - struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; - - if (context->AfterEOF) { - context->error(yylineno, reason, "unexpected EOF"); - } else { - context->error(yylineno, reason, yytext); - } +void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { + context->error(*lloc, reason, yyget_text(context->scanner)); context->recover(); } +int int_constant(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + if (!atoi_clamp(yytext, &(yylval->lex.i))) + yyextra->warning(*yylloc, "Integer overflow", yytext, ""); + return INTCONSTANT; +} + +int float_constant(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + if (!atof_clamp(yytext, &(yylval->lex.f))) + yyextra->warning(*yylloc, "Float overflow", yytext, ""); + return FLOATCONSTANT; +} + int glslang_initialize(TParseContext* context) { yyscan_t scanner = NULL; if (yylex_init_extra(context, &scanner)) @@ -344,12 +333,13 @@ int glslang_finalize(TParseContext* context) { int glslang_scan(size_t count, const char* const string[], const int length[], TParseContext* context) { yyrestart(NULL, context->scanner); - yyset_lineno(EncodeSourceLoc(0, 1), context->scanner); - context->AfterEOF = false; + yyset_column(0, context->scanner); + yyset_lineno(1, context->scanner); // Initialize preprocessor. if (!context->preprocessor.init(count, string, length)) return 1; + context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH); // Define extension macros. const TExtensionBehavior& extBehavior = context->extensionBehavior(); diff --git a/src/3rdparty/angle/src/compiler/glslang.y b/src/3rdparty/angle/src/compiler/glslang.y index 8dbcee32ef..c64f736f41 100644 --- a/src/3rdparty/angle/src/compiler/glslang.y +++ b/src/3rdparty/angle/src/compiler/glslang.y @@ -39,7 +39,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #include "GLSLANG/ShaderLang.h" #define YYENABLE_NLS 0 -#define YYLTYPE_IS_TRIVIAL 1 #define YYLEX_PARAM context->scanner %} @@ -47,10 +46,16 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). %expect 1 /* One shift reduce conflict because of if | else */ %pure-parser %parse-param {TParseContext* context} +%locations + +%code requires { +#define YYLTYPE TSourceLoc +#define YYLTYPE_IS_DECLARED 1 +#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec. +} %union { struct { - TSourceLoc line; union { TString *string; float f; @@ -60,7 +65,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TSymbol* symbol; } lex; struct { - TSourceLoc line; TOperator op; union { TIntermNode* intermNode; @@ -74,23 +78,31 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TQualifier qualifier; TFunction* function; TParameter param; - TTypeLine typeLine; - TTypeList* typeList; + TField* field; + TFieldList* fieldList; }; } interm; } %{ -extern int yylex(YYSTYPE* yylval_param, void* yyscanner); -extern void yyerror(TParseContext* context, const char* reason); - -#define FRAG_VERT_ONLY(S, L) { \ - if (context->shaderType != SH_FRAGMENT_SHADER && \ - context->shaderType != SH_VERTEX_SHADER) { \ - context->error(L, " supported in vertex/fragment shaders only ", S); \ - context->recover(); \ - } \ -} +extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); +extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); + +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (YYID(N)) { \ + (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + } \ + else { \ + (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ + (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ + } \ + } while (0) #define VERTEX_ONLY(S, L) { \ if (context->shaderType != SH_VERTEX_SHADER) { \ @@ -116,7 +128,6 @@ extern void yyerror(TParseContext* context, const char* reason); %token SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT %token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT -%token FIELD_SELECTION %token LEFT_OP RIGHT_OP %token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP %token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN @@ -127,6 +138,7 @@ extern void yyerror(TParseContext* context, const char* reason); %token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT %token LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION +%type identifier %type assignment_operator unary_operator %type variable_identifier primary_expression postfix_expression %type expression integer_expression assignment_expression @@ -154,8 +166,8 @@ extern void yyerror(TParseContext* context, const char* reason); %type type_qualifier fully_specified_type type_specifier %type type_specifier_no_prec type_specifier_nonarray %type struct_specifier -%type struct_declarator -%type struct_declarator_list struct_declaration struct_declaration_list +%type struct_declarator +%type struct_declarator_list struct_declaration struct_declaration_list %type function_header function_declarator function_identifier %type function_header_with_parameters function_call_header %type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype @@ -164,13 +176,17 @@ extern void yyerror(TParseContext* context, const char* reason); %start translation_unit %% +identifier + : IDENTIFIER + | TYPE_NAME + variable_identifier : IDENTIFIER { // The symbol table search was done in the lexical phase const TSymbol* symbol = $1.symbol; const TVariable* variable; if (symbol == 0) { - context->error($1.line, "undeclared identifier", $1.string->c_str()); + context->error(@1, "undeclared identifier", $1.string->c_str()); context->recover(); TType type(EbtFloat, EbpUndefined); TVariable* fakeVariable = new TVariable($1.string, type); @@ -179,10 +195,17 @@ variable_identifier } else { // This identifier can only be a variable type symbol if (! symbol->isVariable()) { - context->error($1.line, "variable expected", $1.string->c_str()); + context->error(@1, "variable expected", $1.string->c_str()); context->recover(); } + variable = static_cast(symbol); + + if (context->symbolTable.findBuiltIn(variable->getName()) && + !variable->getExtension().empty() && + context->extensionErrorCheck(@1, variable->getExtension())) { + context->recover(); + } } // don't delete $1.string, it's used by error recovery, and the pool @@ -191,11 +214,12 @@ variable_identifier if (variable->getType().getQualifier() == EvqConst ) { ConstantUnion* constArray = variable->getConstPointer(); TType t(variable->getType()); - $$ = context->intermediate.addConstantUnion(constArray, t, $1.line); + $$ = context->intermediate.addConstantUnion(constArray, t, @1); } else $$ = context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), $1.line); + variable->getName(), + variable->getType(), + @1); } ; @@ -204,27 +228,19 @@ primary_expression $$ = $1; } | INTCONSTANT { - // - // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders, - // check for overflow for constants - // - if (abs($1.i) >= (1 << 16)) { - context->error($1.line, " integer constant overflow", ""); - context->recover(); - } ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst($1.i); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1); } | FLOATCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst($1.f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); } | BOOLCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst($1.b); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1); } | LEFT_PAREN expression RIGHT_PAREN { $$ = $2; @@ -236,103 +252,27 @@ postfix_expression $$ = $1; } | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { - if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) { - if ($1->getAsSymbolNode()) - context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str()); - else - context->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression"); - context->recover(); - } - if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) { - if ($1->isArray()) { // constant folding for arrays - $$ = context->addConstArrayNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line); - } else if ($1->isVector()) { // constant folding for vectors - TVectorFields fields; - fields.num = 1; - fields.offsets[0] = $3->getAsConstantUnion()->getIConst(0); // need to do it this way because v.xy sends fields integer array - $$ = context->addConstVectorNode(fields, $1, $2.line); - } else if ($1->isMatrix()) { // constant folding for matrices - $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line); - } - } else { - if ($3->getQualifier() == EvqConst) { - if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getIConst(0) && !$1->isArray() ) { - std::stringstream extraInfoStream; - extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; - std::string extraInfo = extraInfoStream.str(); - context->error($2.line, "", "[", extraInfo.c_str()); - context->recover(); - } else { - if ($1->isArray()) { - if ($1->getType().getArraySize() == 0) { - if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getIConst(0)) { - if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getIConst(0), true, $2.line)) - context->recover(); - } else { - if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line)) - context->recover(); - } - } else if ( $3->getAsConstantUnion()->getIConst(0) >= $1->getType().getArraySize()) { - std::stringstream extraInfoStream; - extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; - std::string extraInfo = extraInfoStream.str(); - context->error($2.line, "", "[", extraInfo.c_str()); - context->recover(); - } - } - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line); - } - } else { - if ($1->isArray() && $1->getType().getArraySize() == 0) { - context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); - context->recover(); - } - - $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line); - } - } - if ($$ == 0) { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line); - } else if ($1->isArray()) { - if ($1->getType().getStruct()) - $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName())); - else - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix())); - - if ($1->getType().getQualifier() == EvqConst) - $$->getTypePointer()->setQualifier(EvqConst); - } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize())); - else if ($1->isMatrix()) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize())); - else if ($1->isVector() && $1->getType().getQualifier() == EvqConst) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst)); - else if ($1->isVector()) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary)); - else - $$->setType($1->getType()); + $$ = context->addIndexExpression($1, @2, $3); } | function_call { $$ = $1; } - | postfix_expression DOT FIELD_SELECTION { + | postfix_expression DOT identifier { if ($1->isArray()) { - context->error($3.line, "cannot apply dot operator to an array", "."); + context->error(@3, "cannot apply dot operator to an array", "."); context->recover(); } if ($1->isVector()) { TVectorFields fields; - if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) { fields.num = 1; fields.offsets[0] = 0; context->recover(); } if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields - $$ = context->addConstVectorNode(fields, $1, $3.line); + $$ = context->addConstVectorNode(fields, $1, @3); if ($$ == 0) { context->recover(); $$ = $1; @@ -341,13 +281,13 @@ postfix_expression $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size())); } else { TString vectorString = *$3.string; - TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line); - $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addSwizzle(fields, @3); + $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size())); } } else if ($1->isMatrix()) { TMatrixFields fields; - if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) { fields.wholeRow = false; fields.wholeCol = false; fields.row = 0; @@ -356,84 +296,78 @@ postfix_expression } if (fields.wholeRow || fields.wholeCol) { - context->error($2.line, " non-scalar fields not implemented yet", "."); + context->error(@2, " non-scalar fields not implemented yet", "."); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(0); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize())); } else { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision())); } } else if ($1->getBasicType() == EbtStruct) { bool fieldFound = false; - const TTypeList* fields = $1->getType().getStruct(); - if (fields == 0) { - context->error($2.line, "structure has no fields", "Internal Error"); - context->recover(); - $$ = $1; - } else { - unsigned int i; - for (i = 0; i < fields->size(); ++i) { - if ((*fields)[i].type->getFieldName() == *$3.string) { - fieldFound = true; - break; - } + const TFieldList& fields = $1->getType().getStruct()->fields(); + unsigned int i; + for (i = 0; i < fields.size(); ++i) { + if (fields[i]->name() == *$3.string) { + fieldFound = true; + break; } - if (fieldFound) { - if ($1->getType().getQualifier() == EvqConst) { - $$ = context->addConstStruct(*$3.string, $1, $2.line); - if ($$ == 0) { - context->recover(); - $$ = $1; - } - else { - $$->setType(*(*fields)[i].type); - // change the qualifier of the return type, not of the structure field - // as the structure definition is shared between various structures. - $$->getTypePointer()->setQualifier(EvqConst); - } - } else { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(i); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line); - $$->setType(*(*fields)[i].type); + } + if (fieldFound) { + if ($1->getType().getQualifier() == EvqConst) { + $$ = context->addConstStruct(*$3.string, $1, @2); + if ($$ == 0) { + context->recover(); + $$ = $1; + } + else { + $$->setType(*fields[i]->type()); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + $$->getTypePointer()->setQualifier(EvqConst); } } else { - context->error($2.line, " no such field in structure", $3.string->c_str()); - context->recover(); - $$ = $1; + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3); + $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2); + $$->setType(*fields[i]->type()); } + } else { + context->error(@2, " no such field in structure", $3.string->c_str()); + context->recover(); + $$ = $1; } } else { - context->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); + context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); context->recover(); $$ = $1; } // don't delete $3.string, it's from the pool } | postfix_expression INC_OP { - if (context->lValueErrorCheck($2.line, "++", $1)) + if (context->lValueErrorCheck(@2, "++", $1)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable); if ($$ == 0) { - context->unaryOpError($2.line, "++", $1->getCompleteString()); + context->unaryOpError(@2, "++", $1->getCompleteString()); context->recover(); $$ = $1; } } | postfix_expression DEC_OP { - if (context->lValueErrorCheck($2.line, "--", $1)) + if (context->lValueErrorCheck(@2, "--", $1)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable); if ($$ == 0) { - context->unaryOpError($2.line, "--", $1->getCompleteString()); + context->unaryOpError(@2, "--", $1->getCompleteString()); context->recover(); $$ = $1; } @@ -461,18 +395,18 @@ function_call // Their parameters will be verified algorithmically. // TType type(EbtVoid, EbpUndefined); // use this to get the type back - if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) { + if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) { $$ = 0; } else { // // It's a constructor, of type 'type'. // - $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line); + $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1); } if ($$ == 0) { context->recover(); - $$ = context->intermediate.setAggregateOperator(0, op, $1.line); + $$ = context->intermediate.setAggregateOperator(0, op, @1); } $$->setType(type); } else { @@ -481,13 +415,13 @@ function_call // const TFunction* fnCandidate; bool builtIn; - fnCandidate = context->findFunction($1.line, fnCall, &builtIn); + fnCandidate = context->findFunction(@1, fnCall, &builtIn); if (fnCandidate) { // // A declared function. // if (builtIn && !fnCandidate->getExtension().empty() && - context->extensionErrorCheck($1.line, fnCandidate->getExtension())) { + context->extensionErrorCheck(@1, fnCandidate->getExtension())) { context->recover(); } op = fnCandidate->getBuiltInOp(); @@ -499,7 +433,7 @@ function_call // // Treat it like a built-in unary operator. // - $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable); + $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable); if ($$ == 0) { std::stringstream extraInfoStream; extraInfoStream << "built in unary operator function. Type: " << static_cast($1.intermNode)->getCompleteString(); @@ -508,12 +442,12 @@ function_call YYERROR; } } else { - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line); + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); } } else { // This is a real function call - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line); + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); $$->setType(fnCandidate->getReturnType()); // this is how we know whether the given function is a builtIn function or a user defined function @@ -540,7 +474,7 @@ function_call // Put on a dummy node for error recovery ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); context->recover(); } } @@ -553,7 +487,7 @@ function_call_or_method $$ = $1; } | postfix_expression DOT function_call_generic { - context->error($3.line, "methods are not supported", ""); + context->error(@3, "methods are not supported", ""); context->recover(); $$ = $3; } @@ -562,11 +496,9 @@ function_call_or_method function_call_generic : function_call_header_with_parameters RIGHT_PAREN { $$ = $1; - $$.line = $2.line; } | function_call_header_no_parameters RIGHT_PAREN { $$ = $1; - $$.line = $2.line; } ; @@ -592,7 +524,7 @@ function_call_header_with_parameters TParameter param = { 0, new TType($3->getType()) }; $1.function->addParameter(param); $$.function = $1.function; - $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, $2.line); + $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2); } ; @@ -617,39 +549,39 @@ function_identifier case EbtFloat: if ($1.matrix) { switch($1.size) { - case 2: op = EOpConstructMat2; break; - case 3: op = EOpConstructMat3; break; - case 4: op = EOpConstructMat4; break; + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; } } else { switch($1.size) { - case 1: op = EOpConstructFloat; break; - case 2: op = EOpConstructVec2; break; - case 3: op = EOpConstructVec3; break; - case 4: op = EOpConstructVec4; break; + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; } } break; case EbtInt: switch($1.size) { - case 1: op = EOpConstructInt; break; - case 2: FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break; - case 3: FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break; - case 4: FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break; + case 1: op = EOpConstructInt; break; + case 2: op = EOpConstructIVec2; break; + case 3: op = EOpConstructIVec3; break; + case 4: op = EOpConstructIVec4; break; } break; case EbtBool: switch($1.size) { - case 1: op = EOpConstructBool; break; - case 2: FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break; - case 3: FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break; - case 4: FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break; + case 1: op = EOpConstructBool; break; + case 2: op = EOpConstructBVec2; break; + case 3: op = EOpConstructBVec3; break; + case 4: op = EOpConstructBVec4; break; } break; default: break; } if (op == EOpNull) { - context->error($1.line, "cannot construct this type", getBasicString($1.type)); + context->error(@1, "cannot construct this type", getBasicString($1.type)); context->recover(); $1.type = EbtFloat; op = EOpConstructFloat; @@ -661,14 +593,7 @@ function_identifier $$ = function; } | IDENTIFIER { - if (context->reservedErrorCheck($1.line, *$1.string)) - context->recover(); - TType type(EbtVoid, EbpUndefined); - TFunction *function = new TFunction($1.string, type); - $$ = function; - } - | FIELD_SELECTION { - if (context->reservedErrorCheck($1.line, *$1.string)) + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); TType type(EbtVoid, EbpUndefined); TFunction *function = new TFunction($1.string, type); @@ -681,28 +606,28 @@ unary_expression $$ = $1; } | INC_OP unary_expression { - if (context->lValueErrorCheck($1.line, "++", $2)) + if (context->lValueErrorCheck(@1, "++", $2)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable); if ($$ == 0) { - context->unaryOpError($1.line, "++", $2->getCompleteString()); + context->unaryOpError(@1, "++", $2->getCompleteString()); context->recover(); $$ = $2; } } | DEC_OP unary_expression { - if (context->lValueErrorCheck($1.line, "--", $2)) + if (context->lValueErrorCheck(@1, "--", $2)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable); if ($$ == 0) { - context->unaryOpError($1.line, "--", $2->getCompleteString()); + context->unaryOpError(@1, "--", $2->getCompleteString()); context->recover(); $$ = $2; } } | unary_operator unary_expression { if ($1.op != EOpNull) { - $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable); if ($$ == 0) { const char* errorOp = ""; switch($1.op) { @@ -710,7 +635,7 @@ unary_expression case EOpLogicalNot: errorOp = "!"; break; default: break; } - context->unaryOpError($1.line, errorOp, $2->getCompleteString()); + context->unaryOpError(@1, errorOp, $2->getCompleteString()); context->recover(); $$ = $2; } @@ -721,28 +646,26 @@ unary_expression // Grammar Note: No traditional style type casts. unary_operator - : PLUS { $$.line = $1.line; $$.op = EOpNull; } - | DASH { $$.line = $1.line; $$.op = EOpNegative; } - | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; } + : PLUS { $$.op = EOpNull; } + | DASH { $$.op = EOpNegative; } + | BANG { $$.op = EOpLogicalNot; } ; // Grammar Note: No '*' or '&' unary ops. Pointers are not supported. multiplicative_expression : unary_expression { $$ = $1; } | multiplicative_expression STAR unary_expression { - FRAG_VERT_ONLY("*", $2.line); - $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } } | multiplicative_expression SLASH unary_expression { - FRAG_VERT_ONLY("/", $2.line); - $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -752,17 +675,17 @@ multiplicative_expression additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } } | additive_expression DASH multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -776,43 +699,43 @@ shift_expression relational_expression : shift_expression { $$ = $1; } | relational_expression LEFT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression LE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression GE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -820,23 +743,23 @@ relational_expression equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | equality_expression NE_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -856,13 +779,13 @@ inclusive_or_expression logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -870,13 +793,13 @@ logical_and_expression logical_xor_expression : logical_and_expression { $$ = $1; } | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -884,13 +807,13 @@ logical_xor_expression logical_or_expression : logical_xor_expression { $$ = $1; } | logical_or_expression OR_OP logical_xor_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -898,15 +821,15 @@ logical_or_expression conditional_expression : logical_or_expression { $$ = $1; } | logical_or_expression QUESTION expression COLON assignment_expression { - if (context->boolErrorCheck($2.line, $1)) + if (context->boolErrorCheck(@2, $1)) context->recover(); - $$ = context->intermediate.addSelection($1, $3, $5, $2.line); + $$ = context->intermediate.addSelection($1, $3, $5, @2); if ($3->getType() != $5->getType()) $$ = 0; if ($$ == 0) { - context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString()); + context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString()); context->recover(); $$ = $5; } @@ -916,11 +839,11 @@ conditional_expression assignment_expression : conditional_expression { $$ = $1; } | unary_expression assignment_operator assignment_expression { - if (context->lValueErrorCheck($2.line, "assign", $1)) + if (context->lValueErrorCheck(@2, "assign", $1)) context->recover(); - $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line); + $$ = context->intermediate.addAssign($2.op, $1, $3, @2); if ($$ == 0) { - context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString()); + context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -928,11 +851,11 @@ assignment_expression ; assignment_operator - : EQUAL { $$.line = $1.line; $$.op = EOpAssign; } - | MUL_ASSIGN { FRAG_VERT_ONLY("*=", $1.line); $$.line = $1.line; $$.op = EOpMulAssign; } - | DIV_ASSIGN { FRAG_VERT_ONLY("/=", $1.line); $$.line = $1.line; $$.op = EOpDivAssign; } - | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; } - | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; } + : EQUAL { $$.op = EOpAssign; } + | MUL_ASSIGN { $$.op = EOpMulAssign; } + | DIV_ASSIGN { $$.op = EOpDivAssign; } + | ADD_ASSIGN { $$.op = EOpAddAssign; } + | SUB_ASSIGN { $$.op = EOpSubAssign; } ; expression @@ -940,9 +863,9 @@ expression $$ = $1; } | expression COMMA assignment_expression { - $$ = context->intermediate.addComma($1, $3, $2.line); + $$ = context->intermediate.addComma($1, $3, @2); if ($$ == 0) { - context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $3; } @@ -970,13 +893,13 @@ declaration const TParameter ¶m = function.getParam(i); if (param.name != 0) { - TVariable *variable = new TVariable(param.name, *param.type); + TVariable variable(param.name, *param.type); - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1); } else { - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1); } } @@ -992,11 +915,11 @@ declaration } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { - context->error($1.line, "precision is not supported in fragment shader", "highp"); + context->error(@1, "precision is not supported in fragment shader", "highp"); context->recover(); } if (!context->symbolTable.setDefaultPrecision( $3, $2 )) { - context->error($1.line, "illegal type argument for default precision qualifier", getBasicString($3.type)); + context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type)); context->recover(); } $$ = 0; @@ -1016,24 +939,41 @@ function_prototype TFunction* prevDec = static_cast(context->symbolTable.find($1->getMangledName())); if (prevDec) { if (prevDec->getReturnType() != $1->getReturnType()) { - context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); + context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); context->recover(); } for (size_t i = 0; i < prevDec->getParamCount(); ++i) { if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) { - context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); + context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); context->recover(); } } } + // + // Check for previously declared variables using the same name. + // + TSymbol *prevSym = context->symbolTable.find($1->getName()); + if (prevSym) + { + if (!prevSym->isFunction()) + { + context->error(@2, "redefinition", $1->getName().c_str(), "function"); + context->recover(); + } + } + else + { + // Insert the unmangled name to detect potential future redefinition as a variable. + context->symbolTable.getOuterLevel()->insert($1->getName(), *$1); + } + // // If this is a redeclaration, it could also be a definition, // in which case, we want to use the variable names from this one, and not the one that's // being redeclared. So, pass back up this declaration, not the one in the symbol table. // $$.function = $1; - $$.line = $2.line; // We're at the inner scope level of the function's arguments and body statement. // Add the function prototype to the surrounding scope instead. @@ -1069,7 +1009,7 @@ function_header_with_parameters // // This parameter > first is void // - context->error($2.line, "cannot be an argument type except for '(void)'", "void"); + context->error(@2, "cannot be an argument type except for '(void)'", "void"); context->recover(); delete $3.param.type; } else { @@ -1083,11 +1023,11 @@ function_header_with_parameters function_header : fully_specified_type IDENTIFIER LEFT_PAREN { if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) { - context->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier)); + context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier)); context->recover(); } // make sure a sampler is not involved as well... - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); // Add the function as a prototype after parsing it (we do not support recursion) @@ -1102,33 +1042,31 @@ function_header parameter_declarator // Type + name - : type_specifier IDENTIFIER { + : type_specifier identifier { if ($1.type == EbtVoid) { - context->error($2.line, "illegal use of type 'void'", $2.string->c_str()); + context->error(@2, "illegal use of type 'void'", $2.string->c_str()); context->recover(); } - if (context->reservedErrorCheck($2.line, *$2.string)) + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); TParameter param = {$2.string, new TType($1)}; - $$.line = $2.line; $$.param = param; } - | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { // Check that we can make an array out of this type - if (context->arrayTypeErrorCheck($3.line, $1)) + if (context->arrayTypeErrorCheck(@3, $1)) context->recover(); - if (context->reservedErrorCheck($2.line, *$2.string)) + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); int size; - if (context->arraySizeErrorCheck($3.line, $4, size)) + if (context->arraySizeErrorCheck(@3, $4, size)) context->recover(); $1.setArray(true, size); TType* type = new TType($1); TParameter param = { $2.string, type }; - $$.line = $2.line; $$.param = param; } ; @@ -1144,14 +1082,14 @@ parameter_declaration // : type_qualifier parameter_qualifier parameter_declarator { $$ = $3; - if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) context->recover(); } | parameter_qualifier parameter_declarator { $$ = $2; - if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) context->recover(); - if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) context->recover(); } // @@ -1159,14 +1097,14 @@ parameter_declaration // | type_qualifier parameter_qualifier parameter_type_specifier { $$ = $3; - if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) context->recover(); } | parameter_qualifier parameter_type_specifier { $$ = $2; - if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) context->recover(); - if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) context->recover(); } ; @@ -1197,83 +1135,83 @@ init_declarator_list : single_declaration { $$ = $1; } - | init_declarator_list COMMA IDENTIFIER { + | init_declarator_list COMMA identifier { if ($1.type.type == EbtInvariant && !$3.symbol) { - context->error($3.line, "undeclared identifier declared as invariant", $3.string->c_str()); + context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str()); context->recover(); } - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3); - if (context->structQualifierErrorCheck($3.line, $$.type)) + if (context->structQualifierErrorCheck(@3, $$.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type, false)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false)) context->recover(); TVariable* variable = 0; - if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable)) + if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable)) context->recover(); if (symbol && variable) symbol->setId(variable->getUniqueId()); } - | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) context->recover(); $$ = $1; - if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) context->recover(); else { $1.type.setArray(true); TVariable* variable; - if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) context->recover(); } } - | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) context->recover(); $$ = $1; - if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($4.line, $5, size)) + if (context->arraySizeErrorCheck(@4, $5, size)) context->recover(); $1.type.setArray(true, size); TVariable* variable = 0; - if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) context->recover(); TType type = TType($1.type); type.setArraySize(size); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3); } } - | init_declarator_list COMMA IDENTIFIER EQUAL initializer { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier EQUAL initializer { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); $$ = $1; TIntermNode* intermNode; - if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) { + if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) { // // build the intermediate representation // if (intermNode) - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4); else $$.intermAggregate = $1.intermAggregate; } else { @@ -1286,79 +1224,79 @@ init_declarator_list single_declaration : fully_specified_type { $$.type = $1; - $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line); + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1); } - | fully_specified_type IDENTIFIER { - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + | fully_specified_type identifier { + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - if (context->structQualifierErrorCheck($2.line, $$.type)) + if (context->structQualifierErrorCheck(@2, $$.type)) context->recover(); - if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false)) + if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false)) context->recover(); $$.type = $1; TVariable* variable = 0; - if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable)) + if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable)) context->recover(); if (variable && symbol) symbol->setId(variable->getUniqueId()); } - | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { - context->error($2.line, "unsized array declarations not supported", $2.string->c_str()); + | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET { + context->error(@2, "unsized array declarations not supported", $2.string->c_str()); context->recover(); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); $$.type = $1; } - | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { TType type = TType($1); int size; - if (context->arraySizeErrorCheck($2.line, $4, size)) + if (context->arraySizeErrorCheck(@2, $4, size)) context->recover(); type.setArraySize(size); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); - if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true)) + if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true)) context->recover(); $$.type = $1; - if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1)) + if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($3.line, $4, size)) + if (context->arraySizeErrorCheck(@3, $4, size)) context->recover(); $1.setArray(true, size); TVariable* variable = 0; - if (context->arrayErrorCheck($3.line, *$2.string, $1, variable)) + if (context->arrayErrorCheck(@3, *$2.string, $1, variable)) context->recover(); if (variable && symbol) symbol->setId(variable->getUniqueId()); } } - | fully_specified_type IDENTIFIER EQUAL initializer { - if (context->structQualifierErrorCheck($2.line, $1)) + | fully_specified_type identifier EQUAL initializer { + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); $$.type = $1; TIntermNode* intermNode; - if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) { + if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) { // // Build intermediate representation // if(intermNode) - $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line); + $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3); else $$.intermAggregate = 0; } else { @@ -1367,118 +1305,50 @@ single_declaration } } | INVARIANT IDENTIFIER { - VERTEX_ONLY("invariant declaration", $1.line); - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying")) + VERTEX_ONLY("invariant declaration", @1); + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); - $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, $2.line); + $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); if (!$2.symbol) { - context->error($2.line, "undeclared identifier declared as invariant", $2.string->c_str()); + context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str()); context->recover(); $$.intermAggregate = 0; } else { - TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); } } - -// -// Place holder for the pack/unpack languages. -// -// | buffer_specifier { -// $$.intermAggregate = 0; -// } ; -// Grammar Note: No 'enum', or 'typedef'. - -// -// Place holder for the pack/unpack languages. -// -//%type buffer_declaration -//%type buffer_specifier input_or_output buffer_declaration_list -//buffer_specifier -// : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE { -// } -// ; -// -//input_or_output -// : INPUT { -// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input")) -// context->recover(); -// UNPACK_ONLY("input", $1.line); -// $$.qualifier = EvqInput; -// } -// | OUTPUT { -// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output")) -// context->recover(); -// PACK_ONLY("output", $1.line); -// $$.qualifier = EvqOutput; -// } -// ; - -// -// Place holder for the pack/unpack languages. -// -//buffer_declaration_list -// : buffer_declaration { -// } -// | buffer_declaration_list buffer_declaration { -// } -// ; - -// -// Input/output semantics: -// float must be 16 or 32 bits -// float alignment restrictions? -// check for only one input and only one output -// sum of bitfields has to be multiple of 32 -// - -// -// Place holder for the pack/unpack languages. -// -//buffer_declaration -// : type_specifier IDENTIFIER COLON constant_expression SEMICOLON { -// if (context->reservedErrorCheck($2.line, *$2.string, context)) -// context->recover(); -// $$.variable = new TVariable($2.string, $1); -// if (! context->symbolTable.insert(*$$.variable)) { -// context->error($2.line, "redefinition", $$.variable->getName().c_str()); -// context->recover(); -// // don't have to delete $$.variable, the pool pop will take care of it -// } -// } -// ; - fully_specified_type : type_specifier { $$ = $1; if ($1.array) { - context->error($1.line, "not supported", "first-class array"); + context->error(@1, "not supported", "first-class array"); context->recover(); $1.setArray(false); } } | type_qualifier type_specifier { if ($2.array) { - context->error($2.line, "not supported", "first-class array"); + context->error(@2, "not supported", "first-class array"); context->recover(); $2.setArray(false); } if ($1.qualifier == EvqAttribute && ($2.type == EbtBool || $2.type == EbtInt)) { - context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier)); + context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); context->recover(); } if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) && ($2.type == EbtBool || $2.type == EbtInt)) { - context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier)); + context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); context->recover(); } $$ = $2; @@ -1488,34 +1358,34 @@ fully_specified_type type_qualifier : CONST_QUAL { - $$.setBasic(EbtVoid, EvqConst, $1.line); + $$.setBasic(EbtVoid, EvqConst, @1); } | ATTRIBUTE { - VERTEX_ONLY("attribute", $1.line); - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute")) + VERTEX_ONLY("attribute", @1); + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute")) context->recover(); - $$.setBasic(EbtVoid, EvqAttribute, $1.line); + $$.setBasic(EbtVoid, EvqAttribute, @1); } | VARYING { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "varying")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying")) context->recover(); if (context->shaderType == SH_VERTEX_SHADER) - $$.setBasic(EbtVoid, EvqVaryingOut, $1.line); + $$.setBasic(EbtVoid, EvqVaryingOut, @1); else - $$.setBasic(EbtVoid, EvqVaryingIn, $1.line); + $$.setBasic(EbtVoid, EvqVaryingIn, @1); } | INVARIANT VARYING { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); if (context->shaderType == SH_VERTEX_SHADER) - $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line); + $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1); else - $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line); + $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1); } | UNIFORM { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform")) context->recover(); - $$.setBasic(EbtVoid, EvqUniform, $1.line); + $$.setBasic(EbtVoid, EvqUniform, @1); } ; @@ -1525,7 +1395,7 @@ type_specifier if ($$.precision == EbpUndefined) { $$.precision = context->symbolTable.getDefaultPrecision($1.type); - if (context->precisionErrorCheck($1.line, $$.precision, $1.type)) { + if (context->precisionErrorCheck(@1, $$.precision, $1.type)) { context->recover(); } } @@ -1555,11 +1425,11 @@ type_specifier_no_prec | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { $$ = $1; - if (context->arrayTypeErrorCheck($2.line, $1)) + if (context->arrayTypeErrorCheck(@2, $1)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($2.line, $3, size)) + if (context->arraySizeErrorCheck(@2, $3, size)) context->recover(); $$.setArray(true, size); } @@ -1569,118 +1439,105 @@ type_specifier_no_prec type_specifier_nonarray : VOID_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtVoid, qual, $1.line); + $$.setBasic(EbtVoid, qual, @1); } | FLOAT_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); } | INT_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); } | BOOL_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); } -// | UNSIGNED INT_TYPE { -// PACK_UNPACK_ONLY("unsigned", $1.line); -// TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; -// $$.setBasic(EbtInt, qual, $1.line); -// } | VEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(2); } | VEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(3); } | VEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(4); } | BVEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(2); } | BVEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(3); } | BVEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(4); } | IVEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(2); } | IVEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(3); } | IVEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(4); } | MATRIX2 { - FRAG_VERT_ONLY("mat2", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(2, true); } | MATRIX3 { - FRAG_VERT_ONLY("mat3", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(3, true); } | MATRIX4 { - FRAG_VERT_ONLY("mat4", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(4, true); } | SAMPLER2D { - FRAG_VERT_ONLY("sampler2D", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSampler2D, qual, $1.line); + $$.setBasic(EbtSampler2D, qual, @1); } | SAMPLERCUBE { - FRAG_VERT_ONLY("samplerCube", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSamplerCube, qual, $1.line); + $$.setBasic(EbtSamplerCube, qual, @1); } | SAMPLER_EXTERNAL_OES { if (!context->supportsExtension("GL_OES_EGL_image_external")) { - context->error($1.line, "unsupported type", "samplerExternalOES"); + context->error(@1, "unsupported type", "samplerExternalOES"); context->recover(); } - FRAG_VERT_ONLY("samplerExternalOES", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSamplerExternalOES, qual, $1.line); + $$.setBasic(EbtSamplerExternalOES, qual, @1); } | SAMPLER2DRECT { if (!context->supportsExtension("GL_ARB_texture_rectangle")) { - context->error($1.line, "unsupported type", "sampler2DRect"); + context->error(@1, "unsupported type", "sampler2DRect"); context->recover(); } - FRAG_VERT_ONLY("sampler2DRect", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSampler2DRect, qual, $1.line); + $$.setBasic(EbtSampler2DRect, qual, @1); } | struct_specifier { - FRAG_VERT_ONLY("struct", $1.line); $$ = $1; $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; } @@ -1691,29 +1548,29 @@ type_specifier_nonarray // TType& structure = static_cast($1.symbol)->getType(); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtStruct, qual, $1.line); + $$.setBasic(EbtStruct, qual, @1); $$.userDef = &structure; } ; struct_specifier - : STRUCT IDENTIFIER LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - if (context->reservedErrorCheck($2.line, *$2.string)) + : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); - TType* structure = new TType($5, *$2.string); + TType* structure = new TType(new TStructure($2.string, $5)); TVariable* userTypeDef = new TVariable($2.string, *structure, true); if (! context->symbolTable.insert(*userTypeDef)) { - context->error($2.line, "redefinition", $2.string->c_str(), "struct"); + context->error(@2, "redefinition", $2.string->c_str(), "struct"); context->recover(); } - $$.setBasic(EbtStruct, EvqTemporary, $1.line); + $$.setBasic(EbtStruct, EvqTemporary, @1); $$.userDef = structure; context->exitStructDeclaration(); } - | STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - TType* structure = new TType($4, TString("")); - $$.setBasic(EbtStruct, EvqTemporary, $1.line); + | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { + TType* structure = new TType(new TStructure(NewPoolTString(""), $4)); + $$.setBasic(EbtStruct, EvqTemporary, @1); $$.userDef = structure; context->exitStructDeclaration(); } @@ -1725,14 +1582,15 @@ struct_declaration_list } | struct_declaration_list struct_declaration { $$ = $1; - for (unsigned int i = 0; i < $2->size(); ++i) { - for (unsigned int j = 0; j < $$->size(); ++j) { - if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) { - context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str()); + for (size_t i = 0; i < $2->size(); ++i) { + TField* field = (*$2)[i]; + for (size_t j = 0; j < $$->size(); ++j) { + if ((*$$)[j]->name() == field->name()) { + context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str()); context->recover(); } } - $$->push_back((*$2)[i]); + $$->push_back(field); } } ; @@ -1741,14 +1599,14 @@ struct_declaration : type_specifier struct_declarator_list SEMICOLON { $$ = $2; - if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { + if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) { context->recover(); } for (unsigned int i = 0; i < $$->size(); ++i) { // // Careful not to replace already known aspects of type, like array-ness // - TType* type = (*$$)[i].type; + TType* type = (*$$)[i]->type(); type->setBasicType($1.type); type->setNominalSize($1.size); type->setMatrix($1.matrix); @@ -1756,26 +1614,23 @@ struct_declaration // don't allow arrays of arrays if (type->isArray()) { - if (context->arrayTypeErrorCheck($1.line, $1)) + if (context->arrayTypeErrorCheck(@1, $1)) context->recover(); } if ($1.array) type->setArraySize($1.arraySize); - if ($1.userDef) { + if ($1.userDef) type->setStruct($1.userDef->getStruct()); - type->setTypeName($1.userDef->getTypeName()); - } - if (context->structNestingErrorCheck($1.line, *type)) { + if (context->structNestingErrorCheck(@1, *(*$$)[i])) context->recover(); - } } } ; struct_declarator_list : struct_declarator { - $$ = NewPoolTTypeList(); + $$ = NewPoolTFieldList(); $$->push_back($1); } | struct_declarator_list COMMA struct_declarator { @@ -1784,26 +1639,24 @@ struct_declarator_list ; struct_declarator - : IDENTIFIER { - if (context->reservedErrorCheck($1.line, *$1.string)) + : identifier { + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); - $$.type = new TType(EbtVoid, EbpUndefined); - $$.line = $1.line; - $$.type->setFieldName(*$1.string); + TType* type = new TType(EbtVoid, EbpUndefined); + $$ = new TField(type, $1.string); } - | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->reservedErrorCheck($1.line, *$1.string)) + | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); - $$.type = new TType(EbtVoid, EbpUndefined); - $$.line = $1.line; - $$.type->setFieldName(*$1.string); - - int size; - if (context->arraySizeErrorCheck($2.line, $3, size)) + TType* type = new TType(EbtVoid, EbpUndefined); + int size = 0; + if (context->arraySizeErrorCheck(@3, $3, size)) context->recover(); - $$.type->setArraySize(size); + type->setArraySize(size); + + $$ = new TField(type, $1.string); } ; @@ -1835,7 +1688,7 @@ compound_statement | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { if ($3 != 0) { $3->setOp(EOpSequence); - $3->setEndLine($5.line); + $3->setLine(@$); } $$ = $3; } @@ -1859,7 +1712,7 @@ compound_statement_no_new_scope | LEFT_BRACE statement_list RIGHT_BRACE { if ($2) { $2->setOp(EOpSequence); - $2->setEndLine($3.line); + $2->setLine(@$); } $$ = $2; } @@ -1867,10 +1720,10 @@ compound_statement_no_new_scope statement_list : statement { - $$ = context->intermediate.makeAggregate($1, 0); + $$ = context->intermediate.makeAggregate($1, @$); } | statement_list statement { - $$ = context->intermediate.growAggregate($1, $2, 0); + $$ = context->intermediate.growAggregate($1, $2, @$); } ; @@ -1881,9 +1734,9 @@ expression_statement selection_statement : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - if (context->boolErrorCheck($1.line, $3)) + if (context->boolErrorCheck(@1, $3)) context->recover(); - $$ = context->intermediate.addSelection($3, $5, $1.line); + $$ = context->intermediate.addSelection($3, $5, @1); } ; @@ -1907,14 +1760,14 @@ condition if (context->boolErrorCheck($1->getLine(), $1)) context->recover(); } - | fully_specified_type IDENTIFIER EQUAL initializer { + | fully_specified_type identifier EQUAL initializer { TIntermNode* intermNode; - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); - if (context->boolErrorCheck($2.line, $1)) + if (context->boolErrorCheck(@2, $1)) context->recover(); - if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) + if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) $$ = $4; else { context->recover(); @@ -1926,19 +1779,19 @@ condition iteration_statement : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); - $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, $1.line); + $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1); --context->loopNestingLevel; } | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - if (context->boolErrorCheck($8.line, $6)) + if (context->boolErrorCheck(@8, $6)) context->recover(); - $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line); + $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); --context->loopNestingLevel; } | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); - $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, $1.line); + $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, @1); --context->loopNestingLevel; } ; @@ -1975,39 +1828,39 @@ for_rest_statement jump_statement : CONTINUE SEMICOLON { if (context->loopNestingLevel <= 0) { - context->error($1.line, "continue statement only allowed in loops", ""); + context->error(@1, "continue statement only allowed in loops", ""); context->recover(); } - $$ = context->intermediate.addBranch(EOpContinue, $1.line); + $$ = context->intermediate.addBranch(EOpContinue, @1); } | BREAK SEMICOLON { if (context->loopNestingLevel <= 0) { - context->error($1.line, "break statement only allowed in loops", ""); + context->error(@1, "break statement only allowed in loops", ""); context->recover(); } - $$ = context->intermediate.addBranch(EOpBreak, $1.line); + $$ = context->intermediate.addBranch(EOpBreak, @1); } | RETURN SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $1.line); + $$ = context->intermediate.addBranch(EOpReturn, @1); if (context->currentFunctionType->getBasicType() != EbtVoid) { - context->error($1.line, "non-void function must return a value", "return"); + context->error(@1, "non-void function must return a value", "return"); context->recover(); } } | RETURN expression SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $2, $1.line); + $$ = context->intermediate.addBranch(EOpReturn, $2, @1); context->functionReturnsValue = true; if (context->currentFunctionType->getBasicType() == EbtVoid) { - context->error($1.line, "void function cannot return a value", "return"); + context->error(@1, "void function cannot return a value", "return"); context->recover(); } else if (*(context->currentFunctionType) != $2->getType()) { - context->error($1.line, "function return is not matching type:", "return"); + context->error(@1, "function return is not matching type:", "return"); context->recover(); } } | DISCARD SEMICOLON { - FRAG_ONLY("discard", $1.line); - $$ = context->intermediate.addBranch(EOpKill, $1.line); + FRAG_ONLY("discard", @1); + $$ = context->intermediate.addBranch(EOpKill, @1); } ; @@ -2019,7 +1872,7 @@ translation_unit context->treeRoot = $$; } | translation_unit external_declaration { - $$ = context->intermediate.growAggregate($1, $2, 0); + $$ = context->intermediate.growAggregate($1, $2, @$); context->treeRoot = $$; } ; @@ -2041,7 +1894,7 @@ function_definition if (builtIn) { - context->error($1.line, "built-in functions cannot be redefined", function->getName().c_str()); + context->error(@1, "built-in functions cannot be redefined", function->getName().c_str()); context->recover(); } @@ -2055,7 +1908,7 @@ function_definition // // Then this function already has a body. // - context->error($1.line, "function already has a body", function->getName().c_str()); + context->error(@1, "function already has a body", function->getName().c_str()); context->recover(); } prevDec->setDefined(); @@ -2065,11 +1918,11 @@ function_definition // if (function->getName() == "main") { if (function->getParamCount() > 0) { - context->error($1.line, "function cannot take any parameter(s)", function->getName().c_str()); + context->error(@1, "function cannot take any parameter(s)", function->getName().c_str()); context->recover(); } if (function->getReturnType().getBasicType() != EbtVoid) { - context->error($1.line, "", function->getReturnType().getBasicString(), "main function cannot return a value"); + context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value"); context->recover(); } } @@ -2097,7 +1950,7 @@ function_definition // Insert the parameters with name in the symbol table. // if (! context->symbolTable.insert(*variable)) { - context->error($1.line, "redefinition", variable->getName().c_str()); + context->error(@1, "redefinition", variable->getName().c_str()); context->recover(); delete variable; } @@ -2108,14 +1961,15 @@ function_definition paramNodes = context->intermediate.growAggregate( paramNodes, context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), $1.line), - $1.line); + variable->getName(), + variable->getType(), + @1), + @1); } else { - paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1); } } - context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line); + context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1); $1.intermAggregate = paramNodes; context->loopNestingLevel = 0; } @@ -2123,12 +1977,12 @@ function_definition //?? Check that all paths return a value if return type != void ? // May be best done as post process phase on intermediate code if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { - context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str()); + context->error(@1, "function does not return a value:", "", $1.function->getName().c_str()); context->recover(); } - $$ = context->intermediate.growAggregate($1.intermAggregate, $3, 0); - context->intermediate.setAggregateOperator($$, EOpFunction, $1.line); + $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$); + context->intermediate.setAggregateOperator($$, EOpFunction, @1); $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); $$->getAsAggregate()->setType($1.function->getReturnType()); @@ -2137,9 +1991,6 @@ function_definition $$->getAsAggregate()->setOptimize(context->pragma().optimize); $$->getAsAggregate()->setDebug(context->pragma().debug); - if ($3 && $3->getAsAggregate()) - $$->getAsAggregate()->setEndLine($3->getAsAggregate()->getEndLine()); - context->symbolTable.pop(); } ; diff --git a/src/3rdparty/angle/src/compiler/intermOut.cpp b/src/3rdparty/angle/src/compiler/intermOut.cpp index f48a049c63..13aa96af6d 100644 --- a/src/3rdparty/angle/src/compiler/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/intermOut.cpp @@ -189,7 +189,9 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) case EOpAny: out << "any"; break; case EOpAll: out << "all"; break; - default: out.message(EPrefixError, "Bad unary op"); + default: + out.prefix(EPrefixError); + out << "Bad unary op"; } out << " (" << node->getCompleteString() << ")"; @@ -204,7 +206,8 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) TInfoSinkBase& out = sink; if (node->getOp() == EOpNull) { - out.message(EPrefixError, "node is still EOpNull!"); + out.prefix(EPrefixError); + out << "node is still EOpNull!"; return true; } @@ -263,7 +266,9 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) case EOpDeclaration: out << "Declaration: "; break; - default: out.message(EPrefixError, "Bad aggregation op"); + default: + out.prefix(EPrefixError); + out << "Bad aggregation op"; } if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) @@ -311,9 +316,9 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) { TInfoSinkBase& out = sink; - int size = node->getType().getObjectSize(); + size_t size = node->getType().getObjectSize(); - for (int i = 0; i < size; i++) { + for (size_t i = 0; i < size; i++) { OutputTreeText(out, node, depth); switch (node->getUnionArrayPointer()[i].getType()) { case EbtBool: @@ -334,7 +339,7 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) out << " (const int)\n"; break; default: - out.message(EPrefixInternalError, "Unknown constant", node->getLine()); + out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); break; } } diff --git a/src/3rdparty/angle/src/compiler/intermediate.h b/src/3rdparty/angle/src/compiler/intermediate.h index 8e76ef921f..738621fe70 100644 --- a/src/3rdparty/angle/src/compiler/intermediate.h +++ b/src/3rdparty/angle/src/compiler/intermediate.h @@ -18,6 +18,7 @@ #include "GLSLANG/ShaderLang.h" +#include #include "compiler/Common.h" #include "compiler/Types.h" #include "compiler/ConstantUnion.h" @@ -204,12 +205,17 @@ class TInfoSink; // class TIntermNode { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - - TIntermNode() : line(0) {} + POOL_ALLOCATOR_NEW_DELETE(); + TIntermNode() { + // TODO: Move this to TSourceLoc constructor + // after getting rid of TPublicType. + line.first_file = line.last_file = 0; + line.first_line = line.last_line = 0; + } + virtual ~TIntermNode() { } - TSourceLoc getLine() const { return line; } - void setLine(TSourceLoc l) { line = l; } + const TSourceLoc& getLine() const { return line; } + void setLine(const TSourceLoc& l) { line = l; } virtual void traverse(TIntermTraverser*) = 0; virtual TIntermTyped* getAsTyped() { return 0; } @@ -220,7 +226,6 @@ public: virtual TIntermSelection* getAsSelectionNode() { return 0; } virtual TIntermSymbol* getAsSymbolNode() { return 0; } virtual TIntermLoop* getAsLoopNode() { return 0; } - virtual ~TIntermNode() { } protected: TSourceLoc line; @@ -454,7 +459,7 @@ typedef TVector TQualifierList; // class TIntermAggregate : public TIntermOperator { public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), endLine(0), useEmulatedFunction(false) { } + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { } TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { } ~TIntermAggregate() { } @@ -474,9 +479,6 @@ public: void setDebug(bool d) { debug = d; } bool getDebug() { return debug; } - void setEndLine(TSourceLoc line) { endLine = line; } - TSourceLoc getEndLine() const { return endLine; } - void setUseEmulatedFunction() { useEmulatedFunction = true; } bool getUseEmulatedFunction() { return useEmulatedFunction; } @@ -489,7 +491,6 @@ protected: bool optimize; bool debug; - TSourceLoc endLine; // If set to true, replace the built-in function call with an emulated one // to work around driver bugs. @@ -538,14 +539,14 @@ enum Visit class TIntermTraverser { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - + POOL_ALLOCATOR_NEW_DELETE(); TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : preVisit(preVisit), inVisit(inVisit), postVisit(postVisit), rightToLeft(rightToLeft), - depth(0) {} + depth(0), + maxDepth(0) {} virtual ~TIntermTraverser() {}; virtual void visitSymbol(TIntermSymbol*) {} @@ -557,7 +558,8 @@ public: virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} - void incrementDepth() {depth++;} + int getMaxDepth() const {return maxDepth;} + void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); } void decrementDepth() {depth--;} // Return the original name if hash function pointer is NULL; @@ -571,6 +573,7 @@ public: protected: int depth; + int maxDepth; }; #endif // __INTERMEDIATE_H diff --git a/src/3rdparty/angle/src/compiler/localintermediate.h b/src/3rdparty/angle/src/compiler/localintermediate.h index 56890bd569..1214d821eb 100644 --- a/src/3rdparty/angle/src/compiler/localintermediate.h +++ b/src/3rdparty/angle/src/compiler/localintermediate.h @@ -22,37 +22,36 @@ struct TVectorFields { class TInfoSink; class TIntermediate { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - + POOL_ALLOCATOR_NEW_DELETE(); TIntermediate(TInfoSink& i) : infoSink(i) { } - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc); + + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); - TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&); - TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); - TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); - TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&); - TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc); - TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc); - TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc); - TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc); - TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc); - TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc); - TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc); + TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); + TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); + TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); + TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&); + TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&); TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; - bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); - TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc); - TIntermBranch* addBranch(TOperator, TSourceLoc); - TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); - TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc); + bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); + TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); + TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&); bool postProcess(TIntermNode*); - void remove(TIntermNode*); + void remove(TIntermNode*); void outputTree(TIntermNode*); - -protected: - TInfoSink& infoSink; private: void operator=(TIntermediate&); // prevent assignments + + TInfoSink& infoSink; }; #endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/parseConst.cpp b/src/3rdparty/angle/src/compiler/parseConst.cpp index 421d31f586..1cc5db8d77 100644 --- a/src/3rdparty/angle/src/compiler/parseConst.cpp +++ b/src/3rdparty/angle/src/compiler/parseConst.cpp @@ -38,16 +38,16 @@ protected: bool visitLoop(Visit visit, TIntermLoop*); bool visitBranch(Visit visit, TIntermBranch*); - int index; + size_t index; ConstantUnion *unionArray; TType type; TOperator constructorType; bool singleConstantParam; TInfoSink& infoSink; TSymbolTable& symbolTable; - int size; // size of the constructor ( 4 for vec4) + size_t size; // size of the constructor ( 4 for vec4) bool isMatrix; - int matrixSize; // dimension of the matrix (nominal size and not the instance size) + size_t matrixSize; // dimension of the matrix (nominal size and not the instance size) }; // @@ -61,7 +61,7 @@ protected: void TConstTraverser::visitSymbol(TIntermSymbol* node) { - infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor"); return; } @@ -74,12 +74,12 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) TString buf; buf.append("'constructor' : assigning non-constant to "); buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; return false; } - infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor"); return false; } @@ -89,7 +89,7 @@ bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) TString buf; buf.append("'constructor' : assigning non-constant to "); buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; return false; } @@ -100,7 +100,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) TString buf; buf.append("'constructor' : assigning non-constant to "); buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; return false; } @@ -144,7 +144,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) { - infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor"); error = true; return false; } @@ -159,16 +159,16 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) } ConstantUnion* leftUnionArray = unionArray; - int instanceSize = type.getObjectSize(); + size_t instanceSize = type.getObjectSize(); if (index >= instanceSize) return; if (!singleConstantParam) { - int size = node->getType().getObjectSize(); + size_t size = node->getType().getObjectSize(); ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - for (int i=0; i < size; i++) { + for (size_t i = 0; i < size; i++) { if (index >= instanceSize) return; leftUnionArray[index] = rightUnionArray[i]; @@ -176,11 +176,11 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) (index)++; } } else { - int totalSize = index + size; + size_t totalSize = index + size; ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); if (!isMatrix) { - int count = 0; - for (int i = index; i < totalSize; i++) { + size_t count = 0; + for (size_t i = index; i < totalSize; i++) { if (i >= instanceSize) return; @@ -192,9 +192,9 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) count++; } } else { // for matrix constructors - int count = 0; - int element = index; - for (int i = index; i < totalSize; i++) { + size_t count = 0; + size_t element = index; + for (size_t i = index; i < totalSize; i++) { if (i >= instanceSize) return; if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) @@ -213,14 +213,14 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) { - infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor"); error = true; return false; } bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) { - infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor"); error = true; return false; } @@ -230,7 +230,7 @@ bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) // Individual functions can be initialized to 0 to skip processing of that // type of node. It's children will still be processed. // -bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) +bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) { if (root == 0) return false; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp index 5ffc6420bc..b615c85dce 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp @@ -81,6 +81,11 @@ void Preprocessor::predefineMacro(const char* name, int value) mImpl->macroSet[name] = macro; } +void Preprocessor::setMaxTokenLength(size_t maxLength) +{ + mImpl->tokenizer.setMaxTokenLength(maxLength); +} + void Preprocessor::lex(Token* token) { bool validToken = false; @@ -95,34 +100,6 @@ void Preprocessor::lex(Token* token) case Token::PP_HASH: assert(false); break; - case Token::CONST_INT: - { - int val = 0; - if (!token->iValue(&val)) - { - // Do not mark the token as invalid. - // Just emit the diagnostic and reset value to 0. - mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - token->text.assign("0"); - } - validToken = true; - break; - } - case Token::CONST_FLOAT: - { - float val = 0; - if (!token->fValue(&val)) - { - // Do not mark the token as invalid. - // Just emit the diagnostic and reset value to 0.0. - mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW, - token->location, token->text); - token->text.assign("0.0"); - } - validToken = true; - break; - } case Token::PP_NUMBER: mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, token->location, token->text); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h index 7b70180fc8..9a90d79a1a 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h @@ -37,6 +37,12 @@ class Preprocessor bool init(size_t count, const char* const string[], const int length[]); // Adds a pre-defined macro. void predefineMacro(const char* name, int value); + // Sets maximum allowed token length. + // If token length exceeds this limit, + // the token text will be truncated to the given maximum length, and + // TOKEN_TOO_LONG diagnostic will be generated. + // The maximum length defaults to 256. + void setMaxTokenLength(size_t maxLength); void lex(Token* token); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h index 7a6fa87b04..9d131f865a 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h @@ -32,13 +32,13 @@ class Tokenizer : public Lexer bool leadingSpace; bool lineStart; }; - static const std::size_t kMaxTokenLength; Tokenizer(Diagnostics* diagnostics); ~Tokenizer(); bool init(size_t count, const char* const string[], const int length[]); + void setMaxTokenLength(size_t maxLength) { mMaxTokenLength = maxLength; } void setFileNumber(int file); void setLineNumber(int line); @@ -51,6 +51,7 @@ class Tokenizer : public Lexer void* mHandle; // Scanner handle. Context mContext; // Scanner extra. + size_t mMaxTokenLength; }; } // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l index fc81d84f37..01f0177b6c 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l @@ -267,11 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") namespace pp { -// TODO(alokp): Maximum token length should ideally be specified by -// the preprocessor client, i.e., the compiler. -const size_t Tokenizer::kMaxTokenLength = 256; - -Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0) +Tokenizer::Tokenizer(Diagnostics* diagnostics) + : mHandle(0), + mMaxTokenLength(256) { mContext.diagnostics = diagnostics; } @@ -304,11 +302,11 @@ void Tokenizer::setLineNumber(int line) void Tokenizer::lex(Token* token) { token->type = yylex(&token->text, &token->location, mHandle); - if (token->text.size() > kMaxTokenLength) + if (token->text.size() > mMaxTokenLength) { mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG, token->location, token->text); - token->text.erase(kMaxTokenLength); + token->text.erase(mMaxTokenLength); } token->flags = 0; diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp index 524c6cf53a..355eb62d65 100644 --- a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp +++ b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp @@ -10,8 +10,8 @@ void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node) { if (IsSampler(node->getBasicType())) { ++mNumErrors; - mSink.prefix(EPrefixError); - mSink.location(node->getLine()); - mSink << "Samplers are not permitted in vertex shaders.\n"; + mSink.message(EPrefixError, + node->getLine(), + "Samplers are not permitted in vertex shaders"); } } diff --git a/src/3rdparty/angle/src/compiler/util.cpp b/src/3rdparty/angle/src/compiler/util.cpp index b46e4d0e34..d6e5eeed91 100644 --- a/src/3rdparty/angle/src/compiler/util.cpp +++ b/src/3rdparty/angle/src/compiler/util.cpp @@ -4,30 +4,25 @@ // found in the LICENSE file. // -#include -#include +#include "compiler/util.h" -#include "util.h" +#include -#ifdef _MSC_VER - #include -#else - #include -#endif +#include "compiler/preprocessor/numeric_lex.h" -double atof_dot(const char *str) +bool atof_clamp(const char *str, float *value) { -#ifdef _MSC_VER - _locale_t l = _create_locale(LC_NUMERIC, "C"); - double result = _atof_l(str, l); - _free_locale(l); - return result; -#else - double result; - std::istringstream s(str); - std::locale l("C"); - s.imbue(l); - s >> result; - return result; -#endif + bool success = pp::numeric_lex_float(str, value); + if (!success) + *value = std::numeric_limits::max(); + return success; } + +bool atoi_clamp(const char *str, int *value) +{ + bool success = pp::numeric_lex_int(str, value); + if (!success) + *value = std::numeric_limits::max(); + return success; +} + diff --git a/src/3rdparty/angle/src/compiler/util.h b/src/3rdparty/angle/src/compiler/util.h index 35288b7396..dc69f39060 100644 --- a/src/3rdparty/angle/src/compiler/util.h +++ b/src/3rdparty/angle/src/compiler/util.h @@ -7,15 +7,14 @@ #ifndef COMPILER_UTIL_H #define COMPILER_UTIL_H -#ifdef __cplusplus -extern "C" { -#endif +// atof_clamp is like atof but +// 1. it forces C locale, i.e. forcing '.' as decimal point. +// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens. +// Return false if overflow happens. +extern bool atof_clamp(const char *str, float *value); -// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point. -double atof_dot(const char *str); - -#ifdef __cplusplus -} // end extern "C" -#endif +// If overflow happens, clamp the value to INT_MIN or INT_MAX. +// Return false if overflow happens. +extern bool atoi_clamp(const char *str, int *value); #endif // COMPILER_UTIL_H -- cgit v1.2.3