Apply the Apache 2.0 license. Change-Id: I4a7aeefedcd2d891093520d5a10ebefadcddb5be Reviewed-on: https://swiftshader-review.googlesource.com/5320 Reviewed-by: Nicolas Capens <capn@google.com> Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/compiler/AnalyzeCallDepth.cpp b/src/OpenGL/compiler/AnalyzeCallDepth.cpp index d4f30fa..60991af 100644 --- a/src/OpenGL/compiler/AnalyzeCallDepth.cpp +++ b/src/OpenGL/compiler/AnalyzeCallDepth.cpp
@@ -1,196 +1,204 @@ -// -// 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 "AnalyzeCallDepth.h" - -AnalyzeCallDepth::FunctionNode::FunctionNode(TIntermAggregate *node) : node(node) -{ - visit = PreVisit; - callDepth = 0; -} - -const TString &AnalyzeCallDepth::FunctionNode::getName() const -{ - return node->getName(); -} - -void AnalyzeCallDepth::FunctionNode::addCallee(AnalyzeCallDepth::FunctionNode *callee) -{ - for(size_t i = 0; i < callees.size(); i++) - { - if(callees[i] == callee) - { - return; - } - } - - callees.push_back(callee); -} - -unsigned int AnalyzeCallDepth::FunctionNode::analyzeCallDepth(AnalyzeCallDepth *analyzeCallDepth) -{ - ASSERT(visit == PreVisit); - ASSERT(analyzeCallDepth); - - callDepth = 0; - visit = InVisit; - - for(size_t i = 0; i < callees.size(); i++) - { - unsigned int calleeDepth = 0; - switch(callees[i]->visit) - { - case InVisit: - // Cycle detected (recursion) - return UINT_MAX; - case PostVisit: - calleeDepth = callees[i]->getLastDepth(); - break; - case PreVisit: - calleeDepth = callees[i]->analyzeCallDepth(analyzeCallDepth); - break; - default: - UNREACHABLE(callees[i]->visit); - break; - } - if(calleeDepth != UINT_MAX) ++calleeDepth; - callDepth = std::max(callDepth, calleeDepth); - } - - visit = PostVisit; - return callDepth; -} - -unsigned int AnalyzeCallDepth::FunctionNode::getLastDepth() const -{ - return callDepth; -} - -void AnalyzeCallDepth::FunctionNode::removeIfUnreachable() -{ - if(visit == PreVisit) - { - node->setOp(EOpPrototype); - node->getSequence().resize(1); // Remove function body - } -} - -AnalyzeCallDepth::AnalyzeCallDepth(TIntermNode *root) - : TIntermTraverser(true, false, true, false), - currentFunction(0) -{ - root->traverse(this); -} - -AnalyzeCallDepth::~AnalyzeCallDepth() -{ - for(size_t i = 0; i < functions.size(); i++) - { - delete functions[i]; - } -} - -bool AnalyzeCallDepth::visitAggregate(Visit visit, TIntermAggregate *node) -{ - switch(node->getOp()) - { - case EOpFunction: // Function definition - { - if(visit == PreVisit) - { - currentFunction = findFunctionByName(node->getName()); - - if(!currentFunction) - { - currentFunction = new FunctionNode(node); - functions.push_back(currentFunction); - } - } - else if(visit == PostVisit) - { - currentFunction = 0; - } - } - break; - case EOpFunctionCall: - { - if(!node->isUserDefined()) - { - return true; // Check the arguments for function calls - } - - if(visit == PreVisit) - { - FunctionNode *function = findFunctionByName(node->getName()); - - if(!function) - { - function = new FunctionNode(node); - functions.push_back(function); - } - - if(currentFunction) - { - currentFunction->addCallee(function); - } - else - { - globalFunctionCalls.insert(function); - } - } - } - break; - default: - break; - } - - return true; -} - -unsigned int AnalyzeCallDepth::analyzeCallDepth() -{ - FunctionNode *main = findFunctionByName("main("); - - if(!main) - { - return 0; - } - - unsigned int depth = main->analyzeCallDepth(this); - if(depth != UINT_MAX) ++depth; - - for(FunctionSet::iterator globalCall = globalFunctionCalls.begin(); globalCall != globalFunctionCalls.end(); globalCall++) - { - unsigned int globalDepth = (*globalCall)->analyzeCallDepth(this); - if(globalDepth != UINT_MAX) ++globalDepth; - - if(globalDepth > depth) - { - depth = globalDepth; - } - } - - for(size_t i = 0; i < functions.size(); i++) - { - functions[i]->removeIfUnreachable(); - } - - return depth; -} - -AnalyzeCallDepth::FunctionNode *AnalyzeCallDepth::findFunctionByName(const TString &name) -{ - for(size_t i = 0; i < functions.size(); i++) - { - if(functions[i]->getName() == name) - { - return functions[i]; - } - } - - return 0; -} - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "AnalyzeCallDepth.h" + +AnalyzeCallDepth::FunctionNode::FunctionNode(TIntermAggregate *node) : node(node) +{ + visit = PreVisit; + callDepth = 0; +} + +const TString &AnalyzeCallDepth::FunctionNode::getName() const +{ + return node->getName(); +} + +void AnalyzeCallDepth::FunctionNode::addCallee(AnalyzeCallDepth::FunctionNode *callee) +{ + for(size_t i = 0; i < callees.size(); i++) + { + if(callees[i] == callee) + { + return; + } + } + + callees.push_back(callee); +} + +unsigned int AnalyzeCallDepth::FunctionNode::analyzeCallDepth(AnalyzeCallDepth *analyzeCallDepth) +{ + ASSERT(visit == PreVisit); + ASSERT(analyzeCallDepth); + + callDepth = 0; + visit = InVisit; + + for(size_t i = 0; i < callees.size(); i++) + { + unsigned int calleeDepth = 0; + switch(callees[i]->visit) + { + case InVisit: + // Cycle detected (recursion) + return UINT_MAX; + case PostVisit: + calleeDepth = callees[i]->getLastDepth(); + break; + case PreVisit: + calleeDepth = callees[i]->analyzeCallDepth(analyzeCallDepth); + break; + default: + UNREACHABLE(callees[i]->visit); + break; + } + if(calleeDepth != UINT_MAX) ++calleeDepth; + callDepth = std::max(callDepth, calleeDepth); + } + + visit = PostVisit; + return callDepth; +} + +unsigned int AnalyzeCallDepth::FunctionNode::getLastDepth() const +{ + return callDepth; +} + +void AnalyzeCallDepth::FunctionNode::removeIfUnreachable() +{ + if(visit == PreVisit) + { + node->setOp(EOpPrototype); + node->getSequence().resize(1); // Remove function body + } +} + +AnalyzeCallDepth::AnalyzeCallDepth(TIntermNode *root) + : TIntermTraverser(true, false, true, false), + currentFunction(0) +{ + root->traverse(this); +} + +AnalyzeCallDepth::~AnalyzeCallDepth() +{ + for(size_t i = 0; i < functions.size(); i++) + { + delete functions[i]; + } +} + +bool AnalyzeCallDepth::visitAggregate(Visit visit, TIntermAggregate *node) +{ + switch(node->getOp()) + { + case EOpFunction: // Function definition + { + if(visit == PreVisit) + { + currentFunction = findFunctionByName(node->getName()); + + if(!currentFunction) + { + currentFunction = new FunctionNode(node); + functions.push_back(currentFunction); + } + } + else if(visit == PostVisit) + { + currentFunction = 0; + } + } + break; + case EOpFunctionCall: + { + if(!node->isUserDefined()) + { + return true; // Check the arguments for function calls + } + + if(visit == PreVisit) + { + FunctionNode *function = findFunctionByName(node->getName()); + + if(!function) + { + function = new FunctionNode(node); + functions.push_back(function); + } + + if(currentFunction) + { + currentFunction->addCallee(function); + } + else + { + globalFunctionCalls.insert(function); + } + } + } + break; + default: + break; + } + + return true; +} + +unsigned int AnalyzeCallDepth::analyzeCallDepth() +{ + FunctionNode *main = findFunctionByName("main("); + + if(!main) + { + return 0; + } + + unsigned int depth = main->analyzeCallDepth(this); + if(depth != UINT_MAX) ++depth; + + for(FunctionSet::iterator globalCall = globalFunctionCalls.begin(); globalCall != globalFunctionCalls.end(); globalCall++) + { + unsigned int globalDepth = (*globalCall)->analyzeCallDepth(this); + if(globalDepth != UINT_MAX) ++globalDepth; + + if(globalDepth > depth) + { + depth = globalDepth; + } + } + + for(size_t i = 0; i < functions.size(); i++) + { + functions[i]->removeIfUnreachable(); + } + + return depth; +} + +AnalyzeCallDepth::FunctionNode *AnalyzeCallDepth::findFunctionByName(const TString &name) +{ + for(size_t i = 0; i < functions.size(); i++) + { + if(functions[i]->getName() == name) + { + return functions[i]; + } + } + + return 0; +} +
diff --git a/src/OpenGL/compiler/AnalyzeCallDepth.h b/src/OpenGL/compiler/AnalyzeCallDepth.h index f0621e9..b2ca07a 100644 --- a/src/OpenGL/compiler/AnalyzeCallDepth.h +++ b/src/OpenGL/compiler/AnalyzeCallDepth.h
@@ -1,55 +1,63 @@ -// -// 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_ANALYZE_CALL_DEPTH_H_ -#define COMPILER_ANALYZE_CALL_DEPTH_H_ - -#include "intermediate.h" - -#include <set> -#include <limits.h> - -// Traverses intermediate tree to analyze call depth or detect function recursion -class AnalyzeCallDepth : public TIntermTraverser -{ -public: - AnalyzeCallDepth(TIntermNode *root); - ~AnalyzeCallDepth(); - - virtual bool visitAggregate(Visit, TIntermAggregate*); - - unsigned int analyzeCallDepth(); - -private: - class FunctionNode - { - public: - FunctionNode(TIntermAggregate *node); - - const TString &getName() const; - void addCallee(FunctionNode *callee); - unsigned int analyzeCallDepth(AnalyzeCallDepth *analyzeCallDepth); - unsigned int getLastDepth() const; - - void removeIfUnreachable(); - - private: - TIntermAggregate *const node; - TVector<FunctionNode*> callees; - - Visit visit; - unsigned int callDepth; - }; - - FunctionNode *findFunctionByName(const TString &name); - - std::vector<FunctionNode*> functions; - typedef std::set<FunctionNode*> FunctionSet; - FunctionSet globalFunctionCalls; - FunctionNode *currentFunction; -}; - -#endif // COMPILER_ANALYZE_CALL_DEPTH_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_ANALYZE_CALL_DEPTH_H_ +#define COMPILER_ANALYZE_CALL_DEPTH_H_ + +#include "intermediate.h" + +#include <set> +#include <limits.h> + +// Traverses intermediate tree to analyze call depth or detect function recursion +class AnalyzeCallDepth : public TIntermTraverser +{ +public: + AnalyzeCallDepth(TIntermNode *root); + ~AnalyzeCallDepth(); + + virtual bool visitAggregate(Visit, TIntermAggregate*); + + unsigned int analyzeCallDepth(); + +private: + class FunctionNode + { + public: + FunctionNode(TIntermAggregate *node); + + const TString &getName() const; + void addCallee(FunctionNode *callee); + unsigned int analyzeCallDepth(AnalyzeCallDepth *analyzeCallDepth); + unsigned int getLastDepth() const; + + void removeIfUnreachable(); + + private: + TIntermAggregate *const node; + TVector<FunctionNode*> callees; + + Visit visit; + unsigned int callDepth; + }; + + FunctionNode *findFunctionByName(const TString &name); + + std::vector<FunctionNode*> functions; + typedef std::set<FunctionNode*> FunctionSet; + FunctionSet globalFunctionCalls; + FunctionNode *currentFunction; +}; + +#endif // COMPILER_ANALYZE_CALL_DEPTH_H_
diff --git a/src/OpenGL/compiler/BaseTypes.h b/src/OpenGL/compiler/BaseTypes.h index 1a58d54..58c0856 100644 --- a/src/OpenGL/compiler/BaseTypes.h +++ b/src/OpenGL/compiler/BaseTypes.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _BASICTYPES_INCLUDED_ #define _BASICTYPES_INCLUDED_ @@ -14,22 +22,22 @@ // enum TPrecision : unsigned char { - // These need to be kept sorted - EbpUndefined, - EbpLow, - EbpMedium, - EbpHigh + // These need to be kept sorted + EbpUndefined, + EbpLow, + EbpMedium, + EbpHigh }; inline const char *getPrecisionString(TPrecision precision) { - switch(precision) - { - case EbpHigh: return "highp"; break; - case EbpMedium: return "mediump"; break; - case EbpLow: return "lowp"; break; - default: return "mediump"; break; // Safest fallback - } + switch(precision) + { + case EbpHigh: return "highp"; break; + case EbpMedium: return "mediump"; break; + case EbpLow: return "lowp"; break; + default: return "mediump"; break; // Safest fallback + } } // @@ -37,46 +45,46 @@ // enum TBasicType : unsigned char { - EbtVoid, - EbtFloat, - EbtInt, - EbtUInt, - EbtBool, - EbtGVec4, // non type: represents vec4, ivec4, and uvec4 - EbtGenType, // non type: represents float, vec2, vec3, and vec4 - EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4 - EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4 - EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4 - EbtVec, // non type: represents vec2, vec3, and vec4 - EbtIVec, // non type: represents ivec2, ivec3, and ivec4 - EbtUVec, // non type: represents uvec2, uvec3, and uvec4 - EbtBVec, // non type: represents bvec2, bvec3, and bvec4 - EbtGuardSamplerBegin, // non type: see implementation of IsSampler() - EbtSampler2D, - EbtSampler3D, - EbtSamplerCube, - EbtSampler2DArray, - EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists. - EbtISampler2D, - EbtISampler3D, - EbtISamplerCube, - EbtISampler2DArray, - EbtUSampler2D, - EbtUSampler3D, - EbtUSamplerCube, - EbtUSampler2DArray, - EbtSampler2DShadow, - EbtSamplerCubeShadow, - EbtSampler2DArrayShadow, - EbtGuardSamplerEnd, // non type: see implementation of IsSampler() - EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D - EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D - EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube - EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray - EbtStruct, - EbtInterfaceBlock, - EbtAddress, // should be deprecated?? - EbtInvariant // used as a type when qualifying a previously declared variable as being invariant + EbtVoid, + EbtFloat, + EbtInt, + EbtUInt, + EbtBool, + EbtGVec4, // non type: represents vec4, ivec4, and uvec4 + EbtGenType, // non type: represents float, vec2, vec3, and vec4 + EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4 + EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4 + EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4 + EbtVec, // non type: represents vec2, vec3, and vec4 + EbtIVec, // non type: represents ivec2, ivec3, and ivec4 + EbtUVec, // non type: represents uvec2, uvec3, and uvec4 + EbtBVec, // non type: represents bvec2, bvec3, and bvec4 + EbtGuardSamplerBegin, // non type: see implementation of IsSampler() + EbtSampler2D, + EbtSampler3D, + EbtSamplerCube, + EbtSampler2DArray, + EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists. + EbtISampler2D, + EbtISampler3D, + EbtISamplerCube, + EbtISampler2DArray, + EbtUSampler2D, + EbtUSampler3D, + EbtUSamplerCube, + EbtUSampler2DArray, + EbtSampler2DShadow, + EbtSamplerCubeShadow, + EbtSampler2DArrayShadow, + EbtGuardSamplerEnd, // non type: see implementation of IsSampler() + EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D + EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D + EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube + EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray + EbtStruct, + EbtInterfaceBlock, + EbtAddress, // should be deprecated?? + EbtInvariant // used as a type when qualifying a previously declared variable as being invariant }; enum TLayoutMatrixPacking @@ -96,20 +104,20 @@ inline const char *getBasicString(TBasicType type) { - switch(type) - { - case EbtVoid: return "void"; - case EbtFloat: return "float"; - case EbtInt: return "int"; - case EbtUInt: return "uint"; - case EbtBool: return "bool"; - case EbtSampler2D: return "sampler2D"; - case EbtSamplerCube: return "samplerCube"; - case EbtSamplerExternalOES: return "samplerExternalOES"; + switch(type) + { + case EbtVoid: return "void"; + case EbtFloat: return "float"; + case EbtInt: return "int"; + case EbtUInt: return "uint"; + case EbtBool: return "bool"; + case EbtSampler2D: return "sampler2D"; + case EbtSamplerCube: return "samplerCube"; + case EbtSamplerExternalOES: return "samplerExternalOES"; case EbtSampler3D: return "sampler3D"; - case EbtStruct: return "structure"; - default: UNREACHABLE(type); return "unknown type"; - } + case EbtStruct: return "structure"; + default: UNREACHABLE(type); return "unknown type"; + } } inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq) @@ -137,7 +145,7 @@ inline bool IsSampler(TBasicType type) { - return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; + return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; } inline bool IsIntegerSampler(TBasicType type) @@ -332,81 +340,81 @@ // enum TQualifier : unsigned char { - EvqTemporary, // For temporaries (within a function), read/write - EvqGlobal, // For globals read/write - EvqConstExpr, // User defined constants - EvqAttribute, // Readonly - EvqVaryingIn, // readonly, fragment shaders only - EvqVaryingOut, // vertex shaders only read/write - EvqInvariantVaryingIn, // readonly, fragment shaders only - EvqInvariantVaryingOut, // vertex shaders only read/write - EvqUniform, // Readonly, vertex and fragment + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqConstExpr, // User defined constants + EvqAttribute, // Readonly + EvqVaryingIn, // readonly, fragment shaders only + EvqVaryingOut, // vertex shaders only read/write + EvqInvariantVaryingIn, // readonly, fragment shaders only + EvqInvariantVaryingOut, // vertex shaders only read/write + EvqUniform, // Readonly, vertex and fragment - EvqVertexIn, // Vertex shader input - EvqFragmentOut, // Fragment shader output - EvqVertexOut, // Vertex shader output - EvqFragmentIn, // Fragment shader input + EvqVertexIn, // Vertex shader input + EvqFragmentOut, // Fragment shader output + EvqVertexOut, // Vertex shader output + EvqFragmentIn, // Fragment shader input - // pack/unpack input and output - EvqInput, - EvqOutput, + // pack/unpack input and output + EvqInput, + EvqOutput, - // parameters - EvqIn, - EvqOut, - EvqInOut, - EvqConstReadOnly, + // parameters + EvqIn, + EvqOut, + EvqInOut, + EvqConstReadOnly, - // built-ins written by vertex shader - EvqPosition, - EvqPointSize, - EvqInstanceID, + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + EvqInstanceID, - // built-ins read by fragment shader - EvqFragCoord, - EvqFrontFacing, - EvqPointCoord, + // built-ins read by fragment shader + EvqFragCoord, + EvqFrontFacing, + EvqPointCoord, - // built-ins written by fragment shader - EvqFragColor, - EvqFragData, - EvqFragDepth, + // built-ins written by fragment shader + EvqFragColor, + EvqFragData, + EvqFragDepth, - // GLSL ES 3.0 vertex output and fragment input - EvqSmooth, // Incomplete qualifier, smooth is the default - EvqFlat, // Incomplete qualifier - EvqSmoothOut = EvqSmooth, - EvqFlatOut = EvqFlat, - EvqCentroidOut, // Implies smooth - EvqSmoothIn, - EvqFlatIn, - EvqCentroidIn, // Implies smooth + // GLSL ES 3.0 vertex output and fragment input + EvqSmooth, // Incomplete qualifier, smooth is the default + EvqFlat, // Incomplete qualifier + EvqSmoothOut = EvqSmooth, + EvqFlatOut = EvqFlat, + EvqCentroidOut, // Implies smooth + EvqSmoothIn, + EvqFlatIn, + EvqCentroidIn, // Implies smooth - // end of list - EvqLast + // end of list + EvqLast }; struct TLayoutQualifier { - static TLayoutQualifier create() - { - TLayoutQualifier layoutQualifier; + static TLayoutQualifier create() + { + TLayoutQualifier layoutQualifier; - layoutQualifier.location = -1; - layoutQualifier.matrixPacking = EmpUnspecified; - layoutQualifier.blockStorage = EbsUnspecified; + layoutQualifier.location = -1; + layoutQualifier.matrixPacking = EmpUnspecified; + layoutQualifier.blockStorage = EbsUnspecified; - return layoutQualifier; - } + return layoutQualifier; + } - bool isEmpty() const - { - return location == -1 && matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified; - } + bool isEmpty() const + { + return location == -1 && matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified; + } - int location; - TLayoutMatrixPacking matrixPacking; - TLayoutBlockStorage blockStorage; + int location; + TLayoutMatrixPacking matrixPacking; + TLayoutBlockStorage blockStorage; }; // @@ -414,43 +422,43 @@ // inline const char *getQualifierString(TQualifier qualifier) { - switch(qualifier) - { - case EvqTemporary: return "Temporary"; break; - case EvqGlobal: return "Global"; break; - case EvqConstExpr: return "const"; break; - case EvqConstReadOnly: return "const"; break; - case EvqAttribute: return "attribute"; break; - case EvqVaryingIn: return "varying"; break; - case EvqVaryingOut: return "varying"; break; - case EvqInvariantVaryingIn: return "invariant varying"; break; - case EvqInvariantVaryingOut:return "invariant varying"; break; - case EvqUniform: return "uniform"; break; - case EvqVertexIn: return "in"; break; - case EvqFragmentOut: return "out"; break; - case EvqVertexOut: return "out"; break; - case EvqFragmentIn: return "in"; break; - 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 EvqInstanceID: return "InstanceID"; 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; - case EvqSmooth: return "Smooth"; break; - case EvqFlat: return "Flat"; break; - case EvqCentroidOut: return "CentroidOut"; break; - case EvqSmoothIn: return "SmoothIn"; break; - case EvqFlatIn: return "FlatIn"; break; - case EvqCentroidIn: return "CentroidIn"; break; - default: UNREACHABLE(qualifier); return "unknown qualifier"; - } + switch(qualifier) + { + case EvqTemporary: return "Temporary"; break; + case EvqGlobal: return "Global"; break; + case EvqConstExpr: return "const"; break; + case EvqConstReadOnly: return "const"; break; + case EvqAttribute: return "attribute"; break; + case EvqVaryingIn: return "varying"; break; + case EvqVaryingOut: return "varying"; break; + case EvqInvariantVaryingIn: return "invariant varying"; break; + case EvqInvariantVaryingOut:return "invariant varying"; break; + case EvqUniform: return "uniform"; break; + case EvqVertexIn: return "in"; break; + case EvqFragmentOut: return "out"; break; + case EvqVertexOut: return "out"; break; + case EvqFragmentIn: return "in"; break; + 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 EvqInstanceID: return "InstanceID"; 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; + case EvqSmooth: return "Smooth"; break; + case EvqFlat: return "Flat"; break; + case EvqCentroidOut: return "CentroidOut"; break; + case EvqSmoothIn: return "SmoothIn"; break; + case EvqFlatIn: return "FlatIn"; break; + case EvqCentroidIn: return "CentroidIn"; break; + default: UNREACHABLE(qualifier); return "unknown qualifier"; + } } #endif // _BASICTYPES_INCLUDED_
diff --git a/src/OpenGL/compiler/Common.h b/src/OpenGL/compiler/Common.h index f3bf435..b6fe5d6 100644 --- a/src/OpenGL/compiler/Common.h +++ b/src/OpenGL/compiler/Common.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _COMMON_INCLUDED_ #define _COMMON_INCLUDED_ @@ -25,14 +33,14 @@ // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // #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 *) { } + 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 *) { } // // Pool version of string. @@ -58,20 +66,20 @@ // template <class T> class TVector : public std::vector<T, pool_allocator<T> > { public: - typedef typename std::vector<T, pool_allocator<T> >::size_type size_type; - TVector() : std::vector<T, pool_allocator<T> >() {} - TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {} - TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {} + typedef typename std::vector<T, pool_allocator<T> >::size_type size_type; + TVector() : std::vector<T, pool_allocator<T> >() {} + TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {} + TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {} }; -template <class K, class D, class CMP = std::less<K> > +template <class K, class D, class CMP = std::less<K> > class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > { public: - typedef pool_allocator<std::pair<const K, D> > tAllocator; + typedef pool_allocator<std::pair<const K, D> > tAllocator; - TMap() : std::map<K, D, CMP, tAllocator>() {} - // use correct two-stage name lookup supported in gcc 3.4 and above - TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {} + TMap() : std::map<K, D, CMP, tAllocator>() {} + // use correct two-stage name lookup supported in gcc 3.4 and above + TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {} }; #endif // _COMMON_INCLUDED_
diff --git a/src/OpenGL/compiler/Compiler.cpp b/src/OpenGL/compiler/Compiler.cpp index cbb04f5..7861acf 100644 --- a/src/OpenGL/compiler/Compiler.cpp +++ b/src/OpenGL/compiler/Compiler.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "Compiler.h" @@ -13,23 +21,25 @@ #include "ParseHelper.h" #include "ValidateLimitations.h" -namespace +namespace { class TScopedPoolAllocator { public: - TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop) - : mAllocator(allocator), mPushPopAllocator(pushPop) { - if (mPushPopAllocator) mAllocator->push(); - SetGlobalPoolAllocator(mAllocator); - } - ~TScopedPoolAllocator() { - SetGlobalPoolAllocator(NULL); - if (mPushPopAllocator) mAllocator->pop(); - } + TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop) + : mAllocator(allocator), mPushPopAllocator(pushPop) + { + if (mPushPopAllocator) mAllocator->push(); + SetGlobalPoolAllocator(mAllocator); + } + ~TScopedPoolAllocator() + { + SetGlobalPoolAllocator(nullptr); + if (mPushPopAllocator) mAllocator->pop(); + } private: - TPoolAllocator* mAllocator; - bool mPushPopAllocator; + TPoolAllocator* mAllocator; + bool mPushPopAllocator; }; } // namespace @@ -38,125 +48,125 @@ // ShBuiltInResources::ShBuiltInResources() { - // Constants. - MaxVertexAttribs = 8; - MaxVertexUniformVectors = 128; - MaxVaryingVectors = 8; - MaxVertexTextureImageUnits = 0; - MaxCombinedTextureImageUnits = 8; - MaxTextureImageUnits = 8; - MaxFragmentUniformVectors = 16; - MaxDrawBuffers = 1; - MaxVertexOutputVectors = 16; - MaxFragmentInputVectors = 15; - MinProgramTexelOffset = -8; - MaxProgramTexelOffset = 7; + // Constants. + MaxVertexAttribs = 8; + MaxVertexUniformVectors = 128; + MaxVaryingVectors = 8; + MaxVertexTextureImageUnits = 0; + MaxCombinedTextureImageUnits = 8; + MaxTextureImageUnits = 8; + MaxFragmentUniformVectors = 16; + MaxDrawBuffers = 1; + MaxVertexOutputVectors = 16; + MaxFragmentInputVectors = 15; + MinProgramTexelOffset = -8; + MaxProgramTexelOffset = 7; - // Extensions. - OES_standard_derivatives = 0; + // Extensions. + OES_standard_derivatives = 0; OES_fragment_precision_high = 0; - OES_EGL_image_external = 0; + OES_EGL_image_external = 0; MaxCallStackDepth = UINT_MAX; } TCompiler::TCompiler(GLenum type) - : shaderType(type), - maxCallStackDepth(UINT_MAX) + : shaderType(type), + maxCallStackDepth(UINT_MAX) { allocator.push(); - SetGlobalPoolAllocator(&allocator); + SetGlobalPoolAllocator(&allocator); } TCompiler::~TCompiler() { - SetGlobalPoolAllocator(NULL); - allocator.popAll(); + SetGlobalPoolAllocator(nullptr); + allocator.popAll(); } bool TCompiler::Init(const ShBuiltInResources& resources) { - shaderVersion = 100; - maxCallStackDepth = resources.MaxCallStackDepth; - TScopedPoolAllocator scopedAlloc(&allocator, false); + shaderVersion = 100; + maxCallStackDepth = resources.MaxCallStackDepth; + TScopedPoolAllocator scopedAlloc(&allocator, false); - // Generate built-in symbol table. - if (!InitBuiltInSymbolTable(resources)) - return false; - InitExtensionBehavior(resources, extensionBehavior); + // Generate built-in symbol table. + if (!InitBuiltInSymbolTable(resources)) + return false; + InitExtensionBehavior(resources, extensionBehavior); - return true; + return true; } bool TCompiler::compile(const char* const shaderStrings[], const int numStrings, int compileOptions) { - TScopedPoolAllocator scopedAlloc(&allocator, true); - clearResults(); + TScopedPoolAllocator scopedAlloc(&allocator, true); + clearResults(); - if (numStrings == 0) - return true; + if (numStrings == 0) + return true; - // First string is path of source file if flag is set. The actual source follows. - const char* sourcePath = NULL; - int firstSource = 0; - if (compileOptions & SH_SOURCE_PATH) - { - sourcePath = shaderStrings[0]; - ++firstSource; - } + // First string is path of source file if flag is set. The actual source follows. + const char* sourcePath = nullptr; + int firstSource = 0; + if (compileOptions & SH_SOURCE_PATH) + { + sourcePath = shaderStrings[0]; + ++firstSource; + } - TIntermediate intermediate(infoSink); - TParseContext parseContext(symbolTable, extensionBehavior, intermediate, - shaderType, compileOptions, true, - sourcePath, infoSink); - SetGlobalParseContext(&parseContext); + TIntermediate intermediate(infoSink); + TParseContext parseContext(symbolTable, extensionBehavior, intermediate, + shaderType, compileOptions, true, + sourcePath, infoSink); + 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"); + // 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"); - // Parse shader. - bool success = - (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) && - (parseContext.getTreeRoot() != NULL); + // Parse shader. + bool success = + (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, &parseContext) == 0) && + (parseContext.getTreeRoot() != nullptr); - shaderVersion = parseContext.getShaderVersion(); + shaderVersion = parseContext.getShaderVersion(); - if (success) { - TIntermNode* root = parseContext.getTreeRoot(); - success = intermediate.postProcess(root); + if (success) { + TIntermNode* root = parseContext.getTreeRoot(); + success = intermediate.postProcess(root); - if (success) - success = validateCallDepth(root, infoSink); + if (success) + success = validateCallDepth(root, infoSink); - if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) - success = validateLimitations(root); + if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) + success = validateLimitations(root); - if (success && (compileOptions & SH_INTERMEDIATE_TREE)) - intermediate.outputTree(root); + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) + intermediate.outputTree(root); - if (success && (compileOptions & SH_OBJECT_CODE)) - success = translate(root); - } + if (success && (compileOptions & SH_OBJECT_CODE)) + success = translate(root); + } - // Ensure symbol table is returned to the built-in level, - // throwing away all but the built-ins. - while (!symbolTable.atBuiltInLevel()) - symbolTable.pop(); + // Ensure symbol table is returned to the built-in level, + // throwing away all but the built-ins. + while (!symbolTable.atBuiltInLevel()) + symbolTable.pop(); - return success; + return success; } bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) { - assert(symbolTable.isEmpty()); - symbolTable.push(); // COMMON_BUILTINS - symbolTable.push(); // ESSL1_BUILTINS - symbolTable.push(); // ESSL3_BUILTINS + assert(symbolTable.isEmpty()); + symbolTable.push(); // COMMON_BUILTINS + symbolTable.push(); // ESSL1_BUILTINS + symbolTable.push(); // ESSL3_BUILTINS TPublicType integer; integer.type = EbtInt; @@ -172,88 +182,88 @@ switch(shaderType) { - case GL_FRAGMENT_SHADER: + case GL_FRAGMENT_SHADER: symbolTable.setDefaultPrecision(integer, EbpMedium); - break; - case GL_VERTEX_SHADER: + break; + case GL_VERTEX_SHADER: symbolTable.setDefaultPrecision(integer, EbpHigh); symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); - break; - default: assert(false && "Language not supported"); - } + break; + default: assert(false && "Language not supported"); + } InsertBuiltInFunctions(shaderType, resources, symbolTable); - IdentifyBuiltIns(shaderType, resources, symbolTable); + IdentifyBuiltIns(shaderType, resources, symbolTable); - return true; + return true; } void TCompiler::clearResults() { - infoSink.info.erase(); - infoSink.obj.erase(); - infoSink.debug.erase(); + infoSink.info.erase(); + infoSink.obj.erase(); + infoSink.debug.erase(); } bool TCompiler::validateCallDepth(TIntermNode *root, TInfoSink &infoSink) { - AnalyzeCallDepth validator(root); - + AnalyzeCallDepth validator(root); + unsigned int depth = validator.analyzeCallDepth(); - + if(depth == 0) { - infoSink.info.prefix(EPrefixError); - infoSink.info << "Missing main()"; - return false; + infoSink.info.prefix(EPrefixError); + infoSink.info << "Missing main()"; + return false; } - else if(depth == UINT_MAX) + else if(depth == UINT_MAX) { - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function recursion detected"; - return false; + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function recursion detected"; + return false; } else if(depth > maxCallStackDepth) { - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function call stack too deep"; - return false; + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function call stack too deep"; + return false; } - return true; + return true; } bool TCompiler::validateLimitations(TIntermNode* root) { - ValidateLimitations validate(shaderType, infoSink.info); - root->traverse(&validate); - return validate.numErrors() == 0; + ValidateLimitations validate(shaderType, infoSink.info); + root->traverse(&validate); + return validate.numErrors() == 0; } const TExtensionBehavior& TCompiler::getExtensionBehavior() const { - return extensionBehavior; + return extensionBehavior; } bool InitCompilerGlobals() { - if(!InitializePoolIndex()) + if(!InitializePoolIndex()) { - assert(0 && "InitCompilerGlobals(): Failed to initalize global pool"); - return false; - } + assert(0 && "InitCompilerGlobals(): Failed to initalize global pool"); + return false; + } - if(!InitializeParseContextIndex()) + if(!InitializeParseContextIndex()) { - assert(0 && "InitCompilerGlobals(): Failed to initalize parse context"); - return false; - } + assert(0 && "InitCompilerGlobals(): Failed to initalize parse context"); + return false; + } - return true; + return true; } void FreeCompilerGlobals() { - FreeParseContextIndex(); - FreePoolIndex(); + FreeParseContextIndex(); + FreePoolIndex(); }
diff --git a/src/OpenGL/compiler/Compiler.h b/src/OpenGL/compiler/Compiler.h index c90dbd2..8cdc755 100644 --- a/src/OpenGL/compiler/Compiler.h +++ b/src/OpenGL/compiler/Compiler.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _COMPILER_INCLUDED_ #define _COMPILER_INCLUDED_ @@ -30,28 +38,28 @@ { ShBuiltInResources(); - // Constants. - int MaxVertexAttribs; - int MaxVertexUniformVectors; - int MaxVaryingVectors; - int MaxVertexTextureImageUnits; - int MaxCombinedTextureImageUnits; - int MaxTextureImageUnits; - int MaxFragmentUniformVectors; - int MaxDrawBuffers; - int MaxVertexOutputVectors; - int MaxFragmentInputVectors; - int MinProgramTexelOffset; - int MaxProgramTexelOffset; + // Constants. + int MaxVertexAttribs; + int MaxVertexUniformVectors; + int MaxVaryingVectors; + int MaxVertexTextureImageUnits; + int MaxCombinedTextureImageUnits; + int MaxTextureImageUnits; + int MaxFragmentUniformVectors; + int MaxDrawBuffers; + int MaxVertexOutputVectors; + int MaxFragmentInputVectors; + int MinProgramTexelOffset; + int MaxProgramTexelOffset; - // Extensions. - // Set to 1 to enable the extension, else 0. - int OES_standard_derivatives; + // Extensions. + // Set to 1 to enable the extension, else 0. + int OES_standard_derivatives; int OES_fragment_precision_high; - int OES_EGL_image_external; + int OES_EGL_image_external; int EXT_draw_buffers; - unsigned int MaxCallStackDepth; + unsigned int MaxCallStackDepth; }; typedef unsigned int GLenum; @@ -65,53 +73,53 @@ class TCompiler { public: - TCompiler(GLenum shaderType); - virtual ~TCompiler(); - virtual TCompiler* getAsCompiler() { return this; } + TCompiler(GLenum shaderType); + virtual ~TCompiler(); + virtual TCompiler* getAsCompiler() { return this; } - bool Init(const ShBuiltInResources& resources); - bool compile(const char* const shaderStrings[], - const int numStrings, - int compileOptions); + bool Init(const ShBuiltInResources& resources); + bool compile(const char* const shaderStrings[], + const int numStrings, + int compileOptions); - // Get results of the last compilation. - int getShaderVersion() const { return shaderVersion; } - TInfoSink& getInfoSink() { return infoSink; } + // Get results of the last compilation. + int getShaderVersion() const { return shaderVersion; } + TInfoSink& getInfoSink() { return infoSink; } protected: - GLenum getShaderType() const { return shaderType; } - // Initialize symbol-table with built-in symbols. - bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); - // Clears the results from the previous compilation. - void clearResults(); - // Return true if function recursion is detected or call depth exceeded. - bool validateCallDepth(TIntermNode *root, TInfoSink &infoSink); - // Returns true if the given shader does not exceed the minimum - // functionality mandated in GLSL 1.0 spec Appendix A. - bool validateLimitations(TIntermNode *root); - // Translate to object code. - virtual bool translate(TIntermNode *root) = 0; - // Get built-in extensions with default behavior. - const TExtensionBehavior& getExtensionBehavior() const; + GLenum getShaderType() const { return shaderType; } + // Initialize symbol-table with built-in symbols. + bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); + // Clears the results from the previous compilation. + void clearResults(); + // Return true if function recursion is detected or call depth exceeded. + bool validateCallDepth(TIntermNode *root, TInfoSink &infoSink); + // Returns true if the given shader does not exceed the minimum + // functionality mandated in GLSL 1.0 spec Appendix A. + bool validateLimitations(TIntermNode *root); + // Translate to object code. + virtual bool translate(TIntermNode *root) = 0; + // Get built-in extensions with default behavior. + const TExtensionBehavior& getExtensionBehavior() const; private: - GLenum shaderType; + GLenum shaderType; - unsigned int maxCallStackDepth; + unsigned int maxCallStackDepth; - // Built-in symbol table for the given language, spec, and resources. - // It is preserved from compile-to-compile. - TSymbolTable symbolTable; - // Built-in extensions with default behavior. - TExtensionBehavior extensionBehavior; + // Built-in symbol table for the given language, spec, and resources. + // It is preserved from compile-to-compile. + TSymbolTable symbolTable; + // Built-in extensions with default behavior. + TExtensionBehavior extensionBehavior; - // Results of compilation. - int shaderVersion; - TInfoSink infoSink; // Output sink. + // Results of compilation. + int shaderVersion; + TInfoSink infoSink; // Output sink. - // Memory allocator. Allocates and tracks memory required by the compiler. - // Deallocates all memory when compiler is destructed. - TPoolAllocator allocator; + // Memory allocator. Allocates and tracks memory required by the compiler. + // Deallocates all memory when compiler is destructed. + TPoolAllocator allocator; }; bool InitCompilerGlobals();
diff --git a/src/OpenGL/compiler/ConstantUnion.h b/src/OpenGL/compiler/ConstantUnion.h index b001ec4..27f816c 100644 --- a/src/OpenGL/compiler/ConstantUnion.h +++ b/src/OpenGL/compiler/ConstantUnion.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2014 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _CONSTANT_UNION_INCLUDED_ #define _CONSTANT_UNION_INCLUDED_ @@ -16,82 +24,82 @@ class ConstantUnion { public: POOL_ALLOCATOR_NEW_DELETE(); - ConstantUnion() - { - iConst = 0; - type = EbtVoid; - } + ConstantUnion() + { + iConst = 0; + type = EbtVoid; + } - bool cast(TBasicType newType, const ConstantUnion &constant) - { - switch (newType) - { - case EbtFloat: - switch (constant.type) - { - case EbtInt: setFConst(static_cast<float>(constant.getIConst())); break; - case EbtUInt: setFConst(static_cast<float>(constant.getUConst())); break; - case EbtBool: setFConst(static_cast<float>(constant.getBConst())); break; - case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break; - default: return false; - } - break; - case EbtInt: - switch (constant.type) - { - case EbtInt: setIConst(static_cast<int>(constant.getIConst())); break; - case EbtUInt: setIConst(static_cast<int>(constant.getUConst())); break; - case EbtBool: setIConst(static_cast<int>(constant.getBConst())); break; - case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break; - default: return false; - } - break; - case EbtUInt: - switch (constant.type) - { - case EbtInt: setUConst(static_cast<unsigned int>(constant.getIConst())); break; - case EbtUInt: setUConst(static_cast<unsigned int>(constant.getUConst())); break; - case EbtBool: setUConst(static_cast<unsigned int>(constant.getBConst())); break; - case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break; - default: return false; - } - break; - case EbtBool: - switch (constant.type) - { - case EbtInt: setBConst(constant.getIConst() != 0); break; - case EbtUInt: setBConst(constant.getUConst() != 0); break; - case EbtBool: setBConst(constant.getBConst()); break; - case EbtFloat: setBConst(constant.getFConst() != 0.0f); break; - default: return false; - } - break; - case EbtStruct: // Struct fields don't get cast - switch (constant.type) - { - case EbtInt: setIConst(constant.getIConst()); break; - case EbtUInt: setUConst(constant.getUConst()); break; - case EbtBool: setBConst(constant.getBConst()); break; - case EbtFloat: setFConst(constant.getFConst()); break; - default: return false; - } - break; - default: - return false; - } + bool cast(TBasicType newType, const ConstantUnion &constant) + { + switch (newType) + { + case EbtFloat: + switch (constant.type) + { + case EbtInt: setFConst(static_cast<float>(constant.getIConst())); break; + case EbtUInt: setFConst(static_cast<float>(constant.getUConst())); break; + case EbtBool: setFConst(static_cast<float>(constant.getBConst())); break; + case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break; + default: return false; + } + break; + case EbtInt: + switch (constant.type) + { + case EbtInt: setIConst(static_cast<int>(constant.getIConst())); break; + case EbtUInt: setIConst(static_cast<int>(constant.getUConst())); break; + case EbtBool: setIConst(static_cast<int>(constant.getBConst())); break; + case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break; + default: return false; + } + break; + case EbtUInt: + switch (constant.type) + { + case EbtInt: setUConst(static_cast<unsigned int>(constant.getIConst())); break; + case EbtUInt: setUConst(static_cast<unsigned int>(constant.getUConst())); break; + case EbtBool: setUConst(static_cast<unsigned int>(constant.getBConst())); break; + case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break; + default: return false; + } + break; + case EbtBool: + switch (constant.type) + { + case EbtInt: setBConst(constant.getIConst() != 0); break; + case EbtUInt: setBConst(constant.getUConst() != 0); break; + case EbtBool: setBConst(constant.getBConst()); break; + case EbtFloat: setBConst(constant.getFConst() != 0.0f); break; + default: return false; + } + break; + case EbtStruct: // Struct fields don't get cast + switch (constant.type) + { + case EbtInt: setIConst(constant.getIConst()); break; + case EbtUInt: setUConst(constant.getUConst()); break; + case EbtBool: setBConst(constant.getBConst()); break; + case EbtFloat: setFConst(constant.getFConst()); break; + default: return false; + } + break; + default: + return false; + } - return true; - } + return true; + } - void setIConst(int i) {iConst = i; type = EbtInt; } - void setUConst(unsigned int u) { uConst = u; type = EbtUInt; } - void setFConst(float f) {fConst = f; type = EbtFloat; } - void setBConst(bool b) {bConst = b; type = EbtBool; } + void setIConst(int i) {iConst = i; type = EbtInt; } + void setUConst(unsigned int u) { uConst = u; type = EbtUInt; } + void setFConst(float f) {fConst = f; type = EbtFloat; } + void setBConst(bool b) {bConst = b; type = EbtBool; } - int getIConst() const { return iConst; } - unsigned int getUConst() const { return uConst; } - float getFConst() const { return fConst; } - bool getBConst() const { return bConst; } + int getIConst() const { return iConst; } + unsigned int getUConst() const { return uConst; } + float getFConst() const { return fConst; } + bool getBConst() const { return bConst; } float getAsFloat() const { @@ -99,306 +107,306 @@ switch(type) { - case EbtInt: return reinterpret_cast<const float&>(iConst); + case EbtInt: return reinterpret_cast<const float&>(iConst); case EbtUInt: return reinterpret_cast<const float&>(uConst); - case EbtFloat: return fConst; + case EbtFloat: return fConst; case EbtBool: return (bConst == true) ? reinterpret_cast<const float&>(FFFFFFFFh) : 0; - default: return 0; - } + default: return 0; + } } - bool operator==(const int i) const - { - return i == iConst; - } + bool operator==(const int i) const + { + return i == iConst; + } - bool operator==(const unsigned int u) const - { - return u == uConst; - } + bool operator==(const unsigned int u) const + { + return u == uConst; + } - bool operator==(const float f) const - { - return f == fConst; - } + bool operator==(const float f) const + { + return f == fConst; + } - bool operator==(const bool b) const - { - return b == bConst; - } + bool operator==(const bool b) const + { + return b == bConst; + } - bool operator==(const ConstantUnion& constant) const - { - if (constant.type != type) - return false; + bool operator==(const ConstantUnion& constant) const + { + if (constant.type != type) + return false; - switch (type) { - case EbtInt: - return constant.iConst == iConst; - case EbtUInt: - return constant.uConst == uConst; - case EbtFloat: - return constant.fConst == fConst; - case EbtBool: - return constant.bConst == bConst; - default: - return false; - } + switch (type) { + case EbtInt: + return constant.iConst == iConst; + case EbtUInt: + return constant.uConst == uConst; + case EbtFloat: + return constant.fConst == fConst; + case EbtBool: + return constant.bConst == bConst; + default: + return false; + } - return false; - } + return false; + } - bool operator!=(const int i) const - { - return !operator==(i); - } + bool operator!=(const int i) const + { + return !operator==(i); + } - bool operator!=(const unsigned int u) const - { - return !operator==(u); - } + bool operator!=(const unsigned int u) const + { + return !operator==(u); + } - bool operator!=(const float f) const - { - return !operator==(f); - } + bool operator!=(const float f) const + { + return !operator==(f); + } - bool operator!=(const bool b) const - { - return !operator==(b); - } + bool operator!=(const bool b) const + { + return !operator==(b); + } - bool operator!=(const ConstantUnion& constant) const - { - return !operator==(constant); - } + bool operator!=(const ConstantUnion& constant) const + { + return !operator==(constant); + } - bool operator>(const ConstantUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case EbtInt: - return iConst > constant.iConst; - case EbtUInt: - return uConst > constant.uConst; - case EbtFloat: - return fConst > constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } + bool operator>(const ConstantUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst > constant.iConst; + case EbtUInt: + return uConst > constant.uConst; + case EbtFloat: + return fConst > constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } - return false; - } + return false; + } - bool operator<(const ConstantUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case EbtInt: - return iConst < constant.iConst; - case EbtUInt: - return uConst < constant.uConst; - case EbtFloat: - return fConst < constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } + bool operator<(const ConstantUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst < constant.iConst; + case EbtUInt: + return uConst < constant.uConst; + case EbtFloat: + return fConst < constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } - return false; - } + return false; + } bool operator<=(const ConstantUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case EbtInt: - return iConst <= constant.iConst; - case EbtUInt: - return uConst <= constant.uConst; - case EbtFloat: - return fConst <= constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst <= constant.iConst; + case EbtUInt: + return uConst <= constant.uConst; + case EbtFloat: + return fConst <= constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } - return false; - } + return false; + } bool operator>=(const ConstantUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case EbtInt: - return iConst >= constant.iConst; - case EbtUInt: - return uConst >= constant.uConst; - case EbtFloat: - return fConst >= constant.fConst; - default: - return false; // Invalid operation, handled at semantic analysis - } + { + assert(type == constant.type); + switch (type) { + case EbtInt: + return iConst >= constant.iConst; + case EbtUInt: + return uConst >= constant.uConst; + case EbtFloat: + return fConst >= constant.fConst; + default: + return false; // Invalid operation, handled at semantic analysis + } - return false; - } + return false; + } - ConstantUnion operator+(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break; - case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator+(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break; + case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator-(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break; - case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator-(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break; + case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator*(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break; - case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator*(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break; + case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator%(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator%(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator>>(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator>>(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator<<(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - // The signedness of the second parameter might be different, but we - // don't care, since the result is undefined if the second parameter is - // negative, and aliasing should not be a problem with unions. - assert(constant.type == EbtInt || constant.type == EbtUInt); - switch (type) { - case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator<<(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + // The signedness of the second parameter might be different, but we + // don't care, since the result is undefined if the second parameter is + // negative, and aliasing should not be a problem with unions. + assert(constant.type == EbtInt || constant.type == EbtUInt); + switch (type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator&(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(constant.type == EbtInt || constant.type == EbtUInt); - switch (type) { - case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator&(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(constant.type == EbtInt || constant.type == EbtUInt); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator|(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator|(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator^(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; - case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator^(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator&&(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator&&(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - ConstantUnion operator||(const ConstantUnion& constant) const - { - ConstantUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; - default: assert(false && "Default missing"); - } + ConstantUnion operator||(const ConstantUnion& constant) const + { + ConstantUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } - return returnValue; - } + return returnValue; + } - TBasicType getType() const { return type; } + TBasicType getType() const { return type; } private: - union { - int iConst; // used for ivec, scalar ints - unsigned int uConst; // used for uvec, scalar uints - bool bConst; // used for bvec, scalar bools - float fConst; // used for vec, mat, scalar floats - } ; + union { + int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints + bool bConst; // used for bvec, scalar bools + float fConst; // used for vec, mat, scalar floats + } ; - TBasicType type; + TBasicType type; }; #endif // _CONSTANT_UNION_INCLUDED_
diff --git a/src/OpenGL/compiler/Diagnostics.cpp b/src/OpenGL/compiler/Diagnostics.cpp index 65aa6ed..490ecfe 100644 --- a/src/OpenGL/compiler/Diagnostics.cpp +++ b/src/OpenGL/compiler/Diagnostics.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "Diagnostics.h" @@ -11,10 +19,10 @@ #include "preprocessor/SourceLocation.h" TDiagnostics::TDiagnostics(TInfoSink& infoSink) : - mShaderVersion(100), - mInfoSink(infoSink), - mNumErrors(0), - mNumWarnings(0) + mShaderVersion(100), + mInfoSink(infoSink), + mNumErrors(0), + mNumWarnings(0) { } @@ -24,7 +32,7 @@ void TDiagnostics::setShaderVersion(int version) { - mShaderVersion = version; + mShaderVersion = version; } void TDiagnostics::writeInfo(Severity severity, @@ -33,40 +41,40 @@ const std::string& token, const std::string& extra) { - TPrefixType prefix = EPrefixNone; - switch (severity) - { - case PP_ERROR: - ++mNumErrors; - prefix = EPrefixError; - break; - case PP_WARNING: - ++mNumWarnings; - prefix = EPrefixWarning; - break; - default: - UNREACHABLE(severity); - break; - } + TPrefixType prefix = EPrefixNone; + switch(severity) + { + case PP_ERROR: + ++mNumErrors; + prefix = EPrefixError; + break; + case PP_WARNING: + ++mNumWarnings; + prefix = EPrefixWarning; + break; + default: + UNREACHABLE(severity); + break; + } - TInfoSinkBase& sink = mInfoSink.info; - /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ - sink.prefix(prefix); - TSourceLoc sourceLoc; - sourceLoc.first_file = sourceLoc.last_file = loc.file; - sourceLoc.first_line = sourceLoc.last_line = loc.line; - sink.location(sourceLoc); - sink << "'" << token << "' : " << reason << " " << extra << "\n"; + TInfoSinkBase& sink = mInfoSink.info; + /* VC++ format: file(linenum) : error #: 'token' : extrainfo */ + sink.prefix(prefix); + TSourceLoc sourceLoc; + sourceLoc.first_file = sourceLoc.last_file = loc.file; + sourceLoc.first_line = sourceLoc.last_line = loc.line; + sink.location(sourceLoc); + sink << "'" << token << "' : " << reason << " " << extra << "\n"; } void TDiagnostics::writeDebug(const std::string& str) { - mInfoSink.debug << str; + mInfoSink.debug << str; } void TDiagnostics::print(ID id, const pp::SourceLocation& loc, const std::string& text) { - writeInfo(severity(id), loc, message(id), text, ""); + writeInfo(severity(id), loc, message(id), text, ""); }
diff --git a/src/OpenGL/compiler/Diagnostics.h b/src/OpenGL/compiler/Diagnostics.h index 1726924..35983ac 100644 --- a/src/OpenGL/compiler/Diagnostics.h +++ b/src/OpenGL/compiler/Diagnostics.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef COMPILER_DIAGNOSTICS_H_ #define COMPILER_DIAGNOSTICS_H_ @@ -13,37 +21,37 @@ class TDiagnostics : public pp::Diagnostics { - public: - TDiagnostics(TInfoSink& infoSink); - virtual ~TDiagnostics(); +public: + TDiagnostics(TInfoSink& infoSink); + virtual ~TDiagnostics(); - int shaderVersion() const { return mShaderVersion; } - TInfoSink& infoSink() { return mInfoSink; } + int shaderVersion() const { return mShaderVersion; } + TInfoSink& infoSink() { return mInfoSink; } - int numErrors() const { return mNumErrors; } - int numWarnings() const { return mNumWarnings; } + int numErrors() const { return mNumErrors; } + int numWarnings() const { return mNumWarnings; } - void setShaderVersion(int version); + void setShaderVersion(int version); - void writeInfo(Severity severity, - const pp::SourceLocation& loc, - const std::string& reason, - const std::string& token, - const std::string& extra); + void writeInfo(Severity severity, + const pp::SourceLocation& loc, + const std::string& reason, + const std::string& token, + const std::string& extra); - void writeDebug(const std::string& str); + void writeDebug(const std::string& str); - protected: - virtual void print(ID id, - const pp::SourceLocation& loc, - const std::string& text); +protected: + virtual void print(ID id, + const pp::SourceLocation& loc, + const std::string& text); - private: - int mShaderVersion; +private: + int mShaderVersion; - TInfoSink& mInfoSink; - int mNumErrors; - int mNumWarnings; + TInfoSink& mInfoSink; + int mNumErrors; + int mNumWarnings; }; #endif // COMPILER_DIAGNOSTICS_H_
diff --git a/src/OpenGL/compiler/DirectiveHandler.cpp b/src/OpenGL/compiler/DirectiveHandler.cpp index c9368b1..2391d35 100644 --- a/src/OpenGL/compiler/DirectiveHandler.cpp +++ b/src/OpenGL/compiler/DirectiveHandler.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "DirectiveHandler.h" @@ -13,24 +21,24 @@ static TBehavior getBehavior(const std::string& str) { - static const std::string kRequire("require"); - static const std::string kEnable("enable"); - static const std::string kDisable("disable"); - static const std::string kWarn("warn"); + static const std::string kRequire("require"); + static const std::string kEnable("enable"); + static const std::string kDisable("disable"); + static const std::string kWarn("warn"); - if (str == kRequire) return EBhRequire; - else if (str == kEnable) return EBhEnable; - else if (str == kDisable) return EBhDisable; - else if (str == kWarn) return EBhWarn; - return EBhUndefined; + if (str == kRequire) return EBhRequire; + else if (str == kEnable) return EBhEnable; + else if (str == kDisable) return EBhDisable; + else if (str == kWarn) return EBhWarn; + return EBhUndefined; } TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior, TDiagnostics& diagnostics, int& shaderVersion) - : mExtensionBehavior(extBehavior), - mDiagnostics(diagnostics), - mShaderVersion(shaderVersion) + : mExtensionBehavior(extBehavior), + mDiagnostics(diagnostics), + mShaderVersion(shaderVersion) { } @@ -41,126 +49,126 @@ void TDirectiveHandler::handleError(const pp::SourceLocation& loc, const std::string& msg) { - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", ""); + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", ""); } void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, const std::string& name, const std::string& value) { - static const std::string kSTDGL("STDGL"); - static const std::string kOptimize("optimize"); - static const std::string kDebug("debug"); - static const std::string kOn("on"); - static const std::string kOff("off"); + static const std::string kSTDGL("STDGL"); + static const std::string kOptimize("optimize"); + static const std::string kDebug("debug"); + static const std::string kOn("on"); + static const std::string kOff("off"); - bool invalidValue = false; - if (name == kSTDGL) - { - // The STDGL pragma is used to reserve pragmas for use by future - // revisions of GLSL. Ignore it. - return; - } - else if (name == kOptimize) - { - if (value == kOn) mPragma.optimize = true; - else if (value == kOff) mPragma.optimize = false; - else invalidValue = true; - } - else if (name == kDebug) - { - if (value == kOn) mPragma.debug = true; - else if (value == kOff) mPragma.debug = false; - else invalidValue = true; - } - else - { - mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name); - return; - } + bool invalidValue = false; + if (name == kSTDGL) + { + // The STDGL pragma is used to reserve pragmas for use by future + // revisions of GLSL. Ignore it. + return; + } + else if (name == kOptimize) + { + if (value == kOn) mPragma.optimize = true; + else if (value == kOff) mPragma.optimize = false; + else invalidValue = true; + } + else if (name == kDebug) + { + if (value == kOn) mPragma.debug = true; + else if (value == kOff) mPragma.debug = false; + else invalidValue = true; + } + else + { + mDiagnostics.report(pp::Diagnostics::UNRECOGNIZED_PRAGMA, loc, name); + return; + } - if (invalidValue) - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, - "invalid pragma value", value, - "'on' or 'off' expected"); + if (invalidValue) + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "invalid pragma value", value, + "'on' or 'off' expected"); } void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, const std::string& name, const std::string& behavior) { - static const std::string kExtAll("all"); + static const std::string kExtAll("all"); - TBehavior behaviorVal = getBehavior(behavior); - if (behaviorVal == EBhUndefined) - { - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, - "behavior", name, "invalid"); - return; - } + TBehavior behaviorVal = getBehavior(behavior); + if (behaviorVal == EBhUndefined) + { + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "behavior", name, "invalid"); + return; + } - if (name == kExtAll) - { - if (behaviorVal == EBhRequire) - { - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, - "extension", name, - "cannot have 'require' behavior"); - } - else if (behaviorVal == EBhEnable) - { - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, - "extension", name, - "cannot have 'enable' behavior"); - } - else - { - for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); - iter != mExtensionBehavior.end(); ++iter) - iter->second = behaviorVal; - } - return; - } + if (name == kExtAll) + { + if (behaviorVal == EBhRequire) + { + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "extension", name, + "cannot have 'require' behavior"); + } + else if (behaviorVal == EBhEnable) + { + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "extension", name, + "cannot have 'enable' behavior"); + } + else + { + for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); + iter != mExtensionBehavior.end(); ++iter) + iter->second = behaviorVal; + } + return; + } - TExtensionBehavior::iterator iter = mExtensionBehavior.find(name); - if (iter != mExtensionBehavior.end()) - { - iter->second = behaviorVal; - return; - } + TExtensionBehavior::iterator iter = mExtensionBehavior.find(name); + if (iter != mExtensionBehavior.end()) + { + iter->second = behaviorVal; + return; + } - pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR; - switch (behaviorVal) { - case EBhRequire: - severity = pp::Diagnostics::PP_ERROR; - break; - case EBhEnable: - case EBhWarn: - case EBhDisable: - severity = pp::Diagnostics::PP_WARNING; - break; - default: - UNREACHABLE(behaviorVal); - break; - } - mDiagnostics.writeInfo(severity, loc, - "extension", name, "is not supported"); + pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR; + switch (behaviorVal) { + case EBhRequire: + severity = pp::Diagnostics::PP_ERROR; + break; + case EBhEnable: + case EBhWarn: + case EBhDisable: + severity = pp::Diagnostics::PP_WARNING; + break; + default: + UNREACHABLE(behaviorVal); + break; + } + mDiagnostics.writeInfo(severity, loc, + "extension", name, "is not supported"); } void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc, int version) { - if (version == 100 || - version == 300) - { - mShaderVersion = version; - } - else - { - std::stringstream stream; - stream << version; - std::string str = stream.str(); - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, - "version number", str, "not supported"); - } + if (version == 100 || + version == 300) + { + mShaderVersion = version; + } + else + { + std::stringstream stream; + stream << version; + std::string str = stream.str(); + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "version number", str, "not supported"); + } }
diff --git a/src/OpenGL/compiler/DirectiveHandler.h b/src/OpenGL/compiler/DirectiveHandler.h index 48b3c04..f77d1f9 100644 --- a/src/OpenGL/compiler/DirectiveHandler.h +++ b/src/OpenGL/compiler/DirectiveHandler.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef COMPILER_DIRECTIVE_HANDLER_H_ #define COMPILER_DIRECTIVE_HANDLER_H_ @@ -16,33 +24,33 @@ class TDirectiveHandler : public pp::DirectiveHandler { public: - TDirectiveHandler(TExtensionBehavior& extBehavior, - TDiagnostics& diagnostics, - int& shaderVersion); - virtual ~TDirectiveHandler(); + TDirectiveHandler(TExtensionBehavior& extBehavior, + TDiagnostics& diagnostics, + int& shaderVersion); + virtual ~TDirectiveHandler(); - const TPragma& pragma() const { return mPragma; } - const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; } + const TPragma& pragma() const { return mPragma; } + const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; } - virtual void handleError(const pp::SourceLocation& loc, - const std::string& msg); + virtual void handleError(const pp::SourceLocation& loc, + const std::string& msg); - virtual void handlePragma(const pp::SourceLocation& loc, - const std::string& name, - const std::string& value); + virtual void handlePragma(const pp::SourceLocation& loc, + const std::string& name, + const std::string& value); - virtual void handleExtension(const pp::SourceLocation& loc, - const std::string& name, - const std::string& behavior); + virtual void handleExtension(const pp::SourceLocation& loc, + const std::string& name, + const std::string& behavior); - virtual void handleVersion(const pp::SourceLocation& loc, - int version); + virtual void handleVersion(const pp::SourceLocation& loc, + int version); private: - TPragma mPragma; - TExtensionBehavior& mExtensionBehavior; - TDiagnostics& mDiagnostics; - int& mShaderVersion; + TPragma mPragma; + TExtensionBehavior& mExtensionBehavior; + TDiagnostics& mDiagnostics; + int& mShaderVersion; }; #endif // COMPILER_DIRECTIVE_HANDLER_H_
diff --git a/src/OpenGL/compiler/ExtensionBehavior.h b/src/OpenGL/compiler/ExtensionBehavior.h index 1318dd3..eb035e5 100644 --- a/src/OpenGL/compiler/ExtensionBehavior.h +++ b/src/OpenGL/compiler/ExtensionBehavior.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _EXTENSION_BEHAVIOR_INCLUDED_ #define _EXTENSION_BEHAVIOR_INCLUDED_ @@ -12,23 +20,23 @@ typedef enum { - EBhRequire, - EBhEnable, - EBhWarn, - EBhDisable, - EBhUndefined + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable, + EBhUndefined } TBehavior; inline const char *getBehaviorString(TBehavior b) { - switch(b) - { - case EBhRequire: return "require"; - case EBhEnable: return "enable"; - case EBhWarn: return "warn"; - case EBhDisable: return "disable"; - default: return NULL; - } + switch(b) + { + case EBhRequire: return "require"; + case EBhEnable: return "enable"; + case EBhWarn: return "warn"; + case EBhDisable: return "disable"; + default: return nullptr; + } } // Mapping between extension name and behavior.
diff --git a/src/OpenGL/compiler/InfoSink.cpp b/src/OpenGL/compiler/InfoSink.cpp index 53efd17..d059d05 100644 --- a/src/OpenGL/compiler/InfoSink.cpp +++ b/src/OpenGL/compiler/InfoSink.cpp
@@ -1,58 +1,66 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "InfoSink.h" void TInfoSinkBase::prefix(TPrefixType message) { - switch(message) { - case EPrefixNone: - break; - case EPrefixWarning: - sink.append("WARNING: "); - break; - case EPrefixError: - sink.append("ERROR: "); - break; - case EPrefixInternalError: - sink.append("INTERNAL ERROR: "); - break; - case EPrefixUnimplemented: - sink.append("UNIMPLEMENTED: "); - break; - case EPrefixNote: - sink.append("NOTE: "); - break; - default: - sink.append("UNKOWN ERROR: "); - break; - } + switch(message) { + case EPrefixNone: + break; + case EPrefixWarning: + sink.append("WARNING: "); + break; + case EPrefixError: + sink.append("ERROR: "); + break; + case EPrefixInternalError: + sink.append("INTERNAL ERROR: "); + break; + case EPrefixUnimplemented: + sink.append("UNIMPLEMENTED: "); + break; + case EPrefixNote: + sink.append("NOTE: "); + break; + default: + sink.append("UNKOWN ERROR: "); + break; + } } void TInfoSinkBase::location(const TSourceLoc& loc) { - int string = loc.first_file, line = loc.first_line; + int string = loc.first_file, line = loc.first_line; - TPersistStringStream stream; - if (line) - stream << string << ":" << line; - else - stream << string << ":? "; - stream << ": "; + TPersistStringStream stream; + if (line) + stream << string << ":" << line; + else + stream << string << ":? "; + stream << ": "; - sink.append(stream.str()); + sink.append(stream.str()); } void TInfoSinkBase::message(TPrefixType message, const char* s) { - prefix(message); - sink.append(s); - sink.append("\n"); + prefix(message); + sink.append(s); + sink.append("\n"); } void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) { - prefix(message); - location(loc); - sink.append(s); - sink.append("\n"); + prefix(message); + location(loc); + sink.append(s); + sink.append("\n"); }
diff --git a/src/OpenGL/compiler/InfoSink.h b/src/OpenGL/compiler/InfoSink.h index 160ba2e..711e4e4 100644 --- a/src/OpenGL/compiler/InfoSink.h +++ b/src/OpenGL/compiler/InfoSink.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _INFOSINK_INCLUDED_ #define _INFOSINK_INCLUDED_ @@ -21,12 +29,12 @@ // See below. // enum TPrefixType { - EPrefixNone, - EPrefixWarning, - EPrefixError, - EPrefixInternalError, - EPrefixUnimplemented, - EPrefixNote + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote }; // @@ -37,79 +45,79 @@ // class TInfoSinkBase { public: - TInfoSinkBase() {} + TInfoSinkBase() {} - template <typename T> - TInfoSinkBase& operator<<(const T& t) { - TPersistStringStream stream; - stream << t; - sink.append(stream.str()); - return *this; - } - // Override << operator for specific types. It is faster to append strings - // and characters directly to the sink. - TInfoSinkBase& operator<<(char c) { - sink.append(1, c); - return *this; - } - TInfoSinkBase& operator<<(const char* str) { - sink.append(str); - return *this; - } - TInfoSinkBase& operator<<(const TPersistString& str) { - sink.append(str); - return *this; - } - TInfoSinkBase& operator<<(const TString& str) { - sink.append(str.c_str()); - return *this; - } - // Make sure floats are written with correct precision. - TInfoSinkBase& operator<<(float f) { - // Make sure that at least one decimal point is written. If a number - // does not have a fractional part, the default precision format does - // not write the decimal portion which gets interpreted as integer by - // the compiler. - TPersistStringStream stream; - if (fractionalPart(f) == 0.0f) { - stream.precision(1); - stream << std::showpoint << std::fixed << f; - } else { - stream.unsetf(std::ios::fixed); - stream.unsetf(std::ios::scientific); - stream.precision(8); - stream << f; - } - sink.append(stream.str()); - return *this; - } - // Write boolean values as their names instead of integral value. - TInfoSinkBase& operator<<(bool b) { - const char* str = b ? "true" : "false"; - sink.append(str); - return *this; - } + template <typename T> + TInfoSinkBase& operator<<(const T& t) { + TPersistStringStream stream; + stream << t; + sink.append(stream.str()); + return *this; + } + // Override << operator for specific types. It is faster to append strings + // and characters directly to the sink. + TInfoSinkBase& operator<<(char c) { + sink.append(1, c); + return *this; + } + TInfoSinkBase& operator<<(const char* str) { + sink.append(str); + return *this; + } + TInfoSinkBase& operator<<(const TPersistString& str) { + sink.append(str); + return *this; + } + TInfoSinkBase& operator<<(const TString& str) { + sink.append(str.c_str()); + return *this; + } + // Make sure floats are written with correct precision. + TInfoSinkBase& operator<<(float f) { + // Make sure that at least one decimal point is written. If a number + // does not have a fractional part, the default precision format does + // not write the decimal portion which gets interpreted as integer by + // the compiler. + TPersistStringStream stream; + if (fractionalPart(f) == 0.0f) { + stream.precision(1); + stream << std::showpoint << std::fixed << f; + } else { + stream.unsetf(std::ios::fixed); + stream.unsetf(std::ios::scientific); + stream.precision(8); + stream << f; + } + sink.append(stream.str()); + return *this; + } + // Write boolean values as their names instead of integral value. + TInfoSinkBase& operator<<(bool b) { + const char* str = b ? "true" : "false"; + sink.append(str); + return *this; + } - void erase() { sink.clear(); } - int size() { return static_cast<int>(sink.size()); } + void erase() { sink.clear(); } + int size() { return static_cast<int>(sink.size()); } - const TPersistString& str() const { return sink; } - const char* c_str() const { return sink.c_str(); } + const TPersistString& str() const { return sink; } + const char* c_str() const { return sink.c_str(); } - void prefix(TPrefixType message); - void location(const TSourceLoc& loc); - void message(TPrefixType message, const char* s); - void message(TPrefixType message, const char* s, TSourceLoc loc); + void prefix(TPrefixType message); + void location(const TSourceLoc& loc); + void message(TPrefixType message, const char* s); + void message(TPrefixType message, const char* s, TSourceLoc loc); private: - TPersistString sink; + TPersistString sink; }; class TInfoSink { public: - TInfoSinkBase info; - TInfoSinkBase debug; - TInfoSinkBase obj; + TInfoSinkBase info; + TInfoSinkBase debug; + TInfoSinkBase obj; }; #endif // _INFOSINK_INCLUDED_
diff --git a/src/OpenGL/compiler/Initialize.cpp b/src/OpenGL/compiler/Initialize.cpp index 2fc517f..1948a57 100644 --- a/src/OpenGL/compiler/Initialize.cpp +++ b/src/OpenGL/compiler/Initialize.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // // Create strings that declare built-in definitions, add built-ins that @@ -22,83 +30,83 @@ TType *float4 = new TType(EbtFloat, 4); TType *genType = new TType(EbtGenType); - TType *int1 = new TType(EbtInt); + TType *int1 = new TType(EbtInt); TType *int2 = new TType(EbtInt, 2); TType *int3 = new TType(EbtInt, 3); - TType *uint1 = new TType(EbtUInt); - TType *genIType = new TType(EbtGenIType); - TType *genUType = new TType(EbtGenUType); - TType *genBType = new TType(EbtGenBType); + TType *uint1 = new TType(EbtUInt); + TType *genIType = new TType(EbtGenIType); + TType *genUType = new TType(EbtGenUType); + TType *genBType = new TType(EbtGenBType); - // - // Angle and Trigonometric Functions. - // - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRadians, genType, "radians", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDegrees, genType, "degrees", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSin, genType, "sin", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCos, genType, "cos", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpTan, genType, "tan", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAsin, genType, "asin", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAcos, genType, "acos", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSinh, genType, "sinh", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpCosh, genType, "cosh", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTanh, genType, "tanh", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAsinh, genType, "asinh", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAcosh, genType, "acosh", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAtanh, genType, "atanh", genType); + // + // Angle and Trigonometric Functions. + // + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRadians, genType, "radians", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDegrees, genType, "degrees", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSin, genType, "sin", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCos, genType, "cos", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpTan, genType, "tan", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAsin, genType, "asin", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAcos, genType, "acos", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSinh, genType, "sinh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpCosh, genType, "cosh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTanh, genType, "tanh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAsinh, genType, "asinh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAcosh, genType, "acosh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAtanh, genType, "atanh", genType); - // - // Exponential Functions. - // - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpPow, genType, "pow", genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp, genType, "exp", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog, genType, "log", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp2, genType, "exp2", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog2, genType, "log2", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSqrt, genType, "sqrt", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpInverseSqrt, genType, "inversesqrt", genType); + // + // Exponential Functions. + // + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpPow, genType, "pow", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp, genType, "exp", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog, genType, "log", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp2, genType, "exp2", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog2, genType, "log2", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSqrt, genType, "sqrt", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpInverseSqrt, genType, "inversesqrt", genType); - // - // Common Functions. - // - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAbs, genType, "abs", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAbs, genIType, "abs", genIType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSign, genType, "sign", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSign, genIType, "sign", genIType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFloor, genType, "floor", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTrunc, genType, "trunc", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRound, genType, "round", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRoundEven, genType, "roundEven", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCeil, genType, "ceil", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFract, genType, "fract", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, genIType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, genUType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, uint1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, genIType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, genUType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, uint1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, genType, genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, int1, int1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, genIType, genIType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, uint1, uint1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", float1, float1, genType); + // + // Common Functions. + // + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAbs, genType, "abs", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAbs, genIType, "abs", genIType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSign, genType, "sign", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSign, genIType, "sign", genIType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFloor, genType, "floor", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTrunc, genType, "trunc", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRound, genType, "round", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRoundEven, genType, "roundEven", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCeil, genType, "ceil", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFract, genType, "fract", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, genUType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, uint1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, genUType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, uint1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, int1, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, uint1, uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", float1, float1, genType); TType *outFloat1 = new TType(EbtFloat, EbpUndefined, EvqOut); TType *outFloat2 = new TType(EbtFloat, EbpUndefined, EvqOut, 2); @@ -110,31 +118,31 @@ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float3, "modf", float3, outFloat3); symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float4, "modf", float4, outFloat4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsNan, genBType, "isnan", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsInf, genBType, "isinf", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, "floatBitsToInt", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, "floatBitsToUint", genType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, "intBitsToFloat", genIType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, "uintBitsToFloat", genUType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsNan, genBType, "isnan", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsInf, genBType, "isinf", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, "floatBitsToInt", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, "floatBitsToUint", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, "intBitsToFloat", genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, "uintBitsToFloat", genUType); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, "packSnorm2x16", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, "packUnorm2x16", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, "packHalf2x16", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, "unpackSnorm2x16", uint1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, "unpackUnorm2x16", uint1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, "unpackHalf2x16", uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, "packSnorm2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, "packUnorm2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, "packHalf2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, "unpackSnorm2x16", uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, "unpackUnorm2x16", uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, "unpackHalf2x16", uint1); - // - // Geometric Functions. - // - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLength, float1, "length", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDistance, float1, "distance", genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDot, float1, "dot", genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCross, float3, "cross", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpNormalize, genType, "normalize", genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFaceForward, genType, "faceforward", genType, genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1); + // + // Geometric Functions. + // + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLength, float1, "length", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDistance, float1, "distance", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDot, float1, "dot", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCross, float3, "cross", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpNormalize, genType, "normalize", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFaceForward, genType, "faceforward", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1); TType *mat2 = new TType(EbtFloat, 2, 2); TType *mat2x3 = new TType(EbtFloat, 2, 3); @@ -146,46 +154,46 @@ TType *mat4x3 = new TType(EbtFloat, 4, 3); TType *mat4 = new TType(EbtFloat, 4, 4); - // - // Matrix Functions. - // - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat2, "matrixCompMult", mat2, mat2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat3, "matrixCompMult", mat3, mat3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat4, "matrixCompMult", mat4, mat4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x3, "matrixCompMult", mat2x3, mat2x3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x2, "matrixCompMult", mat3x2, mat3x2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x4, "matrixCompMult", mat2x4, mat2x4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x2, "matrixCompMult", mat4x2, mat4x2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x4, "matrixCompMult", mat3x4, mat3x4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x3, "matrixCompMult", mat4x3, mat4x3); + // + // Matrix Functions. + // + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat2, "matrixCompMult", mat2, mat2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat3, "matrixCompMult", mat3, mat3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat4, "matrixCompMult", mat4, mat4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x3, "matrixCompMult", mat2x3, mat2x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x2, "matrixCompMult", mat3x2, mat3x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x4, "matrixCompMult", mat2x4, mat2x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x2, "matrixCompMult", mat4x2, mat4x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x4, "matrixCompMult", mat3x4, mat3x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x3, "matrixCompMult", mat4x3, mat4x3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2, "outerProduct", float2, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3, "outerProduct", float3, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4, "outerProduct", float4, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, "outerProduct", float3, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, "outerProduct", float2, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, "outerProduct", float4, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, "outerProduct", float2, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, "outerProduct", float4, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, "outerProduct", float3, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2, "outerProduct", float2, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3, "outerProduct", float3, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4, "outerProduct", float4, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, "outerProduct", float3, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, "outerProduct", float2, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, "outerProduct", float4, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, "outerProduct", float2, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, "outerProduct", float4, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, "outerProduct", float3, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2, "transpose", mat2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3, "transpose", mat3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4, "transpose", mat4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x3, "transpose", mat3x2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x2, "transpose", mat2x3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x4, "transpose", mat4x2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x2, "transpose", mat2x4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x4, "transpose", mat4x3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x3, "transpose", mat3x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2, "transpose", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3, "transpose", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4, "transpose", mat4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x3, "transpose", mat3x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x2, "transpose", mat2x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x4, "transpose", mat4x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x2, "transpose", mat2x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x4, "transpose", mat4x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x3, "transpose", mat3x4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat2, "inverse", mat2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat3, "inverse", mat3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat4, "inverse", mat4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat2, "inverse", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat3, "inverse", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat4, "inverse", mat4); TType *bool1 = new TType(EbtBool); @@ -194,62 +202,62 @@ TType *uvec = new TType(EbtUVec); TType *bvec = new TType(EbtBVec); - // - // Vector relational functions. - // - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", vec, vec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", ivec, ivec); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThan, bvec, "lessThan", uvec, uvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", vec, vec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", ivec, ivec); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", uvec, uvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", vec, vec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", ivec, ivec); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThan, bvec, "greaterThan", uvec, uvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", vec, vec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", ivec, ivec); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", uvec, uvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", vec, vec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", ivec, ivec); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorEqual, bvec, "equal", uvec, uvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", bvec, bvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", vec, vec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", ivec, ivec); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", uvec, uvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", bvec, bvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAny, bool1, "any", bvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec); - symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec); + // + // Vector relational functions. + // + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThan, bvec, "lessThan", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThan, bvec, "greaterThan", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorEqual, bvec, "equal", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", bvec, bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", bvec, bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAny, bool1, "any", bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec); TType *sampler2D = new TType(EbtSampler2D); TType *samplerCube = new TType(EbtSamplerCube); TType *sampler3D = new TType(EbtSampler3D); - // - // Texture Functions for GLSL ES 1.0 - // - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3); + // + // Texture Functions for GLSL ES 1.0 + // + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3); symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture3D", sampler3D, float3); if(resources.OES_EGL_image_external) - { - TType *samplerExternalOES = new TType(EbtSamplerExternalOES); + { + TType *samplerExternalOES = new TType(EbtSamplerExternalOES); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float4); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float4); symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture3D", samplerExternalOES, float3); - } + } if(type == GL_FRAGMENT_SHADER) { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3, float1); if(resources.OES_standard_derivatives) { @@ -268,38 +276,38 @@ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture3DLod", sampler3D, float3, float1); } - TType *gvec4 = new TType(EbtGVec4); + TType *gvec4 = new TType(EbtGVec4); - TType *gsampler2D = new TType(EbtGSampler2D); - TType *gsamplerCube = new TType(EbtGSamplerCube); - TType *gsampler3D = new TType(EbtGSampler3D); - TType *gsampler2DArray = new TType(EbtGSampler2DArray); + TType *gsampler2D = new TType(EbtGSampler2D); + TType *gsamplerCube = new TType(EbtGSamplerCube); + TType *gsampler3D = new TType(EbtGSampler3D); + TType *gsampler2DArray = new TType(EbtGSampler2DArray); - // - // Texture Functions for GLSL ES 3.0 - // - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler3D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1); + // + // Texture Functions for GLSL ES 3.0 + // + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler3D, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1); - if(type == GL_FRAGMENT_SHADER) - { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1); - } + if(type == GL_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1); + } TType *sampler2DShadow = new TType(EbtSampler2DShadow); TType *samplerCubeShadow = new TType(EbtSamplerCubeShadow); @@ -406,9 +414,9 @@ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4, float3, float3, int3); symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow, float4, float2, float2, int2); - // - // Depth range in window coordinates - // + // + // Depth range in window coordinates + // TFieldList *fields = NewPoolTFieldList(); TSourceLoc zeroSourceLoc = { 0, 0, 0, 0 }; TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"), zeroSourceLoc); @@ -424,73 +432,73 @@ depthRange->setQualifier(EvqUniform); symbolTable.insert(COMMON_BUILTINS, *depthRange); - // - // Implementation dependent built-in constants. - // - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits", resources.MaxTextureImageUnits); - symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors); - symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors); - symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", resources.MaxVertexOutputVectors); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors", resources.MaxFragmentInputVectors); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset", resources.MinProgramTexelOffset); - symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset", resources.MaxProgramTexelOffset); + // + // Implementation dependent built-in constants. + // + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits", resources.MaxTextureImageUnits); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors); + symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors); + symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers); + symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", resources.MaxVertexOutputVectors); + symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors", resources.MaxFragmentInputVectors); + symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset", resources.MinProgramTexelOffset); + symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset", resources.MaxProgramTexelOffset); } void IdentifyBuiltIns(GLenum shaderType, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { - // - // First, insert some special built-in variables that are not in - // the built-in header files. - // - switch(shaderType) + // + // First, insert some special built-in variables that are not in + // the built-in header files. + // + switch(shaderType) { - case GL_FRAGMENT_SHADER: - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); - symbolTable.insert(ESSL3_BUILTINS, *new TVariable(NewPoolTString("gl_FragDepth"), TType(EbtFloat, EbpHigh, EvqFragDepth, 1))); - break; - case GL_VERTEX_SHADER: - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); - symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); - symbolTable.insert(ESSL3_BUILTINS, *new TVariable(NewPoolTString("gl_InstanceID"), TType(EbtInt, EbpHigh, EvqInstanceID, 1))); - break; - default: assert(false && "Language not supported"); - } + case GL_FRAGMENT_SHADER: + symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); + symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); + symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); + symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); + symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); + symbolTable.insert(ESSL3_BUILTINS, *new TVariable(NewPoolTString("gl_FragDepth"), TType(EbtFloat, EbpHigh, EvqFragDepth, 1))); + break; + case GL_VERTEX_SHADER: + symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); + symbolTable.insert(COMMON_BUILTINS, *new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); + symbolTable.insert(ESSL3_BUILTINS, *new TVariable(NewPoolTString("gl_InstanceID"), TType(EbtInt, EbpHigh, EvqInstanceID, 1))); + break; + default: assert(false && "Language not supported"); + } - // Finally add resource-specific variables. - switch(shaderType) - { - case GL_FRAGMENT_SHADER: + // Finally add resource-specific variables. + switch(shaderType) + { + case GL_FRAGMENT_SHADER: { - // Set up gl_FragData. The array size. - TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); - fragData.setArraySize(resources.MaxDrawBuffers); - symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragData"), fragData)); + // Set up gl_FragData. The array size. + TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); + fragData.setArraySize(resources.MaxDrawBuffers); + symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragData"), fragData)); } break; - default: break; - } + default: break; + } } void InitExtensionBehavior(const ShBuiltInResources& resources, TExtensionBehavior& extBehavior) { - if(resources.OES_standard_derivatives) - extBehavior["GL_OES_standard_derivatives"] = EBhUndefined; + if(resources.OES_standard_derivatives) + extBehavior["GL_OES_standard_derivatives"] = EBhUndefined; if(resources.OES_fragment_precision_high) - extBehavior["GL_FRAGMENT_PRECISION_HIGH"] = EBhUndefined; - if(resources.OES_EGL_image_external) - extBehavior["GL_OES_EGL_image_external"] = EBhUndefined; + extBehavior["GL_FRAGMENT_PRECISION_HIGH"] = EBhUndefined; + if(resources.OES_EGL_image_external) + extBehavior["GL_OES_EGL_image_external"] = EBhUndefined; if(resources.EXT_draw_buffers) - extBehavior["GL_EXT_draw_buffers"] = EBhUndefined; + extBehavior["GL_EXT_draw_buffers"] = EBhUndefined; }
diff --git a/src/OpenGL/compiler/Initialize.h b/src/OpenGL/compiler/Initialize.h index e96aa69..e5fcbf2 100644 --- a/src/OpenGL/compiler/Initialize.h +++ b/src/OpenGL/compiler/Initialize.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _INITIALIZE_INCLUDED_ #define _INITIALIZE_INCLUDED_
diff --git a/src/OpenGL/compiler/InitializeGlobals.h b/src/OpenGL/compiler/InitializeGlobals.h index 0715941..3ddb048 100644 --- a/src/OpenGL/compiler/InitializeGlobals.h +++ b/src/OpenGL/compiler/InitializeGlobals.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef __INITIALIZE_GLOBALS_INCLUDED_ #define __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/src/OpenGL/compiler/InitializeParseContext.cpp b/src/OpenGL/compiler/InitializeParseContext.cpp index 70116bd..06b72d9 100644 --- a/src/OpenGL/compiler/InitializeParseContext.cpp +++ b/src/OpenGL/compiler/InitializeParseContext.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "InitializeParseContext.h" @@ -12,29 +20,29 @@ bool InitializeParseContextIndex() { - assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); + assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); - GlobalParseContextIndex = OS_AllocTLSIndex(); - return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; + GlobalParseContextIndex = OS_AllocTLSIndex(); + return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; } void FreeParseContextIndex() { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - OS_FreeTLSIndex(GlobalParseContextIndex); - GlobalParseContextIndex = OS_INVALID_TLS_INDEX; + OS_FreeTLSIndex(GlobalParseContextIndex); + GlobalParseContextIndex = OS_INVALID_TLS_INDEX; } void SetGlobalParseContext(TParseContext* context) { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - OS_SetTLSValue(GlobalParseContextIndex, context); + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(GlobalParseContextIndex, context); } TParseContext* GetGlobalParseContext() { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex)); + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex)); }
diff --git a/src/OpenGL/compiler/InitializeParseContext.h b/src/OpenGL/compiler/InitializeParseContext.h index 79d691f..c55eae2 100644 --- a/src/OpenGL/compiler/InitializeParseContext.h +++ b/src/OpenGL/compiler/InitializeParseContext.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_ #define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/src/OpenGL/compiler/IntermTraverse.cpp b/src/OpenGL/compiler/IntermTraverse.cpp index 3ed50e2..09c8e6e 100644 --- a/src/OpenGL/compiler/IntermTraverse.cpp +++ b/src/OpenGL/compiler/IntermTraverse.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "intermediate.h" @@ -47,7 +55,7 @@ { visit = it->visitBinary(PreVisit, this); } - + // // Visit the children, in the right order. // @@ -55,13 +63,13 @@ { it->incrementDepth(this); - if(it->rightToLeft) + if(it->rightToLeft) { if(right) { right->traverse(it); } - + if(it->inVisit) { visit = it->visitBinary(InVisit, this); @@ -78,7 +86,7 @@ { left->traverse(it); } - + if(it->inVisit) { visit = it->visitBinary(InVisit, this); @@ -118,7 +126,7 @@ operand->traverse(it); it->decrementDepth(); } - + if (visit && it->postVisit) it->visitUnary(PostVisit, this); } @@ -129,12 +137,12 @@ void TIntermAggregate::traverse(TIntermTraverser* it) { bool visit = true; - + if(it->preVisit) { visit = it->visitAggregate(PreVisit, this); } - + if(visit) { it->incrementDepth(this); @@ -169,7 +177,7 @@ } } } - + it->decrementDepth(); } @@ -188,7 +196,7 @@ if (it->preVisit) visit = it->visitSelection(PreVisit, this); - + if (visit) { it->incrementDepth(this); if (it->rightToLeft) { @@ -276,7 +284,7 @@ { visit = it->visitLoop(PreVisit, this); } - + if(visit) { it->incrementDepth(this); @@ -334,7 +342,7 @@ if (it->preVisit) visit = it->visitBranch(PreVisit, this); - + if (visit && expression) { it->incrementDepth(this); expression->traverse(it);
diff --git a/src/OpenGL/compiler/Intermediate.cpp b/src/OpenGL/compiler/Intermediate.cpp index ca0e59e..dbbfb19 100644 --- a/src/OpenGL/compiler/Intermediate.cpp +++ b/src/OpenGL/compiler/Intermediate.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // // Build the intermediate representation. @@ -19,7 +27,7 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){ - return left > right ? left : right; + return left > right ? left : right; } static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right) @@ -55,114 +63,114 @@ } const char* getOperatorString(TOperator op) { - switch (op) { - case EOpInitialize: return "="; - case EOpAssign: return "="; - case EOpAddAssign: return "+="; - case EOpSubAssign: return "-="; - case EOpDivAssign: return "/="; - case EOpIModAssign: return "%="; - case EOpBitShiftLeftAssign: return "<<="; - case EOpBitShiftRightAssign: return ">>="; - case EOpBitwiseAndAssign: return "&="; - case EOpBitwiseXorAssign: return "^="; - case EOpBitwiseOrAssign: return "|="; + switch (op) { + case EOpInitialize: return "="; + case EOpAssign: return "="; + case EOpAddAssign: return "+="; + case EOpSubAssign: return "-="; + case EOpDivAssign: return "/="; + case EOpIModAssign: return "%="; + case EOpBitShiftLeftAssign: return "<<="; + case EOpBitShiftRightAssign: return ">>="; + case EOpBitwiseAndAssign: return "&="; + case EOpBitwiseXorAssign: return "^="; + case EOpBitwiseOrAssign: return "|="; - // Fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: return "*="; + // Fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: return "*="; - // Fall-through. - case EOpIndexDirect: - case EOpIndexIndirect: return "[]"; + // Fall-through. + case EOpIndexDirect: + case EOpIndexIndirect: return "[]"; - case EOpIndexDirectStruct: return "."; - case EOpVectorSwizzle: return "."; - case EOpAdd: return "+"; - case EOpSub: return "-"; - case EOpMul: return "*"; - case EOpDiv: return "/"; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: return "=="; - case EOpNotEqual: return "!="; - case EOpLessThan: return "<"; - case EOpGreaterThan: return ">"; - case EOpLessThanEqual: return "<="; - case EOpGreaterThanEqual: return ">="; + case EOpIndexDirectStruct: return "."; + case EOpVectorSwizzle: return "."; + case EOpAdd: return "+"; + case EOpSub: return "-"; + case EOpMul: return "*"; + case EOpDiv: return "/"; + case EOpMod: UNIMPLEMENTED(); break; + case EOpEqual: return "=="; + case EOpNotEqual: return "!="; + case EOpLessThan: return "<"; + case EOpGreaterThan: return ">"; + case EOpLessThanEqual: return "<="; + case EOpGreaterThanEqual: return ">="; - // Fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: return "*"; + // Fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: return "*"; - case EOpLogicalOr: return "||"; - case EOpLogicalXor: return "^^"; - case EOpLogicalAnd: return "&&"; - case EOpIMod: return "%"; - case EOpBitShiftLeft: return "<<"; - case EOpBitShiftRight: return ">>"; - case EOpBitwiseAnd: return "&"; - case EOpBitwiseXor: return "^"; - case EOpBitwiseOr: return "|"; - case EOpNegative: return "-"; - case EOpVectorLogicalNot: return "not"; - case EOpLogicalNot: return "!"; - case EOpBitwiseNot: return "~"; - case EOpPostIncrement: return "++"; - case EOpPostDecrement: return "--"; - case EOpPreIncrement: return "++"; - case EOpPreDecrement: return "--"; + case EOpLogicalOr: return "||"; + case EOpLogicalXor: return "^^"; + case EOpLogicalAnd: return "&&"; + case EOpIMod: return "%"; + case EOpBitShiftLeft: return "<<"; + case EOpBitShiftRight: return ">>"; + case EOpBitwiseAnd: return "&"; + case EOpBitwiseXor: return "^"; + case EOpBitwiseOr: return "|"; + case EOpNegative: return "-"; + case EOpVectorLogicalNot: return "not"; + case EOpLogicalNot: return "!"; + case EOpBitwiseNot: return "~"; + case EOpPostIncrement: return "++"; + case EOpPostDecrement: return "--"; + case EOpPreIncrement: return "++"; + case EOpPreDecrement: return "--"; - case EOpRadians: return "radians"; - case EOpDegrees: return "degrees"; - case EOpSin: return "sin"; - case EOpCos: return "cos"; - case EOpTan: return "tan"; - case EOpAsin: return "asin"; - case EOpAcos: return "acos"; - case EOpAtan: return "atan"; - case EOpSinh: return "sinh"; - case EOpCosh: return "cosh"; - case EOpTanh: return "tanh"; - case EOpAsinh: return "asinh"; - case EOpAcosh: return "acosh"; - case EOpAtanh: return "atanh"; - case EOpExp: return "exp"; - case EOpLog: return "log"; - case EOpExp2: return "exp2"; - case EOpLog2: return "log2"; - case EOpSqrt: return "sqrt"; - case EOpInverseSqrt: return "inversesqrt"; - case EOpAbs: return "abs"; - case EOpSign: return "sign"; - case EOpFloor: return "floor"; - case EOpTrunc: return "trunc"; - case EOpRound: return "round"; - case EOpRoundEven: return "roundEven"; - case EOpCeil: return "ceil"; - case EOpFract: return "fract"; - case EOpLength: return "length"; - case EOpNormalize: return "normalize"; - case EOpDFdx: return "dFdx"; - case EOpDFdy: return "dFdy"; - case EOpFwidth: return "fwidth"; - case EOpAny: return "any"; - case EOpAll: return "all"; - case EOpIsNan: return "isnan"; - case EOpIsInf: return "isinf"; - case EOpOuterProduct: return "outerProduct"; - case EOpTranspose: return "transpose"; - case EOpDeterminant: return "determinant"; - case EOpInverse: return "inverse"; + case EOpRadians: return "radians"; + case EOpDegrees: return "degrees"; + case EOpSin: return "sin"; + case EOpCos: return "cos"; + case EOpTan: return "tan"; + case EOpAsin: return "asin"; + case EOpAcos: return "acos"; + case EOpAtan: return "atan"; + case EOpSinh: return "sinh"; + case EOpCosh: return "cosh"; + case EOpTanh: return "tanh"; + case EOpAsinh: return "asinh"; + case EOpAcosh: return "acosh"; + case EOpAtanh: return "atanh"; + case EOpExp: return "exp"; + case EOpLog: return "log"; + case EOpExp2: return "exp2"; + case EOpLog2: return "log2"; + case EOpSqrt: return "sqrt"; + case EOpInverseSqrt: return "inversesqrt"; + case EOpAbs: return "abs"; + case EOpSign: return "sign"; + case EOpFloor: return "floor"; + case EOpTrunc: return "trunc"; + case EOpRound: return "round"; + case EOpRoundEven: return "roundEven"; + case EOpCeil: return "ceil"; + case EOpFract: return "fract"; + case EOpLength: return "length"; + case EOpNormalize: return "normalize"; + case EOpDFdx: return "dFdx"; + case EOpDFdy: return "dFdy"; + case EOpFwidth: return "fwidth"; + case EOpAny: return "any"; + case EOpAll: return "all"; + case EOpIsNan: return "isnan"; + case EOpIsInf: return "isinf"; + case EOpOuterProduct: return "outerProduct"; + case EOpTranspose: return "transpose"; + case EOpDeterminant: return "determinant"; + case EOpInverse: return "inverse"; - default: break; - } - return ""; + default: break; + } + return ""; } //////////////////////////////////////////////////////////////////////////// @@ -180,10 +188,10 @@ // TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc &line) { - TIntermSymbol* node = new TIntermSymbol(id, name, type); - node->setLine(line); + TIntermSymbol* node = new TIntermSymbol(id, name, type); + node->setLine(line); - return node; + return node; } // @@ -193,94 +201,94 @@ // TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line) { - bool isBitShift = false; - switch (op) { - case EOpEqual: - case EOpNotEqual: - if (left->isArray()) - return 0; - break; - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { - return 0; - } - break; - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { - return 0; - } - break; - case EOpBitwiseOr: - case EOpBitwiseXor: - case EOpBitwiseAnd: - if (!IsInteger(left->getBasicType()) || left->isMatrix() || left->isArray()) { - return 0; - } - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) { - return 0; - } - break; - case EOpIMod: - // Note that this is only for the % operator, not for mod() - if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) { - return 0; - } - break; - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - // Unsigned can be bit-shifted by signed and vice versa, but we need to - // check that the basic type is an integer type. - isBitShift = true; - if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType())) - { - return 0; - } - break; - default: break; - } + bool isBitShift = false; + switch (op) { + case EOpEqual: + case EOpNotEqual: + if (left->isArray()) + return 0; + break; + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { + return 0; + } + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { + return 0; + } + break; + case EOpBitwiseOr: + case EOpBitwiseXor: + case EOpBitwiseAnd: + if (!IsInteger(left->getBasicType()) || left->isMatrix() || left->isArray()) { + return 0; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) { + return 0; + } + break; + case EOpIMod: + // Note that this is only for the % operator, not for mod() + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) { + return 0; + } + break; + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + // Unsigned can be bit-shifted by signed and vice versa, but we need to + // check that the basic type is an integer type. + isBitShift = true; + if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType())) + { + return 0; + } + break; + default: break; + } - if(!isBitShift && left->getBasicType() != right->getBasicType()) - { - return 0; - } + if(!isBitShift && left->getBasicType() != right->getBasicType()) + { + return 0; + } - // - // Need a new node holding things together then. Make - // one and promote it to the right type. - // - TIntermBinary* node = new TIntermBinary(op); - node->setLine(line); + // + // Need a new node holding things together then. Make + // one and promote it to the right type. + // + TIntermBinary* node = new TIntermBinary(op); + node->setLine(line); - node->setLeft(left); - node->setRight(right); - if (!node->promote(infoSink)) - return 0; + node->setLeft(left); + node->setRight(right); + if (!node->promote(infoSink)) + return 0; - // - // See if we can fold constants. - // - TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); - TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); - if (leftTempConstant && rightTempConstant) { - TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); + // + // See if we can fold constants. + // + TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); + TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); + if (leftTempConstant && rightTempConstant) { + TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); - if (typedReturnNode) - return typedReturnNode; - } + if (typedReturnNode) + return typedReturnNode; + } - return node; + return node; } // @@ -290,23 +298,23 @@ // TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line) { - if (left->getType().getStruct() || right->getType().getStruct()) - { - if (left->getType() != right->getType()) - { - return 0; - } - } + if (left->getType().getStruct() || right->getType().getStruct()) + { + if (left->getType() != right->getType()) + { + return 0; + } + } - TIntermBinary* node = new TIntermBinary(op); - node->setLine(line); + TIntermBinary* node = new TIntermBinary(op); + node->setLine(line); - node->setLeft(left); - node->setRight(right); - if (! node->promote(infoSink)) - return 0; + node->setLeft(left); + node->setRight(right); + if (! node->promote(infoSink)) + return 0; - return node; + return node; } // @@ -318,14 +326,14 @@ // TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line) { - TIntermBinary* node = new TIntermBinary(op); - node->setLine(line); - node->setLeft(base); - node->setRight(index); + TIntermBinary* node = new TIntermBinary(op); + node->setLine(line); + node->setLeft(base); + node->setRight(index); - // caller should set the type + // caller should set the type - return node; + return node; } // @@ -335,56 +343,56 @@ // TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc &line, const TType *funcReturnType) { - if (child == 0) { - infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); - return 0; - } + if (child == 0) { + infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); + return 0; + } - switch (op) { - case EOpBitwiseNot: - if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) { - return 0; - } - break; + switch (op) { + case EOpBitwiseNot: + if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) { + return 0; + } + break; - case EOpLogicalNot: - if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { - return 0; - } - break; + case EOpLogicalNot: + if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { + return 0; + } + break; - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) - return 0; - default: break; - } + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) + return 0; + default: break; + } - TIntermConstantUnion *childTempConstant = 0; - if (child->getAsConstantUnion()) - childTempConstant = child->getAsConstantUnion(); + TIntermConstantUnion *childTempConstant = 0; + if (child->getAsConstantUnion()) + childTempConstant = child->getAsConstantUnion(); - // - // Make a new node for the operator. - // - TIntermUnary *node = new TIntermUnary(op); - node->setLine(line); - node->setOperand(child); + // + // Make a new node for the operator. + // + TIntermUnary *node = new TIntermUnary(op); + node->setLine(line); + node->setOperand(child); - if (! node->promote(infoSink, funcReturnType)) - return 0; + if (! node->promote(infoSink, funcReturnType)) + return 0; - if (childTempConstant) { - TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); + if (childTempConstant) { + TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); - if (newChild) - return newChild; - } + if (newChild) + return newChild; + } - return node; + return node; } // @@ -399,29 +407,29 @@ // TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line) { - TIntermAggregate* aggNode; + TIntermAggregate* aggNode; - // - // Make sure we have an aggregate. If not turn it into one. - // - if (node) { - aggNode = node->getAsAggregate(); - if (aggNode == 0 || aggNode->getOp() != EOpNull) { - // - // Make an aggregate containing this node. - // - aggNode = new TIntermAggregate(); - aggNode->getSequence().push_back(node); - } - } else - aggNode = new TIntermAggregate(); + // + // Make sure we have an aggregate. If not turn it into one. + // + if (node) { + aggNode = node->getAsAggregate(); + if (aggNode == 0 || aggNode->getOp() != EOpNull) { + // + // Make an aggregate containing this node. + // + aggNode = new TIntermAggregate(); + aggNode->getSequence().push_back(node); + } + } else + aggNode = new TIntermAggregate(); - // - // Set the operator. - // - aggNode->setOp(op); + // + // Set the operator. + // + aggNode->setOp(op); - return aggNode; + return aggNode; } // @@ -433,24 +441,24 @@ // TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line) { - if (left == 0 && right == 0) - return 0; + if (left == 0 && right == 0) + return 0; - TIntermAggregate* aggNode = 0; - if (left) - aggNode = left->getAsAggregate(); - if (!aggNode || aggNode->getOp() != EOpNull) { - aggNode = new TIntermAggregate; - if (left) - aggNode->getSequence().push_back(left); - } + TIntermAggregate* aggNode = 0; + if (left) + aggNode = left->getAsAggregate(); + if (!aggNode || aggNode->getOp() != EOpNull) { + aggNode = new TIntermAggregate; + if (left) + aggNode->getSequence().push_back(left); + } - if (right) - aggNode->getSequence().push_back(right); + if (right) + aggNode->getSequence().push_back(right); - aggNode->setLine(line); + aggNode->setLine(line); - return aggNode; + return aggNode; } // @@ -460,15 +468,15 @@ // TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line) { - if (node == 0) - return 0; + if (node == 0) + return 0; - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->getSequence().push_back(node); + TIntermAggregate* aggNode = new TIntermAggregate; + aggNode->getSequence().push_back(node); - aggNode->setLine(line); + aggNode->setLine(line); - return aggNode; + return aggNode; } // @@ -480,36 +488,36 @@ // TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line) { - // - // For compile time constant selections, prune the code and - // test now. - // + // + // For compile time constant selections, prune the code and + // test now. + // - if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { - if (cond->getAsConstantUnion()->getBConst(0) == true) - return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; - else - return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; - } + if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { + if (cond->getAsConstantUnion()->getBConst(0) == true) + return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : nullptr; + else + return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : nullptr; + } - TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); - node->setLine(line); + TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); + node->setLine(line); - return node; + return node; } TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line) { - if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) { - return right; - } else { - TIntermTyped *commaAggregate = growAggregate(left, right, line); - commaAggregate->getAsAggregate()->setOp(EOpComma); - commaAggregate->setType(right->getType()); - commaAggregate->getTypePointer()->setQualifier(EvqTemporary); - return commaAggregate; - } + if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) { + return right; + } else { + TIntermTyped *commaAggregate = growAggregate(left, right, line); + commaAggregate->getAsAggregate()->setOp(EOpComma); + commaAggregate->setType(right->getType()); + commaAggregate->getTypePointer()->setQualifier(EvqTemporary); + return commaAggregate; + } } // @@ -521,30 +529,30 @@ // TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line) { - if (trueBlock->getType() != falseBlock->getType()) - { - return 0; - } + if (trueBlock->getType() != falseBlock->getType()) + { + return 0; + } - // - // See if all the operands are constant, then fold it otherwise not. - // + // + // See if all the operands are constant, then fold it otherwise not. + // - if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { - if (cond->getAsConstantUnion()->getBConst(0)) - return trueBlock; - else - return falseBlock; - } + if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { + if (cond->getAsConstantUnion()->getBConst(0)) + return trueBlock; + else + return falseBlock; + } - // - // Make a selection node. - // - TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); - node->getTypePointer()->setQualifier(EvqTemporary); - node->setLine(line); + // + // Make a selection node. + // + TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); + node->getTypePointer()->setQualifier(EvqTemporary); + node->setLine(line); - return node; + return node; } TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line) @@ -571,30 +579,30 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line) { - TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); - node->setLine(line); + TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); + node->setLine(line); - return node; + return node; } TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line) { - TIntermAggregate* node = new TIntermAggregate(EOpSequence); + TIntermAggregate* node = new TIntermAggregate(EOpSequence); - node->setLine(line); - TIntermConstantUnion* constIntNode; - TIntermSequence &sequenceVector = node->getSequence(); - ConstantUnion* unionArray; + node->setLine(line); + TIntermConstantUnion* constIntNode; + TIntermSequence &sequenceVector = node->getSequence(); + ConstantUnion* unionArray; - for (int i = 0; i < fields.num; i++) { - unionArray = new ConstantUnion[1]; - unionArray->setIConst(fields.offsets[i]); - constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line); - sequenceVector.push_back(constIntNode); - } + for (int i = 0; i < fields.num; i++) { + unionArray = new ConstantUnion[1]; + unionArray->setIConst(fields.offsets[i]); + constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line); + sequenceVector.push_back(constIntNode); + } - return node; + return node; } // @@ -602,10 +610,10 @@ // 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); + TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); + node->setLine(line); - return node; + return node; } // @@ -613,15 +621,15 @@ // TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line) { - return addBranch(branchOp, 0, line); + return addBranch(branchOp, 0, line); } TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line) { - TIntermBranch* node = new TIntermBranch(branchOp, expression); - node->setLine(line); + TIntermBranch* node = new TIntermBranch(branchOp, expression); + node->setLine(line); - return node; + return node; } // @@ -630,17 +638,17 @@ // bool TIntermediate::postProcess(TIntermNode* root) { - if (root == 0) - return true; + if (root == 0) + return true; - // - // First, finish off the top level sequence, if any - // - TIntermAggregate* aggRoot = root->getAsAggregate(); - if (aggRoot && aggRoot->getOp() == EOpNull) - aggRoot->setOp(EOpSequence); + // + // First, finish off the top level sequence, if any + // + TIntermAggregate* aggRoot = root->getAsAggregate(); + if (aggRoot && aggRoot->getOp() == EOpNull) + aggRoot->setOp(EOpSequence); - return true; + return true; } //////////////////////////////////////////////////////////////// @@ -656,30 +664,30 @@ // bool TIntermOperator::modifiesState() const { - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - case EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - return true; - default: - return false; - } + switch (op) { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + return true; + default: + return false; + } } // @@ -687,37 +695,37 @@ // bool TIntermOperator::isConstructor() const { - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4: - case EOpConstructFloat: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUInt: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - case EOpConstructStruct: - return true; - default: - return false; - } + switch (op) { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat2x3: + case EOpConstructMat2x4: + case EOpConstructMat3x2: + case EOpConstructMat3: + case EOpConstructMat3x4: + case EOpConstructMat4x2: + case EOpConstructMat4x3: + case EOpConstructMat4: + case EOpConstructFloat: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + case EOpConstructUVec2: + case EOpConstructUVec3: + case EOpConstructUVec4: + case EOpConstructUInt: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + case EOpConstructStruct: + return true; + default: + return false; + } } // @@ -731,33 +739,33 @@ setType(funcReturnType ? *funcReturnType : operand->getType()); // Unary operations result in temporary variables unless const. - if(type.getQualifier() != EvqConstExpr) + if(type.getQualifier() != EvqConstExpr) { - type.setQualifier(EvqTemporary); - } + type.setQualifier(EvqTemporary); + } - switch (op) { - case EOpLogicalNot: - if (operand->getBasicType() != EbtBool) - return false; - break; - case EOpBitwiseNot: - if (!IsInteger(operand->getBasicType())) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (operand->getBasicType() == EbtBool) - return false; - break; + switch (op) { + case EOpLogicalNot: + if (operand->getBasicType() != EbtBool) + return false; + break; + case EOpBitwiseNot: + if (!IsInteger(operand->getBasicType())) + return false; + break; + case EOpNegative: + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (operand->getBasicType() == EbtBool) + return false; + break; - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: case EOpAbs: case EOpSign: case EOpIsNan: @@ -772,14 +780,14 @@ case EOpUnpackSnorm2x16: case EOpUnpackUnorm2x16: case EOpUnpackHalf2x16: - return true; + return true; - default: - if (operand->getBasicType() != EbtFloat) - return false; - } + default: + if (operand->getBasicType() != EbtFloat) + return false; + } - return true; + return true; } // @@ -792,228 +800,228 @@ { ASSERT(left->isArray() == right->isArray()); - // GLSL ES 2.0 does not support implicit type casting. - // So the basic type should always match. + // GLSL ES 2.0 does not support implicit type casting. + // So the basic type should always match. // GLSL ES 3.0 supports integer shift operands of different signedness. if(op != EOpBitShiftLeft && op != EOpBitShiftRight && op != EOpBitShiftLeftAssign && op != EOpBitShiftRightAssign && left->getBasicType() != right->getBasicType()) - { - return false; - } + { + return false; + } - // - // Base assumption: just make the type the same as the left - // operand. Then only deviations from this need be coded. - // - setType(left->getType()); + // + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + // + setType(left->getType()); - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); + // The result gets promoted to the highest precision. + TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); + getTypePointer()->setPrecision(higherPrecision); - // Binary operations results in temporary variables unless both - // operands are const. - if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) { - getTypePointer()->setQualifier(EvqTemporary); - } + // Binary operations results in temporary variables unless both + // operands are const. + if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) { + getTypePointer()->setQualifier(EvqTemporary); + } - int primarySize = std::max(left->getNominalSize(), right->getNominalSize()); + int primarySize = std::max(left->getNominalSize(), right->getNominalSize()); - // - // All scalars. Code after this test assumes this case is removed! - // - if (primarySize == 1) { - switch (op) { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined)); - break; + // + // All scalars. Code after this test assumes this case is removed! + // + if (primarySize == 1) { + switch (op) { + // + // Promote to conditional + // + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + setType(TType(EbtBool, EbpUndefined)); + break; - // - // And and Or operate on conditionals - // - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - // Both operands must be of type bool. - if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) - return false; - setType(TType(EbtBool, EbpUndefined)); - break; + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalOr: + case EOpLogicalXor: + // Both operands must be of type bool. + if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) + return false; + setType(TType(EbtBool, EbpUndefined)); + break; - default: - break; - } - return true; - } + default: + break; + } + return true; + } - // If we reach here, at least one of the operands is vector or matrix. - // The other operand could be a scalar, vector, or matrix. - // Can these two operands be combined? - // - TBasicType basicType = left->getBasicType(); - switch (op) { - case EOpMul: - if (!left->isMatrix() && right->isMatrix()) { - if (left->isVector()) - { - op = EOpVectorTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, - static_cast<unsigned char>(right->getNominalSize()), 1)); - } - else { - op = EOpMatrixTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, - static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize()))); - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - op = EOpMatrixTimesVector; - setType(TType(basicType, higherPrecision, EvqTemporary, - static_cast<unsigned char>(left->getSecondarySize()), 1)); - } else { - op = EOpMatrixTimesScalar; - } - } else if (left->isMatrix() && right->isMatrix()) { - op = EOpMatrixTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, - static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize()))); - } else if (!left->isMatrix() && !right->isMatrix()) { - if (left->isVector() && right->isVector()) { - // leave as component product - } else if (left->isVector() || right->isVector()) { - op = EOpVectorTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, - static_cast<unsigned char>(primarySize), 1)); - } - } else { - infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); - return false; - } + // If we reach here, at least one of the operands is vector or matrix. + // The other operand could be a scalar, vector, or matrix. + // Can these two operands be combined? + // + TBasicType basicType = left->getBasicType(); + switch (op) { + case EOpMul: + if (!left->isMatrix() && right->isMatrix()) { + if (left->isVector()) + { + op = EOpVectorTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + static_cast<unsigned char>(right->getNominalSize()), 1)); + } + else { + op = EOpMatrixTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize()))); + } + } else if (left->isMatrix() && !right->isMatrix()) { + if (right->isVector()) { + op = EOpMatrixTimesVector; + setType(TType(basicType, higherPrecision, EvqTemporary, + static_cast<unsigned char>(left->getSecondarySize()), 1)); + } else { + op = EOpMatrixTimesScalar; + } + } else if (left->isMatrix() && right->isMatrix()) { + op = EOpMatrixTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize()))); + } else if (!left->isMatrix() && !right->isMatrix()) { + if (left->isVector() && right->isVector()) { + // leave as component product + } else if (left->isVector() || right->isVector()) { + op = EOpVectorTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + static_cast<unsigned char>(primarySize), 1)); + } + } else { + infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + return false; + } - if(!ValidateMultiplication(op, left->getType(), right->getType())) - { - return false; - } - break; - case EOpMulAssign: - if (!left->isMatrix() && right->isMatrix()) { - if (left->isVector()) - op = EOpVectorTimesMatrixAssign; - else { - return false; - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - return false; - } else { - op = EOpMatrixTimesScalarAssign; - } - } else if (left->isMatrix() && right->isMatrix()) { - op = EOpMatrixTimesMatrixAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, - static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize()))); - } else if (!left->isMatrix() && !right->isMatrix()) { - if (left->isVector() && right->isVector()) { - // leave as component product - } else if (left->isVector() || right->isVector()) { - if (! left->isVector()) - return false; - op = EOpVectorTimesScalarAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, - static_cast<unsigned char>(left->getNominalSize()), 1)); - } - } else { - infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); - return false; - } + if(!ValidateMultiplication(op, left->getType(), right->getType())) + { + return false; + } + break; + case EOpMulAssign: + if (!left->isMatrix() && right->isMatrix()) { + if (left->isVector()) + op = EOpVectorTimesMatrixAssign; + else { + return false; + } + } else if (left->isMatrix() && !right->isMatrix()) { + if (right->isVector()) { + return false; + } else { + op = EOpMatrixTimesScalarAssign; + } + } else if (left->isMatrix() && right->isMatrix()) { + op = EOpMatrixTimesMatrixAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize()))); + } else if (!left->isMatrix() && !right->isMatrix()) { + if (left->isVector() && right->isVector()) { + // leave as component product + } else if (left->isVector() || right->isVector()) { + if (! left->isVector()) + return false; + op = EOpVectorTimesScalarAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + static_cast<unsigned char>(left->getNominalSize()), 1)); + } + } else { + infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); + return false; + } - if(!ValidateMultiplication(op, left->getType(), right->getType())) - { - return false; - } - break; + if(!ValidateMultiplication(op, left->getType(), right->getType())) + { + return false; + } + break; - case EOpAssign: - case EOpInitialize: - // No more additional checks are needed. - if ((left->getNominalSize() != right->getNominalSize()) || - (left->getSecondarySize() != right->getSecondarySize())) - return false; - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpIMod: - case EOpBitShiftLeft: - case EOpBitShiftRight: - case EOpBitwiseAnd: - case EOpBitwiseXor: - case EOpBitwiseOr: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpIModAssign: - case EOpBitShiftLeftAssign: - case EOpBitShiftRightAssign: - case EOpBitwiseAndAssign: - case EOpBitwiseXorAssign: - case EOpBitwiseOrAssign: - if ((left->isMatrix() && right->isVector()) || - (left->isVector() && right->isMatrix())) - return false; + case EOpAssign: + case EOpInitialize: + // No more additional checks are needed. + if ((left->getNominalSize() != right->getNominalSize()) || + (left->getSecondarySize() != right->getSecondarySize())) + return false; + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpIMod: + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + if ((left->isMatrix() && right->isVector()) || + (left->isVector() && right->isMatrix())) + return false; - // Are the sizes compatible? - if(left->getNominalSize() != right->getNominalSize() || - left->getSecondarySize() != right->getSecondarySize()) - { - // If the nominal sizes of operands do not match: - // One of them must be a scalar. - if(!left->isScalar() && !right->isScalar()) - return false; + // Are the sizes compatible? + if(left->getNominalSize() != right->getNominalSize() || + left->getSecondarySize() != right->getSecondarySize()) + { + // If the nominal sizes of operands do not match: + // One of them must be a scalar. + if(!left->isScalar() && !right->isScalar()) + return false; - // In the case of compound assignment other than multiply-assign, - // the right side needs to be a scalar. Otherwise a vector/matrix - // would be assigned to a scalar. A scalar can't be shifted by a - // vector either. - if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight)) - return false; - } + // In the case of compound assignment other than multiply-assign, + // the right side needs to be a scalar. Otherwise a vector/matrix + // would be assigned to a scalar. A scalar can't be shifted by a + // vector either. + if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight)) + return false; + } - { - const int secondarySize = std::max( - left->getSecondarySize(), right->getSecondarySize()); - setType(TType(basicType, higherPrecision, EvqTemporary, - static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize))); - if(left->isArray()) - { - ASSERT(left->getArraySize() == right->getArraySize()); - type.setArraySize(left->getArraySize()); - } - } - break; + { + const int secondarySize = std::max( + left->getSecondarySize(), right->getSecondarySize()); + setType(TType(basicType, higherPrecision, EvqTemporary, + static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize))); + if(left->isArray()) + { + ASSERT(left->getArraySize() == right->getArraySize()); + type.setArraySize(left->getArraySize()); + } + } + break; - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if ((left->getNominalSize() != right->getNominalSize()) || - (left->getSecondarySize() != right->getSecondarySize())) - return false; - setType(TType(EbtBool, EbpUndefined)); - break; + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((left->getNominalSize() != right->getNominalSize()) || + (left->getSecondarySize() != right->getSecondarySize())) + return false; + setType(TType(EbtBool, EbpUndefined)); + break; case EOpOuterProduct: if(!left->isVector() || !right->isVector()) @@ -1039,54 +1047,54 @@ setType(right->getType()); break; - default: - return false; - } + default: + return false; + } - return true; + return true; } bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) { - const TFieldList& fields = leftNodeType.getStruct()->fields(); + const TFieldList& fields = leftNodeType.getStruct()->fields(); - size_t structSize = fields.size(); - int index = 0; + size_t structSize = fields.size(); + int index = 0; - for (size_t j = 0; j < structSize; j++) { - 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++; - } + for (size_t j = 0; j < structSize; j++) { + 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; + } + } + return true; } bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) { - if (leftNodeType.isArray()) { - TType typeWithoutArrayness = leftNodeType; - typeWithoutArrayness.clearArrayness(); + if (leftNodeType.isArray()) { + TType typeWithoutArrayness = leftNodeType; + typeWithoutArrayness.clearArrayness(); - int arraySize = leftNodeType.getArraySize(); + int arraySize = leftNodeType.getArraySize(); - for (int i = 0; i < arraySize; ++i) { - size_t offset = typeWithoutArrayness.getObjectSize() * i; - if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) - return false; - } - } else - return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + for (int i = 0; i < arraySize; ++i) { + size_t offset = typeWithoutArrayness.getObjectSize() * i; + if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) + return false; + } + } else + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); - return true; + return true; } float determinant2(float m00, float m01, float m10, float m11) @@ -1095,23 +1103,23 @@ } float determinant3(float m00, float m01, float m02, - float m10, float m11, float m12, - float m20, float m21, float m22) + float m10, float m11, float m12, + float m20, float m21, float m22) { return m00 * determinant2(m11, m12, m21, m22) - - m10 * determinant2(m01, m02, m21, m22) + - m20 * determinant2(m01, m02, m11, m12); + m10 * determinant2(m01, m02, m21, m22) + + m20 * determinant2(m01, m02, m11, m12); } float determinant4(float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23, - float m30, float m31, float m32, float m33) + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) { return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) - - m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) + - m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) - - m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23); + m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) + + m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) - + m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23); } float ComputeDeterminant(int size, ConstantUnion* unionArray) @@ -1120,36 +1128,36 @@ { case 2: return determinant2(unionArray[0].getFConst(), - unionArray[1].getFConst(), - unionArray[2].getFConst(), - unionArray[3].getFConst()); + unionArray[1].getFConst(), + unionArray[2].getFConst(), + unionArray[3].getFConst()); case 3: return determinant3(unionArray[0].getFConst(), - unionArray[1].getFConst(), - unionArray[2].getFConst(), - unionArray[3].getFConst(), - unionArray[4].getFConst(), - unionArray[5].getFConst(), - unionArray[6].getFConst(), - unionArray[7].getFConst(), - unionArray[8].getFConst()); + unionArray[1].getFConst(), + unionArray[2].getFConst(), + unionArray[3].getFConst(), + unionArray[4].getFConst(), + unionArray[5].getFConst(), + unionArray[6].getFConst(), + unionArray[7].getFConst(), + unionArray[8].getFConst()); case 4: return determinant4(unionArray[0].getFConst(), - unionArray[1].getFConst(), - unionArray[2].getFConst(), - unionArray[3].getFConst(), - unionArray[4].getFConst(), - unionArray[5].getFConst(), - unionArray[6].getFConst(), - unionArray[7].getFConst(), - unionArray[8].getFConst(), - unionArray[9].getFConst(), - unionArray[10].getFConst(), - unionArray[11].getFConst(), - unionArray[12].getFConst(), - unionArray[13].getFConst(), - unionArray[14].getFConst(), - unionArray[15].getFConst()); + unionArray[1].getFConst(), + unionArray[2].getFConst(), + unionArray[3].getFConst(), + unionArray[4].getFConst(), + unionArray[5].getFConst(), + unionArray[6].getFConst(), + unionArray[7].getFConst(), + unionArray[8].getFConst(), + unionArray[9].getFConst(), + unionArray[10].getFConst(), + unionArray[11].getFConst(), + unionArray[12].getFConst(), + unionArray[13].getFConst(), + unionArray[14].getFConst(), + unionArray[15].getFConst()); default: UNREACHABLE(size); return 0.0f; @@ -1253,88 +1261,88 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink) { - ConstantUnion *unionArray = getUnionArrayPointer(); - size_t objectSize = getType().getObjectSize(); + ConstantUnion *unionArray = getUnionArrayPointer(); + size_t objectSize = getType().getObjectSize(); - if (constantNode) { // binary operations - TIntermConstantUnion *node = constantNode->getAsConstantUnion(); - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - TType returnType = getType(); + if (constantNode) { // binary operations + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + TType returnType = getType(); - // 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 (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 (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) - unionArray[i] = *getUnionArrayPointer(); - returnType = node->getType(); - objectSize = constantNode->getType().getObjectSize(); - } + // 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 (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 (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) + unionArray[i] = *getUnionArrayPointer(); + returnType = node->getType(); + objectSize = constantNode->getType().getObjectSize(); + } - ConstantUnion* tempConstArray = 0; - TIntermConstantUnion *tempNode; + ConstantUnion* tempConstArray = 0; + TIntermConstantUnion *tempNode; - switch(op) { - case EOpAdd: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - 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 (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] - rightUnionArray[i]; - } - break; + switch(op) { + case EOpAdd: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + 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 (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; + } + break; - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - 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()); - return 0; - } - {// support MSVC++6.0 - int leftNumCols = getNominalSize(); - int leftNumRows = getSecondarySize(); - int rightNumCols = node->getNominalSize(); - int rightNumRows = node->getSecondarySize(); - if(leftNumCols != rightNumRows) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine()); - return 0; - } - int tempNumCols = rightNumCols; - int tempNumRows = leftNumRows; - int tempNumAdds = leftNumCols; - tempConstArray = new ConstantUnion[tempNumCols*tempNumRows]; - for (int row = 0; row < tempNumRows; row++) { - for (int column = 0; column < tempNumCols; column++) { - tempConstArray[tempNumRows * column + row].setFConst(0.0f); - for (int i = 0; i < tempNumAdds; i++) { - tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst())); - } - } - } - // update return type for matrix product - returnType.setNominalSize(static_cast<unsigned char>(tempNumCols)); - returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows)); - } - break; + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + 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()); + return 0; + } + {// support MSVC++6.0 + int leftNumCols = getNominalSize(); + int leftNumRows = getSecondarySize(); + int rightNumCols = node->getNominalSize(); + int rightNumRows = node->getSecondarySize(); + if(leftNumCols != rightNumRows) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine()); + return 0; + } + int tempNumCols = rightNumCols; + int tempNumRows = leftNumRows; + int tempNumAdds = leftNumCols; + tempConstArray = new ConstantUnion[tempNumCols*tempNumRows]; + for (int row = 0; row < tempNumRows; row++) { + for (int column = 0; column < tempNumCols; column++) { + tempConstArray[tempNumRows * column + row].setFConst(0.0f); + for (int i = 0; i < tempNumAdds; i++) { + tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst())); + } + } + } + // update return type for matrix product + returnType.setNominalSize(static_cast<unsigned char>(tempNumCols)); + returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows)); + } + break; case EOpOuterProduct: { @@ -1395,267 +1403,267 @@ } break; - case EOpDiv: - case EOpIMod: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - 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()); - tempConstArray[i].setFConst(FLT_MAX); - } else { - ASSERT(op == EOpDiv); - tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); - } - break; - - case EbtInt: - if (rightUnionArray[i] == 0) { - infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); - tempConstArray[i].setIConst(INT_MAX); - } else { - if(op == EOpDiv) { - tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); - } else { - ASSERT(op == EOpIMod); - tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst()); - } - } - break; - case EbtUInt: - if (rightUnionArray[i] == 0) { - infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); - tempConstArray[i].setUConst(UINT_MAX); - } else { - if(op == EOpDiv) { - tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst()); - } else { - ASSERT(op == EOpIMod); - tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst()); - } - } - break; - default: - infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine()); - return 0; - } - } - } - break; - - case EOpMatrixTimesVector: - if (node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine()); - return 0; - } - tempConstArray = new ConstantUnion[getNominalSize()]; - - {// support MSVC++6.0 - for (int size = getNominalSize(), i = 0; i < size; i++) { - tempConstArray[i].setFConst(0.0f); - for (int j = 0; j < size; j++) { - tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst())); - } - } - } - - tempNode = new TIntermConstantUnion(tempConstArray, node->getType()); - tempNode->setLine(getLine()); - - return tempNode; - - case EOpVectorTimesMatrix: - if (getType().getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine()); - return 0; - } - - tempConstArray = new ConstantUnion[getNominalSize()]; - {// support MSVC++6.0 - for (int size = getNominalSize(), i = 0; i < size; i++) { - tempConstArray[i].setFConst(0.0f); - for (int j = 0; j < size; j++) { - tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst())); - } - } - } - break; - - case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] && rightUnionArray[i]; - } - break; - - case EOpLogicalOr: // this code is written for possible future use, will not get executed currently - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] || rightUnionArray[i]; - } - break; - - case EOpLogicalXor: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - 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"); - } - } - break; - - case EOpBitwiseAnd: - tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] & rightUnionArray[i]; - break; - case EOpBitwiseXor: - tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] ^ rightUnionArray[i]; - break; - case EOpBitwiseOr: - tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] | rightUnionArray[i]; - break; - case EOpBitShiftLeft: - tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] << rightUnionArray[i]; - break; - case EOpBitShiftRight: - tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] >> rightUnionArray[i]; - break; - - case EOpLessThan: - tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) - tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]); - returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize); - break; - case EOpGreaterThan: + case EOpDiv: + case EOpIMod: tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) + {// support MSVC++6.0 + 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()); + tempConstArray[i].setFConst(FLT_MAX); + } else { + ASSERT(op == EOpDiv); + tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); + } + break; + + case EbtInt: + if (rightUnionArray[i] == 0) { + infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + tempConstArray[i].setIConst(INT_MAX); + } else { + if(op == EOpDiv) { + tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); + } else { + ASSERT(op == EOpIMod); + tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst()); + } + } + break; + case EbtUInt: + if (rightUnionArray[i] == 0) { + infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); + tempConstArray[i].setUConst(UINT_MAX); + } else { + if(op == EOpDiv) { + tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst()); + } else { + ASSERT(op == EOpIMod); + tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst()); + } + } + break; + default: + infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine()); + return 0; + } + } + } + break; + + case EOpMatrixTimesVector: + if (node->getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine()); + return 0; + } + tempConstArray = new ConstantUnion[getNominalSize()]; + + {// support MSVC++6.0 + for (int size = getNominalSize(), i = 0; i < size; i++) { + tempConstArray[i].setFConst(0.0f); + for (int j = 0; j < size; j++) { + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst())); + } + } + } + + tempNode = new TIntermConstantUnion(tempConstArray, node->getType()); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpVectorTimesMatrix: + if (getType().getBasicType() != EbtFloat) { + infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine()); + return 0; + } + + tempConstArray = new ConstantUnion[getNominalSize()]; + {// support MSVC++6.0 + for (int size = getNominalSize(), i = 0; i < size; i++) { + tempConstArray[i].setFConst(0.0f); + for (int j = 0; j < size; j++) { + tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst())); + } + } + } + break; + + case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + } + break; + + case EOpLogicalOr: // this code is written for possible future use, will not get executed currently + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + } + break; + + case EOpLogicalXor: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + 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"); + } + } + break; + + case EOpBitwiseAnd: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] & rightUnionArray[i]; + break; + case EOpBitwiseXor: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] ^ rightUnionArray[i]; + break; + case EOpBitwiseOr: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] | rightUnionArray[i]; + break; + case EOpBitShiftLeft: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] << rightUnionArray[i]; + break; + case EOpBitShiftRight: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] >> rightUnionArray[i]; + break; + + case EOpLessThan: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) + tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]); + returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize); + break; + case EOpGreaterThan: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) tempConstArray[i].setBConst(unionArray[i] > rightUnionArray[i]); - returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize); - break; - case EOpLessThanEqual: - tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) + returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize); + break; + case EOpLessThanEqual: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) tempConstArray[i].setBConst(unionArray[i] <= rightUnionArray[i]); - returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize); - break; - case EOpGreaterThanEqual: - tempConstArray = new ConstantUnion[objectSize]; - for(size_t i = 0; i < objectSize; i++) + returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize); + break; + case EOpGreaterThanEqual: + tempConstArray = new ConstantUnion[objectSize]; + for(size_t i = 0; i < objectSize; i++) tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]); - returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize); - break; - case EOpEqual: + returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize); + break; + case EOpEqual: tempConstArray = new ConstantUnion[1]; if(getType().getBasicType() == EbtStruct) { tempConstArray->setBConst(CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)); - } else { + } else { bool boolNodeFlag = true; - for (size_t i = 0; i < objectSize; i++) { - if (unionArray[i] != rightUnionArray[i]) { - boolNodeFlag = false; - break; // break out of for loop - } - } + for (size_t i = 0; i < objectSize; i++) { + if (unionArray[i] != rightUnionArray[i]) { + boolNodeFlag = false; + break; // break out of for loop + } + } tempConstArray->setBConst(boolNodeFlag); - } + } - tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr)); - tempNode->setLine(getLine()); + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr)); + tempNode->setLine(getLine()); - return tempNode; + return tempNode; - case EOpNotEqual: + case EOpNotEqual: tempConstArray = new ConstantUnion[1]; if(getType().getBasicType() == EbtStruct) { tempConstArray->setBConst(!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)); - } else { + } else { bool boolNodeFlag = false; - for (size_t i = 0; i < objectSize; i++) { - if (unionArray[i] != rightUnionArray[i]) { - boolNodeFlag = true; - break; // break out of for loop - } - } + for (size_t i = 0; i < objectSize; i++) { + if (unionArray[i] != rightUnionArray[i]) { + boolNodeFlag = true; + break; // break out of for loop + } + } tempConstArray->setBConst(boolNodeFlag); - } + } - tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr)); - tempNode->setLine(getLine()); + tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr)); + tempNode->setLine(getLine()); - return tempNode; + return tempNode; case EOpMax: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i]; - } - break; - case EOpMin: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i]; - } - break; - default: - return 0; - } - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i]; + } + break; + case EOpMin: + tempConstArray = new ConstantUnion[objectSize]; + {// support MSVC++6.0 + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i]; + } + break; + default: + return 0; + } + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); - return tempNode; - } else { - // - // Do unary operations - // - TIntermConstantUnion *newNode = 0; - ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - 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()); - return 0; - } - break; - case EOpLogicalNot: // this code is written for possible future use, will not get executed currently - switch (getType().getBasicType()) { - case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; - default: - infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); - return 0; - } - break; - case EOpBitwiseNot: - switch(getType().getBasicType()) { - case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break; - case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break; - default: - infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); - return 0; - } - break; + return tempNode; + } else { + // + // Do unary operations + // + TIntermConstantUnion *newNode = 0; + ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; + 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()); + return 0; + } + break; + case EOpLogicalNot: // this code is written for possible future use, will not get executed currently + switch (getType().getBasicType()) { + case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; + default: + infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + return 0; + } + break; + case EOpBitwiseNot: + switch(getType().getBasicType()) { + case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break; + case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break; + default: + infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine()); + return 0; + } + break; case EOpRadians: switch(getType().getBasicType()) { case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 1.74532925e-2f); break; @@ -1817,108 +1825,108 @@ } break; default: - return 0; - } - } - newNode = new TIntermConstantUnion(tempConstArray, getType()); - newNode->setLine(getLine()); - return newNode; - } + return 0; + } + } + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; + } } TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) { - size_t size = node->getType().getObjectSize(); + size_t size = node->getType().getObjectSize(); - ConstantUnion *leftUnionArray = new ConstantUnion[size]; + ConstantUnion *leftUnionArray = new ConstantUnion[size]; - for(size_t i = 0; i < size; i++) { - switch (promoteTo) { - case EbtFloat: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i))); - break; - case EbtUInt: - leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i))); - break; - case EbtBool: - leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); - return 0; - } - break; - case EbtInt: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i))); - break; - case EbtUInt: - leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i))); - break; - case EbtBool: - leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); - return 0; - } - break; - case EbtUInt: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i))); - break; - case EbtUInt: - leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i))); - break; - case EbtBool: - leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); - return 0; - } - break; - case EbtBool: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setBConst(node->getIConst(i) != 0); - break; - case EbtUInt: - leftUnionArray[i].setBConst(node->getUConst(i) != 0); - break; - case EbtBool: - leftUnionArray[i].setBConst(node->getBConst(i)); - break; - case EbtFloat: - leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); - break; - default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); - return 0; - } + for(size_t i = 0; i < size; i++) { + switch (promoteTo) { + case EbtFloat: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i))); + break; + case EbtUInt: + leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i))); + break; + case EbtBool: + leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i))); + break; + case EbtFloat: + leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i))); + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } + break; + case EbtInt: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i))); + break; + case EbtUInt: + leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i))); + break; + case EbtBool: + leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i))); + break; + case EbtFloat: + leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i))); + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } + break; + case EbtUInt: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i))); + break; + case EbtUInt: + leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i))); + break; + case EbtBool: + leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i))); + break; + case EbtFloat: + leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i))); + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } + break; + case EbtBool: + switch (node->getType().getBasicType()) { + case EbtInt: + leftUnionArray[i].setBConst(node->getIConst(i) != 0); + break; + case EbtUInt: + leftUnionArray[i].setBConst(node->getUConst(i) != 0); + break; + case EbtBool: + leftUnionArray[i].setBConst(node->getBConst(i)); + break; + case EbtFloat: + leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); + break; + default: + infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + return 0; + } - break; - default: - infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine()); - return 0; - } + break; + default: + infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine()); + return 0; + } - } + } - const TType& t = node->getType(); + const TType& t = node->getType(); return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine()); }
diff --git a/src/OpenGL/compiler/MMap.h b/src/OpenGL/compiler/MMap.h index a308671..925cf6e 100644 --- a/src/OpenGL/compiler/MMap.h +++ b/src/OpenGL/compiler/MMap.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _MMAP_INCLUDED_ #define _MMAP_INCLUDED_ @@ -13,44 +21,44 @@ class TMMap { public: - TMMap(const char* fileName) : - fSize(-1), // -1 is the error value returned by GetFileSize() - fp(NULL), - fBuff(0) // 0 is the error value returned by MapViewOfFile() - { - if ((fp = fopen(fileName, "r")) == NULL) - return; - char c = getc(fp); - fSize = 0; - while (c != EOF) { - fSize++; - c = getc(fp); - } - if (c == EOF) - fSize++; - rewind(fp); - fBuff = (char*)malloc(sizeof(char) * fSize); - int count = 0; - c = getc(fp); - while (c != EOF) { - fBuff[count++] = c; - c = getc(fp); - } - fBuff[count++] = c; - } + TMMap(const char* fileName) : + fSize(-1), // -1 is the error value returned by GetFileSize() + fp(nullptr), + fBuff(0) // 0 is the error value returned by MapViewOfFile() + { + if ((fp = fopen(fileName, "r")) == NULL) + return; + char c = getc(fp); + fSize = 0; + while (c != EOF) { + fSize++; + c = getc(fp); + } + if (c == EOF) + fSize++; + rewind(fp); + fBuff = (char*)malloc(sizeof(char) * fSize); + int count = 0; + c = getc(fp); + while (c != EOF) { + fBuff[count++] = c; + c = getc(fp); + } + fBuff[count++] = c; + } - char* getData() { return fBuff; } - int getSize() { return fSize; } + char* getData() { return fBuff; } + int getSize() { return fSize; } - ~TMMap() { - if (fp != NULL) - fclose(fp); - } - + ~TMMap() { + if (fp != NULL) + fclose(fp); + } + private: - int fSize; // size of file to map in - FILE *fp; - char* fBuff; // the actual data; + int fSize; // size of file to map in + FILE *fp; + char* fBuff; // the actual data; }; #endif // _MMAP_INCLUDED_
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp index 91f6418..59949f1 100644 --- a/src/OpenGL/compiler/OutputASM.cpp +++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -1,3581 +1,3584 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -#include "OutputASM.h" -#include "Common/Math.hpp" - -#include "common/debug.h" -#include "InfoSink.h" - -#include "libGLESv2/Shader.h" - -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <GLES3/gl3.h> - -namespace glsl -{ - // Integer to TString conversion - TString str(int i) - { - char buffer[20]; - sprintf(buffer, "%d", i); - return buffer; - } - - class Temporary : public TIntermSymbol - { - public: - Temporary(OutputASM *assembler) : TIntermSymbol(TSymbolTableLevel::nextUniqueId(), "tmp", TType(EbtFloat, EbpHigh, EvqTemporary, 4, 1, false)), assembler(assembler) - { - } - - ~Temporary() - { - assembler->freeTemporary(this); - } - - private: - OutputASM *const assembler; - }; - - class Constant : public TIntermConstantUnion - { - public: - Constant(float x, float y, float z, float w) : TIntermConstantUnion(constants, TType(EbtFloat, EbpHigh, EvqConstExpr, 4, 1, false)) - { - constants[0].setFConst(x); - constants[1].setFConst(y); - constants[2].setFConst(z); - constants[3].setFConst(w); - } - - Constant(bool b) : TIntermConstantUnion(constants, TType(EbtBool, EbpHigh, EvqConstExpr, 1, 1, false)) - { - constants[0].setBConst(b); - } - - Constant(int i) : TIntermConstantUnion(constants, TType(EbtInt, EbpHigh, EvqConstExpr, 1, 1, false)) - { - constants[0].setIConst(i); - } - - ~Constant() - { - } - - private: - ConstantUnion constants[4]; - }; - - Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, int arraySize, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo) : - type(type), precision(precision), name(name), arraySize(arraySize), registerIndex(registerIndex), blockId(blockId), blockInfo(blockMemberInfo) - { - } - - UniformBlock::UniformBlock(const std::string& name, unsigned int dataSize, unsigned int arraySize, - TLayoutBlockStorage layout, bool isRowMajorLayout, int registerIndex, int blockId) : - name(name), dataSize(dataSize), arraySize(arraySize), layout(layout), - isRowMajorLayout(isRowMajorLayout), registerIndex(registerIndex), blockId(blockId) - { - } - - BlockLayoutEncoder::BlockLayoutEncoder(bool rowMajor) - : mCurrentOffset(0), isRowMajor(rowMajor) - { - } - - BlockMemberInfo BlockLayoutEncoder::encodeType(const TType &type) - { - int arrayStride; - int matrixStride; - - getBlockLayoutInfo(type, type.getArraySize(), isRowMajor, &arrayStride, &matrixStride); - - const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent), - static_cast<int>(arrayStride * BytesPerComponent), - static_cast<int>(matrixStride * BytesPerComponent), - (matrixStride > 0) && isRowMajor); - - advanceOffset(type, type.getArraySize(), isRowMajor, arrayStride, matrixStride); - - return memberInfo; - } - - // static - size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info) - { - return (info.offset / BytesPerComponent) / ComponentsPerRegister; - } - - // static - size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info) - { - return (info.offset / BytesPerComponent) % ComponentsPerRegister; - } - - void BlockLayoutEncoder::nextRegister() - { - mCurrentOffset = sw::align(mCurrentOffset, ComponentsPerRegister); - } - - Std140BlockEncoder::Std140BlockEncoder(bool rowMajor) : BlockLayoutEncoder(rowMajor) - { - } - - void Std140BlockEncoder::enterAggregateType() - { - nextRegister(); - } - - void Std140BlockEncoder::exitAggregateType() - { - nextRegister(); - } - - void Std140BlockEncoder::getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) - { - size_t baseAlignment = 0; - int matrixStride = 0; - int arrayStride = 0; - - if(type.isMatrix()) - { - baseAlignment = ComponentsPerRegister; - matrixStride = ComponentsPerRegister; - - if(arraySize > 0) - { - const int numRegisters = isRowMajorMatrix ? type.getSecondarySize() : type.getNominalSize(); - arrayStride = ComponentsPerRegister * numRegisters; - } - } - else if(arraySize > 0) - { - baseAlignment = ComponentsPerRegister; - arrayStride = ComponentsPerRegister; - } - else - { - const size_t numComponents = type.getElementSize(); - baseAlignment = (numComponents == 3 ? 4u : numComponents); - } - - mCurrentOffset = sw::align(mCurrentOffset, baseAlignment); - - *matrixStrideOut = matrixStride; - *arrayStrideOut = arrayStride; - } - - void Std140BlockEncoder::advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) - { - if(arraySize > 0) - { - mCurrentOffset += arrayStride * arraySize; - } - else if(type.isMatrix()) - { - ASSERT(matrixStride == ComponentsPerRegister); - const int numRegisters = isRowMajorMatrix ? type.getSecondarySize() : type.getNominalSize(); - mCurrentOffset += ComponentsPerRegister * numRegisters; - } - else - { - mCurrentOffset += type.getElementSize(); - } - } - - Attribute::Attribute() - { - type = GL_NONE; - arraySize = 0; - registerIndex = 0; - } - - Attribute::Attribute(GLenum type, const std::string &name, int arraySize, int location, int registerIndex) - { - this->type = type; - this->name = name; - this->arraySize = arraySize; - this->location = location; - this->registerIndex = registerIndex; - } - - sw::PixelShader *Shader::getPixelShader() const - { - return 0; - } - - sw::VertexShader *Shader::getVertexShader() const - { - return 0; - } - - OutputASM::TextureFunction::TextureFunction(const TString& nodeName) : method(IMPLICIT), proj(false), offset(false) - { - TString name = TFunction::unmangleName(nodeName); - - if(name == "texture2D" || name == "textureCube" || name == "texture" || name == "texture3D") - { - method = IMPLICIT; - } - else if(name == "texture2DProj" || name == "textureProj") - { - method = IMPLICIT; - proj = true; - } - else if(name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod") - { - method = LOD; - } - else if(name == "texture2DProjLod" || name == "textureProjLod") - { - method = LOD; - proj = true; - } - else if(name == "textureSize") - { - method = SIZE; - } - else if(name == "textureOffset") - { - method = IMPLICIT; - offset = true; - } - else if(name == "textureProjOffset") - { - method = IMPLICIT; - offset = true; - proj = true; - } - else if(name == "textureLodOffset") - { - method = LOD; - offset = true; - } - else if(name == "textureProjLodOffset") - { - method = LOD; - proj = true; - offset = true; - } - else if(name == "texelFetch") - { - method = FETCH; - } - else if(name == "texelFetchOffset") - { - method = FETCH; - offset = true; - } - else if(name == "textureGrad") - { - method = GRAD; - } - else if(name == "textureGradOffset") - { - method = GRAD; - offset = true; - } - else if(name == "textureProjGrad") - { - method = GRAD; - proj = true; - } - else if(name == "textureProjGradOffset") - { - method = GRAD; - proj = true; - offset = true; - } - else UNREACHABLE(0); - } - - OutputASM::OutputASM(TParseContext &context, Shader *shaderObject) : TIntermTraverser(true, true, true), shaderObject(shaderObject), mContext(context) - { - shader = 0; - pixelShader = 0; - vertexShader = 0; - - if(shaderObject) - { - shader = shaderObject->getShader(); - pixelShader = shaderObject->getPixelShader(); - vertexShader = shaderObject->getVertexShader(); - } - - functionArray.push_back(Function(0, "main(", 0, 0)); - currentFunction = 0; - outputQualifier = EvqOutput; // Set outputQualifier to any value other than EvqFragColor or EvqFragData - } - - OutputASM::~OutputASM() - { - } - - void OutputASM::output() - { - if(shader) - { - emitShader(GLOBAL); - - if(functionArray.size() > 1) // Only call main() when there are other functions - { - Instruction *callMain = emit(sw::Shader::OPCODE_CALL); - callMain->dst.type = sw::Shader::PARAMETER_LABEL; - callMain->dst.index = 0; // main() - - emit(sw::Shader::OPCODE_RET); - } - - emitShader(FUNCTION); - } - } - - void OutputASM::emitShader(Scope scope) - { - emitScope = scope; - currentScope = GLOBAL; - mContext.getTreeRoot()->traverse(this); - } - - void OutputASM::freeTemporary(Temporary *temporary) - { - free(temporaries, temporary); - } - - sw::Shader::Opcode OutputASM::getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const - { - TBasicType baseType = in->getType().getBasicType(); - - switch(op) - { - case sw::Shader::OPCODE_NEG: - switch(baseType) - { - case EbtInt: - case EbtUInt: - return sw::Shader::OPCODE_INEG; - case EbtFloat: - default: - return op; - } - case sw::Shader::OPCODE_ABS: - switch(baseType) - { - case EbtInt: - return sw::Shader::OPCODE_IABS; - case EbtFloat: - default: - return op; - } - case sw::Shader::OPCODE_SGN: - switch(baseType) - { - case EbtInt: - return sw::Shader::OPCODE_ISGN; - case EbtFloat: - default: - return op; - } - case sw::Shader::OPCODE_ADD: - switch(baseType) - { - case EbtInt: - case EbtUInt: - return sw::Shader::OPCODE_IADD; - case EbtFloat: - default: - return op; - } - case sw::Shader::OPCODE_SUB: - switch(baseType) - { - case EbtInt: - case EbtUInt: - return sw::Shader::OPCODE_ISUB; - case EbtFloat: - default: - return op; - } - case sw::Shader::OPCODE_MUL: - switch(baseType) - { - case EbtInt: - case EbtUInt: - return sw::Shader::OPCODE_IMUL; - case EbtFloat: - default: - return op; - } - case sw::Shader::OPCODE_DIV: - switch(baseType) - { - case EbtInt: - return sw::Shader::OPCODE_IDIV; - case EbtUInt: - return sw::Shader::OPCODE_UDIV; - case EbtFloat: - default: - return op; - } - case sw::Shader::OPCODE_IMOD: - return baseType == EbtUInt ? sw::Shader::OPCODE_UMOD : op; - case sw::Shader::OPCODE_ISHR: - return baseType == EbtUInt ? sw::Shader::OPCODE_USHR : op; - case sw::Shader::OPCODE_MIN: - switch(baseType) - { - case EbtInt: - return sw::Shader::OPCODE_IMIN; - case EbtUInt: - return sw::Shader::OPCODE_UMIN; - case EbtFloat: - default: - return op; - } - case sw::Shader::OPCODE_MAX: - switch(baseType) - { - case EbtInt: - return sw::Shader::OPCODE_IMAX; - case EbtUInt: - return sw::Shader::OPCODE_UMAX; - case EbtFloat: - default: - return op; - } - default: - return op; - } - } - - void OutputASM::visitSymbol(TIntermSymbol *symbol) - { - // Vertex varyings don't have to be actively used to successfully link - // against pixel shaders that use them. So make sure they're declared. - if(symbol->getQualifier() == EvqVaryingOut || symbol->getQualifier() == EvqInvariantVaryingOut || symbol->getQualifier() == EvqVertexOut) - { - if(symbol->getBasicType() != EbtInvariant) // Typeless declarations are not new varyings - { - declareVarying(symbol, -1); - } - } - - TInterfaceBlock* block = symbol->getType().getInterfaceBlock(); - // OpenGL ES 3.0.4 spec, section 2.12.6 Uniform Variables: - // "All members of a named uniform block declared with a shared or std140 layout qualifier - // are considered active, even if they are not referenced in any shader in the program. - // The uniform block itself is also considered active, even if no member of the block is referenced." - if(block && ((block->blockStorage() == EbsShared) || (block->blockStorage() == EbsStd140))) - { - uniformRegister(symbol); - } - } - - bool OutputASM::visitBinary(Visit visit, TIntermBinary *node) - { - if(currentScope != emitScope) - { - return false; - } - - TIntermTyped *result = node; - TIntermTyped *left = node->getLeft(); - TIntermTyped *right = node->getRight(); - const TType &leftType = left->getType(); - const TType &rightType = right->getType(); - const TType &resultType = node->getType(); - - if(isSamplerRegister(result)) - { - return false; // Don't traverse, the register index is determined statically - } - - switch(node->getOp()) - { - case EOpAssign: - if(visit == PostVisit) - { - assignLvalue(left, right); - copy(result, right); - } - break; - case EOpInitialize: - if(visit == PostVisit) - { - copy(left, right); - } - break; - case EOpMatrixTimesScalarAssign: - if(visit == PostVisit) - { - for(int i = 0; i < leftType.getNominalSize(); i++) - { - emit(sw::Shader::OPCODE_MUL, result, i, left, i, right); - } - - assignLvalue(left, result); - } - break; - case EOpVectorTimesMatrixAssign: - if(visit == PostVisit) - { - int size = leftType.getNominalSize(); - - for(int i = 0; i < size; i++) - { - Instruction *dot = emit(sw::Shader::OPCODE_DP(size), result, 0, left, 0, right, i); - dot->dst.mask = 1 << i; - } - - assignLvalue(left, result); - } - break; - case EOpMatrixTimesMatrixAssign: - if(visit == PostVisit) - { - int dim = leftType.getNominalSize(); - - for(int i = 0; i < dim; i++) - { - Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, i, left, 0, right, i); - mul->src[1].swizzle = 0x00; - - for(int j = 1; j < dim; j++) - { - Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, i, left, j, right, i, result, i); - mad->src[1].swizzle = j * 0x55; - } - } - - assignLvalue(left, result); - } - break; - case EOpIndexDirect: - if(visit == PostVisit) - { - int index = right->getAsConstantUnion()->getIConst(0); - - if(result->isMatrix() || result->isStruct() || result->isInterfaceBlock()) - { - ASSERT(left->isArray()); - copy(result, left, index * left->elementRegisterCount()); - } - else if(result->isRegister()) - { - int srcIndex = 0; - if(left->isRegister()) - { - srcIndex = 0; - } - else if(left->isArray()) - { - srcIndex = index * left->elementRegisterCount(); - } - else if(left->isMatrix()) - { - ASSERT(index < left->getNominalSize()); // FIXME: Report semantic error - srcIndex = index; - } - else UNREACHABLE(0); - - Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, 0, left, srcIndex); - - if(left->isRegister()) - { - mov->src[0].swizzle = index; - } - } - else UNREACHABLE(0); - } - break; - case EOpIndexIndirect: - if(visit == PostVisit) - { - if(left->isArray() || left->isMatrix()) - { - for(int index = 0; index < result->totalRegisterCount(); index++) - { - Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, index, left, index); - mov->dst.mask = writeMask(result, index); - - if(left->totalRegisterCount() > 1) - { - sw::Shader::SourceParameter relativeRegister; - argument(relativeRegister, right); - - mov->src[0].rel.type = relativeRegister.type; - mov->src[0].rel.index = relativeRegister.index; - mov->src[0].rel.scale = result->totalRegisterCount(); - mov->src[0].rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform); - } - } - } - else if(left->isRegister()) - { - emit(sw::Shader::OPCODE_EXTRACT, result, left, right); - } - else UNREACHABLE(0); - } - break; - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - if(visit == PostVisit) - { - ASSERT(leftType.isStruct() || (leftType.isInterfaceBlock())); - - const TFieldList& fields = (node->getOp() == EOpIndexDirectStruct) ? - leftType.getStruct()->fields() : - leftType.getInterfaceBlock()->fields(); - int index = right->getAsConstantUnion()->getIConst(0); - int fieldOffset = 0; - - for(int i = 0; i < index; i++) - { - fieldOffset += fields[i]->type()->totalRegisterCount(); - } - - copy(result, left, fieldOffset); - } - break; - case EOpVectorSwizzle: - if(visit == PostVisit) - { - int swizzle = 0; - TIntermAggregate *components = right->getAsAggregate(); - - if(components) - { - TIntermSequence &sequence = components->getSequence(); - int component = 0; - - for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) - { - TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); - - if(element) - { - int i = element->getUnionArrayPointer()[0].getIConst(); - swizzle |= i << (component * 2); - component++; - } - else UNREACHABLE(0); - } - } - else UNREACHABLE(0); - - Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, left); - mov->src[0].swizzle = swizzle; - } - break; - case EOpAddAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_ADD, result), result, left, left, right); break; - case EOpAdd: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_ADD, result), result, left, right); break; - case EOpSubAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_SUB, result), result, left, left, right); break; - case EOpSub: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_SUB, result), result, left, right); break; - case EOpMulAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_MUL, result), result, left, left, right); break; - case EOpMul: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_MUL, result), result, left, right); break; - case EOpDivAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_DIV, result), result, left, left, right); break; - case EOpDiv: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_DIV, result), result, left, right); break; - case EOpIModAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_IMOD, result), result, left, left, right); break; - case EOpIMod: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_IMOD, result), result, left, right); break; - case EOpBitShiftLeftAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_SHL, result, left, left, right); break; - case EOpBitShiftLeft: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_SHL, result, left, right); break; - case EOpBitShiftRightAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_ISHR, result), result, left, left, right); break; - case EOpBitShiftRight: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_ISHR, result), result, left, right); break; - case EOpBitwiseAndAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_AND, result, left, left, right); break; - case EOpBitwiseAnd: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_AND, result, left, right); break; - case EOpBitwiseXorAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_XOR, result, left, left, right); break; - case EOpBitwiseXor: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_XOR, result, left, right); break; - case EOpBitwiseOrAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_OR, result, left, left, right); break; - case EOpBitwiseOr: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_OR, result, left, right); break; - case EOpEqual: - if(visit == PostVisit) - { - emitBinary(sw::Shader::OPCODE_EQ, result, left, right); - - for(int index = 1; index < left->totalRegisterCount(); index++) - { - Temporary equal(this); - emit(sw::Shader::OPCODE_EQ, &equal, 0, left, index, right, index); - emit(sw::Shader::OPCODE_AND, result, result, &equal); - } - } - break; - case EOpNotEqual: - if(visit == PostVisit) - { - emitBinary(sw::Shader::OPCODE_NE, result, left, right); - - for(int index = 1; index < left->totalRegisterCount(); index++) - { - Temporary notEqual(this); - emit(sw::Shader::OPCODE_NE, ¬Equal, 0, left, index, right, index); - emit(sw::Shader::OPCODE_OR, result, result, ¬Equal); - } - } - break; - case EOpLessThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LT, result, left, right); break; - case EOpGreaterThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GT, result, left, right); break; - case EOpLessThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LE, result, left, right); break; - case EOpGreaterThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GE, result, left, right); break; - case EOpVectorTimesScalarAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_MUL, left), result, left, left, right); break; - case EOpVectorTimesScalar: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MUL, left), result, left, right); break; - case EOpMatrixTimesScalar: - if(visit == PostVisit) - { - if(left->isMatrix()) - { - for(int i = 0; i < leftType.getNominalSize(); i++) - { - emit(sw::Shader::OPCODE_MUL, result, i, left, i, right, 0); - } - } - else if(right->isMatrix()) - { - for(int i = 0; i < rightType.getNominalSize(); i++) - { - emit(sw::Shader::OPCODE_MUL, result, i, left, 0, right, i); - } - } - else UNREACHABLE(0); - } - break; - case EOpVectorTimesMatrix: - if(visit == PostVisit) - { - sw::Shader::Opcode dpOpcode = sw::Shader::OPCODE_DP(leftType.getNominalSize()); - - int size = rightType.getNominalSize(); - for(int i = 0; i < size; i++) - { - Instruction *dot = emit(dpOpcode, result, 0, left, 0, right, i); - dot->dst.mask = 1 << i; - } - } - break; - case EOpMatrixTimesVector: - if(visit == PostVisit) - { - Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, left, right); - mul->src[1].swizzle = 0x00; - - int size = rightType.getNominalSize(); - for(int i = 1; i < size; i++) - { - Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, 0, left, i, right, 0, result); - mad->src[1].swizzle = i * 0x55; - } - } - break; - case EOpMatrixTimesMatrix: - if(visit == PostVisit) - { - int dim = leftType.getNominalSize(); - - int size = rightType.getNominalSize(); - for(int i = 0; i < size; i++) - { - Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, i, left, 0, right, i); - mul->src[1].swizzle = 0x00; - - for(int j = 1; j < dim; j++) - { - Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, i, left, j, right, i, result, i); - mad->src[1].swizzle = j * 0x55; - } - } - } - break; - case EOpLogicalOr: - if(trivial(right, 6)) - { - if(visit == PostVisit) - { - emit(sw::Shader::OPCODE_OR, result, left, right); - } - } - else // Short-circuit evaluation - { - if(visit == InVisit) - { - emit(sw::Shader::OPCODE_MOV, result, left); - Instruction *ifnot = emit(sw::Shader::OPCODE_IF, 0, result); - ifnot->src[0].modifier = sw::Shader::MODIFIER_NOT; - } - else if(visit == PostVisit) - { - emit(sw::Shader::OPCODE_MOV, result, right); - emit(sw::Shader::OPCODE_ENDIF); - } - } - break; - case EOpLogicalXor: if(visit == PostVisit) emit(sw::Shader::OPCODE_XOR, result, left, right); break; - case EOpLogicalAnd: - if(trivial(right, 6)) - { - if(visit == PostVisit) - { - emit(sw::Shader::OPCODE_AND, result, left, right); - } - } - else // Short-circuit evaluation - { - if(visit == InVisit) - { - emit(sw::Shader::OPCODE_MOV, result, left); - emit(sw::Shader::OPCODE_IF, 0, result); - } - else if(visit == PostVisit) - { - emit(sw::Shader::OPCODE_MOV, result, right); - emit(sw::Shader::OPCODE_ENDIF); - } - } - break; - default: UNREACHABLE(node->getOp()); - } - - return true; - } - - void OutputASM::emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col, int row, int outCol, int outRow) - { - switch(size) - { - case 1: // Used for cofactor computation only - { - // For a 2x2 matrix, the cofactor is simply a transposed move or negate - bool isMov = (row == col); - sw::Shader::Opcode op = isMov ? sw::Shader::OPCODE_MOV : sw::Shader::OPCODE_NEG; - Instruction *mov = emit(op, result, outCol, arg, isMov ? 1 - row : row); - mov->src[0].swizzle = 0x55 * (isMov ? 1 - col : col); - mov->dst.mask = 1 << outRow; - } - break; - case 2: - { - static const unsigned int swizzle[3] = { 0x99, 0x88, 0x44 }; // xy?? : yzyz, xzxz, xyxy - - bool isCofactor = (col >= 0) && (row >= 0); - int col0 = (isCofactor && (col <= 0)) ? 1 : 0; - int col1 = (isCofactor && (col <= 1)) ? 2 : 1; - bool negate = isCofactor && ((col & 0x01) ^ (row & 0x01)); - - Instruction *det = emit(sw::Shader::OPCODE_DET2, result, outCol, arg, negate ? col1 : col0, arg, negate ? col0 : col1); - det->src[0].swizzle = det->src[1].swizzle = swizzle[isCofactor ? row : 2]; - det->dst.mask = 1 << outRow; - } - break; - case 3: - { - static const unsigned int swizzle[4] = { 0xF9, 0xF8, 0xF4, 0xE4 }; // xyz? : yzww, xzww, xyww, xyzw - - bool isCofactor = (col >= 0) && (row >= 0); - int col0 = (isCofactor && (col <= 0)) ? 1 : 0; - int col1 = (isCofactor && (col <= 1)) ? 2 : 1; - int col2 = (isCofactor && (col <= 2)) ? 3 : 2; - bool negate = isCofactor && ((col & 0x01) ^ (row & 0x01)); - - Instruction *det = emit(sw::Shader::OPCODE_DET3, result, outCol, arg, col0, arg, negate ? col2 : col1, arg, negate ? col1 : col2); - det->src[0].swizzle = det->src[1].swizzle = det->src[2].swizzle = swizzle[isCofactor ? row : 3]; - det->dst.mask = 1 << outRow; - } - break; - case 4: - { - Instruction *det = emit(sw::Shader::OPCODE_DET4, result, outCol, arg, 0, arg, 1, arg, 2, arg, 3); - det->dst.mask = 1 << outRow; - } - break; - default: - UNREACHABLE(size); - break; - } - } - - bool OutputASM::visitUnary(Visit visit, TIntermUnary *node) - { - if(currentScope != emitScope) - { - return false; - } - - TIntermTyped *result = node; - TIntermTyped *arg = node->getOperand(); - TBasicType basicType = arg->getType().getBasicType(); - - union - { - float f; - int i; - } one_value; - - if(basicType == EbtInt || basicType == EbtUInt) - { - one_value.i = 1; - } - else - { - one_value.f = 1.0f; - } - - Constant one(one_value.f, one_value.f, one_value.f, one_value.f); - Constant rad(1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f); - Constant deg(5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f); - - switch(node->getOp()) - { - case EOpNegative: - if(visit == PostVisit) - { - sw::Shader::Opcode negOpcode = getOpcode(sw::Shader::OPCODE_NEG, arg); - for(int index = 0; index < arg->totalRegisterCount(); index++) - { - emit(negOpcode, result, index, arg, index); - } - } - break; - case EOpVectorLogicalNot: if(visit == PostVisit) emit(sw::Shader::OPCODE_NOT, result, arg); break; - case EOpLogicalNot: if(visit == PostVisit) emit(sw::Shader::OPCODE_NOT, result, arg); break; - case EOpPostIncrement: - if(visit == PostVisit) - { - copy(result, arg); - - sw::Shader::Opcode addOpcode = getOpcode(sw::Shader::OPCODE_ADD, arg); - for(int index = 0; index < arg->totalRegisterCount(); index++) - { - emit(addOpcode, arg, index, arg, index, &one); - } - - assignLvalue(arg, arg); - } - break; - case EOpPostDecrement: - if(visit == PostVisit) - { - copy(result, arg); - - sw::Shader::Opcode subOpcode = getOpcode(sw::Shader::OPCODE_SUB, arg); - for(int index = 0; index < arg->totalRegisterCount(); index++) - { - emit(subOpcode, arg, index, arg, index, &one); - } - - assignLvalue(arg, arg); - } - break; - case EOpPreIncrement: - if(visit == PostVisit) - { - sw::Shader::Opcode addOpcode = getOpcode(sw::Shader::OPCODE_ADD, arg); - for(int index = 0; index < arg->totalRegisterCount(); index++) - { - emit(addOpcode, result, index, arg, index, &one); - } - - assignLvalue(arg, result); - } - break; - case EOpPreDecrement: - if(visit == PostVisit) - { - sw::Shader::Opcode subOpcode = getOpcode(sw::Shader::OPCODE_SUB, arg); - for(int index = 0; index < arg->totalRegisterCount(); index++) - { - emit(subOpcode, result, index, arg, index, &one); - } - - assignLvalue(arg, result); - } - break; - case EOpRadians: if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, arg, &rad); break; - case EOpDegrees: if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, arg, °); break; - case EOpSin: if(visit == PostVisit) emit(sw::Shader::OPCODE_SIN, result, arg); break; - case EOpCos: if(visit == PostVisit) emit(sw::Shader::OPCODE_COS, result, arg); break; - case EOpTan: if(visit == PostVisit) emit(sw::Shader::OPCODE_TAN, result, arg); break; - case EOpAsin: if(visit == PostVisit) emit(sw::Shader::OPCODE_ASIN, result, arg); break; - case EOpAcos: if(visit == PostVisit) emit(sw::Shader::OPCODE_ACOS, result, arg); break; - case EOpAtan: if(visit == PostVisit) emit(sw::Shader::OPCODE_ATAN, result, arg); break; - case EOpSinh: if(visit == PostVisit) emit(sw::Shader::OPCODE_SINH, result, arg); break; - case EOpCosh: if(visit == PostVisit) emit(sw::Shader::OPCODE_COSH, result, arg); break; - case EOpTanh: if(visit == PostVisit) emit(sw::Shader::OPCODE_TANH, result, arg); break; - case EOpAsinh: if(visit == PostVisit) emit(sw::Shader::OPCODE_ASINH, result, arg); break; - case EOpAcosh: if(visit == PostVisit) emit(sw::Shader::OPCODE_ACOSH, result, arg); break; - case EOpAtanh: if(visit == PostVisit) emit(sw::Shader::OPCODE_ATANH, result, arg); break; - case EOpExp: if(visit == PostVisit) emit(sw::Shader::OPCODE_EXP, result, arg); break; - case EOpLog: if(visit == PostVisit) emit(sw::Shader::OPCODE_LOG, result, arg); break; - case EOpExp2: if(visit == PostVisit) emit(sw::Shader::OPCODE_EXP2, result, arg); break; - case EOpLog2: if(visit == PostVisit) emit(sw::Shader::OPCODE_LOG2, result, arg); break; - case EOpSqrt: if(visit == PostVisit) emit(sw::Shader::OPCODE_SQRT, result, arg); break; - case EOpInverseSqrt: if(visit == PostVisit) emit(sw::Shader::OPCODE_RSQ, result, arg); break; - case EOpAbs: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_ABS, result), result, arg); break; - case EOpSign: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_SGN, result), result, arg); break; - case EOpFloor: if(visit == PostVisit) emit(sw::Shader::OPCODE_FLOOR, result, arg); break; - case EOpTrunc: if(visit == PostVisit) emit(sw::Shader::OPCODE_TRUNC, result, arg); break; - case EOpRound: if(visit == PostVisit) emit(sw::Shader::OPCODE_ROUND, result, arg); break; - case EOpRoundEven: if(visit == PostVisit) emit(sw::Shader::OPCODE_ROUNDEVEN, result, arg); break; - case EOpCeil: if(visit == PostVisit) emit(sw::Shader::OPCODE_CEIL, result, arg, result); break; - case EOpFract: if(visit == PostVisit) emit(sw::Shader::OPCODE_FRC, result, arg); break; - case EOpIsNan: if(visit == PostVisit) emit(sw::Shader::OPCODE_ISNAN, result, arg); break; - case EOpIsInf: if(visit == PostVisit) emit(sw::Shader::OPCODE_ISINF, result, arg); break; - case EOpLength: if(visit == PostVisit) emit(sw::Shader::OPCODE_LEN(dim(arg)), result, arg); break; - case EOpNormalize: if(visit == PostVisit) emit(sw::Shader::OPCODE_NRM(dim(arg)), result, arg); break; - case EOpDFdx: if(visit == PostVisit) emit(sw::Shader::OPCODE_DFDX, result, arg); break; - case EOpDFdy: if(visit == PostVisit) emit(sw::Shader::OPCODE_DFDY, result, arg); break; - case EOpFwidth: if(visit == PostVisit) emit(sw::Shader::OPCODE_FWIDTH, result, arg); break; - case EOpAny: if(visit == PostVisit) emit(sw::Shader::OPCODE_ANY, result, arg); break; - case EOpAll: if(visit == PostVisit) emit(sw::Shader::OPCODE_ALL, result, arg); break; - case EOpFloatBitsToInt: if(visit == PostVisit) emit(sw::Shader::OPCODE_FLOATBITSTOINT, result, arg); break; - case EOpFloatBitsToUint: if(visit == PostVisit) emit(sw::Shader::OPCODE_FLOATBITSTOUINT, result, arg); break; - case EOpIntBitsToFloat: if(visit == PostVisit) emit(sw::Shader::OPCODE_INTBITSTOFLOAT, result, arg); break; - case EOpUintBitsToFloat: if(visit == PostVisit) emit(sw::Shader::OPCODE_UINTBITSTOFLOAT, result, arg); break; - case EOpPackSnorm2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_PACKSNORM2x16, result, arg); break; - case EOpPackUnorm2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_PACKUNORM2x16, result, arg); break; - case EOpPackHalf2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_PACKHALF2x16, result, arg); break; - case EOpUnpackSnorm2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_UNPACKSNORM2x16, result, arg); break; - case EOpUnpackUnorm2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_UNPACKUNORM2x16, result, arg); break; - case EOpUnpackHalf2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_UNPACKHALF2x16, result, arg); break; - case EOpTranspose: - if(visit == PostVisit) - { - int numCols = arg->getNominalSize(); - int numRows = arg->getSecondarySize(); - for(int i = 0; i < numCols; ++i) - { - for(int j = 0; j < numRows; ++j) - { - Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, j, arg, i); - mov->src[0].swizzle = 0x55 * j; - mov->dst.mask = 1 << i; - } - } - } - break; - case EOpDeterminant: - if(visit == PostVisit) - { - int size = arg->getNominalSize(); - ASSERT(size == arg->getSecondarySize()); - - emitDeterminant(result, arg, size); - } - break; - case EOpInverse: - if(visit == PostVisit) - { - int size = arg->getNominalSize(); - ASSERT(size == arg->getSecondarySize()); - - // Compute transposed matrix of cofactors - for(int i = 0; i < size; ++i) - { - for(int j = 0; j < size; ++j) - { - // For a 2x2 matrix, the cofactor is simply a transposed move or negate - // For a 3x3 or 4x4 matrix, the cofactor is a transposed determinant - emitDeterminant(result, arg, size - 1, j, i, i, j); - } - } - - // Compute 1 / determinant - Temporary invDet(this); - emitDeterminant(&invDet, arg, size); - Constant one(1.0f, 1.0f, 1.0f, 1.0f); - Instruction *div = emit(sw::Shader::OPCODE_DIV, &invDet, &one, &invDet); - div->src[1].swizzle = 0x00; // xxxx - - // Divide transposed matrix of cofactors by determinant - for(int i = 0; i < size; ++i) - { - emit(sw::Shader::OPCODE_MUL, result, i, result, i, &invDet); - } - } - break; - default: UNREACHABLE(node->getOp()); - } - - return true; - } - - bool OutputASM::visitAggregate(Visit visit, TIntermAggregate *node) - { - if(currentScope != emitScope && node->getOp() != EOpFunction && node->getOp() != EOpSequence) - { - return false; - } - - Constant zero(0.0f, 0.0f, 0.0f, 0.0f); - - TIntermTyped *result = node; - const TType &resultType = node->getType(); - TIntermSequence &arg = node->getSequence(); - size_t argumentCount = arg.size(); - - switch(node->getOp()) - { - case EOpSequence: break; - case EOpDeclaration: break; - case EOpInvariantDeclaration: break; - case EOpPrototype: break; - case EOpComma: - if(visit == PostVisit) - { - copy(result, arg[1]); - } - break; - case EOpFunction: - if(visit == PreVisit) - { - const TString &name = node->getName(); - - if(emitScope == FUNCTION) - { - if(functionArray.size() > 1) // No need for a label when there's only main() - { - Instruction *label = emit(sw::Shader::OPCODE_LABEL); - label->dst.type = sw::Shader::PARAMETER_LABEL; - - const Function *function = findFunction(name); - ASSERT(function); // Should have been added during global pass - label->dst.index = function->label; - currentFunction = function->label; - } - } - else if(emitScope == GLOBAL) - { - if(name != "main(") - { - TIntermSequence &arguments = node->getSequence()[0]->getAsAggregate()->getSequence(); - functionArray.push_back(Function(functionArray.size(), name, &arguments, node)); - } - } - else UNREACHABLE(emitScope); - - currentScope = FUNCTION; - } - else if(visit == PostVisit) - { - if(emitScope == FUNCTION) - { - if(functionArray.size() > 1) // No need to return when there's only main() - { - emit(sw::Shader::OPCODE_RET); - } - } - - currentScope = GLOBAL; - } - break; - case EOpFunctionCall: - if(visit == PostVisit) - { - if(node->isUserDefined()) - { - const TString &name = node->getName(); - const Function *function = findFunction(name); - - if(!function) - { - mContext.error(node->getLine(), "function definition not found", name.c_str()); - return false; - } - - TIntermSequence &arguments = *function->arg; - - for(size_t i = 0; i < argumentCount; i++) - { - TIntermTyped *in = arguments[i]->getAsTyped(); - - if(in->getQualifier() == EvqIn || - in->getQualifier() == EvqInOut || - in->getQualifier() == EvqConstReadOnly) - { - copy(in, arg[i]); - } - } - - Instruction *call = emit(sw::Shader::OPCODE_CALL); - call->dst.type = sw::Shader::PARAMETER_LABEL; - call->dst.index = function->label; - - if(function->ret && function->ret->getType().getBasicType() != EbtVoid) - { - copy(result, function->ret); - } - - for(size_t i = 0; i < argumentCount; i++) - { - TIntermTyped *argument = arguments[i]->getAsTyped(); - TIntermTyped *out = arg[i]->getAsTyped(); - - if(argument->getQualifier() == EvqOut || - argument->getQualifier() == EvqInOut) - { - copy(out, argument); - } - } - } - else - { - const TextureFunction textureFunction(node->getName()); - TIntermTyped *t = arg[1]->getAsTyped(); - - Temporary coord(this); - - if(textureFunction.proj) - { - TIntermConstantUnion* constant = arg[1]->getAsConstantUnion(); - if(constant) - { - float projFactor = 1.0f / constant->getFConst(t->getNominalSize() - 1); - Constant projCoord(constant->getFConst(0) * projFactor, - constant->getFConst(1) * projFactor, - constant->getFConst(2) * projFactor, - 0.0f); - emit(sw::Shader::OPCODE_MOV, &coord, &projCoord); - } - else - { - Instruction *rcp = emit(sw::Shader::OPCODE_RCPX, &coord, arg[1]); - rcp->src[0].swizzle = 0x55 * (t->getNominalSize() - 1); - rcp->dst.mask = 0x7; - - Instruction *mul = emit(sw::Shader::OPCODE_MUL, &coord, arg[1], &coord); - mul->dst.mask = 0x7; - } - } - else - { - emit(sw::Shader::OPCODE_MOV, &coord, arg[1]); - } - - switch(textureFunction.method) - { - case TextureFunction::IMPLICIT: - { - TIntermNode* offset = textureFunction.offset ? arg[2] : 0; - - if(argumentCount == 2 || (textureFunction.offset && argumentCount == 3)) - { - Instruction *tex = emit(textureFunction.offset ? sw::Shader::OPCODE_TEXOFFSET : sw::Shader::OPCODE_TEX, - result, &coord, arg[0], offset); - } - else if(argumentCount == 3 || (textureFunction.offset && argumentCount == 4)) // bias - { - Instruction *bias = emit(sw::Shader::OPCODE_MOV, &coord, arg[textureFunction.offset ? 3 : 2]); - bias->dst.mask = 0x8; - - Instruction *tex = emit(textureFunction.offset ? sw::Shader::OPCODE_TEXOFFSET : sw::Shader::OPCODE_TEX, - result, &coord, arg[0], offset); // FIXME: Implement an efficient TEXLDB instruction - tex->bias = true; - } - else UNREACHABLE(argumentCount); - } - break; - case TextureFunction::LOD: - { - Instruction *lod = emit(sw::Shader::OPCODE_MOV, &coord, arg[2]); - lod->dst.mask = 0x8; - - emit(textureFunction.offset ? sw::Shader::OPCODE_TEXLDLOFFSET : sw::Shader::OPCODE_TEXLDL, - result, &coord, arg[0], textureFunction.offset ? arg[3] : nullptr); - } - break; - case TextureFunction::FETCH: - { - if(argumentCount == 3 || (textureFunction.offset && argumentCount == 4)) - { - TIntermNode *offset = textureFunction.offset ? arg[3] : nullptr; - - emit(textureFunction.offset ? sw::Shader::OPCODE_TEXELFETCHOFFSET : sw::Shader::OPCODE_TEXELFETCH, - result, arg[1], arg[0], arg[2], offset); - } - else UNREACHABLE(argumentCount); - } - break; - case TextureFunction::GRAD: - { - if(argumentCount == 4 || (textureFunction.offset && argumentCount == 5)) - { - TIntermNode *offset = textureFunction.offset ? arg[4] : nullptr; - - emit(textureFunction.offset ? sw::Shader::OPCODE_TEXGRADOFFSET : sw::Shader::OPCODE_TEXGRAD, - result, &coord, arg[0], arg[2], arg[3], offset); - } - else UNREACHABLE(argumentCount); - } - break; - case TextureFunction::SIZE: - emit(sw::Shader::OPCODE_TEXSIZE, result, arg[1], arg[0]); - break; - default: - UNREACHABLE(textureFunction.method); - } - } - } - break; - case EOpParameters: - break; - case EOpConstructFloat: - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructBool: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructInt: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructUInt: - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - if(visit == PostVisit) - { - int component = 0; - - for(size_t i = 0; i < argumentCount; i++) - { - TIntermTyped *argi = arg[i]->getAsTyped(); - int size = argi->getNominalSize(); - - if(!argi->isMatrix()) - { - Instruction *mov = emitCast(result, argi); - mov->dst.mask = (0xF << component) & 0xF; - mov->src[0].swizzle = readSwizzle(argi, size) << (component * 2); - - component += size; - } - else // Matrix - { - int column = 0; - - while(component < resultType.getNominalSize()) - { - Instruction *mov = emitCast(result, 0, argi, column); - mov->dst.mask = (0xF << component) & 0xF; - mov->src[0].swizzle = readSwizzle(argi, size) << (component * 2); - - column++; - component += size; - } - } - } - } - break; - case EOpConstructMat2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4: - if(visit == PostVisit) - { - TIntermTyped *arg0 = arg[0]->getAsTyped(); - const int outCols = result->getNominalSize(); - const int outRows = result->getSecondarySize(); - - if(arg0->isScalar() && arg.size() == 1) // Construct scale matrix - { - for(int i = 0; i < outCols; i++) - { - Instruction *init = emit(sw::Shader::OPCODE_MOV, result, i, &zero); - Instruction *mov = emitCast(result, i, arg0, 0); - mov->dst.mask = 1 << i; - ASSERT(mov->src[0].swizzle == 0x00); - } - } - else if(arg0->isMatrix()) - { - const int inCols = arg0->getNominalSize(); - const int inRows = arg0->getSecondarySize(); - - for(int i = 0; i < outCols; i++) - { - if(i >= inCols || outRows > inRows) - { - // Initialize to identity matrix - Constant col((i == 0 ? 1.0f : 0.0f), (i == 1 ? 1.0f : 0.0f), (i == 2 ? 1.0f : 0.0f), (i == 3 ? 1.0f : 0.0f)); - Instruction *mov = emitCast(result, i, &col, 0); - } - - if(i < inCols) - { - Instruction *mov = emitCast(result, i, arg0, i); - mov->dst.mask = 0xF >> (4 - inRows); - } - } - } - else - { - int column = 0; - int row = 0; - - for(size_t i = 0; i < argumentCount; i++) - { - TIntermTyped *argi = arg[i]->getAsTyped(); - int size = argi->getNominalSize(); - int element = 0; - - while(element < size) - { - Instruction *mov = emitCast(result, column, argi, 0); - mov->dst.mask = (0xF << row) & 0xF; - mov->src[0].swizzle = (readSwizzle(argi, size) << (row * 2)) + 0x55 * element; - - int end = row + size - element; - column = end >= outRows ? column + 1 : column; - element = element + outRows - row; - row = end >= outRows ? 0 : end; - } - } - } - } - break; - case EOpConstructStruct: - if(visit == PostVisit) - { - int offset = 0; - for(size_t i = 0; i < argumentCount; i++) - { - TIntermTyped *argi = arg[i]->getAsTyped(); - int size = argi->totalRegisterCount(); - - for(int index = 0; index < size; index++) - { - Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, index + offset, argi, index); - mov->dst.mask = writeMask(result, offset + index); - } - - offset += size; - } - } - break; - case EOpLessThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LT, result, arg[0], arg[1]); break; - case EOpGreaterThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GT, result, arg[0], arg[1]); break; - case EOpLessThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LE, result, arg[0], arg[1]); break; - case EOpGreaterThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GE, result, arg[0], arg[1]); break; - case EOpVectorEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_EQ, result, arg[0], arg[1]); break; - case EOpVectorNotEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_NE, result, arg[0], arg[1]); break; - case EOpMod: if(visit == PostVisit) emit(sw::Shader::OPCODE_MOD, result, arg[0], arg[1]); break; - case EOpModf: - if(visit == PostVisit) - { - TIntermTyped* arg1 = arg[1]->getAsTyped(); - emit(sw::Shader::OPCODE_TRUNC, arg1, arg[0]); - assignLvalue(arg1, arg1); - emitBinary(sw::Shader::OPCODE_SUB, result, arg[0], arg1); - } - break; - case EOpPow: if(visit == PostVisit) emit(sw::Shader::OPCODE_POW, result, arg[0], arg[1]); break; - case EOpAtan: if(visit == PostVisit) emit(sw::Shader::OPCODE_ATAN2, result, arg[0], arg[1]); break; - case EOpMin: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MIN, result), result, arg[0], arg[1]); break; - case EOpMax: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MAX, result), result, arg[0], arg[1]); break; - case EOpClamp: - if(visit == PostVisit) - { - emit(getOpcode(sw::Shader::OPCODE_MAX, result), result, arg[0], arg[1]); - emit(getOpcode(sw::Shader::OPCODE_MIN, result), result, result, arg[2]); - } - break; - case EOpMix: if(visit == PostVisit) emit(sw::Shader::OPCODE_LRP, result, arg[2], arg[1], arg[0]); break; - case EOpStep: if(visit == PostVisit) emit(sw::Shader::OPCODE_STEP, result, arg[0], arg[1]); break; - case EOpSmoothStep: if(visit == PostVisit) emit(sw::Shader::OPCODE_SMOOTH, result, arg[0], arg[1], arg[2]); break; - case EOpDistance: if(visit == PostVisit) emit(sw::Shader::OPCODE_DIST(dim(arg[0])), result, arg[0], arg[1]); break; - case EOpDot: if(visit == PostVisit) emit(sw::Shader::OPCODE_DP(dim(arg[0])), result, arg[0], arg[1]); break; - case EOpCross: if(visit == PostVisit) emit(sw::Shader::OPCODE_CRS, result, arg[0], arg[1]); break; - case EOpFaceForward: if(visit == PostVisit) emit(sw::Shader::OPCODE_FORWARD(dim(arg[0])), result, arg[0], arg[1], arg[2]); break; - case EOpReflect: if(visit == PostVisit) emit(sw::Shader::OPCODE_REFLECT(dim(arg[0])), result, arg[0], arg[1]); break; - case EOpRefract: if(visit == PostVisit) emit(sw::Shader::OPCODE_REFRACT(dim(arg[0])), result, arg[0], arg[1], arg[2]); break; - case EOpMul: - if(visit == PostVisit) - { - TIntermTyped *arg0 = arg[0]->getAsTyped(); - TIntermTyped *arg1 = arg[1]->getAsTyped(); - ASSERT((arg0->getNominalSize() == arg1->getNominalSize()) && (arg0->getSecondarySize() == arg1->getSecondarySize())); - - int size = arg0->getNominalSize(); - for(int i = 0; i < size; i++) - { - emit(sw::Shader::OPCODE_MUL, result, i, arg[0], i, arg[1], i); - } - } - break; - case EOpOuterProduct: - if(visit == PostVisit) - { - for(int i = 0; i < dim(arg[1]); i++) - { - Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, i, arg[0], 0, arg[1]); - mul->src[1].swizzle = 0x55 * i; - } - } - break; - default: UNREACHABLE(node->getOp()); - } - - return true; - } - - bool OutputASM::visitSelection(Visit visit, TIntermSelection *node) - { - if(currentScope != emitScope) - { - return false; - } - - TIntermTyped *condition = node->getCondition(); - TIntermNode *trueBlock = node->getTrueBlock(); - TIntermNode *falseBlock = node->getFalseBlock(); - TIntermConstantUnion *constantCondition = condition->getAsConstantUnion(); - - condition->traverse(this); - - if(node->usesTernaryOperator()) - { - if(constantCondition) - { - bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst(); - - if(trueCondition) - { - trueBlock->traverse(this); - copy(node, trueBlock); - } - else - { - falseBlock->traverse(this); - copy(node, falseBlock); - } - } - else if(trivial(node, 6)) // Fast to compute both potential results and no side effects - { - trueBlock->traverse(this); - falseBlock->traverse(this); - emit(sw::Shader::OPCODE_SELECT, node, condition, trueBlock, falseBlock); - } - else - { - emit(sw::Shader::OPCODE_IF, 0, condition); - - if(trueBlock) - { - trueBlock->traverse(this); - copy(node, trueBlock); - } - - if(falseBlock) - { - emit(sw::Shader::OPCODE_ELSE); - falseBlock->traverse(this); - copy(node, falseBlock); - } - - emit(sw::Shader::OPCODE_ENDIF); - } - } - else // if/else statement - { - if(constantCondition) - { - bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst(); - - if(trueCondition) - { - if(trueBlock) - { - trueBlock->traverse(this); - } - } - else - { - if(falseBlock) - { - falseBlock->traverse(this); - } - } - } - else - { - emit(sw::Shader::OPCODE_IF, 0, condition); - - if(trueBlock) - { - trueBlock->traverse(this); - } - - if(falseBlock) - { - emit(sw::Shader::OPCODE_ELSE); - falseBlock->traverse(this); - } - - emit(sw::Shader::OPCODE_ENDIF); - } - } - - return false; - } - - bool OutputASM::visitLoop(Visit visit, TIntermLoop *node) - { - if(currentScope != emitScope) - { - return false; - } - - unsigned int iterations = loopCount(node); - - if(iterations == 0) - { - return false; - } - - bool unroll = (iterations <= 4); - - if(unroll) - { - LoopUnrollable loopUnrollable; - unroll = loopUnrollable.traverse(node); - } - - TIntermNode *init = node->getInit(); - TIntermTyped *condition = node->getCondition(); - TIntermTyped *expression = node->getExpression(); - TIntermNode *body = node->getBody(); - Constant True(true); - - if(node->getType() == ELoopDoWhile) - { - Temporary iterate(this); - emit(sw::Shader::OPCODE_MOV, &iterate, &True); - - emit(sw::Shader::OPCODE_WHILE, 0, &iterate); // FIXME: Implement real do-while - - if(body) - { - body->traverse(this); - } - - emit(sw::Shader::OPCODE_TEST); - - condition->traverse(this); - emit(sw::Shader::OPCODE_MOV, &iterate, condition); - - emit(sw::Shader::OPCODE_ENDWHILE); - } - else - { - if(init) - { - init->traverse(this); - } - - if(unroll) - { - for(unsigned int i = 0; i < iterations; i++) - { - // condition->traverse(this); // Condition could contain statements, but not in an unrollable loop - - if(body) - { - body->traverse(this); - } - - if(expression) - { - expression->traverse(this); - } - } - } - else - { - if(condition) - { - condition->traverse(this); - } - else - { - condition = &True; - } - - emit(sw::Shader::OPCODE_WHILE, 0, condition); - - if(body) - { - body->traverse(this); - } - - emit(sw::Shader::OPCODE_TEST); - - if(expression) - { - expression->traverse(this); - } - - if(condition) - { - condition->traverse(this); - } - - emit(sw::Shader::OPCODE_ENDWHILE); - } - } - - return false; - } - - bool OutputASM::visitBranch(Visit visit, TIntermBranch *node) - { - if(currentScope != emitScope) - { - return false; - } - - switch(node->getFlowOp()) - { - case EOpKill: if(visit == PostVisit) emit(sw::Shader::OPCODE_DISCARD); break; - case EOpBreak: if(visit == PostVisit) emit(sw::Shader::OPCODE_BREAK); break; - case EOpContinue: if(visit == PostVisit) emit(sw::Shader::OPCODE_CONTINUE); break; - case EOpReturn: - if(visit == PostVisit) - { - TIntermTyped *value = node->getExpression(); - - if(value) - { - copy(functionArray[currentFunction].ret, value); - } - - emit(sw::Shader::OPCODE_LEAVE); - } - break; - default: UNREACHABLE(node->getFlowOp()); - } - - return true; - } - - Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, TIntermNode *src3, TIntermNode *src4) - { - return emit(op, dst, 0, src0, 0, src1, 0, src2, 0, src3, 0, src4, 0); - } - - Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0, int index0, TIntermNode *src1, int index1, - TIntermNode *src2, int index2, TIntermNode *src3, int index3, TIntermNode *src4, int index4) - { - Instruction *instruction = new Instruction(op); - - if(dst) - { - instruction->dst.type = registerType(dst); - instruction->dst.index = registerIndex(dst) + dstIndex; - instruction->dst.mask = writeMask(dst); - instruction->dst.integer = (dst->getBasicType() == EbtInt); - } - - argument(instruction->src[0], src0, index0); - argument(instruction->src[1], src1, index1); - argument(instruction->src[2], src2, index2); - argument(instruction->src[3], src3, index3); - argument(instruction->src[4], src4, index4); - - shader->append(instruction); - - return instruction; - } - - Instruction *OutputASM::emitCast(TIntermTyped *dst, TIntermTyped *src) - { - return emitCast(dst, 0, src, 0); - } - - Instruction *OutputASM::emitCast(TIntermTyped *dst, int dstIndex, TIntermTyped *src, int srcIndex) - { - switch(src->getBasicType()) - { - case EbtBool: - switch(dst->getBasicType()) - { - case EbtInt: return emit(sw::Shader::OPCODE_B2I, dst, dstIndex, src, srcIndex); - case EbtUInt: return emit(sw::Shader::OPCODE_B2I, dst, dstIndex, src, srcIndex); - case EbtFloat: return emit(sw::Shader::OPCODE_B2F, dst, dstIndex, src, srcIndex); - default: break; - } - break; - case EbtInt: - switch(dst->getBasicType()) - { - case EbtBool: return emit(sw::Shader::OPCODE_I2B, dst, dstIndex, src, srcIndex); - case EbtFloat: return emit(sw::Shader::OPCODE_I2F, dst, dstIndex, src, srcIndex); - default: break; - } - break; - case EbtUInt: - switch(dst->getBasicType()) - { - case EbtBool: return emit(sw::Shader::OPCODE_I2B, dst, dstIndex, src, srcIndex); - case EbtFloat: return emit(sw::Shader::OPCODE_U2F, dst, dstIndex, src, srcIndex); - default: break; - } - break; - case EbtFloat: - switch(dst->getBasicType()) - { - case EbtBool: return emit(sw::Shader::OPCODE_F2B, dst, dstIndex, src, srcIndex); - case EbtInt: return emit(sw::Shader::OPCODE_F2I, dst, dstIndex, src, srcIndex); - case EbtUInt: return emit(sw::Shader::OPCODE_F2U, dst, dstIndex, src, srcIndex); - default: break; - } - break; - default: - break; - } - - ASSERT((src->getBasicType() == dst->getBasicType()) || - ((src->getBasicType() == EbtInt) && (dst->getBasicType() == EbtUInt)) || - ((src->getBasicType() == EbtUInt) && (dst->getBasicType() == EbtInt))); - - return emit(sw::Shader::OPCODE_MOV, dst, dstIndex, src, srcIndex); - } - - void OutputASM::emitBinary(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2) - { - for(int index = 0; index < dst->elementRegisterCount(); index++) - { - emit(op, dst, index, src0, index, src1, index, src2, index); - } - } - - void OutputASM::emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1) - { - emitBinary(op, result, src0, src1); - assignLvalue(lhs, result); - } - - void OutputASM::emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index) - { - sw::Shader::Opcode opcode; - switch(left->getAsTyped()->getBasicType()) - { - case EbtBool: - case EbtInt: - opcode = sw::Shader::OPCODE_ICMP; - break; - case EbtUInt: - opcode = sw::Shader::OPCODE_UCMP; - break; - default: - opcode = sw::Shader::OPCODE_CMP; - break; - } - - Instruction *cmp = emit(opcode, dst, 0, left, index, right, index); - cmp->control = cmpOp; - } - - int componentCount(const TType &type, int registers) - { - if(registers == 0) - { - return 0; - } - - if(type.isArray() && registers >= type.elementRegisterCount()) - { - int index = registers / type.elementRegisterCount(); - registers -= index * type.elementRegisterCount(); - return index * type.getElementSize() + componentCount(type, registers); - } - - if(type.isStruct() || type.isInterfaceBlock()) - { - const TFieldList& fields = type.getStruct() ? type.getStruct()->fields() : type.getInterfaceBlock()->fields(); - int elements = 0; - - for(TFieldList::const_iterator field = fields.begin(); field != fields.end(); field++) - { - const TType &fieldType = *((*field)->type()); - - if(fieldType.totalRegisterCount() <= registers) - { - registers -= fieldType.totalRegisterCount(); - elements += fieldType.getObjectSize(); - } - else // Register within this field - { - return elements + componentCount(fieldType, registers); - } - } - } - else if(type.isMatrix()) - { - return registers * type.registerSize(); - } - - UNREACHABLE(0); - return 0; - } - - int registerSize(const TType &type, int registers) - { - if(registers == 0) - { - if(type.isStruct()) - { - return registerSize(*((*(type.getStruct()->fields().begin()))->type()), 0); - } - else if(type.isInterfaceBlock()) - { - return registerSize(*((*(type.getInterfaceBlock()->fields().begin()))->type()), 0); - } - - return type.registerSize(); - } - - if(type.isArray() && registers >= type.elementRegisterCount()) - { - int index = registers / type.elementRegisterCount(); - registers -= index * type.elementRegisterCount(); - return registerSize(type, registers); - } - - if(type.isStruct() || type.isInterfaceBlock()) - { - const TFieldList& fields = type.getStruct() ? type.getStruct()->fields() : type.getInterfaceBlock()->fields(); - int elements = 0; - - for(TFieldList::const_iterator field = fields.begin(); field != fields.end(); field++) - { - const TType &fieldType = *((*field)->type()); - - if(fieldType.totalRegisterCount() <= registers) - { - registers -= fieldType.totalRegisterCount(); - elements += fieldType.getObjectSize(); - } - else // Register within this field - { - return registerSize(fieldType, registers); - } - } - } - else if(type.isMatrix()) - { - return registerSize(type, 0); - } - - UNREACHABLE(0); - return 0; - } - - int OutputASM::getBlockId(TIntermTyped *arg) - { - if(arg) - { - const TType &type = arg->getType(); - TInterfaceBlock* block = type.getInterfaceBlock(); - if(block && (type.getQualifier() == EvqUniform)) - { - // Make sure the uniform block is declared - uniformRegister(arg); - - const char* blockName = block->name().c_str(); - - // Fetch uniform block index from array of blocks - for(ActiveUniformBlocks::const_iterator it = shaderObject->activeUniformBlocks.begin(); it != shaderObject->activeUniformBlocks.end(); ++it) - { - if(blockName == it->name) - { - return it->blockId; - } - } - - ASSERT(false); - } - } - - return -1; - } - - OutputASM::ArgumentInfo OutputASM::getArgumentInfo(TIntermTyped *arg, int index) - { - const TType &type = arg->getType(); - int blockId = getBlockId(arg); - ArgumentInfo argumentInfo(BlockMemberInfo::getDefaultBlockInfo(), type, -1, -1); - if(blockId != -1) - { - argumentInfo.bufferIndex = 0; - for(int i = 0; i < blockId; ++i) - { - int blockArraySize = shaderObject->activeUniformBlocks[i].arraySize; - argumentInfo.bufferIndex += blockArraySize > 0 ? blockArraySize : 1; - } - - const BlockDefinitionIndexMap& blockDefinition = blockDefinitions[blockId]; - - BlockDefinitionIndexMap::const_iterator itEnd = blockDefinition.end(); - BlockDefinitionIndexMap::const_iterator it = itEnd; - - argumentInfo.clampedIndex = index; - if(type.isInterfaceBlock()) - { - // Offset index to the beginning of the selected instance - int blockRegisters = type.elementRegisterCount(); - int bufferOffset = argumentInfo.clampedIndex / blockRegisters; - argumentInfo.bufferIndex += bufferOffset; - argumentInfo.clampedIndex -= bufferOffset * blockRegisters; - } - - int regIndex = registerIndex(arg); - for(int i = regIndex + argumentInfo.clampedIndex; i >= regIndex; --i) - { - it = blockDefinition.find(i); - if(it != itEnd) - { - argumentInfo.clampedIndex -= (i - regIndex); - break; - } - } - ASSERT(it != itEnd); - - argumentInfo.typedMemberInfo = it->second; - - int registerCount = argumentInfo.typedMemberInfo.type.totalRegisterCount(); - argumentInfo.clampedIndex = (argumentInfo.clampedIndex >= registerCount) ? registerCount - 1 : argumentInfo.clampedIndex; - } - else - { - argumentInfo.clampedIndex = (index >= arg->totalRegisterCount()) ? arg->totalRegisterCount() - 1 : index; - } - - return argumentInfo; - } - - void OutputASM::argument(sw::Shader::SourceParameter ¶meter, TIntermNode *argument, int index) - { - if(argument) - { - TIntermTyped *arg = argument->getAsTyped(); - Temporary unpackedUniform(this); - - const TType& srcType = arg->getType(); - TInterfaceBlock* srcBlock = srcType.getInterfaceBlock(); - if(srcBlock && (srcType.getQualifier() == EvqUniform)) - { - const ArgumentInfo argumentInfo = getArgumentInfo(arg, index); - const TType &memberType = argumentInfo.typedMemberInfo.type; - - if(memberType.getBasicType() == EbtBool) - { - int arraySize = (memberType.isArray() ? memberType.getArraySize() : 1); - ASSERT(argumentInfo.clampedIndex < arraySize); - - // Convert the packed bool, which is currently an int, to a true bool - Instruction *instruction = new Instruction(sw::Shader::OPCODE_I2B); - instruction->dst.type = sw::Shader::PARAMETER_TEMP; - instruction->dst.index = registerIndex(&unpackedUniform); - instruction->src[0].type = sw::Shader::PARAMETER_CONST; - instruction->src[0].bufferIndex = argumentInfo.bufferIndex; - instruction->src[0].index = argumentInfo.typedMemberInfo.offset + argumentInfo.clampedIndex * argumentInfo.typedMemberInfo.arrayStride; - - shader->append(instruction); - - arg = &unpackedUniform; - index = 0; - } - else if((srcBlock->matrixPacking() == EmpRowMajor) && memberType.isMatrix()) - { - int numCols = memberType.getNominalSize(); - int numRows = memberType.getSecondarySize(); - int arraySize = (memberType.isArray() ? memberType.getArraySize() : 1); - - ASSERT(argumentInfo.clampedIndex < (numCols * arraySize)); - - unsigned int dstIndex = registerIndex(&unpackedUniform); - unsigned int srcSwizzle = (argumentInfo.clampedIndex % numCols) * 0x55; - int arrayIndex = argumentInfo.clampedIndex / numCols; - int matrixStartOffset = argumentInfo.typedMemberInfo.offset + arrayIndex * argumentInfo.typedMemberInfo.arrayStride; - - for(int j = 0; j < numRows; ++j) - { - // Transpose the row major matrix - Instruction *instruction = new Instruction(sw::Shader::OPCODE_MOV); - instruction->dst.type = sw::Shader::PARAMETER_TEMP; - instruction->dst.index = dstIndex; - instruction->dst.mask = 1 << j; - instruction->src[0].type = sw::Shader::PARAMETER_CONST; - instruction->src[0].bufferIndex = argumentInfo.bufferIndex; - instruction->src[0].index = matrixStartOffset + j * argumentInfo.typedMemberInfo.matrixStride; - instruction->src[0].swizzle = srcSwizzle; - - shader->append(instruction); - } - - arg = &unpackedUniform; - index = 0; - } - } - - const ArgumentInfo argumentInfo = getArgumentInfo(arg, index); - const TType &type = argumentInfo.typedMemberInfo.type; - - int size = registerSize(type, argumentInfo.clampedIndex); - - parameter.type = registerType(arg); - parameter.bufferIndex = argumentInfo.bufferIndex; - - if(arg->getAsConstantUnion() && arg->getAsConstantUnion()->getUnionArrayPointer()) - { - int component = componentCount(type, argumentInfo.clampedIndex); - ConstantUnion *constants = arg->getAsConstantUnion()->getUnionArrayPointer(); - - for(int i = 0; i < 4; i++) - { - if(size == 1) // Replicate - { - parameter.value[i] = constants[component + 0].getAsFloat(); - } - else if(i < size) - { - parameter.value[i] = constants[component + i].getAsFloat(); - } - else - { - parameter.value[i] = 0.0f; - } - } - } - else - { - parameter.index = registerIndex(arg) + argumentInfo.clampedIndex; - - if(parameter.bufferIndex != -1) - { - int stride = (argumentInfo.typedMemberInfo.matrixStride > 0) ? argumentInfo.typedMemberInfo.matrixStride : argumentInfo.typedMemberInfo.arrayStride; - parameter.index = argumentInfo.typedMemberInfo.offset + argumentInfo.clampedIndex * stride; - } - } - - if(!IsSampler(arg->getBasicType())) - { - parameter.swizzle = readSwizzle(arg, size); - } - } - } - - void OutputASM::copy(TIntermTyped *dst, TIntermNode *src, int offset) - { - for(int index = 0; index < dst->totalRegisterCount(); index++) - { - Instruction *mov = emit(sw::Shader::OPCODE_MOV, dst, index, src, offset + index); - mov->dst.mask = writeMask(dst, index); - } - } - - int swizzleElement(int swizzle, int index) - { - return (swizzle >> (index * 2)) & 0x03; - } - - int swizzleSwizzle(int leftSwizzle, int rightSwizzle) - { - return (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 0)) << 0) | - (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 1)) << 2) | - (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 2)) << 4) | - (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 3)) << 6); - } - - void OutputASM::assignLvalue(TIntermTyped *dst, TIntermTyped *src) - { - if(src && - ((src->isVector() && (!dst->isVector() || (src->getNominalSize() != dst->getNominalSize()))) || - (src->isMatrix() && (!dst->isMatrix() || (src->getNominalSize() != dst->getNominalSize()) || (src->getSecondarySize() != dst->getSecondarySize()))))) - { - return mContext.error(src->getLine(), "Result type should match the l-value type in compound assignment", src->isVector() ? "vector" : "matrix"); - } - - TIntermBinary *binary = dst->getAsBinaryNode(); - - if(binary && binary->getOp() == EOpIndexIndirect && binary->getLeft()->isVector() && dst->isScalar()) - { - Instruction *insert = new Instruction(sw::Shader::OPCODE_INSERT); - - Temporary address(this); - lvalue(insert->dst, address, dst); - - insert->src[0].type = insert->dst.type; - insert->src[0].index = insert->dst.index; - insert->src[0].rel = insert->dst.rel; - argument(insert->src[1], src); - argument(insert->src[2], binary->getRight()); - - shader->append(insert); - } - else - { - for(int offset = 0; offset < dst->totalRegisterCount(); offset++) - { - Instruction *mov = new Instruction(sw::Shader::OPCODE_MOV); - - Temporary address(this); - int swizzle = lvalue(mov->dst, address, dst); - mov->dst.index += offset; - - if(offset > 0) - { - mov->dst.mask = writeMask(dst, offset); - } - - argument(mov->src[0], src, offset); - mov->src[0].swizzle = swizzleSwizzle(mov->src[0].swizzle, swizzle); - - shader->append(mov); - } - } - } - - int OutputASM::lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node) - { - TIntermTyped *result = node; - TIntermBinary *binary = node->getAsBinaryNode(); - TIntermSymbol *symbol = node->getAsSymbolNode(); - - if(binary) - { - TIntermTyped *left = binary->getLeft(); - TIntermTyped *right = binary->getRight(); - - int leftSwizzle = lvalue(dst, address, left); // Resolve the l-value of the left side - - switch(binary->getOp()) - { - case EOpIndexDirect: - { - int rightIndex = right->getAsConstantUnion()->getIConst(0); - - if(left->isRegister()) - { - int leftMask = dst.mask; - - dst.mask = 1; - while((leftMask & dst.mask) == 0) - { - dst.mask = dst.mask << 1; - } - - int element = swizzleElement(leftSwizzle, rightIndex); - dst.mask = 1 << element; - - return element; - } - else if(left->isArray() || left->isMatrix()) - { - dst.index += rightIndex * result->totalRegisterCount(); - return 0xE4; - } - else UNREACHABLE(0); - } - break; - case EOpIndexIndirect: - { - if(left->isRegister()) - { - // Requires INSERT instruction (handled by calling function) - } - else if(left->isArray() || left->isMatrix()) - { - int scale = result->totalRegisterCount(); - - if(dst.rel.type == sw::Shader::PARAMETER_VOID) // Use the index register as the relative address directly - { - if(left->totalRegisterCount() > 1) - { - sw::Shader::SourceParameter relativeRegister; - argument(relativeRegister, right); - - dst.rel.index = relativeRegister.index; - dst.rel.type = relativeRegister.type; - dst.rel.scale = scale; - dst.rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform); - } - } - else if(dst.rel.index != registerIndex(&address)) // Move the previous index register to the address register - { - if(scale == 1) - { - Constant oldScale((int)dst.rel.scale); - Instruction *mad = emit(sw::Shader::OPCODE_IMAD, &address, &address, &oldScale, right); - mad->src[0].index = dst.rel.index; - mad->src[0].type = dst.rel.type; - } - else - { - Constant oldScale((int)dst.rel.scale); - Instruction *mul = emit(sw::Shader::OPCODE_IMUL, &address, &address, &oldScale); - mul->src[0].index = dst.rel.index; - mul->src[0].type = dst.rel.type; - - Constant newScale(scale); - emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address); - } - - dst.rel.type = sw::Shader::PARAMETER_TEMP; - dst.rel.index = registerIndex(&address); - dst.rel.scale = 1; - } - else // Just add the new index to the address register - { - if(scale == 1) - { - emit(sw::Shader::OPCODE_IADD, &address, &address, right); - } - else - { - Constant newScale(scale); - emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address); - } - } - } - else UNREACHABLE(0); - } - break; - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - { - const TFieldList& fields = (binary->getOp() == EOpIndexDirectStruct) ? - left->getType().getStruct()->fields() : - left->getType().getInterfaceBlock()->fields(); - int index = right->getAsConstantUnion()->getIConst(0); - int fieldOffset = 0; - - for(int i = 0; i < index; i++) - { - fieldOffset += fields[i]->type()->totalRegisterCount(); - } - - dst.type = registerType(left); - dst.index += fieldOffset; - dst.mask = writeMask(right); - - return 0xE4; - } - break; - case EOpVectorSwizzle: - { - ASSERT(left->isRegister()); - - int leftMask = dst.mask; - - int swizzle = 0; - int rightMask = 0; - - TIntermSequence &sequence = right->getAsAggregate()->getSequence(); - - for(unsigned int i = 0; i < sequence.size(); i++) - { - int index = sequence[i]->getAsConstantUnion()->getIConst(0); - - int element = swizzleElement(leftSwizzle, index); - rightMask = rightMask | (1 << element); - swizzle = swizzle | swizzleElement(leftSwizzle, i) << (element * 2); - } - - dst.mask = leftMask & rightMask; - - return swizzle; - } - break; - default: - UNREACHABLE(binary->getOp()); // Not an l-value operator - break; - } - } - else if(symbol) - { - dst.type = registerType(symbol); - dst.index = registerIndex(symbol); - dst.mask = writeMask(symbol); - return 0xE4; - } - - return 0xE4; - } - - sw::Shader::ParameterType OutputASM::registerType(TIntermTyped *operand) - { - if(isSamplerRegister(operand)) - { - return sw::Shader::PARAMETER_SAMPLER; - } - - const TQualifier qualifier = operand->getQualifier(); - if((EvqFragColor == qualifier) || (EvqFragData == qualifier)) - { - if(((EvqFragData == qualifier) && (EvqFragColor == outputQualifier)) || - ((EvqFragColor == qualifier) && (EvqFragData == outputQualifier))) - { - mContext.error(operand->getLine(), "static assignment to both gl_FragData and gl_FragColor", ""); - } - outputQualifier = qualifier; - } - - if(qualifier == EvqConstExpr && (!operand->getAsConstantUnion() || !operand->getAsConstantUnion()->getUnionArrayPointer())) - { - return sw::Shader::PARAMETER_TEMP; - } - - switch(qualifier) - { - case EvqTemporary: return sw::Shader::PARAMETER_TEMP; - case EvqGlobal: return sw::Shader::PARAMETER_TEMP; - case EvqConstExpr: return sw::Shader::PARAMETER_FLOAT4LITERAL; // All converted to float - case EvqAttribute: return sw::Shader::PARAMETER_INPUT; - case EvqVaryingIn: return sw::Shader::PARAMETER_INPUT; - case EvqVaryingOut: return sw::Shader::PARAMETER_OUTPUT; - case EvqVertexIn: return sw::Shader::PARAMETER_INPUT; - case EvqFragmentOut: return sw::Shader::PARAMETER_COLOROUT; - case EvqVertexOut: return sw::Shader::PARAMETER_OUTPUT; - case EvqFragmentIn: return sw::Shader::PARAMETER_INPUT; - case EvqInvariantVaryingIn: return sw::Shader::PARAMETER_INPUT; // FIXME: Guarantee invariance at the backend - case EvqInvariantVaryingOut: return sw::Shader::PARAMETER_OUTPUT; // FIXME: Guarantee invariance at the backend - case EvqSmooth: return sw::Shader::PARAMETER_OUTPUT; - case EvqFlat: return sw::Shader::PARAMETER_OUTPUT; - case EvqCentroidOut: return sw::Shader::PARAMETER_OUTPUT; - case EvqSmoothIn: return sw::Shader::PARAMETER_INPUT; - case EvqFlatIn: return sw::Shader::PARAMETER_INPUT; - case EvqCentroidIn: return sw::Shader::PARAMETER_INPUT; - case EvqUniform: return sw::Shader::PARAMETER_CONST; - case EvqIn: return sw::Shader::PARAMETER_TEMP; - case EvqOut: return sw::Shader::PARAMETER_TEMP; - case EvqInOut: return sw::Shader::PARAMETER_TEMP; - case EvqConstReadOnly: return sw::Shader::PARAMETER_TEMP; - case EvqPosition: return sw::Shader::PARAMETER_OUTPUT; - case EvqPointSize: return sw::Shader::PARAMETER_OUTPUT; - case EvqInstanceID: return sw::Shader::PARAMETER_MISCTYPE; - case EvqFragCoord: return sw::Shader::PARAMETER_MISCTYPE; - case EvqFrontFacing: return sw::Shader::PARAMETER_MISCTYPE; - case EvqPointCoord: return sw::Shader::PARAMETER_INPUT; - case EvqFragColor: return sw::Shader::PARAMETER_COLOROUT; - case EvqFragData: return sw::Shader::PARAMETER_COLOROUT; - case EvqFragDepth: return sw::Shader::PARAMETER_DEPTHOUT; - default: UNREACHABLE(qualifier); - } - - return sw::Shader::PARAMETER_VOID; - } - - unsigned int OutputASM::registerIndex(TIntermTyped *operand) - { - if(isSamplerRegister(operand)) - { - return samplerRegister(operand); - } - - switch(operand->getQualifier()) - { - case EvqTemporary: return temporaryRegister(operand); - case EvqGlobal: return temporaryRegister(operand); - case EvqConstExpr: return temporaryRegister(operand); // Unevaluated constant expression - case EvqAttribute: return attributeRegister(operand); - case EvqVaryingIn: return varyingRegister(operand); - case EvqVaryingOut: return varyingRegister(operand); - case EvqVertexIn: return attributeRegister(operand); - case EvqFragmentOut: return fragmentOutputRegister(operand); - case EvqVertexOut: return varyingRegister(operand); - case EvqFragmentIn: return varyingRegister(operand); - case EvqInvariantVaryingIn: return varyingRegister(operand); - case EvqInvariantVaryingOut: return varyingRegister(operand); - case EvqSmooth: return varyingRegister(operand); - case EvqFlat: return varyingRegister(operand); - case EvqCentroidOut: return varyingRegister(operand); - case EvqSmoothIn: return varyingRegister(operand); - case EvqFlatIn: return varyingRegister(operand); - case EvqCentroidIn: return varyingRegister(operand); - case EvqUniform: return uniformRegister(operand); - case EvqIn: return temporaryRegister(operand); - case EvqOut: return temporaryRegister(operand); - case EvqInOut: return temporaryRegister(operand); - case EvqConstReadOnly: return temporaryRegister(operand); - case EvqPosition: return varyingRegister(operand); - case EvqPointSize: return varyingRegister(operand); - case EvqInstanceID: vertexShader->instanceIdDeclared = true; return 0; - case EvqFragCoord: pixelShader->vPosDeclared = true; return 0; - case EvqFrontFacing: pixelShader->vFaceDeclared = true; return 1; - case EvqPointCoord: return varyingRegister(operand); - case EvqFragColor: return 0; - case EvqFragData: return fragmentOutputRegister(operand); - case EvqFragDepth: return 0; - default: UNREACHABLE(operand->getQualifier()); - } - - return 0; - } - - int OutputASM::writeMask(TIntermTyped *destination, int index) - { - if(destination->getQualifier() == EvqPointSize) - { - return 0x2; // Point size stored in the y component - } - - return 0xF >> (4 - registerSize(destination->getType(), index)); - } - - int OutputASM::readSwizzle(TIntermTyped *argument, int size) - { - if(argument->getQualifier() == EvqPointSize) - { - return 0x55; // Point size stored in the y component - } - - static const unsigned char swizzleSize[5] = {0x00, 0x00, 0x54, 0xA4, 0xE4}; // (void), xxxx, xyyy, xyzz, xyzw - - return swizzleSize[size]; - } - - // Conservatively checks whether an expression is fast to compute and has no side effects - bool OutputASM::trivial(TIntermTyped *expression, int budget) - { - if(!expression->isRegister()) - { - return false; - } - - return cost(expression, budget) >= 0; - } - - // Returns the remaining computing budget (if < 0 the expression is too expensive or has side effects) - int OutputASM::cost(TIntermNode *expression, int budget) - { - if(budget < 0) - { - return budget; - } - - if(expression->getAsSymbolNode()) - { - return budget; - } - else if(expression->getAsConstantUnion()) - { - return budget; - } - else if(expression->getAsBinaryNode()) - { - TIntermBinary *binary = expression->getAsBinaryNode(); - - switch(binary->getOp()) - { - case EOpVectorSwizzle: - case EOpIndexDirect: - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: - return cost(binary->getLeft(), budget - 0); - case EOpAdd: - case EOpSub: - case EOpMul: - return cost(binary->getLeft(), cost(binary->getRight(), budget - 1)); - default: - return -1; - } - } - else if(expression->getAsUnaryNode()) - { - TIntermUnary *unary = expression->getAsUnaryNode(); - - switch(unary->getOp()) - { - case EOpAbs: - case EOpNegative: - return cost(unary->getOperand(), budget - 1); - default: - return -1; - } - } - else if(expression->getAsSelectionNode()) - { - TIntermSelection *selection = expression->getAsSelectionNode(); - - if(selection->usesTernaryOperator()) - { - TIntermTyped *condition = selection->getCondition(); - TIntermNode *trueBlock = selection->getTrueBlock(); - TIntermNode *falseBlock = selection->getFalseBlock(); - TIntermConstantUnion *constantCondition = condition->getAsConstantUnion(); - - if(constantCondition) - { - bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst(); - - if(trueCondition) - { - return cost(trueBlock, budget - 0); - } - else - { - return cost(falseBlock, budget - 0); - } - } - else - { - return cost(trueBlock, cost(falseBlock, budget - 2)); - } - } - } - - return -1; - } - - const Function *OutputASM::findFunction(const TString &name) - { - for(unsigned int f = 0; f < functionArray.size(); f++) - { - if(functionArray[f].name == name) - { - return &functionArray[f]; - } - } - - return 0; - } - - int OutputASM::temporaryRegister(TIntermTyped *temporary) - { - return allocate(temporaries, temporary); - } - - int OutputASM::varyingRegister(TIntermTyped *varying) - { - int var = lookup(varyings, varying); - - if(var == -1) - { - var = allocate(varyings, varying); - int componentCount = varying->registerSize(); - int registerCount = varying->totalRegisterCount(); - - if(pixelShader) - { - if((var + registerCount) > sw::PixelShader::MAX_INPUT_VARYINGS) - { - mContext.error(varying->getLine(), "Varyings packing failed: Too many varyings", "fragment shader"); - return 0; - } - - if(varying->getQualifier() == EvqPointCoord) - { - ASSERT(varying->isRegister()); - if(componentCount >= 1) pixelShader->semantic[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var); - if(componentCount >= 2) pixelShader->semantic[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var); - if(componentCount >= 3) pixelShader->semantic[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var); - if(componentCount >= 4) pixelShader->semantic[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var); - } - else - { - for(int i = 0; i < varying->totalRegisterCount(); i++) - { - if(componentCount >= 1) pixelShader->semantic[var + i][0] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i); - if(componentCount >= 2) pixelShader->semantic[var + i][1] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i); - if(componentCount >= 3) pixelShader->semantic[var + i][2] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i); - if(componentCount >= 4) pixelShader->semantic[var + i][3] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i); - } - } - } - else if(vertexShader) - { - if((var + registerCount) > sw::VertexShader::MAX_OUTPUT_VARYINGS) - { - mContext.error(varying->getLine(), "Varyings packing failed: Too many varyings", "vertex shader"); - return 0; - } - - if(varying->getQualifier() == EvqPosition) - { - ASSERT(varying->isRegister()); - vertexShader->output[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0); - vertexShader->output[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0); - vertexShader->output[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0); - vertexShader->output[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0); - vertexShader->positionRegister = var; - } - else if(varying->getQualifier() == EvqPointSize) - { - ASSERT(varying->isRegister()); - vertexShader->output[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0); - vertexShader->output[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0); - vertexShader->output[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0); - vertexShader->output[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0); - vertexShader->pointSizeRegister = var; - } - else - { - // Semantic indexes for user varyings will be assigned during program link to match the pixel shader - } - } - else UNREACHABLE(0); - - declareVarying(varying, var); - } - - return var; - } - - void OutputASM::declareVarying(TIntermTyped *varying, int reg) - { - if(varying->getQualifier() != EvqPointCoord) // gl_PointCoord does not need linking - { - const TType &type = varying->getType(); - const char *name = varying->getAsSymbolNode()->getSymbol().c_str(); - VaryingList &activeVaryings = shaderObject->varyings; - - // Check if this varying has been declared before without having a register assigned - for(VaryingList::iterator v = activeVaryings.begin(); v != activeVaryings.end(); v++) - { - if(v->name == name) - { - if(reg >= 0) - { - ASSERT(v->reg < 0 || v->reg == reg); - v->reg = reg; - } - - return; - } - } - - activeVaryings.push_back(glsl::Varying(glVariableType(type), name, varying->getArraySize(), reg, 0)); - } - } - - int OutputASM::uniformRegister(TIntermTyped *uniform) - { - const TType &type = uniform->getType(); - ASSERT(!IsSampler(type.getBasicType())); - TInterfaceBlock *block = type.getAsInterfaceBlock(); - TIntermSymbol *symbol = uniform->getAsSymbolNode(); - ASSERT(symbol || block); - - if(symbol || block) - { - TInterfaceBlock* parentBlock = type.getInterfaceBlock(); - bool isBlockMember = (!block && parentBlock); - int index = isBlockMember ? lookup(uniforms, parentBlock) : lookup(uniforms, uniform); - - if(index == -1 || isBlockMember) - { - if(index == -1) - { - index = allocate(uniforms, uniform); - } - - // Verify if the current uniform is a member of an already declared block - const TString &name = symbol ? symbol->getSymbol() : block->name(); - int blockMemberIndex = blockMemberLookup(type, name, index); - if(blockMemberIndex == -1) - { - declareUniform(type, name, index); - } - else - { - index = blockMemberIndex; - } - } - - return index; - } - - return 0; - } - - int OutputASM::attributeRegister(TIntermTyped *attribute) - { - ASSERT(!attribute->isArray()); - - int index = lookup(attributes, attribute); - - if(index == -1) - { - TIntermSymbol *symbol = attribute->getAsSymbolNode(); - ASSERT(symbol); - - if(symbol) - { - index = allocate(attributes, attribute); - const TType &type = attribute->getType(); - int registerCount = attribute->totalRegisterCount(); - - if(vertexShader && (index + registerCount) <= sw::VertexShader::MAX_INPUT_ATTRIBUTES) - { - for(int i = 0; i < registerCount; i++) - { - vertexShader->input[index + i] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, index + i); - } - } - - ActiveAttributes &activeAttributes = shaderObject->activeAttributes; - - const char *name = symbol->getSymbol().c_str(); - activeAttributes.push_back(Attribute(glVariableType(type), name, type.getArraySize(), type.getLayoutQualifier().location, index)); - } - } - - return index; - } - - int OutputASM::fragmentOutputRegister(TIntermTyped *fragmentOutput) - { - return allocate(fragmentOutputs, fragmentOutput); - } - - int OutputASM::samplerRegister(TIntermTyped *sampler) - { - const TType &type = sampler->getType(); - ASSERT(IsSampler(type.getBasicType()) || type.isStruct()); // Structures can contain samplers - - TIntermSymbol *symbol = sampler->getAsSymbolNode(); - TIntermBinary *binary = sampler->getAsBinaryNode(); - - if(symbol && type.getQualifier() == EvqUniform) - { - return samplerRegister(symbol); - } - else if(binary) - { - TIntermTyped *left = binary->getLeft(); - TIntermTyped *right = binary->getRight(); - const TType &leftType = left->getType(); - int index = right->getAsConstantUnion() ? right->getAsConstantUnion()->getIConst(0) : 0; - int offset = 0; - - switch(binary->getOp()) - { - case EOpIndexDirect: - ASSERT(left->isArray()); - offset = index * leftType.elementRegisterCount(); - break; - case EOpIndexDirectStruct: - ASSERT(leftType.isStruct()); - { - const TFieldList &fields = leftType.getStruct()->fields(); - - for(int i = 0; i < index; i++) - { - offset += fields[i]->type()->totalRegisterCount(); - } - } - break; - case EOpIndexIndirect: // Indirect indexing produces a temporary, not a sampler register - return -1; - case EOpIndexDirectInterfaceBlock: // Interface blocks can't contain samplers - default: - UNREACHABLE(binary->getOp()); - return -1; - } - - int base = samplerRegister(left); - - if(base < 0) - { - return -1; - } - - return base + offset; - } - - UNREACHABLE(0); - return -1; // Not a sampler register - } - - int OutputASM::samplerRegister(TIntermSymbol *sampler) - { - const TType &type = sampler->getType(); - ASSERT(IsSampler(type.getBasicType()) || type.isStruct()); // Structures can contain samplers - - int index = lookup(samplers, sampler); - - if(index == -1) - { - index = allocate(samplers, sampler); - - if(sampler->getQualifier() == EvqUniform) - { - const char *name = sampler->getSymbol().c_str(); - declareUniform(type, name, index); - } - } - - return index; - } - - bool OutputASM::isSamplerRegister(TIntermTyped *operand) - { - return operand && IsSampler(operand->getBasicType()) && samplerRegister(operand) >= 0; - } - - int OutputASM::lookup(VariableArray &list, TIntermTyped *variable) - { - for(unsigned int i = 0; i < list.size(); i++) - { - if(list[i] == variable) - { - return i; // Pointer match - } - } - - TIntermSymbol *varSymbol = variable->getAsSymbolNode(); - TInterfaceBlock *varBlock = variable->getType().getAsInterfaceBlock(); - - if(varBlock) - { - for(unsigned int i = 0; i < list.size(); i++) - { - if(list[i]) - { - TInterfaceBlock *listBlock = list[i]->getType().getAsInterfaceBlock(); - - if(listBlock) - { - if(listBlock->name() == varBlock->name()) - { - ASSERT(listBlock->arraySize() == varBlock->arraySize()); - ASSERT(listBlock->fields() == varBlock->fields()); - ASSERT(listBlock->blockStorage() == varBlock->blockStorage()); - ASSERT(listBlock->matrixPacking() == varBlock->matrixPacking()); - - return i; - } - } - } - } - } - else if(varSymbol) - { - for(unsigned int i = 0; i < list.size(); i++) - { - if(list[i]) - { - TIntermSymbol *listSymbol = list[i]->getAsSymbolNode(); - - if(listSymbol) - { - if(listSymbol->getId() == varSymbol->getId()) - { - ASSERT(listSymbol->getSymbol() == varSymbol->getSymbol()); - ASSERT(listSymbol->getType() == varSymbol->getType()); - ASSERT(listSymbol->getQualifier() == varSymbol->getQualifier()); - - return i; - } - } - } - } - } - - return -1; - } - - int OutputASM::lookup(VariableArray &list, TInterfaceBlock *block) - { - for(unsigned int i = 0; i < list.size(); i++) - { - if(list[i] && (list[i]->getType().getInterfaceBlock() == block)) - { - return i; // Pointer match - } - } - return -1; - } - - int OutputASM::allocate(VariableArray &list, TIntermTyped *variable) - { - int index = lookup(list, variable); - - if(index == -1) - { - unsigned int registerCount = variable->blockRegisterCount(); - - for(unsigned int i = 0; i < list.size(); i++) - { - if(list[i] == 0) - { - unsigned int j = 1; - for( ; j < registerCount && (i + j) < list.size(); j++) - { - if(list[i + j] != 0) - { - break; - } - } - - if(j == registerCount) // Found free slots - { - for(unsigned int j = 0; j < registerCount; j++) - { - list[i + j] = variable; - } - - return i; - } - } - } - - index = list.size(); - - for(unsigned int i = 0; i < registerCount; i++) - { - list.push_back(variable); - } - } - - return index; - } - - void OutputASM::free(VariableArray &list, TIntermTyped *variable) - { - int index = lookup(list, variable); - - if(index >= 0) - { - list[index] = 0; - } - } - - int OutputASM::blockMemberLookup(const TType &type, const TString &name, int registerIndex) - { - const TInterfaceBlock *block = type.getInterfaceBlock(); - - if(block) - { - ActiveUniformBlocks &activeUniformBlocks = shaderObject->activeUniformBlocks; - const TFieldList& fields = block->fields(); - const TString &blockName = block->name(); - int fieldRegisterIndex = registerIndex; - - if(!type.isInterfaceBlock()) - { - // This is a uniform that's part of a block, let's see if the block is already defined - for(size_t i = 0; i < activeUniformBlocks.size(); ++i) - { - if(activeUniformBlocks[i].name == blockName.c_str()) - { - // The block is already defined, find the register for the current uniform and return it - for(size_t j = 0; j < fields.size(); j++) - { - const TString &fieldName = fields[j]->name(); - if(fieldName == name) - { - return fieldRegisterIndex; - } - - fieldRegisterIndex += fields[j]->type()->totalRegisterCount(); - } - - ASSERT(false); - return fieldRegisterIndex; - } - } - } - } - - return -1; - } - - void OutputASM::declareUniform(const TType &type, const TString &name, int registerIndex, int blockId, BlockLayoutEncoder* encoder) - { - const TStructure *structure = type.getStruct(); - const TInterfaceBlock *block = (type.isInterfaceBlock() || (blockId == -1)) ? type.getInterfaceBlock() : nullptr; - - if(!structure && !block) - { - ActiveUniforms &activeUniforms = shaderObject->activeUniforms; - const BlockMemberInfo blockInfo = encoder ? encoder->encodeType(type) : BlockMemberInfo::getDefaultBlockInfo(); - if(blockId >= 0) - { - blockDefinitions[blockId][registerIndex] = TypedMemberInfo(blockInfo, type); - shaderObject->activeUniformBlocks[blockId].fields.push_back(activeUniforms.size()); - } - int fieldRegisterIndex = encoder ? shaderObject->activeUniformBlocks[blockId].registerIndex + BlockLayoutEncoder::getBlockRegister(blockInfo) : registerIndex; - activeUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), - fieldRegisterIndex, blockId, blockInfo)); - if(IsSampler(type.getBasicType())) - { - for(int i = 0; i < type.totalRegisterCount(); i++) - { - shader->declareSampler(fieldRegisterIndex + i); - } - } - } - else if(block) - { - ActiveUniformBlocks &activeUniformBlocks = shaderObject->activeUniformBlocks; - const TFieldList& fields = block->fields(); - const TString &blockName = block->name(); - int fieldRegisterIndex = registerIndex; - bool isUniformBlockMember = !type.isInterfaceBlock() && (blockId == -1); - - blockId = activeUniformBlocks.size(); - bool isRowMajor = block->matrixPacking() == EmpRowMajor; - activeUniformBlocks.push_back(UniformBlock(blockName.c_str(), 0, block->arraySize(), - block->blockStorage(), isRowMajor, registerIndex, blockId)); - blockDefinitions.push_back(BlockDefinitionIndexMap()); - - Std140BlockEncoder currentBlockEncoder(isRowMajor); - currentBlockEncoder.enterAggregateType(); - for(size_t i = 0; i < fields.size(); i++) - { - const TType &fieldType = *(fields[i]->type()); - const TString &fieldName = fields[i]->name(); - if(isUniformBlockMember && (fieldName == name)) - { - registerIndex = fieldRegisterIndex; - } - - const TString uniformName = block->hasInstanceName() ? blockName + "." + fieldName : fieldName; - - declareUniform(fieldType, uniformName, fieldRegisterIndex, blockId, ¤tBlockEncoder); - fieldRegisterIndex += fieldType.totalRegisterCount(); - } - currentBlockEncoder.exitAggregateType(); - activeUniformBlocks[blockId].dataSize = currentBlockEncoder.getBlockSize(); - } - else - { - int fieldRegisterIndex = registerIndex; - - const TFieldList& fields = structure->fields(); - if(type.isArray() && (structure || type.isInterfaceBlock())) - { - for(int i = 0; i < type.getArraySize(); i++) - { - if(encoder) - { - encoder->enterAggregateType(); - } - for(size_t j = 0; j < fields.size(); j++) - { - const TType &fieldType = *(fields[j]->type()); - const TString &fieldName = fields[j]->name(); - const TString uniformName = name + "[" + str(i) + "]." + fieldName; - - declareUniform(fieldType, uniformName, fieldRegisterIndex, blockId, encoder); - fieldRegisterIndex += fieldType.totalRegisterCount(); - } - if(encoder) - { - encoder->exitAggregateType(); - } - } - } - else - { - if(encoder) - { - encoder->enterAggregateType(); - } - for(size_t i = 0; i < fields.size(); i++) - { - const TType &fieldType = *(fields[i]->type()); - const TString &fieldName = fields[i]->name(); - const TString uniformName = name + "." + fieldName; - - declareUniform(fieldType, uniformName, fieldRegisterIndex, blockId, encoder); - fieldRegisterIndex += fieldType.totalRegisterCount(); - } - if(encoder) - { - encoder->exitAggregateType(); - } - } - } - } - - GLenum OutputASM::glVariableType(const TType &type) - { - switch(type.getBasicType()) - { - case EbtFloat: - if(type.isScalar()) - { - return GL_FLOAT; - } - else if(type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_FLOAT_VEC2; - case 3: return GL_FLOAT_VEC3; - case 4: return GL_FLOAT_VEC4; - default: UNREACHABLE(type.getNominalSize()); - } - } - else if(type.isMatrix()) - { - switch(type.getNominalSize()) - { - case 2: - switch(type.getSecondarySize()) - { - case 2: return GL_FLOAT_MAT2; - case 3: return GL_FLOAT_MAT2x3; - case 4: return GL_FLOAT_MAT2x4; - default: UNREACHABLE(type.getSecondarySize()); - } - case 3: - switch(type.getSecondarySize()) - { - case 2: return GL_FLOAT_MAT3x2; - case 3: return GL_FLOAT_MAT3; - case 4: return GL_FLOAT_MAT3x4; - default: UNREACHABLE(type.getSecondarySize()); - } - case 4: - switch(type.getSecondarySize()) - { - case 2: return GL_FLOAT_MAT4x2; - case 3: return GL_FLOAT_MAT4x3; - case 4: return GL_FLOAT_MAT4; - default: UNREACHABLE(type.getSecondarySize()); - } - default: UNREACHABLE(type.getNominalSize()); - } - } - else UNREACHABLE(0); - break; - case EbtInt: - if(type.isScalar()) - { - return GL_INT; - } - else if(type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_INT_VEC2; - case 3: return GL_INT_VEC3; - case 4: return GL_INT_VEC4; - default: UNREACHABLE(type.getNominalSize()); - } - } - else UNREACHABLE(0); - break; - case EbtUInt: - if(type.isScalar()) - { - return GL_UNSIGNED_INT; - } - else if(type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_UNSIGNED_INT_VEC2; - case 3: return GL_UNSIGNED_INT_VEC3; - case 4: return GL_UNSIGNED_INT_VEC4; - default: UNREACHABLE(type.getNominalSize()); - } - } - else UNREACHABLE(0); - break; - case EbtBool: - if(type.isScalar()) - { - return GL_BOOL; - } - else if(type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_BOOL_VEC2; - case 3: return GL_BOOL_VEC3; - case 4: return GL_BOOL_VEC4; - default: UNREACHABLE(type.getNominalSize()); - } - } - else UNREACHABLE(0); - break; - case EbtSampler2D: - return GL_SAMPLER_2D; - case EbtISampler2D: - return GL_INT_SAMPLER_2D; - case EbtUSampler2D: - return GL_UNSIGNED_INT_SAMPLER_2D; - case EbtSamplerCube: - return GL_SAMPLER_CUBE; - case EbtISamplerCube: - return GL_INT_SAMPLER_CUBE; - case EbtUSamplerCube: - return GL_UNSIGNED_INT_SAMPLER_CUBE; - case EbtSamplerExternalOES: - return GL_SAMPLER_EXTERNAL_OES; - case EbtSampler3D: - return GL_SAMPLER_3D_OES; - case EbtISampler3D: - return GL_INT_SAMPLER_3D; - case EbtUSampler3D: - return GL_UNSIGNED_INT_SAMPLER_3D; - case EbtSampler2DArray: - return GL_SAMPLER_2D_ARRAY; - case EbtISampler2DArray: - return GL_INT_SAMPLER_2D_ARRAY; - case EbtUSampler2DArray: - return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; - case EbtSampler2DShadow: - return GL_SAMPLER_2D_SHADOW; - case EbtSamplerCubeShadow: - return GL_SAMPLER_CUBE_SHADOW; - case EbtSampler2DArrayShadow: - return GL_SAMPLER_2D_ARRAY_SHADOW; - default: - UNREACHABLE(type.getBasicType()); - break; - } - - return GL_NONE; - } - - GLenum OutputASM::glVariablePrecision(const TType &type) - { - if(type.getBasicType() == EbtFloat) - { - switch(type.getPrecision()) - { - case EbpHigh: return GL_HIGH_FLOAT; - case EbpMedium: return GL_MEDIUM_FLOAT; - case EbpLow: return GL_LOW_FLOAT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: UNREACHABLE(type.getPrecision()); - } - } - else if(type.getBasicType() == EbtInt) - { - switch(type.getPrecision()) - { - case EbpHigh: return GL_HIGH_INT; - case EbpMedium: return GL_MEDIUM_INT; - case EbpLow: return GL_LOW_INT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: UNREACHABLE(type.getPrecision()); - } - } - - // Other types (boolean, sampler) don't have a precision - return GL_NONE; - } - - int OutputASM::dim(TIntermNode *v) - { - TIntermTyped *vector = v->getAsTyped(); - ASSERT(vector && vector->isRegister()); - return vector->getNominalSize(); - } - - int OutputASM::dim2(TIntermNode *m) - { - TIntermTyped *matrix = m->getAsTyped(); - ASSERT(matrix && matrix->isMatrix() && !matrix->isArray()); - return matrix->getSecondarySize(); - } - - // Returns ~0u if no loop count could be determined - unsigned int OutputASM::loopCount(TIntermLoop *node) - { - // Parse loops of the form: - // for(int index = initial; index [comparator] limit; index += increment) - TIntermSymbol *index = 0; - TOperator comparator = EOpNull; - int initial = 0; - int limit = 0; - int increment = 0; - - // Parse index name and intial value - if(node->getInit()) - { - TIntermAggregate *init = node->getInit()->getAsAggregate(); - - if(init) - { - TIntermSequence &sequence = init->getSequence(); - TIntermTyped *variable = sequence[0]->getAsTyped(); - - if(variable && variable->getQualifier() == EvqTemporary) - { - TIntermBinary *assign = variable->getAsBinaryNode(); - - if(assign->getOp() == EOpInitialize) - { - TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); - TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); - - if(symbol && constant) - { - if(constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) - { - index = symbol; - initial = constant->getUnionArrayPointer()[0].getIConst(); - } - } - } - } - } - } - - // Parse comparator and limit value - if(index && node->getCondition()) - { - TIntermBinary *test = node->getCondition()->getAsBinaryNode(); - - if(test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) - { - TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); - - if(constant) - { - if(constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) - { - comparator = test->getOp(); - limit = constant->getUnionArrayPointer()[0].getIConst(); - } - } - } - } - - // Parse increment - if(index && comparator != EOpNull && node->getExpression()) - { - TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); - TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); - - if(binaryTerminal) - { - TOperator op = binaryTerminal->getOp(); - TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); - - if(constant) - { - if(constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) - { - int value = constant->getUnionArrayPointer()[0].getIConst(); - - switch(op) - { - case EOpAddAssign: increment = value; break; - case EOpSubAssign: increment = -value; break; - default: UNIMPLEMENTED(); - } - } - } - } - else if(unaryTerminal) - { - TOperator op = unaryTerminal->getOp(); - - switch(op) - { - case EOpPostIncrement: increment = 1; break; - case EOpPostDecrement: increment = -1; break; - case EOpPreIncrement: increment = 1; break; - case EOpPreDecrement: increment = -1; break; - default: UNIMPLEMENTED(); - } - } - } - - if(index && comparator != EOpNull && increment != 0) - { - if(comparator == EOpLessThanEqual) - { - comparator = EOpLessThan; - limit += 1; - } - - if(comparator == EOpLessThan) - { - int iterations = (limit - initial) / increment; - - if(iterations <= 0) - { - iterations = 0; - } - - return iterations; - } - else UNIMPLEMENTED(); // Falls through - } - - return ~0u; - } - - bool LoopUnrollable::traverse(TIntermNode *node) - { - loopDepth = 0; - loopUnrollable = true; - - node->traverse(this); - - return loopUnrollable; - } - - bool LoopUnrollable::visitLoop(Visit visit, TIntermLoop *loop) - { - if(visit == PreVisit) - { - loopDepth++; - } - else if(visit == PostVisit) - { - loopDepth++; - } - - return true; - } - - bool LoopUnrollable::visitBranch(Visit visit, TIntermBranch *node) - { - if(!loopUnrollable) - { - return false; - } - - if(!loopDepth) - { - return true; - } - - switch(node->getFlowOp()) - { - case EOpKill: - case EOpReturn: - break; - case EOpBreak: - case EOpContinue: - loopUnrollable = false; - break; - default: UNREACHABLE(node->getFlowOp()); - } - - return loopUnrollable; - } - - bool LoopUnrollable::visitAggregate(Visit visit, TIntermAggregate *node) - { - return loopUnrollable; - } -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "OutputASM.h" +#include "Common/Math.hpp" + +#include "common/debug.h" +#include "InfoSink.h" + +#include "libGLESv2/Shader.h" + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <GLES3/gl3.h> + +namespace glsl +{ + // Integer to TString conversion + TString str(int i) + { + char buffer[20]; + sprintf(buffer, "%d", i); + return buffer; + } + + class Temporary : public TIntermSymbol + { + public: + Temporary(OutputASM *assembler) : TIntermSymbol(TSymbolTableLevel::nextUniqueId(), "tmp", TType(EbtFloat, EbpHigh, EvqTemporary, 4, 1, false)), assembler(assembler) + { + } + + ~Temporary() + { + assembler->freeTemporary(this); + } + + private: + OutputASM *const assembler; + }; + + class Constant : public TIntermConstantUnion + { + public: + Constant(float x, float y, float z, float w) : TIntermConstantUnion(constants, TType(EbtFloat, EbpHigh, EvqConstExpr, 4, 1, false)) + { + constants[0].setFConst(x); + constants[1].setFConst(y); + constants[2].setFConst(z); + constants[3].setFConst(w); + } + + Constant(bool b) : TIntermConstantUnion(constants, TType(EbtBool, EbpHigh, EvqConstExpr, 1, 1, false)) + { + constants[0].setBConst(b); + } + + Constant(int i) : TIntermConstantUnion(constants, TType(EbtInt, EbpHigh, EvqConstExpr, 1, 1, false)) + { + constants[0].setIConst(i); + } + + ~Constant() + { + } + + private: + ConstantUnion constants[4]; + }; + + Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, int arraySize, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo) : + type(type), precision(precision), name(name), arraySize(arraySize), registerIndex(registerIndex), blockId(blockId), blockInfo(blockMemberInfo) + { + } + + UniformBlock::UniformBlock(const std::string& name, unsigned int dataSize, unsigned int arraySize, + TLayoutBlockStorage layout, bool isRowMajorLayout, int registerIndex, int blockId) : + name(name), dataSize(dataSize), arraySize(arraySize), layout(layout), + isRowMajorLayout(isRowMajorLayout), registerIndex(registerIndex), blockId(blockId) + { + } + + BlockLayoutEncoder::BlockLayoutEncoder(bool rowMajor) + : mCurrentOffset(0), isRowMajor(rowMajor) + { + } + + BlockMemberInfo BlockLayoutEncoder::encodeType(const TType &type) + { + int arrayStride; + int matrixStride; + + getBlockLayoutInfo(type, type.getArraySize(), isRowMajor, &arrayStride, &matrixStride); + + const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent), + static_cast<int>(arrayStride * BytesPerComponent), + static_cast<int>(matrixStride * BytesPerComponent), + (matrixStride > 0) && isRowMajor); + + advanceOffset(type, type.getArraySize(), isRowMajor, arrayStride, matrixStride); + + return memberInfo; + } + + // static + size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info) + { + return (info.offset / BytesPerComponent) / ComponentsPerRegister; + } + + // static + size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info) + { + return (info.offset / BytesPerComponent) % ComponentsPerRegister; + } + + void BlockLayoutEncoder::nextRegister() + { + mCurrentOffset = sw::align(mCurrentOffset, ComponentsPerRegister); + } + + Std140BlockEncoder::Std140BlockEncoder(bool rowMajor) : BlockLayoutEncoder(rowMajor) + { + } + + void Std140BlockEncoder::enterAggregateType() + { + nextRegister(); + } + + void Std140BlockEncoder::exitAggregateType() + { + nextRegister(); + } + + void Std140BlockEncoder::getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) + { + size_t baseAlignment = 0; + int matrixStride = 0; + int arrayStride = 0; + + if(type.isMatrix()) + { + baseAlignment = ComponentsPerRegister; + matrixStride = ComponentsPerRegister; + + if(arraySize > 0) + { + const int numRegisters = isRowMajorMatrix ? type.getSecondarySize() : type.getNominalSize(); + arrayStride = ComponentsPerRegister * numRegisters; + } + } + else if(arraySize > 0) + { + baseAlignment = ComponentsPerRegister; + arrayStride = ComponentsPerRegister; + } + else + { + const size_t numComponents = type.getElementSize(); + baseAlignment = (numComponents == 3 ? 4u : numComponents); + } + + mCurrentOffset = sw::align(mCurrentOffset, baseAlignment); + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; + } + + void Std140BlockEncoder::advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) + { + if(arraySize > 0) + { + mCurrentOffset += arrayStride * arraySize; + } + else if(type.isMatrix()) + { + ASSERT(matrixStride == ComponentsPerRegister); + const int numRegisters = isRowMajorMatrix ? type.getSecondarySize() : type.getNominalSize(); + mCurrentOffset += ComponentsPerRegister * numRegisters; + } + else + { + mCurrentOffset += type.getElementSize(); + } + } + + Attribute::Attribute() + { + type = GL_NONE; + arraySize = 0; + registerIndex = 0; + } + + Attribute::Attribute(GLenum type, const std::string &name, int arraySize, int location, int registerIndex) + { + this->type = type; + this->name = name; + this->arraySize = arraySize; + this->location = location; + this->registerIndex = registerIndex; + } + + sw::PixelShader *Shader::getPixelShader() const + { + return 0; + } + + sw::VertexShader *Shader::getVertexShader() const + { + return 0; + } + + OutputASM::TextureFunction::TextureFunction(const TString& nodeName) : method(IMPLICIT), proj(false), offset(false) + { + TString name = TFunction::unmangleName(nodeName); + + if(name == "texture2D" || name == "textureCube" || name == "texture" || name == "texture3D") + { + method = IMPLICIT; + } + else if(name == "texture2DProj" || name == "textureProj") + { + method = IMPLICIT; + proj = true; + } + else if(name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod") + { + method = LOD; + } + else if(name == "texture2DProjLod" || name == "textureProjLod") + { + method = LOD; + proj = true; + } + else if(name == "textureSize") + { + method = SIZE; + } + else if(name == "textureOffset") + { + method = IMPLICIT; + offset = true; + } + else if(name == "textureProjOffset") + { + method = IMPLICIT; + offset = true; + proj = true; + } + else if(name == "textureLodOffset") + { + method = LOD; + offset = true; + } + else if(name == "textureProjLodOffset") + { + method = LOD; + proj = true; + offset = true; + } + else if(name == "texelFetch") + { + method = FETCH; + } + else if(name == "texelFetchOffset") + { + method = FETCH; + offset = true; + } + else if(name == "textureGrad") + { + method = GRAD; + } + else if(name == "textureGradOffset") + { + method = GRAD; + offset = true; + } + else if(name == "textureProjGrad") + { + method = GRAD; + proj = true; + } + else if(name == "textureProjGradOffset") + { + method = GRAD; + proj = true; + offset = true; + } + else UNREACHABLE(0); + } + + OutputASM::OutputASM(TParseContext &context, Shader *shaderObject) : TIntermTraverser(true, true, true), shaderObject(shaderObject), mContext(context) + { + shader = 0; + pixelShader = 0; + vertexShader = 0; + + if(shaderObject) + { + shader = shaderObject->getShader(); + pixelShader = shaderObject->getPixelShader(); + vertexShader = shaderObject->getVertexShader(); + } + + functionArray.push_back(Function(0, "main(", 0, 0)); + currentFunction = 0; + outputQualifier = EvqOutput; // Set outputQualifier to any value other than EvqFragColor or EvqFragData + } + + OutputASM::~OutputASM() + { + } + + void OutputASM::output() + { + if(shader) + { + emitShader(GLOBAL); + + if(functionArray.size() > 1) // Only call main() when there are other functions + { + Instruction *callMain = emit(sw::Shader::OPCODE_CALL); + callMain->dst.type = sw::Shader::PARAMETER_LABEL; + callMain->dst.index = 0; // main() + + emit(sw::Shader::OPCODE_RET); + } + + emitShader(FUNCTION); + } + } + + void OutputASM::emitShader(Scope scope) + { + emitScope = scope; + currentScope = GLOBAL; + mContext.getTreeRoot()->traverse(this); + } + + void OutputASM::freeTemporary(Temporary *temporary) + { + free(temporaries, temporary); + } + + sw::Shader::Opcode OutputASM::getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const + { + TBasicType baseType = in->getType().getBasicType(); + + switch(op) + { + case sw::Shader::OPCODE_NEG: + switch(baseType) + { + case EbtInt: + case EbtUInt: + return sw::Shader::OPCODE_INEG; + case EbtFloat: + default: + return op; + } + case sw::Shader::OPCODE_ABS: + switch(baseType) + { + case EbtInt: + return sw::Shader::OPCODE_IABS; + case EbtFloat: + default: + return op; + } + case sw::Shader::OPCODE_SGN: + switch(baseType) + { + case EbtInt: + return sw::Shader::OPCODE_ISGN; + case EbtFloat: + default: + return op; + } + case sw::Shader::OPCODE_ADD: + switch(baseType) + { + case EbtInt: + case EbtUInt: + return sw::Shader::OPCODE_IADD; + case EbtFloat: + default: + return op; + } + case sw::Shader::OPCODE_SUB: + switch(baseType) + { + case EbtInt: + case EbtUInt: + return sw::Shader::OPCODE_ISUB; + case EbtFloat: + default: + return op; + } + case sw::Shader::OPCODE_MUL: + switch(baseType) + { + case EbtInt: + case EbtUInt: + return sw::Shader::OPCODE_IMUL; + case EbtFloat: + default: + return op; + } + case sw::Shader::OPCODE_DIV: + switch(baseType) + { + case EbtInt: + return sw::Shader::OPCODE_IDIV; + case EbtUInt: + return sw::Shader::OPCODE_UDIV; + case EbtFloat: + default: + return op; + } + case sw::Shader::OPCODE_IMOD: + return baseType == EbtUInt ? sw::Shader::OPCODE_UMOD : op; + case sw::Shader::OPCODE_ISHR: + return baseType == EbtUInt ? sw::Shader::OPCODE_USHR : op; + case sw::Shader::OPCODE_MIN: + switch(baseType) + { + case EbtInt: + return sw::Shader::OPCODE_IMIN; + case EbtUInt: + return sw::Shader::OPCODE_UMIN; + case EbtFloat: + default: + return op; + } + case sw::Shader::OPCODE_MAX: + switch(baseType) + { + case EbtInt: + return sw::Shader::OPCODE_IMAX; + case EbtUInt: + return sw::Shader::OPCODE_UMAX; + case EbtFloat: + default: + return op; + } + default: + return op; + } + } + + void OutputASM::visitSymbol(TIntermSymbol *symbol) + { + // Vertex varyings don't have to be actively used to successfully link + // against pixel shaders that use them. So make sure they're declared. + if(symbol->getQualifier() == EvqVaryingOut || symbol->getQualifier() == EvqInvariantVaryingOut || symbol->getQualifier() == EvqVertexOut) + { + if(symbol->getBasicType() != EbtInvariant) // Typeless declarations are not new varyings + { + declareVarying(symbol, -1); + } + } + + TInterfaceBlock* block = symbol->getType().getInterfaceBlock(); + // OpenGL ES 3.0.4 spec, section 2.12.6 Uniform Variables: + // "All members of a named uniform block declared with a shared or std140 layout qualifier + // are considered active, even if they are not referenced in any shader in the program. + // The uniform block itself is also considered active, even if no member of the block is referenced." + if(block && ((block->blockStorage() == EbsShared) || (block->blockStorage() == EbsStd140))) + { + uniformRegister(symbol); + } + } + + bool OutputASM::visitBinary(Visit visit, TIntermBinary *node) + { + if(currentScope != emitScope) + { + return false; + } + + TIntermTyped *result = node; + TIntermTyped *left = node->getLeft(); + TIntermTyped *right = node->getRight(); + const TType &leftType = left->getType(); + const TType &rightType = right->getType(); + const TType &resultType = node->getType(); + + if(isSamplerRegister(result)) + { + return false; // Don't traverse, the register index is determined statically + } + + switch(node->getOp()) + { + case EOpAssign: + if(visit == PostVisit) + { + assignLvalue(left, right); + copy(result, right); + } + break; + case EOpInitialize: + if(visit == PostVisit) + { + copy(left, right); + } + break; + case EOpMatrixTimesScalarAssign: + if(visit == PostVisit) + { + for(int i = 0; i < leftType.getNominalSize(); i++) + { + emit(sw::Shader::OPCODE_MUL, result, i, left, i, right); + } + + assignLvalue(left, result); + } + break; + case EOpVectorTimesMatrixAssign: + if(visit == PostVisit) + { + int size = leftType.getNominalSize(); + + for(int i = 0; i < size; i++) + { + Instruction *dot = emit(sw::Shader::OPCODE_DP(size), result, 0, left, 0, right, i); + dot->dst.mask = 1 << i; + } + + assignLvalue(left, result); + } + break; + case EOpMatrixTimesMatrixAssign: + if(visit == PostVisit) + { + int dim = leftType.getNominalSize(); + + for(int i = 0; i < dim; i++) + { + Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, i, left, 0, right, i); + mul->src[1].swizzle = 0x00; + + for(int j = 1; j < dim; j++) + { + Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, i, left, j, right, i, result, i); + mad->src[1].swizzle = j * 0x55; + } + } + + assignLvalue(left, result); + } + break; + case EOpIndexDirect: + if(visit == PostVisit) + { + int index = right->getAsConstantUnion()->getIConst(0); + + if(result->isMatrix() || result->isStruct() || result->isInterfaceBlock()) + { + ASSERT(left->isArray()); + copy(result, left, index * left->elementRegisterCount()); + } + else if(result->isRegister()) + { + int srcIndex = 0; + if(left->isRegister()) + { + srcIndex = 0; + } + else if(left->isArray()) + { + srcIndex = index * left->elementRegisterCount(); + } + else if(left->isMatrix()) + { + ASSERT(index < left->getNominalSize()); // FIXME: Report semantic error + srcIndex = index; + } + else UNREACHABLE(0); + + Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, 0, left, srcIndex); + + if(left->isRegister()) + { + mov->src[0].swizzle = index; + } + } + else UNREACHABLE(0); + } + break; + case EOpIndexIndirect: + if(visit == PostVisit) + { + if(left->isArray() || left->isMatrix()) + { + for(int index = 0; index < result->totalRegisterCount(); index++) + { + Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, index, left, index); + mov->dst.mask = writeMask(result, index); + + if(left->totalRegisterCount() > 1) + { + sw::Shader::SourceParameter relativeRegister; + argument(relativeRegister, right); + + mov->src[0].rel.type = relativeRegister.type; + mov->src[0].rel.index = relativeRegister.index; + mov->src[0].rel.scale = result->totalRegisterCount(); + mov->src[0].rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform); + } + } + } + else if(left->isRegister()) + { + emit(sw::Shader::OPCODE_EXTRACT, result, left, right); + } + else UNREACHABLE(0); + } + break; + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + if(visit == PostVisit) + { + ASSERT(leftType.isStruct() || (leftType.isInterfaceBlock())); + + const TFieldList& fields = (node->getOp() == EOpIndexDirectStruct) ? + leftType.getStruct()->fields() : + leftType.getInterfaceBlock()->fields(); + int index = right->getAsConstantUnion()->getIConst(0); + int fieldOffset = 0; + + for(int i = 0; i < index; i++) + { + fieldOffset += fields[i]->type()->totalRegisterCount(); + } + + copy(result, left, fieldOffset); + } + break; + case EOpVectorSwizzle: + if(visit == PostVisit) + { + int swizzle = 0; + TIntermAggregate *components = right->getAsAggregate(); + + if(components) + { + TIntermSequence &sequence = components->getSequence(); + int component = 0; + + for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + { + TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); + + if(element) + { + int i = element->getUnionArrayPointer()[0].getIConst(); + swizzle |= i << (component * 2); + component++; + } + else UNREACHABLE(0); + } + } + else UNREACHABLE(0); + + Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, left); + mov->src[0].swizzle = swizzle; + } + break; + case EOpAddAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_ADD, result), result, left, left, right); break; + case EOpAdd: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_ADD, result), result, left, right); break; + case EOpSubAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_SUB, result), result, left, left, right); break; + case EOpSub: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_SUB, result), result, left, right); break; + case EOpMulAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_MUL, result), result, left, left, right); break; + case EOpMul: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_MUL, result), result, left, right); break; + case EOpDivAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_DIV, result), result, left, left, right); break; + case EOpDiv: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_DIV, result), result, left, right); break; + case EOpIModAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_IMOD, result), result, left, left, right); break; + case EOpIMod: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_IMOD, result), result, left, right); break; + case EOpBitShiftLeftAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_SHL, result, left, left, right); break; + case EOpBitShiftLeft: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_SHL, result, left, right); break; + case EOpBitShiftRightAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_ISHR, result), result, left, left, right); break; + case EOpBitShiftRight: if(visit == PostVisit) emitBinary(getOpcode(sw::Shader::OPCODE_ISHR, result), result, left, right); break; + case EOpBitwiseAndAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_AND, result, left, left, right); break; + case EOpBitwiseAnd: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_AND, result, left, right); break; + case EOpBitwiseXorAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_XOR, result, left, left, right); break; + case EOpBitwiseXor: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_XOR, result, left, right); break; + case EOpBitwiseOrAssign: if(visit == PostVisit) emitAssign(sw::Shader::OPCODE_OR, result, left, left, right); break; + case EOpBitwiseOr: if(visit == PostVisit) emitBinary(sw::Shader::OPCODE_OR, result, left, right); break; + case EOpEqual: + if(visit == PostVisit) + { + emitBinary(sw::Shader::OPCODE_EQ, result, left, right); + + for(int index = 1; index < left->totalRegisterCount(); index++) + { + Temporary equal(this); + emit(sw::Shader::OPCODE_EQ, &equal, 0, left, index, right, index); + emit(sw::Shader::OPCODE_AND, result, result, &equal); + } + } + break; + case EOpNotEqual: + if(visit == PostVisit) + { + emitBinary(sw::Shader::OPCODE_NE, result, left, right); + + for(int index = 1; index < left->totalRegisterCount(); index++) + { + Temporary notEqual(this); + emit(sw::Shader::OPCODE_NE, ¬Equal, 0, left, index, right, index); + emit(sw::Shader::OPCODE_OR, result, result, ¬Equal); + } + } + break; + case EOpLessThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LT, result, left, right); break; + case EOpGreaterThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GT, result, left, right); break; + case EOpLessThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LE, result, left, right); break; + case EOpGreaterThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GE, result, left, right); break; + case EOpVectorTimesScalarAssign: if(visit == PostVisit) emitAssign(getOpcode(sw::Shader::OPCODE_MUL, left), result, left, left, right); break; + case EOpVectorTimesScalar: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MUL, left), result, left, right); break; + case EOpMatrixTimesScalar: + if(visit == PostVisit) + { + if(left->isMatrix()) + { + for(int i = 0; i < leftType.getNominalSize(); i++) + { + emit(sw::Shader::OPCODE_MUL, result, i, left, i, right, 0); + } + } + else if(right->isMatrix()) + { + for(int i = 0; i < rightType.getNominalSize(); i++) + { + emit(sw::Shader::OPCODE_MUL, result, i, left, 0, right, i); + } + } + else UNREACHABLE(0); + } + break; + case EOpVectorTimesMatrix: + if(visit == PostVisit) + { + sw::Shader::Opcode dpOpcode = sw::Shader::OPCODE_DP(leftType.getNominalSize()); + + int size = rightType.getNominalSize(); + for(int i = 0; i < size; i++) + { + Instruction *dot = emit(dpOpcode, result, 0, left, 0, right, i); + dot->dst.mask = 1 << i; + } + } + break; + case EOpMatrixTimesVector: + if(visit == PostVisit) + { + Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, left, right); + mul->src[1].swizzle = 0x00; + + int size = rightType.getNominalSize(); + for(int i = 1; i < size; i++) + { + Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, 0, left, i, right, 0, result); + mad->src[1].swizzle = i * 0x55; + } + } + break; + case EOpMatrixTimesMatrix: + if(visit == PostVisit) + { + int dim = leftType.getNominalSize(); + + int size = rightType.getNominalSize(); + for(int i = 0; i < size; i++) + { + Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, i, left, 0, right, i); + mul->src[1].swizzle = 0x00; + + for(int j = 1; j < dim; j++) + { + Instruction *mad = emit(sw::Shader::OPCODE_MAD, result, i, left, j, right, i, result, i); + mad->src[1].swizzle = j * 0x55; + } + } + } + break; + case EOpLogicalOr: + if(trivial(right, 6)) + { + if(visit == PostVisit) + { + emit(sw::Shader::OPCODE_OR, result, left, right); + } + } + else // Short-circuit evaluation + { + if(visit == InVisit) + { + emit(sw::Shader::OPCODE_MOV, result, left); + Instruction *ifnot = emit(sw::Shader::OPCODE_IF, 0, result); + ifnot->src[0].modifier = sw::Shader::MODIFIER_NOT; + } + else if(visit == PostVisit) + { + emit(sw::Shader::OPCODE_MOV, result, right); + emit(sw::Shader::OPCODE_ENDIF); + } + } + break; + case EOpLogicalXor: if(visit == PostVisit) emit(sw::Shader::OPCODE_XOR, result, left, right); break; + case EOpLogicalAnd: + if(trivial(right, 6)) + { + if(visit == PostVisit) + { + emit(sw::Shader::OPCODE_AND, result, left, right); + } + } + else // Short-circuit evaluation + { + if(visit == InVisit) + { + emit(sw::Shader::OPCODE_MOV, result, left); + emit(sw::Shader::OPCODE_IF, 0, result); + } + else if(visit == PostVisit) + { + emit(sw::Shader::OPCODE_MOV, result, right); + emit(sw::Shader::OPCODE_ENDIF); + } + } + break; + default: UNREACHABLE(node->getOp()); + } + + return true; + } + + void OutputASM::emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col, int row, int outCol, int outRow) + { + switch(size) + { + case 1: // Used for cofactor computation only + { + // For a 2x2 matrix, the cofactor is simply a transposed move or negate + bool isMov = (row == col); + sw::Shader::Opcode op = isMov ? sw::Shader::OPCODE_MOV : sw::Shader::OPCODE_NEG; + Instruction *mov = emit(op, result, outCol, arg, isMov ? 1 - row : row); + mov->src[0].swizzle = 0x55 * (isMov ? 1 - col : col); + mov->dst.mask = 1 << outRow; + } + break; + case 2: + { + static const unsigned int swizzle[3] = { 0x99, 0x88, 0x44 }; // xy?? : yzyz, xzxz, xyxy + + bool isCofactor = (col >= 0) && (row >= 0); + int col0 = (isCofactor && (col <= 0)) ? 1 : 0; + int col1 = (isCofactor && (col <= 1)) ? 2 : 1; + bool negate = isCofactor && ((col & 0x01) ^ (row & 0x01)); + + Instruction *det = emit(sw::Shader::OPCODE_DET2, result, outCol, arg, negate ? col1 : col0, arg, negate ? col0 : col1); + det->src[0].swizzle = det->src[1].swizzle = swizzle[isCofactor ? row : 2]; + det->dst.mask = 1 << outRow; + } + break; + case 3: + { + static const unsigned int swizzle[4] = { 0xF9, 0xF8, 0xF4, 0xE4 }; // xyz? : yzww, xzww, xyww, xyzw + + bool isCofactor = (col >= 0) && (row >= 0); + int col0 = (isCofactor && (col <= 0)) ? 1 : 0; + int col1 = (isCofactor && (col <= 1)) ? 2 : 1; + int col2 = (isCofactor && (col <= 2)) ? 3 : 2; + bool negate = isCofactor && ((col & 0x01) ^ (row & 0x01)); + + Instruction *det = emit(sw::Shader::OPCODE_DET3, result, outCol, arg, col0, arg, negate ? col2 : col1, arg, negate ? col1 : col2); + det->src[0].swizzle = det->src[1].swizzle = det->src[2].swizzle = swizzle[isCofactor ? row : 3]; + det->dst.mask = 1 << outRow; + } + break; + case 4: + { + Instruction *det = emit(sw::Shader::OPCODE_DET4, result, outCol, arg, 0, arg, 1, arg, 2, arg, 3); + det->dst.mask = 1 << outRow; + } + break; + default: + UNREACHABLE(size); + break; + } + } + + bool OutputASM::visitUnary(Visit visit, TIntermUnary *node) + { + if(currentScope != emitScope) + { + return false; + } + + TIntermTyped *result = node; + TIntermTyped *arg = node->getOperand(); + TBasicType basicType = arg->getType().getBasicType(); + + union + { + float f; + int i; + } one_value; + + if(basicType == EbtInt || basicType == EbtUInt) + { + one_value.i = 1; + } + else + { + one_value.f = 1.0f; + } + + Constant one(one_value.f, one_value.f, one_value.f, one_value.f); + Constant rad(1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f, 1.74532925e-2f); + Constant deg(5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f, 5.72957795e+1f); + + switch(node->getOp()) + { + case EOpNegative: + if(visit == PostVisit) + { + sw::Shader::Opcode negOpcode = getOpcode(sw::Shader::OPCODE_NEG, arg); + for(int index = 0; index < arg->totalRegisterCount(); index++) + { + emit(negOpcode, result, index, arg, index); + } + } + break; + case EOpVectorLogicalNot: if(visit == PostVisit) emit(sw::Shader::OPCODE_NOT, result, arg); break; + case EOpLogicalNot: if(visit == PostVisit) emit(sw::Shader::OPCODE_NOT, result, arg); break; + case EOpPostIncrement: + if(visit == PostVisit) + { + copy(result, arg); + + sw::Shader::Opcode addOpcode = getOpcode(sw::Shader::OPCODE_ADD, arg); + for(int index = 0; index < arg->totalRegisterCount(); index++) + { + emit(addOpcode, arg, index, arg, index, &one); + } + + assignLvalue(arg, arg); + } + break; + case EOpPostDecrement: + if(visit == PostVisit) + { + copy(result, arg); + + sw::Shader::Opcode subOpcode = getOpcode(sw::Shader::OPCODE_SUB, arg); + for(int index = 0; index < arg->totalRegisterCount(); index++) + { + emit(subOpcode, arg, index, arg, index, &one); + } + + assignLvalue(arg, arg); + } + break; + case EOpPreIncrement: + if(visit == PostVisit) + { + sw::Shader::Opcode addOpcode = getOpcode(sw::Shader::OPCODE_ADD, arg); + for(int index = 0; index < arg->totalRegisterCount(); index++) + { + emit(addOpcode, result, index, arg, index, &one); + } + + assignLvalue(arg, result); + } + break; + case EOpPreDecrement: + if(visit == PostVisit) + { + sw::Shader::Opcode subOpcode = getOpcode(sw::Shader::OPCODE_SUB, arg); + for(int index = 0; index < arg->totalRegisterCount(); index++) + { + emit(subOpcode, result, index, arg, index, &one); + } + + assignLvalue(arg, result); + } + break; + case EOpRadians: if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, arg, &rad); break; + case EOpDegrees: if(visit == PostVisit) emit(sw::Shader::OPCODE_MUL, result, arg, °); break; + case EOpSin: if(visit == PostVisit) emit(sw::Shader::OPCODE_SIN, result, arg); break; + case EOpCos: if(visit == PostVisit) emit(sw::Shader::OPCODE_COS, result, arg); break; + case EOpTan: if(visit == PostVisit) emit(sw::Shader::OPCODE_TAN, result, arg); break; + case EOpAsin: if(visit == PostVisit) emit(sw::Shader::OPCODE_ASIN, result, arg); break; + case EOpAcos: if(visit == PostVisit) emit(sw::Shader::OPCODE_ACOS, result, arg); break; + case EOpAtan: if(visit == PostVisit) emit(sw::Shader::OPCODE_ATAN, result, arg); break; + case EOpSinh: if(visit == PostVisit) emit(sw::Shader::OPCODE_SINH, result, arg); break; + case EOpCosh: if(visit == PostVisit) emit(sw::Shader::OPCODE_COSH, result, arg); break; + case EOpTanh: if(visit == PostVisit) emit(sw::Shader::OPCODE_TANH, result, arg); break; + case EOpAsinh: if(visit == PostVisit) emit(sw::Shader::OPCODE_ASINH, result, arg); break; + case EOpAcosh: if(visit == PostVisit) emit(sw::Shader::OPCODE_ACOSH, result, arg); break; + case EOpAtanh: if(visit == PostVisit) emit(sw::Shader::OPCODE_ATANH, result, arg); break; + case EOpExp: if(visit == PostVisit) emit(sw::Shader::OPCODE_EXP, result, arg); break; + case EOpLog: if(visit == PostVisit) emit(sw::Shader::OPCODE_LOG, result, arg); break; + case EOpExp2: if(visit == PostVisit) emit(sw::Shader::OPCODE_EXP2, result, arg); break; + case EOpLog2: if(visit == PostVisit) emit(sw::Shader::OPCODE_LOG2, result, arg); break; + case EOpSqrt: if(visit == PostVisit) emit(sw::Shader::OPCODE_SQRT, result, arg); break; + case EOpInverseSqrt: if(visit == PostVisit) emit(sw::Shader::OPCODE_RSQ, result, arg); break; + case EOpAbs: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_ABS, result), result, arg); break; + case EOpSign: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_SGN, result), result, arg); break; + case EOpFloor: if(visit == PostVisit) emit(sw::Shader::OPCODE_FLOOR, result, arg); break; + case EOpTrunc: if(visit == PostVisit) emit(sw::Shader::OPCODE_TRUNC, result, arg); break; + case EOpRound: if(visit == PostVisit) emit(sw::Shader::OPCODE_ROUND, result, arg); break; + case EOpRoundEven: if(visit == PostVisit) emit(sw::Shader::OPCODE_ROUNDEVEN, result, arg); break; + case EOpCeil: if(visit == PostVisit) emit(sw::Shader::OPCODE_CEIL, result, arg, result); break; + case EOpFract: if(visit == PostVisit) emit(sw::Shader::OPCODE_FRC, result, arg); break; + case EOpIsNan: if(visit == PostVisit) emit(sw::Shader::OPCODE_ISNAN, result, arg); break; + case EOpIsInf: if(visit == PostVisit) emit(sw::Shader::OPCODE_ISINF, result, arg); break; + case EOpLength: if(visit == PostVisit) emit(sw::Shader::OPCODE_LEN(dim(arg)), result, arg); break; + case EOpNormalize: if(visit == PostVisit) emit(sw::Shader::OPCODE_NRM(dim(arg)), result, arg); break; + case EOpDFdx: if(visit == PostVisit) emit(sw::Shader::OPCODE_DFDX, result, arg); break; + case EOpDFdy: if(visit == PostVisit) emit(sw::Shader::OPCODE_DFDY, result, arg); break; + case EOpFwidth: if(visit == PostVisit) emit(sw::Shader::OPCODE_FWIDTH, result, arg); break; + case EOpAny: if(visit == PostVisit) emit(sw::Shader::OPCODE_ANY, result, arg); break; + case EOpAll: if(visit == PostVisit) emit(sw::Shader::OPCODE_ALL, result, arg); break; + case EOpFloatBitsToInt: if(visit == PostVisit) emit(sw::Shader::OPCODE_FLOATBITSTOINT, result, arg); break; + case EOpFloatBitsToUint: if(visit == PostVisit) emit(sw::Shader::OPCODE_FLOATBITSTOUINT, result, arg); break; + case EOpIntBitsToFloat: if(visit == PostVisit) emit(sw::Shader::OPCODE_INTBITSTOFLOAT, result, arg); break; + case EOpUintBitsToFloat: if(visit == PostVisit) emit(sw::Shader::OPCODE_UINTBITSTOFLOAT, result, arg); break; + case EOpPackSnorm2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_PACKSNORM2x16, result, arg); break; + case EOpPackUnorm2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_PACKUNORM2x16, result, arg); break; + case EOpPackHalf2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_PACKHALF2x16, result, arg); break; + case EOpUnpackSnorm2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_UNPACKSNORM2x16, result, arg); break; + case EOpUnpackUnorm2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_UNPACKUNORM2x16, result, arg); break; + case EOpUnpackHalf2x16: if(visit == PostVisit) emit(sw::Shader::OPCODE_UNPACKHALF2x16, result, arg); break; + case EOpTranspose: + if(visit == PostVisit) + { + int numCols = arg->getNominalSize(); + int numRows = arg->getSecondarySize(); + for(int i = 0; i < numCols; ++i) + { + for(int j = 0; j < numRows; ++j) + { + Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, j, arg, i); + mov->src[0].swizzle = 0x55 * j; + mov->dst.mask = 1 << i; + } + } + } + break; + case EOpDeterminant: + if(visit == PostVisit) + { + int size = arg->getNominalSize(); + ASSERT(size == arg->getSecondarySize()); + + emitDeterminant(result, arg, size); + } + break; + case EOpInverse: + if(visit == PostVisit) + { + int size = arg->getNominalSize(); + ASSERT(size == arg->getSecondarySize()); + + // Compute transposed matrix of cofactors + for(int i = 0; i < size; ++i) + { + for(int j = 0; j < size; ++j) + { + // For a 2x2 matrix, the cofactor is simply a transposed move or negate + // For a 3x3 or 4x4 matrix, the cofactor is a transposed determinant + emitDeterminant(result, arg, size - 1, j, i, i, j); + } + } + + // Compute 1 / determinant + Temporary invDet(this); + emitDeterminant(&invDet, arg, size); + Constant one(1.0f, 1.0f, 1.0f, 1.0f); + Instruction *div = emit(sw::Shader::OPCODE_DIV, &invDet, &one, &invDet); + div->src[1].swizzle = 0x00; // xxxx + + // Divide transposed matrix of cofactors by determinant + for(int i = 0; i < size; ++i) + { + emit(sw::Shader::OPCODE_MUL, result, i, result, i, &invDet); + } + } + break; + default: UNREACHABLE(node->getOp()); + } + + return true; + } + + bool OutputASM::visitAggregate(Visit visit, TIntermAggregate *node) + { + if(currentScope != emitScope && node->getOp() != EOpFunction && node->getOp() != EOpSequence) + { + return false; + } + + Constant zero(0.0f, 0.0f, 0.0f, 0.0f); + + TIntermTyped *result = node; + const TType &resultType = node->getType(); + TIntermSequence &arg = node->getSequence(); + size_t argumentCount = arg.size(); + + switch(node->getOp()) + { + case EOpSequence: break; + case EOpDeclaration: break; + case EOpInvariantDeclaration: break; + case EOpPrototype: break; + case EOpComma: + if(visit == PostVisit) + { + copy(result, arg[1]); + } + break; + case EOpFunction: + if(visit == PreVisit) + { + const TString &name = node->getName(); + + if(emitScope == FUNCTION) + { + if(functionArray.size() > 1) // No need for a label when there's only main() + { + Instruction *label = emit(sw::Shader::OPCODE_LABEL); + label->dst.type = sw::Shader::PARAMETER_LABEL; + + const Function *function = findFunction(name); + ASSERT(function); // Should have been added during global pass + label->dst.index = function->label; + currentFunction = function->label; + } + } + else if(emitScope == GLOBAL) + { + if(name != "main(") + { + TIntermSequence &arguments = node->getSequence()[0]->getAsAggregate()->getSequence(); + functionArray.push_back(Function(functionArray.size(), name, &arguments, node)); + } + } + else UNREACHABLE(emitScope); + + currentScope = FUNCTION; + } + else if(visit == PostVisit) + { + if(emitScope == FUNCTION) + { + if(functionArray.size() > 1) // No need to return when there's only main() + { + emit(sw::Shader::OPCODE_RET); + } + } + + currentScope = GLOBAL; + } + break; + case EOpFunctionCall: + if(visit == PostVisit) + { + if(node->isUserDefined()) + { + const TString &name = node->getName(); + const Function *function = findFunction(name); + + if(!function) + { + mContext.error(node->getLine(), "function definition not found", name.c_str()); + return false; + } + + TIntermSequence &arguments = *function->arg; + + for(size_t i = 0; i < argumentCount; i++) + { + TIntermTyped *in = arguments[i]->getAsTyped(); + + if(in->getQualifier() == EvqIn || + in->getQualifier() == EvqInOut || + in->getQualifier() == EvqConstReadOnly) + { + copy(in, arg[i]); + } + } + + Instruction *call = emit(sw::Shader::OPCODE_CALL); + call->dst.type = sw::Shader::PARAMETER_LABEL; + call->dst.index = function->label; + + if(function->ret && function->ret->getType().getBasicType() != EbtVoid) + { + copy(result, function->ret); + } + + for(size_t i = 0; i < argumentCount; i++) + { + TIntermTyped *argument = arguments[i]->getAsTyped(); + TIntermTyped *out = arg[i]->getAsTyped(); + + if(argument->getQualifier() == EvqOut || + argument->getQualifier() == EvqInOut) + { + copy(out, argument); + } + } + } + else + { + const TextureFunction textureFunction(node->getName()); + TIntermTyped *t = arg[1]->getAsTyped(); + + Temporary coord(this); + + if(textureFunction.proj) + { + TIntermConstantUnion* constant = arg[1]->getAsConstantUnion(); + if(constant) + { + float projFactor = 1.0f / constant->getFConst(t->getNominalSize() - 1); + Constant projCoord(constant->getFConst(0) * projFactor, + constant->getFConst(1) * projFactor, + constant->getFConst(2) * projFactor, + 0.0f); + emit(sw::Shader::OPCODE_MOV, &coord, &projCoord); + } + else + { + Instruction *rcp = emit(sw::Shader::OPCODE_RCPX, &coord, arg[1]); + rcp->src[0].swizzle = 0x55 * (t->getNominalSize() - 1); + rcp->dst.mask = 0x7; + + Instruction *mul = emit(sw::Shader::OPCODE_MUL, &coord, arg[1], &coord); + mul->dst.mask = 0x7; + } + } + else + { + emit(sw::Shader::OPCODE_MOV, &coord, arg[1]); + } + + switch(textureFunction.method) + { + case TextureFunction::IMPLICIT: + { + TIntermNode* offset = textureFunction.offset ? arg[2] : 0; + + if(argumentCount == 2 || (textureFunction.offset && argumentCount == 3)) + { + Instruction *tex = emit(textureFunction.offset ? sw::Shader::OPCODE_TEXOFFSET : sw::Shader::OPCODE_TEX, + result, &coord, arg[0], offset); + } + else if(argumentCount == 3 || (textureFunction.offset && argumentCount == 4)) // bias + { + Instruction *bias = emit(sw::Shader::OPCODE_MOV, &coord, arg[textureFunction.offset ? 3 : 2]); + bias->dst.mask = 0x8; + + Instruction *tex = emit(textureFunction.offset ? sw::Shader::OPCODE_TEXOFFSET : sw::Shader::OPCODE_TEX, + result, &coord, arg[0], offset); // FIXME: Implement an efficient TEXLDB instruction + tex->bias = true; + } + else UNREACHABLE(argumentCount); + } + break; + case TextureFunction::LOD: + { + Instruction *lod = emit(sw::Shader::OPCODE_MOV, &coord, arg[2]); + lod->dst.mask = 0x8; + + emit(textureFunction.offset ? sw::Shader::OPCODE_TEXLDLOFFSET : sw::Shader::OPCODE_TEXLDL, + result, &coord, arg[0], textureFunction.offset ? arg[3] : nullptr); + } + break; + case TextureFunction::FETCH: + { + if(argumentCount == 3 || (textureFunction.offset && argumentCount == 4)) + { + TIntermNode *offset = textureFunction.offset ? arg[3] : nullptr; + + emit(textureFunction.offset ? sw::Shader::OPCODE_TEXELFETCHOFFSET : sw::Shader::OPCODE_TEXELFETCH, + result, arg[1], arg[0], arg[2], offset); + } + else UNREACHABLE(argumentCount); + } + break; + case TextureFunction::GRAD: + { + if(argumentCount == 4 || (textureFunction.offset && argumentCount == 5)) + { + TIntermNode *offset = textureFunction.offset ? arg[4] : nullptr; + + emit(textureFunction.offset ? sw::Shader::OPCODE_TEXGRADOFFSET : sw::Shader::OPCODE_TEXGRAD, + result, &coord, arg[0], arg[2], arg[3], offset); + } + else UNREACHABLE(argumentCount); + } + break; + case TextureFunction::SIZE: + emit(sw::Shader::OPCODE_TEXSIZE, result, arg[1], arg[0]); + break; + default: + UNREACHABLE(textureFunction.method); + } + } + } + break; + case EOpParameters: + break; + case EOpConstructFloat: + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructBool: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructInt: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructUInt: + case EOpConstructUVec2: + case EOpConstructUVec3: + case EOpConstructUVec4: + if(visit == PostVisit) + { + int component = 0; + + for(size_t i = 0; i < argumentCount; i++) + { + TIntermTyped *argi = arg[i]->getAsTyped(); + int size = argi->getNominalSize(); + + if(!argi->isMatrix()) + { + Instruction *mov = emitCast(result, argi); + mov->dst.mask = (0xF << component) & 0xF; + mov->src[0].swizzle = readSwizzle(argi, size) << (component * 2); + + component += size; + } + else // Matrix + { + int column = 0; + + while(component < resultType.getNominalSize()) + { + Instruction *mov = emitCast(result, 0, argi, column); + mov->dst.mask = (0xF << component) & 0xF; + mov->src[0].swizzle = readSwizzle(argi, size) << (component * 2); + + column++; + component += size; + } + } + } + } + break; + case EOpConstructMat2: + case EOpConstructMat2x3: + case EOpConstructMat2x4: + case EOpConstructMat3x2: + case EOpConstructMat3: + case EOpConstructMat3x4: + case EOpConstructMat4x2: + case EOpConstructMat4x3: + case EOpConstructMat4: + if(visit == PostVisit) + { + TIntermTyped *arg0 = arg[0]->getAsTyped(); + const int outCols = result->getNominalSize(); + const int outRows = result->getSecondarySize(); + + if(arg0->isScalar() && arg.size() == 1) // Construct scale matrix + { + for(int i = 0; i < outCols; i++) + { + Instruction *init = emit(sw::Shader::OPCODE_MOV, result, i, &zero); + Instruction *mov = emitCast(result, i, arg0, 0); + mov->dst.mask = 1 << i; + ASSERT(mov->src[0].swizzle == 0x00); + } + } + else if(arg0->isMatrix()) + { + const int inCols = arg0->getNominalSize(); + const int inRows = arg0->getSecondarySize(); + + for(int i = 0; i < outCols; i++) + { + if(i >= inCols || outRows > inRows) + { + // Initialize to identity matrix + Constant col((i == 0 ? 1.0f : 0.0f), (i == 1 ? 1.0f : 0.0f), (i == 2 ? 1.0f : 0.0f), (i == 3 ? 1.0f : 0.0f)); + Instruction *mov = emitCast(result, i, &col, 0); + } + + if(i < inCols) + { + Instruction *mov = emitCast(result, i, arg0, i); + mov->dst.mask = 0xF >> (4 - inRows); + } + } + } + else + { + int column = 0; + int row = 0; + + for(size_t i = 0; i < argumentCount; i++) + { + TIntermTyped *argi = arg[i]->getAsTyped(); + int size = argi->getNominalSize(); + int element = 0; + + while(element < size) + { + Instruction *mov = emitCast(result, column, argi, 0); + mov->dst.mask = (0xF << row) & 0xF; + mov->src[0].swizzle = (readSwizzle(argi, size) << (row * 2)) + 0x55 * element; + + int end = row + size - element; + column = end >= outRows ? column + 1 : column; + element = element + outRows - row; + row = end >= outRows ? 0 : end; + } + } + } + } + break; + case EOpConstructStruct: + if(visit == PostVisit) + { + int offset = 0; + for(size_t i = 0; i < argumentCount; i++) + { + TIntermTyped *argi = arg[i]->getAsTyped(); + int size = argi->totalRegisterCount(); + + for(int index = 0; index < size; index++) + { + Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, index + offset, argi, index); + mov->dst.mask = writeMask(result, offset + index); + } + + offset += size; + } + } + break; + case EOpLessThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LT, result, arg[0], arg[1]); break; + case EOpGreaterThan: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GT, result, arg[0], arg[1]); break; + case EOpLessThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_LE, result, arg[0], arg[1]); break; + case EOpGreaterThanEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_GE, result, arg[0], arg[1]); break; + case EOpVectorEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_EQ, result, arg[0], arg[1]); break; + case EOpVectorNotEqual: if(visit == PostVisit) emitCmp(sw::Shader::CONTROL_NE, result, arg[0], arg[1]); break; + case EOpMod: if(visit == PostVisit) emit(sw::Shader::OPCODE_MOD, result, arg[0], arg[1]); break; + case EOpModf: + if(visit == PostVisit) + { + TIntermTyped* arg1 = arg[1]->getAsTyped(); + emit(sw::Shader::OPCODE_TRUNC, arg1, arg[0]); + assignLvalue(arg1, arg1); + emitBinary(sw::Shader::OPCODE_SUB, result, arg[0], arg1); + } + break; + case EOpPow: if(visit == PostVisit) emit(sw::Shader::OPCODE_POW, result, arg[0], arg[1]); break; + case EOpAtan: if(visit == PostVisit) emit(sw::Shader::OPCODE_ATAN2, result, arg[0], arg[1]); break; + case EOpMin: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MIN, result), result, arg[0], arg[1]); break; + case EOpMax: if(visit == PostVisit) emit(getOpcode(sw::Shader::OPCODE_MAX, result), result, arg[0], arg[1]); break; + case EOpClamp: + if(visit == PostVisit) + { + emit(getOpcode(sw::Shader::OPCODE_MAX, result), result, arg[0], arg[1]); + emit(getOpcode(sw::Shader::OPCODE_MIN, result), result, result, arg[2]); + } + break; + case EOpMix: if(visit == PostVisit) emit(sw::Shader::OPCODE_LRP, result, arg[2], arg[1], arg[0]); break; + case EOpStep: if(visit == PostVisit) emit(sw::Shader::OPCODE_STEP, result, arg[0], arg[1]); break; + case EOpSmoothStep: if(visit == PostVisit) emit(sw::Shader::OPCODE_SMOOTH, result, arg[0], arg[1], arg[2]); break; + case EOpDistance: if(visit == PostVisit) emit(sw::Shader::OPCODE_DIST(dim(arg[0])), result, arg[0], arg[1]); break; + case EOpDot: if(visit == PostVisit) emit(sw::Shader::OPCODE_DP(dim(arg[0])), result, arg[0], arg[1]); break; + case EOpCross: if(visit == PostVisit) emit(sw::Shader::OPCODE_CRS, result, arg[0], arg[1]); break; + case EOpFaceForward: if(visit == PostVisit) emit(sw::Shader::OPCODE_FORWARD(dim(arg[0])), result, arg[0], arg[1], arg[2]); break; + case EOpReflect: if(visit == PostVisit) emit(sw::Shader::OPCODE_REFLECT(dim(arg[0])), result, arg[0], arg[1]); break; + case EOpRefract: if(visit == PostVisit) emit(sw::Shader::OPCODE_REFRACT(dim(arg[0])), result, arg[0], arg[1], arg[2]); break; + case EOpMul: + if(visit == PostVisit) + { + TIntermTyped *arg0 = arg[0]->getAsTyped(); + TIntermTyped *arg1 = arg[1]->getAsTyped(); + ASSERT((arg0->getNominalSize() == arg1->getNominalSize()) && (arg0->getSecondarySize() == arg1->getSecondarySize())); + + int size = arg0->getNominalSize(); + for(int i = 0; i < size; i++) + { + emit(sw::Shader::OPCODE_MUL, result, i, arg[0], i, arg[1], i); + } + } + break; + case EOpOuterProduct: + if(visit == PostVisit) + { + for(int i = 0; i < dim(arg[1]); i++) + { + Instruction *mul = emit(sw::Shader::OPCODE_MUL, result, i, arg[0], 0, arg[1]); + mul->src[1].swizzle = 0x55 * i; + } + } + break; + default: UNREACHABLE(node->getOp()); + } + + return true; + } + + bool OutputASM::visitSelection(Visit visit, TIntermSelection *node) + { + if(currentScope != emitScope) + { + return false; + } + + TIntermTyped *condition = node->getCondition(); + TIntermNode *trueBlock = node->getTrueBlock(); + TIntermNode *falseBlock = node->getFalseBlock(); + TIntermConstantUnion *constantCondition = condition->getAsConstantUnion(); + + condition->traverse(this); + + if(node->usesTernaryOperator()) + { + if(constantCondition) + { + bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst(); + + if(trueCondition) + { + trueBlock->traverse(this); + copy(node, trueBlock); + } + else + { + falseBlock->traverse(this); + copy(node, falseBlock); + } + } + else if(trivial(node, 6)) // Fast to compute both potential results and no side effects + { + trueBlock->traverse(this); + falseBlock->traverse(this); + emit(sw::Shader::OPCODE_SELECT, node, condition, trueBlock, falseBlock); + } + else + { + emit(sw::Shader::OPCODE_IF, 0, condition); + + if(trueBlock) + { + trueBlock->traverse(this); + copy(node, trueBlock); + } + + if(falseBlock) + { + emit(sw::Shader::OPCODE_ELSE); + falseBlock->traverse(this); + copy(node, falseBlock); + } + + emit(sw::Shader::OPCODE_ENDIF); + } + } + else // if/else statement + { + if(constantCondition) + { + bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst(); + + if(trueCondition) + { + if(trueBlock) + { + trueBlock->traverse(this); + } + } + else + { + if(falseBlock) + { + falseBlock->traverse(this); + } + } + } + else + { + emit(sw::Shader::OPCODE_IF, 0, condition); + + if(trueBlock) + { + trueBlock->traverse(this); + } + + if(falseBlock) + { + emit(sw::Shader::OPCODE_ELSE); + falseBlock->traverse(this); + } + + emit(sw::Shader::OPCODE_ENDIF); + } + } + + return false; + } + + bool OutputASM::visitLoop(Visit visit, TIntermLoop *node) + { + if(currentScope != emitScope) + { + return false; + } + + unsigned int iterations = loopCount(node); + + if(iterations == 0) + { + return false; + } + + bool unroll = (iterations <= 4); + + if(unroll) + { + LoopUnrollable loopUnrollable; + unroll = loopUnrollable.traverse(node); + } + + TIntermNode *init = node->getInit(); + TIntermTyped *condition = node->getCondition(); + TIntermTyped *expression = node->getExpression(); + TIntermNode *body = node->getBody(); + Constant True(true); + + if(node->getType() == ELoopDoWhile) + { + Temporary iterate(this); + emit(sw::Shader::OPCODE_MOV, &iterate, &True); + + emit(sw::Shader::OPCODE_WHILE, 0, &iterate); // FIXME: Implement real do-while + + if(body) + { + body->traverse(this); + } + + emit(sw::Shader::OPCODE_TEST); + + condition->traverse(this); + emit(sw::Shader::OPCODE_MOV, &iterate, condition); + + emit(sw::Shader::OPCODE_ENDWHILE); + } + else + { + if(init) + { + init->traverse(this); + } + + if(unroll) + { + for(unsigned int i = 0; i < iterations; i++) + { + // condition->traverse(this); // Condition could contain statements, but not in an unrollable loop + + if(body) + { + body->traverse(this); + } + + if(expression) + { + expression->traverse(this); + } + } + } + else + { + if(condition) + { + condition->traverse(this); + } + else + { + condition = &True; + } + + emit(sw::Shader::OPCODE_WHILE, 0, condition); + + if(body) + { + body->traverse(this); + } + + emit(sw::Shader::OPCODE_TEST); + + if(expression) + { + expression->traverse(this); + } + + if(condition) + { + condition->traverse(this); + } + + emit(sw::Shader::OPCODE_ENDWHILE); + } + } + + return false; + } + + bool OutputASM::visitBranch(Visit visit, TIntermBranch *node) + { + if(currentScope != emitScope) + { + return false; + } + + switch(node->getFlowOp()) + { + case EOpKill: if(visit == PostVisit) emit(sw::Shader::OPCODE_DISCARD); break; + case EOpBreak: if(visit == PostVisit) emit(sw::Shader::OPCODE_BREAK); break; + case EOpContinue: if(visit == PostVisit) emit(sw::Shader::OPCODE_CONTINUE); break; + case EOpReturn: + if(visit == PostVisit) + { + TIntermTyped *value = node->getExpression(); + + if(value) + { + copy(functionArray[currentFunction].ret, value); + } + + emit(sw::Shader::OPCODE_LEAVE); + } + break; + default: UNREACHABLE(node->getFlowOp()); + } + + return true; + } + + Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, TIntermNode *src3, TIntermNode *src4) + { + return emit(op, dst, 0, src0, 0, src1, 0, src2, 0, src3, 0, src4, 0); + } + + Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0, int index0, TIntermNode *src1, int index1, + TIntermNode *src2, int index2, TIntermNode *src3, int index3, TIntermNode *src4, int index4) + { + Instruction *instruction = new Instruction(op); + + if(dst) + { + instruction->dst.type = registerType(dst); + instruction->dst.index = registerIndex(dst) + dstIndex; + instruction->dst.mask = writeMask(dst); + instruction->dst.integer = (dst->getBasicType() == EbtInt); + } + + argument(instruction->src[0], src0, index0); + argument(instruction->src[1], src1, index1); + argument(instruction->src[2], src2, index2); + argument(instruction->src[3], src3, index3); + argument(instruction->src[4], src4, index4); + + shader->append(instruction); + + return instruction; + } + + Instruction *OutputASM::emitCast(TIntermTyped *dst, TIntermTyped *src) + { + return emitCast(dst, 0, src, 0); + } + + Instruction *OutputASM::emitCast(TIntermTyped *dst, int dstIndex, TIntermTyped *src, int srcIndex) + { + switch(src->getBasicType()) + { + case EbtBool: + switch(dst->getBasicType()) + { + case EbtInt: return emit(sw::Shader::OPCODE_B2I, dst, dstIndex, src, srcIndex); + case EbtUInt: return emit(sw::Shader::OPCODE_B2I, dst, dstIndex, src, srcIndex); + case EbtFloat: return emit(sw::Shader::OPCODE_B2F, dst, dstIndex, src, srcIndex); + default: break; + } + break; + case EbtInt: + switch(dst->getBasicType()) + { + case EbtBool: return emit(sw::Shader::OPCODE_I2B, dst, dstIndex, src, srcIndex); + case EbtFloat: return emit(sw::Shader::OPCODE_I2F, dst, dstIndex, src, srcIndex); + default: break; + } + break; + case EbtUInt: + switch(dst->getBasicType()) + { + case EbtBool: return emit(sw::Shader::OPCODE_I2B, dst, dstIndex, src, srcIndex); + case EbtFloat: return emit(sw::Shader::OPCODE_U2F, dst, dstIndex, src, srcIndex); + default: break; + } + break; + case EbtFloat: + switch(dst->getBasicType()) + { + case EbtBool: return emit(sw::Shader::OPCODE_F2B, dst, dstIndex, src, srcIndex); + case EbtInt: return emit(sw::Shader::OPCODE_F2I, dst, dstIndex, src, srcIndex); + case EbtUInt: return emit(sw::Shader::OPCODE_F2U, dst, dstIndex, src, srcIndex); + default: break; + } + break; + default: + break; + } + + ASSERT((src->getBasicType() == dst->getBasicType()) || + ((src->getBasicType() == EbtInt) && (dst->getBasicType() == EbtUInt)) || + ((src->getBasicType() == EbtUInt) && (dst->getBasicType() == EbtInt))); + + return emit(sw::Shader::OPCODE_MOV, dst, dstIndex, src, srcIndex); + } + + void OutputASM::emitBinary(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2) + { + for(int index = 0; index < dst->elementRegisterCount(); index++) + { + emit(op, dst, index, src0, index, src1, index, src2, index); + } + } + + void OutputASM::emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1) + { + emitBinary(op, result, src0, src1); + assignLvalue(lhs, result); + } + + void OutputASM::emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index) + { + sw::Shader::Opcode opcode; + switch(left->getAsTyped()->getBasicType()) + { + case EbtBool: + case EbtInt: + opcode = sw::Shader::OPCODE_ICMP; + break; + case EbtUInt: + opcode = sw::Shader::OPCODE_UCMP; + break; + default: + opcode = sw::Shader::OPCODE_CMP; + break; + } + + Instruction *cmp = emit(opcode, dst, 0, left, index, right, index); + cmp->control = cmpOp; + } + + int componentCount(const TType &type, int registers) + { + if(registers == 0) + { + return 0; + } + + if(type.isArray() && registers >= type.elementRegisterCount()) + { + int index = registers / type.elementRegisterCount(); + registers -= index * type.elementRegisterCount(); + return index * type.getElementSize() + componentCount(type, registers); + } + + if(type.isStruct() || type.isInterfaceBlock()) + { + const TFieldList& fields = type.getStruct() ? type.getStruct()->fields() : type.getInterfaceBlock()->fields(); + int elements = 0; + + for(TFieldList::const_iterator field = fields.begin(); field != fields.end(); field++) + { + const TType &fieldType = *((*field)->type()); + + if(fieldType.totalRegisterCount() <= registers) + { + registers -= fieldType.totalRegisterCount(); + elements += fieldType.getObjectSize(); + } + else // Register within this field + { + return elements + componentCount(fieldType, registers); + } + } + } + else if(type.isMatrix()) + { + return registers * type.registerSize(); + } + + UNREACHABLE(0); + return 0; + } + + int registerSize(const TType &type, int registers) + { + if(registers == 0) + { + if(type.isStruct()) + { + return registerSize(*((*(type.getStruct()->fields().begin()))->type()), 0); + } + else if(type.isInterfaceBlock()) + { + return registerSize(*((*(type.getInterfaceBlock()->fields().begin()))->type()), 0); + } + + return type.registerSize(); + } + + if(type.isArray() && registers >= type.elementRegisterCount()) + { + int index = registers / type.elementRegisterCount(); + registers -= index * type.elementRegisterCount(); + return registerSize(type, registers); + } + + if(type.isStruct() || type.isInterfaceBlock()) + { + const TFieldList& fields = type.getStruct() ? type.getStruct()->fields() : type.getInterfaceBlock()->fields(); + int elements = 0; + + for(TFieldList::const_iterator field = fields.begin(); field != fields.end(); field++) + { + const TType &fieldType = *((*field)->type()); + + if(fieldType.totalRegisterCount() <= registers) + { + registers -= fieldType.totalRegisterCount(); + elements += fieldType.getObjectSize(); + } + else // Register within this field + { + return registerSize(fieldType, registers); + } + } + } + else if(type.isMatrix()) + { + return registerSize(type, 0); + } + + UNREACHABLE(0); + return 0; + } + + int OutputASM::getBlockId(TIntermTyped *arg) + { + if(arg) + { + const TType &type = arg->getType(); + TInterfaceBlock* block = type.getInterfaceBlock(); + if(block && (type.getQualifier() == EvqUniform)) + { + // Make sure the uniform block is declared + uniformRegister(arg); + + const char* blockName = block->name().c_str(); + + // Fetch uniform block index from array of blocks + for(ActiveUniformBlocks::const_iterator it = shaderObject->activeUniformBlocks.begin(); it != shaderObject->activeUniformBlocks.end(); ++it) + { + if(blockName == it->name) + { + return it->blockId; + } + } + + ASSERT(false); + } + } + + return -1; + } + + OutputASM::ArgumentInfo OutputASM::getArgumentInfo(TIntermTyped *arg, int index) + { + const TType &type = arg->getType(); + int blockId = getBlockId(arg); + ArgumentInfo argumentInfo(BlockMemberInfo::getDefaultBlockInfo(), type, -1, -1); + if(blockId != -1) + { + argumentInfo.bufferIndex = 0; + for(int i = 0; i < blockId; ++i) + { + int blockArraySize = shaderObject->activeUniformBlocks[i].arraySize; + argumentInfo.bufferIndex += blockArraySize > 0 ? blockArraySize : 1; + } + + const BlockDefinitionIndexMap& blockDefinition = blockDefinitions[blockId]; + + BlockDefinitionIndexMap::const_iterator itEnd = blockDefinition.end(); + BlockDefinitionIndexMap::const_iterator it = itEnd; + + argumentInfo.clampedIndex = index; + if(type.isInterfaceBlock()) + { + // Offset index to the beginning of the selected instance + int blockRegisters = type.elementRegisterCount(); + int bufferOffset = argumentInfo.clampedIndex / blockRegisters; + argumentInfo.bufferIndex += bufferOffset; + argumentInfo.clampedIndex -= bufferOffset * blockRegisters; + } + + int regIndex = registerIndex(arg); + for(int i = regIndex + argumentInfo.clampedIndex; i >= regIndex; --i) + { + it = blockDefinition.find(i); + if(it != itEnd) + { + argumentInfo.clampedIndex -= (i - regIndex); + break; + } + } + ASSERT(it != itEnd); + + argumentInfo.typedMemberInfo = it->second; + + int registerCount = argumentInfo.typedMemberInfo.type.totalRegisterCount(); + argumentInfo.clampedIndex = (argumentInfo.clampedIndex >= registerCount) ? registerCount - 1 : argumentInfo.clampedIndex; + } + else + { + argumentInfo.clampedIndex = (index >= arg->totalRegisterCount()) ? arg->totalRegisterCount() - 1 : index; + } + + return argumentInfo; + } + + void OutputASM::argument(sw::Shader::SourceParameter ¶meter, TIntermNode *argument, int index) + { + if(argument) + { + TIntermTyped *arg = argument->getAsTyped(); + Temporary unpackedUniform(this); + + const TType& srcType = arg->getType(); + TInterfaceBlock* srcBlock = srcType.getInterfaceBlock(); + if(srcBlock && (srcType.getQualifier() == EvqUniform)) + { + const ArgumentInfo argumentInfo = getArgumentInfo(arg, index); + const TType &memberType = argumentInfo.typedMemberInfo.type; + + if(memberType.getBasicType() == EbtBool) + { + int arraySize = (memberType.isArray() ? memberType.getArraySize() : 1); + ASSERT(argumentInfo.clampedIndex < arraySize); + + // Convert the packed bool, which is currently an int, to a true bool + Instruction *instruction = new Instruction(sw::Shader::OPCODE_I2B); + instruction->dst.type = sw::Shader::PARAMETER_TEMP; + instruction->dst.index = registerIndex(&unpackedUniform); + instruction->src[0].type = sw::Shader::PARAMETER_CONST; + instruction->src[0].bufferIndex = argumentInfo.bufferIndex; + instruction->src[0].index = argumentInfo.typedMemberInfo.offset + argumentInfo.clampedIndex * argumentInfo.typedMemberInfo.arrayStride; + + shader->append(instruction); + + arg = &unpackedUniform; + index = 0; + } + else if((srcBlock->matrixPacking() == EmpRowMajor) && memberType.isMatrix()) + { + int numCols = memberType.getNominalSize(); + int numRows = memberType.getSecondarySize(); + int arraySize = (memberType.isArray() ? memberType.getArraySize() : 1); + + ASSERT(argumentInfo.clampedIndex < (numCols * arraySize)); + + unsigned int dstIndex = registerIndex(&unpackedUniform); + unsigned int srcSwizzle = (argumentInfo.clampedIndex % numCols) * 0x55; + int arrayIndex = argumentInfo.clampedIndex / numCols; + int matrixStartOffset = argumentInfo.typedMemberInfo.offset + arrayIndex * argumentInfo.typedMemberInfo.arrayStride; + + for(int j = 0; j < numRows; ++j) + { + // Transpose the row major matrix + Instruction *instruction = new Instruction(sw::Shader::OPCODE_MOV); + instruction->dst.type = sw::Shader::PARAMETER_TEMP; + instruction->dst.index = dstIndex; + instruction->dst.mask = 1 << j; + instruction->src[0].type = sw::Shader::PARAMETER_CONST; + instruction->src[0].bufferIndex = argumentInfo.bufferIndex; + instruction->src[0].index = matrixStartOffset + j * argumentInfo.typedMemberInfo.matrixStride; + instruction->src[0].swizzle = srcSwizzle; + + shader->append(instruction); + } + + arg = &unpackedUniform; + index = 0; + } + } + + const ArgumentInfo argumentInfo = getArgumentInfo(arg, index); + const TType &type = argumentInfo.typedMemberInfo.type; + + int size = registerSize(type, argumentInfo.clampedIndex); + + parameter.type = registerType(arg); + parameter.bufferIndex = argumentInfo.bufferIndex; + + if(arg->getAsConstantUnion() && arg->getAsConstantUnion()->getUnionArrayPointer()) + { + int component = componentCount(type, argumentInfo.clampedIndex); + ConstantUnion *constants = arg->getAsConstantUnion()->getUnionArrayPointer(); + + for(int i = 0; i < 4; i++) + { + if(size == 1) // Replicate + { + parameter.value[i] = constants[component + 0].getAsFloat(); + } + else if(i < size) + { + parameter.value[i] = constants[component + i].getAsFloat(); + } + else + { + parameter.value[i] = 0.0f; + } + } + } + else + { + parameter.index = registerIndex(arg) + argumentInfo.clampedIndex; + + if(parameter.bufferIndex != -1) + { + int stride = (argumentInfo.typedMemberInfo.matrixStride > 0) ? argumentInfo.typedMemberInfo.matrixStride : argumentInfo.typedMemberInfo.arrayStride; + parameter.index = argumentInfo.typedMemberInfo.offset + argumentInfo.clampedIndex * stride; + } + } + + if(!IsSampler(arg->getBasicType())) + { + parameter.swizzle = readSwizzle(arg, size); + } + } + } + + void OutputASM::copy(TIntermTyped *dst, TIntermNode *src, int offset) + { + for(int index = 0; index < dst->totalRegisterCount(); index++) + { + Instruction *mov = emit(sw::Shader::OPCODE_MOV, dst, index, src, offset + index); + mov->dst.mask = writeMask(dst, index); + } + } + + int swizzleElement(int swizzle, int index) + { + return (swizzle >> (index * 2)) & 0x03; + } + + int swizzleSwizzle(int leftSwizzle, int rightSwizzle) + { + return (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 0)) << 0) | + (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 1)) << 2) | + (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 2)) << 4) | + (swizzleElement(leftSwizzle, swizzleElement(rightSwizzle, 3)) << 6); + } + + void OutputASM::assignLvalue(TIntermTyped *dst, TIntermTyped *src) + { + if(src && + ((src->isVector() && (!dst->isVector() || (src->getNominalSize() != dst->getNominalSize()))) || + (src->isMatrix() && (!dst->isMatrix() || (src->getNominalSize() != dst->getNominalSize()) || (src->getSecondarySize() != dst->getSecondarySize()))))) + { + return mContext.error(src->getLine(), "Result type should match the l-value type in compound assignment", src->isVector() ? "vector" : "matrix"); + } + + TIntermBinary *binary = dst->getAsBinaryNode(); + + if(binary && binary->getOp() == EOpIndexIndirect && binary->getLeft()->isVector() && dst->isScalar()) + { + Instruction *insert = new Instruction(sw::Shader::OPCODE_INSERT); + + Temporary address(this); + lvalue(insert->dst, address, dst); + + insert->src[0].type = insert->dst.type; + insert->src[0].index = insert->dst.index; + insert->src[0].rel = insert->dst.rel; + argument(insert->src[1], src); + argument(insert->src[2], binary->getRight()); + + shader->append(insert); + } + else + { + for(int offset = 0; offset < dst->totalRegisterCount(); offset++) + { + Instruction *mov = new Instruction(sw::Shader::OPCODE_MOV); + + Temporary address(this); + int swizzle = lvalue(mov->dst, address, dst); + mov->dst.index += offset; + + if(offset > 0) + { + mov->dst.mask = writeMask(dst, offset); + } + + argument(mov->src[0], src, offset); + mov->src[0].swizzle = swizzleSwizzle(mov->src[0].swizzle, swizzle); + + shader->append(mov); + } + } + } + + int OutputASM::lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node) + { + TIntermTyped *result = node; + TIntermBinary *binary = node->getAsBinaryNode(); + TIntermSymbol *symbol = node->getAsSymbolNode(); + + if(binary) + { + TIntermTyped *left = binary->getLeft(); + TIntermTyped *right = binary->getRight(); + + int leftSwizzle = lvalue(dst, address, left); // Resolve the l-value of the left side + + switch(binary->getOp()) + { + case EOpIndexDirect: + { + int rightIndex = right->getAsConstantUnion()->getIConst(0); + + if(left->isRegister()) + { + int leftMask = dst.mask; + + dst.mask = 1; + while((leftMask & dst.mask) == 0) + { + dst.mask = dst.mask << 1; + } + + int element = swizzleElement(leftSwizzle, rightIndex); + dst.mask = 1 << element; + + return element; + } + else if(left->isArray() || left->isMatrix()) + { + dst.index += rightIndex * result->totalRegisterCount(); + return 0xE4; + } + else UNREACHABLE(0); + } + break; + case EOpIndexIndirect: + { + if(left->isRegister()) + { + // Requires INSERT instruction (handled by calling function) + } + else if(left->isArray() || left->isMatrix()) + { + int scale = result->totalRegisterCount(); + + if(dst.rel.type == sw::Shader::PARAMETER_VOID) // Use the index register as the relative address directly + { + if(left->totalRegisterCount() > 1) + { + sw::Shader::SourceParameter relativeRegister; + argument(relativeRegister, right); + + dst.rel.index = relativeRegister.index; + dst.rel.type = relativeRegister.type; + dst.rel.scale = scale; + dst.rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform); + } + } + else if(dst.rel.index != registerIndex(&address)) // Move the previous index register to the address register + { + if(scale == 1) + { + Constant oldScale((int)dst.rel.scale); + Instruction *mad = emit(sw::Shader::OPCODE_IMAD, &address, &address, &oldScale, right); + mad->src[0].index = dst.rel.index; + mad->src[0].type = dst.rel.type; + } + else + { + Constant oldScale((int)dst.rel.scale); + Instruction *mul = emit(sw::Shader::OPCODE_IMUL, &address, &address, &oldScale); + mul->src[0].index = dst.rel.index; + mul->src[0].type = dst.rel.type; + + Constant newScale(scale); + emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address); + } + + dst.rel.type = sw::Shader::PARAMETER_TEMP; + dst.rel.index = registerIndex(&address); + dst.rel.scale = 1; + } + else // Just add the new index to the address register + { + if(scale == 1) + { + emit(sw::Shader::OPCODE_IADD, &address, &address, right); + } + else + { + Constant newScale(scale); + emit(sw::Shader::OPCODE_IMAD, &address, right, &newScale, &address); + } + } + } + else UNREACHABLE(0); + } + break; + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + { + const TFieldList& fields = (binary->getOp() == EOpIndexDirectStruct) ? + left->getType().getStruct()->fields() : + left->getType().getInterfaceBlock()->fields(); + int index = right->getAsConstantUnion()->getIConst(0); + int fieldOffset = 0; + + for(int i = 0; i < index; i++) + { + fieldOffset += fields[i]->type()->totalRegisterCount(); + } + + dst.type = registerType(left); + dst.index += fieldOffset; + dst.mask = writeMask(right); + + return 0xE4; + } + break; + case EOpVectorSwizzle: + { + ASSERT(left->isRegister()); + + int leftMask = dst.mask; + + int swizzle = 0; + int rightMask = 0; + + TIntermSequence &sequence = right->getAsAggregate()->getSequence(); + + for(unsigned int i = 0; i < sequence.size(); i++) + { + int index = sequence[i]->getAsConstantUnion()->getIConst(0); + + int element = swizzleElement(leftSwizzle, index); + rightMask = rightMask | (1 << element); + swizzle = swizzle | swizzleElement(leftSwizzle, i) << (element * 2); + } + + dst.mask = leftMask & rightMask; + + return swizzle; + } + break; + default: + UNREACHABLE(binary->getOp()); // Not an l-value operator + break; + } + } + else if(symbol) + { + dst.type = registerType(symbol); + dst.index = registerIndex(symbol); + dst.mask = writeMask(symbol); + return 0xE4; + } + + return 0xE4; + } + + sw::Shader::ParameterType OutputASM::registerType(TIntermTyped *operand) + { + if(isSamplerRegister(operand)) + { + return sw::Shader::PARAMETER_SAMPLER; + } + + const TQualifier qualifier = operand->getQualifier(); + if((EvqFragColor == qualifier) || (EvqFragData == qualifier)) + { + if(((EvqFragData == qualifier) && (EvqFragColor == outputQualifier)) || + ((EvqFragColor == qualifier) && (EvqFragData == outputQualifier))) + { + mContext.error(operand->getLine(), "static assignment to both gl_FragData and gl_FragColor", ""); + } + outputQualifier = qualifier; + } + + if(qualifier == EvqConstExpr && (!operand->getAsConstantUnion() || !operand->getAsConstantUnion()->getUnionArrayPointer())) + { + return sw::Shader::PARAMETER_TEMP; + } + + switch(qualifier) + { + case EvqTemporary: return sw::Shader::PARAMETER_TEMP; + case EvqGlobal: return sw::Shader::PARAMETER_TEMP; + case EvqConstExpr: return sw::Shader::PARAMETER_FLOAT4LITERAL; // All converted to float + case EvqAttribute: return sw::Shader::PARAMETER_INPUT; + case EvqVaryingIn: return sw::Shader::PARAMETER_INPUT; + case EvqVaryingOut: return sw::Shader::PARAMETER_OUTPUT; + case EvqVertexIn: return sw::Shader::PARAMETER_INPUT; + case EvqFragmentOut: return sw::Shader::PARAMETER_COLOROUT; + case EvqVertexOut: return sw::Shader::PARAMETER_OUTPUT; + case EvqFragmentIn: return sw::Shader::PARAMETER_INPUT; + case EvqInvariantVaryingIn: return sw::Shader::PARAMETER_INPUT; // FIXME: Guarantee invariance at the backend + case EvqInvariantVaryingOut: return sw::Shader::PARAMETER_OUTPUT; // FIXME: Guarantee invariance at the backend + case EvqSmooth: return sw::Shader::PARAMETER_OUTPUT; + case EvqFlat: return sw::Shader::PARAMETER_OUTPUT; + case EvqCentroidOut: return sw::Shader::PARAMETER_OUTPUT; + case EvqSmoothIn: return sw::Shader::PARAMETER_INPUT; + case EvqFlatIn: return sw::Shader::PARAMETER_INPUT; + case EvqCentroidIn: return sw::Shader::PARAMETER_INPUT; + case EvqUniform: return sw::Shader::PARAMETER_CONST; + case EvqIn: return sw::Shader::PARAMETER_TEMP; + case EvqOut: return sw::Shader::PARAMETER_TEMP; + case EvqInOut: return sw::Shader::PARAMETER_TEMP; + case EvqConstReadOnly: return sw::Shader::PARAMETER_TEMP; + case EvqPosition: return sw::Shader::PARAMETER_OUTPUT; + case EvqPointSize: return sw::Shader::PARAMETER_OUTPUT; + case EvqInstanceID: return sw::Shader::PARAMETER_MISCTYPE; + case EvqFragCoord: return sw::Shader::PARAMETER_MISCTYPE; + case EvqFrontFacing: return sw::Shader::PARAMETER_MISCTYPE; + case EvqPointCoord: return sw::Shader::PARAMETER_INPUT; + case EvqFragColor: return sw::Shader::PARAMETER_COLOROUT; + case EvqFragData: return sw::Shader::PARAMETER_COLOROUT; + case EvqFragDepth: return sw::Shader::PARAMETER_DEPTHOUT; + default: UNREACHABLE(qualifier); + } + + return sw::Shader::PARAMETER_VOID; + } + + unsigned int OutputASM::registerIndex(TIntermTyped *operand) + { + if(isSamplerRegister(operand)) + { + return samplerRegister(operand); + } + + switch(operand->getQualifier()) + { + case EvqTemporary: return temporaryRegister(operand); + case EvqGlobal: return temporaryRegister(operand); + case EvqConstExpr: return temporaryRegister(operand); // Unevaluated constant expression + case EvqAttribute: return attributeRegister(operand); + case EvqVaryingIn: return varyingRegister(operand); + case EvqVaryingOut: return varyingRegister(operand); + case EvqVertexIn: return attributeRegister(operand); + case EvqFragmentOut: return fragmentOutputRegister(operand); + case EvqVertexOut: return varyingRegister(operand); + case EvqFragmentIn: return varyingRegister(operand); + case EvqInvariantVaryingIn: return varyingRegister(operand); + case EvqInvariantVaryingOut: return varyingRegister(operand); + case EvqSmooth: return varyingRegister(operand); + case EvqFlat: return varyingRegister(operand); + case EvqCentroidOut: return varyingRegister(operand); + case EvqSmoothIn: return varyingRegister(operand); + case EvqFlatIn: return varyingRegister(operand); + case EvqCentroidIn: return varyingRegister(operand); + case EvqUniform: return uniformRegister(operand); + case EvqIn: return temporaryRegister(operand); + case EvqOut: return temporaryRegister(operand); + case EvqInOut: return temporaryRegister(operand); + case EvqConstReadOnly: return temporaryRegister(operand); + case EvqPosition: return varyingRegister(operand); + case EvqPointSize: return varyingRegister(operand); + case EvqInstanceID: vertexShader->instanceIdDeclared = true; return 0; + case EvqFragCoord: pixelShader->vPosDeclared = true; return 0; + case EvqFrontFacing: pixelShader->vFaceDeclared = true; return 1; + case EvqPointCoord: return varyingRegister(operand); + case EvqFragColor: return 0; + case EvqFragData: return fragmentOutputRegister(operand); + case EvqFragDepth: return 0; + default: UNREACHABLE(operand->getQualifier()); + } + + return 0; + } + + int OutputASM::writeMask(TIntermTyped *destination, int index) + { + if(destination->getQualifier() == EvqPointSize) + { + return 0x2; // Point size stored in the y component + } + + return 0xF >> (4 - registerSize(destination->getType(), index)); + } + + int OutputASM::readSwizzle(TIntermTyped *argument, int size) + { + if(argument->getQualifier() == EvqPointSize) + { + return 0x55; // Point size stored in the y component + } + + static const unsigned char swizzleSize[5] = {0x00, 0x00, 0x54, 0xA4, 0xE4}; // (void), xxxx, xyyy, xyzz, xyzw + + return swizzleSize[size]; + } + + // Conservatively checks whether an expression is fast to compute and has no side effects + bool OutputASM::trivial(TIntermTyped *expression, int budget) + { + if(!expression->isRegister()) + { + return false; + } + + return cost(expression, budget) >= 0; + } + + // Returns the remaining computing budget (if < 0 the expression is too expensive or has side effects) + int OutputASM::cost(TIntermNode *expression, int budget) + { + if(budget < 0) + { + return budget; + } + + if(expression->getAsSymbolNode()) + { + return budget; + } + else if(expression->getAsConstantUnion()) + { + return budget; + } + else if(expression->getAsBinaryNode()) + { + TIntermBinary *binary = expression->getAsBinaryNode(); + + switch(binary->getOp()) + { + case EOpVectorSwizzle: + case EOpIndexDirect: + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: + return cost(binary->getLeft(), budget - 0); + case EOpAdd: + case EOpSub: + case EOpMul: + return cost(binary->getLeft(), cost(binary->getRight(), budget - 1)); + default: + return -1; + } + } + else if(expression->getAsUnaryNode()) + { + TIntermUnary *unary = expression->getAsUnaryNode(); + + switch(unary->getOp()) + { + case EOpAbs: + case EOpNegative: + return cost(unary->getOperand(), budget - 1); + default: + return -1; + } + } + else if(expression->getAsSelectionNode()) + { + TIntermSelection *selection = expression->getAsSelectionNode(); + + if(selection->usesTernaryOperator()) + { + TIntermTyped *condition = selection->getCondition(); + TIntermNode *trueBlock = selection->getTrueBlock(); + TIntermNode *falseBlock = selection->getFalseBlock(); + TIntermConstantUnion *constantCondition = condition->getAsConstantUnion(); + + if(constantCondition) + { + bool trueCondition = constantCondition->getUnionArrayPointer()->getBConst(); + + if(trueCondition) + { + return cost(trueBlock, budget - 0); + } + else + { + return cost(falseBlock, budget - 0); + } + } + else + { + return cost(trueBlock, cost(falseBlock, budget - 2)); + } + } + } + + return -1; + } + + const Function *OutputASM::findFunction(const TString &name) + { + for(unsigned int f = 0; f < functionArray.size(); f++) + { + if(functionArray[f].name == name) + { + return &functionArray[f]; + } + } + + return 0; + } + + int OutputASM::temporaryRegister(TIntermTyped *temporary) + { + return allocate(temporaries, temporary); + } + + int OutputASM::varyingRegister(TIntermTyped *varying) + { + int var = lookup(varyings, varying); + + if(var == -1) + { + var = allocate(varyings, varying); + int componentCount = varying->registerSize(); + int registerCount = varying->totalRegisterCount(); + + if(pixelShader) + { + if((var + registerCount) > sw::PixelShader::MAX_INPUT_VARYINGS) + { + mContext.error(varying->getLine(), "Varyings packing failed: Too many varyings", "fragment shader"); + return 0; + } + + if(varying->getQualifier() == EvqPointCoord) + { + ASSERT(varying->isRegister()); + if(componentCount >= 1) pixelShader->semantic[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var); + if(componentCount >= 2) pixelShader->semantic[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var); + if(componentCount >= 3) pixelShader->semantic[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var); + if(componentCount >= 4) pixelShader->semantic[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, var); + } + else + { + for(int i = 0; i < varying->totalRegisterCount(); i++) + { + if(componentCount >= 1) pixelShader->semantic[var + i][0] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i); + if(componentCount >= 2) pixelShader->semantic[var + i][1] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i); + if(componentCount >= 3) pixelShader->semantic[var + i][2] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i); + if(componentCount >= 4) pixelShader->semantic[var + i][3] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, var + i); + } + } + } + else if(vertexShader) + { + if((var + registerCount) > sw::VertexShader::MAX_OUTPUT_VARYINGS) + { + mContext.error(varying->getLine(), "Varyings packing failed: Too many varyings", "vertex shader"); + return 0; + } + + if(varying->getQualifier() == EvqPosition) + { + ASSERT(varying->isRegister()); + vertexShader->output[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0); + vertexShader->output[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0); + vertexShader->output[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0); + vertexShader->output[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_POSITION, 0); + vertexShader->positionRegister = var; + } + else if(varying->getQualifier() == EvqPointSize) + { + ASSERT(varying->isRegister()); + vertexShader->output[var][0] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0); + vertexShader->output[var][1] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0); + vertexShader->output[var][2] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0); + vertexShader->output[var][3] = sw::Shader::Semantic(sw::Shader::USAGE_PSIZE, 0); + vertexShader->pointSizeRegister = var; + } + else + { + // Semantic indexes for user varyings will be assigned during program link to match the pixel shader + } + } + else UNREACHABLE(0); + + declareVarying(varying, var); + } + + return var; + } + + void OutputASM::declareVarying(TIntermTyped *varying, int reg) + { + if(varying->getQualifier() != EvqPointCoord) // gl_PointCoord does not need linking + { + const TType &type = varying->getType(); + const char *name = varying->getAsSymbolNode()->getSymbol().c_str(); + VaryingList &activeVaryings = shaderObject->varyings; + + // Check if this varying has been declared before without having a register assigned + for(VaryingList::iterator v = activeVaryings.begin(); v != activeVaryings.end(); v++) + { + if(v->name == name) + { + if(reg >= 0) + { + ASSERT(v->reg < 0 || v->reg == reg); + v->reg = reg; + } + + return; + } + } + + activeVaryings.push_back(glsl::Varying(glVariableType(type), name, varying->getArraySize(), reg, 0)); + } + } + + int OutputASM::uniformRegister(TIntermTyped *uniform) + { + const TType &type = uniform->getType(); + ASSERT(!IsSampler(type.getBasicType())); + TInterfaceBlock *block = type.getAsInterfaceBlock(); + TIntermSymbol *symbol = uniform->getAsSymbolNode(); + ASSERT(symbol || block); + + if(symbol || block) + { + TInterfaceBlock* parentBlock = type.getInterfaceBlock(); + bool isBlockMember = (!block && parentBlock); + int index = isBlockMember ? lookup(uniforms, parentBlock) : lookup(uniforms, uniform); + + if(index == -1 || isBlockMember) + { + if(index == -1) + { + index = allocate(uniforms, uniform); + } + + // Verify if the current uniform is a member of an already declared block + const TString &name = symbol ? symbol->getSymbol() : block->name(); + int blockMemberIndex = blockMemberLookup(type, name, index); + if(blockMemberIndex == -1) + { + declareUniform(type, name, index); + } + else + { + index = blockMemberIndex; + } + } + + return index; + } + + return 0; + } + + int OutputASM::attributeRegister(TIntermTyped *attribute) + { + ASSERT(!attribute->isArray()); + + int index = lookup(attributes, attribute); + + if(index == -1) + { + TIntermSymbol *symbol = attribute->getAsSymbolNode(); + ASSERT(symbol); + + if(symbol) + { + index = allocate(attributes, attribute); + const TType &type = attribute->getType(); + int registerCount = attribute->totalRegisterCount(); + + if(vertexShader && (index + registerCount) <= sw::VertexShader::MAX_INPUT_ATTRIBUTES) + { + for(int i = 0; i < registerCount; i++) + { + vertexShader->input[index + i] = sw::Shader::Semantic(sw::Shader::USAGE_TEXCOORD, index + i); + } + } + + ActiveAttributes &activeAttributes = shaderObject->activeAttributes; + + const char *name = symbol->getSymbol().c_str(); + activeAttributes.push_back(Attribute(glVariableType(type), name, type.getArraySize(), type.getLayoutQualifier().location, index)); + } + } + + return index; + } + + int OutputASM::fragmentOutputRegister(TIntermTyped *fragmentOutput) + { + return allocate(fragmentOutputs, fragmentOutput); + } + + int OutputASM::samplerRegister(TIntermTyped *sampler) + { + const TType &type = sampler->getType(); + ASSERT(IsSampler(type.getBasicType()) || type.isStruct()); // Structures can contain samplers + + TIntermSymbol *symbol = sampler->getAsSymbolNode(); + TIntermBinary *binary = sampler->getAsBinaryNode(); + + if(symbol && type.getQualifier() == EvqUniform) + { + return samplerRegister(symbol); + } + else if(binary) + { + TIntermTyped *left = binary->getLeft(); + TIntermTyped *right = binary->getRight(); + const TType &leftType = left->getType(); + int index = right->getAsConstantUnion() ? right->getAsConstantUnion()->getIConst(0) : 0; + int offset = 0; + + switch(binary->getOp()) + { + case EOpIndexDirect: + ASSERT(left->isArray()); + offset = index * leftType.elementRegisterCount(); + break; + case EOpIndexDirectStruct: + ASSERT(leftType.isStruct()); + { + const TFieldList &fields = leftType.getStruct()->fields(); + + for(int i = 0; i < index; i++) + { + offset += fields[i]->type()->totalRegisterCount(); + } + } + break; + case EOpIndexIndirect: // Indirect indexing produces a temporary, not a sampler register + return -1; + case EOpIndexDirectInterfaceBlock: // Interface blocks can't contain samplers + default: + UNREACHABLE(binary->getOp()); + return -1; + } + + int base = samplerRegister(left); + + if(base < 0) + { + return -1; + } + + return base + offset; + } + + UNREACHABLE(0); + return -1; // Not a sampler register + } + + int OutputASM::samplerRegister(TIntermSymbol *sampler) + { + const TType &type = sampler->getType(); + ASSERT(IsSampler(type.getBasicType()) || type.isStruct()); // Structures can contain samplers + + int index = lookup(samplers, sampler); + + if(index == -1) + { + index = allocate(samplers, sampler); + + if(sampler->getQualifier() == EvqUniform) + { + const char *name = sampler->getSymbol().c_str(); + declareUniform(type, name, index); + } + } + + return index; + } + + bool OutputASM::isSamplerRegister(TIntermTyped *operand) + { + return operand && IsSampler(operand->getBasicType()) && samplerRegister(operand) >= 0; + } + + int OutputASM::lookup(VariableArray &list, TIntermTyped *variable) + { + for(unsigned int i = 0; i < list.size(); i++) + { + if(list[i] == variable) + { + return i; // Pointer match + } + } + + TIntermSymbol *varSymbol = variable->getAsSymbolNode(); + TInterfaceBlock *varBlock = variable->getType().getAsInterfaceBlock(); + + if(varBlock) + { + for(unsigned int i = 0; i < list.size(); i++) + { + if(list[i]) + { + TInterfaceBlock *listBlock = list[i]->getType().getAsInterfaceBlock(); + + if(listBlock) + { + if(listBlock->name() == varBlock->name()) + { + ASSERT(listBlock->arraySize() == varBlock->arraySize()); + ASSERT(listBlock->fields() == varBlock->fields()); + ASSERT(listBlock->blockStorage() == varBlock->blockStorage()); + ASSERT(listBlock->matrixPacking() == varBlock->matrixPacking()); + + return i; + } + } + } + } + } + else if(varSymbol) + { + for(unsigned int i = 0; i < list.size(); i++) + { + if(list[i]) + { + TIntermSymbol *listSymbol = list[i]->getAsSymbolNode(); + + if(listSymbol) + { + if(listSymbol->getId() == varSymbol->getId()) + { + ASSERT(listSymbol->getSymbol() == varSymbol->getSymbol()); + ASSERT(listSymbol->getType() == varSymbol->getType()); + ASSERT(listSymbol->getQualifier() == varSymbol->getQualifier()); + + return i; + } + } + } + } + } + + return -1; + } + + int OutputASM::lookup(VariableArray &list, TInterfaceBlock *block) + { + for(unsigned int i = 0; i < list.size(); i++) + { + if(list[i] && (list[i]->getType().getInterfaceBlock() == block)) + { + return i; // Pointer match + } + } + return -1; + } + + int OutputASM::allocate(VariableArray &list, TIntermTyped *variable) + { + int index = lookup(list, variable); + + if(index == -1) + { + unsigned int registerCount = variable->blockRegisterCount(); + + for(unsigned int i = 0; i < list.size(); i++) + { + if(list[i] == 0) + { + unsigned int j = 1; + for( ; j < registerCount && (i + j) < list.size(); j++) + { + if(list[i + j] != 0) + { + break; + } + } + + if(j == registerCount) // Found free slots + { + for(unsigned int j = 0; j < registerCount; j++) + { + list[i + j] = variable; + } + + return i; + } + } + } + + index = list.size(); + + for(unsigned int i = 0; i < registerCount; i++) + { + list.push_back(variable); + } + } + + return index; + } + + void OutputASM::free(VariableArray &list, TIntermTyped *variable) + { + int index = lookup(list, variable); + + if(index >= 0) + { + list[index] = 0; + } + } + + int OutputASM::blockMemberLookup(const TType &type, const TString &name, int registerIndex) + { + const TInterfaceBlock *block = type.getInterfaceBlock(); + + if(block) + { + ActiveUniformBlocks &activeUniformBlocks = shaderObject->activeUniformBlocks; + const TFieldList& fields = block->fields(); + const TString &blockName = block->name(); + int fieldRegisterIndex = registerIndex; + + if(!type.isInterfaceBlock()) + { + // This is a uniform that's part of a block, let's see if the block is already defined + for(size_t i = 0; i < activeUniformBlocks.size(); ++i) + { + if(activeUniformBlocks[i].name == blockName.c_str()) + { + // The block is already defined, find the register for the current uniform and return it + for(size_t j = 0; j < fields.size(); j++) + { + const TString &fieldName = fields[j]->name(); + if(fieldName == name) + { + return fieldRegisterIndex; + } + + fieldRegisterIndex += fields[j]->type()->totalRegisterCount(); + } + + ASSERT(false); + return fieldRegisterIndex; + } + } + } + } + + return -1; + } + + void OutputASM::declareUniform(const TType &type, const TString &name, int registerIndex, int blockId, BlockLayoutEncoder* encoder) + { + const TStructure *structure = type.getStruct(); + const TInterfaceBlock *block = (type.isInterfaceBlock() || (blockId == -1)) ? type.getInterfaceBlock() : nullptr; + + if(!structure && !block) + { + ActiveUniforms &activeUniforms = shaderObject->activeUniforms; + const BlockMemberInfo blockInfo = encoder ? encoder->encodeType(type) : BlockMemberInfo::getDefaultBlockInfo(); + if(blockId >= 0) + { + blockDefinitions[blockId][registerIndex] = TypedMemberInfo(blockInfo, type); + shaderObject->activeUniformBlocks[blockId].fields.push_back(activeUniforms.size()); + } + int fieldRegisterIndex = encoder ? shaderObject->activeUniformBlocks[blockId].registerIndex + BlockLayoutEncoder::getBlockRegister(blockInfo) : registerIndex; + activeUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), + fieldRegisterIndex, blockId, blockInfo)); + if(IsSampler(type.getBasicType())) + { + for(int i = 0; i < type.totalRegisterCount(); i++) + { + shader->declareSampler(fieldRegisterIndex + i); + } + } + } + else if(block) + { + ActiveUniformBlocks &activeUniformBlocks = shaderObject->activeUniformBlocks; + const TFieldList& fields = block->fields(); + const TString &blockName = block->name(); + int fieldRegisterIndex = registerIndex; + bool isUniformBlockMember = !type.isInterfaceBlock() && (blockId == -1); + + blockId = activeUniformBlocks.size(); + bool isRowMajor = block->matrixPacking() == EmpRowMajor; + activeUniformBlocks.push_back(UniformBlock(blockName.c_str(), 0, block->arraySize(), + block->blockStorage(), isRowMajor, registerIndex, blockId)); + blockDefinitions.push_back(BlockDefinitionIndexMap()); + + Std140BlockEncoder currentBlockEncoder(isRowMajor); + currentBlockEncoder.enterAggregateType(); + for(size_t i = 0; i < fields.size(); i++) + { + const TType &fieldType = *(fields[i]->type()); + const TString &fieldName = fields[i]->name(); + if(isUniformBlockMember && (fieldName == name)) + { + registerIndex = fieldRegisterIndex; + } + + const TString uniformName = block->hasInstanceName() ? blockName + "." + fieldName : fieldName; + + declareUniform(fieldType, uniformName, fieldRegisterIndex, blockId, ¤tBlockEncoder); + fieldRegisterIndex += fieldType.totalRegisterCount(); + } + currentBlockEncoder.exitAggregateType(); + activeUniformBlocks[blockId].dataSize = currentBlockEncoder.getBlockSize(); + } + else + { + int fieldRegisterIndex = registerIndex; + + const TFieldList& fields = structure->fields(); + if(type.isArray() && (structure || type.isInterfaceBlock())) + { + for(int i = 0; i < type.getArraySize(); i++) + { + if(encoder) + { + encoder->enterAggregateType(); + } + for(size_t j = 0; j < fields.size(); j++) + { + const TType &fieldType = *(fields[j]->type()); + const TString &fieldName = fields[j]->name(); + const TString uniformName = name + "[" + str(i) + "]." + fieldName; + + declareUniform(fieldType, uniformName, fieldRegisterIndex, blockId, encoder); + fieldRegisterIndex += fieldType.totalRegisterCount(); + } + if(encoder) + { + encoder->exitAggregateType(); + } + } + } + else + { + if(encoder) + { + encoder->enterAggregateType(); + } + for(size_t i = 0; i < fields.size(); i++) + { + const TType &fieldType = *(fields[i]->type()); + const TString &fieldName = fields[i]->name(); + const TString uniformName = name + "." + fieldName; + + declareUniform(fieldType, uniformName, fieldRegisterIndex, blockId, encoder); + fieldRegisterIndex += fieldType.totalRegisterCount(); + } + if(encoder) + { + encoder->exitAggregateType(); + } + } + } + } + + GLenum OutputASM::glVariableType(const TType &type) + { + switch(type.getBasicType()) + { + case EbtFloat: + if(type.isScalar()) + { + return GL_FLOAT; + } + else if(type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_FLOAT_VEC2; + case 3: return GL_FLOAT_VEC3; + case 4: return GL_FLOAT_VEC4; + default: UNREACHABLE(type.getNominalSize()); + } + } + else if(type.isMatrix()) + { + switch(type.getNominalSize()) + { + case 2: + switch(type.getSecondarySize()) + { + case 2: return GL_FLOAT_MAT2; + case 3: return GL_FLOAT_MAT2x3; + case 4: return GL_FLOAT_MAT2x4; + default: UNREACHABLE(type.getSecondarySize()); + } + case 3: + switch(type.getSecondarySize()) + { + case 2: return GL_FLOAT_MAT3x2; + case 3: return GL_FLOAT_MAT3; + case 4: return GL_FLOAT_MAT3x4; + default: UNREACHABLE(type.getSecondarySize()); + } + case 4: + switch(type.getSecondarySize()) + { + case 2: return GL_FLOAT_MAT4x2; + case 3: return GL_FLOAT_MAT4x3; + case 4: return GL_FLOAT_MAT4; + default: UNREACHABLE(type.getSecondarySize()); + } + default: UNREACHABLE(type.getNominalSize()); + } + } + else UNREACHABLE(0); + break; + case EbtInt: + if(type.isScalar()) + { + return GL_INT; + } + else if(type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_INT_VEC2; + case 3: return GL_INT_VEC3; + case 4: return GL_INT_VEC4; + default: UNREACHABLE(type.getNominalSize()); + } + } + else UNREACHABLE(0); + break; + case EbtUInt: + if(type.isScalar()) + { + return GL_UNSIGNED_INT; + } + else if(type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_UNSIGNED_INT_VEC2; + case 3: return GL_UNSIGNED_INT_VEC3; + case 4: return GL_UNSIGNED_INT_VEC4; + default: UNREACHABLE(type.getNominalSize()); + } + } + else UNREACHABLE(0); + break; + case EbtBool: + if(type.isScalar()) + { + return GL_BOOL; + } + else if(type.isVector()) + { + switch(type.getNominalSize()) + { + case 2: return GL_BOOL_VEC2; + case 3: return GL_BOOL_VEC3; + case 4: return GL_BOOL_VEC4; + default: UNREACHABLE(type.getNominalSize()); + } + } + else UNREACHABLE(0); + break; + case EbtSampler2D: + return GL_SAMPLER_2D; + case EbtISampler2D: + return GL_INT_SAMPLER_2D; + case EbtUSampler2D: + return GL_UNSIGNED_INT_SAMPLER_2D; + case EbtSamplerCube: + return GL_SAMPLER_CUBE; + case EbtISamplerCube: + return GL_INT_SAMPLER_CUBE; + case EbtUSamplerCube: + return GL_UNSIGNED_INT_SAMPLER_CUBE; + case EbtSamplerExternalOES: + return GL_SAMPLER_EXTERNAL_OES; + case EbtSampler3D: + return GL_SAMPLER_3D_OES; + case EbtISampler3D: + return GL_INT_SAMPLER_3D; + case EbtUSampler3D: + return GL_UNSIGNED_INT_SAMPLER_3D; + case EbtSampler2DArray: + return GL_SAMPLER_2D_ARRAY; + case EbtISampler2DArray: + return GL_INT_SAMPLER_2D_ARRAY; + case EbtUSampler2DArray: + return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; + case EbtSampler2DShadow: + return GL_SAMPLER_2D_SHADOW; + case EbtSamplerCubeShadow: + return GL_SAMPLER_CUBE_SHADOW; + case EbtSampler2DArrayShadow: + return GL_SAMPLER_2D_ARRAY_SHADOW; + default: + UNREACHABLE(type.getBasicType()); + break; + } + + return GL_NONE; + } + + GLenum OutputASM::glVariablePrecision(const TType &type) + { + if(type.getBasicType() == EbtFloat) + { + switch(type.getPrecision()) + { + case EbpHigh: return GL_HIGH_FLOAT; + case EbpMedium: return GL_MEDIUM_FLOAT; + case EbpLow: return GL_LOW_FLOAT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: UNREACHABLE(type.getPrecision()); + } + } + else if(type.getBasicType() == EbtInt) + { + switch(type.getPrecision()) + { + case EbpHigh: return GL_HIGH_INT; + case EbpMedium: return GL_MEDIUM_INT; + case EbpLow: return GL_LOW_INT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: UNREACHABLE(type.getPrecision()); + } + } + + // Other types (boolean, sampler) don't have a precision + return GL_NONE; + } + + int OutputASM::dim(TIntermNode *v) + { + TIntermTyped *vector = v->getAsTyped(); + ASSERT(vector && vector->isRegister()); + return vector->getNominalSize(); + } + + int OutputASM::dim2(TIntermNode *m) + { + TIntermTyped *matrix = m->getAsTyped(); + ASSERT(matrix && matrix->isMatrix() && !matrix->isArray()); + return matrix->getSecondarySize(); + } + + // Returns ~0u if no loop count could be determined + unsigned int OutputASM::loopCount(TIntermLoop *node) + { + // Parse loops of the form: + // for(int index = initial; index [comparator] limit; index += increment) + TIntermSymbol *index = 0; + TOperator comparator = EOpNull; + int initial = 0; + int limit = 0; + int increment = 0; + + // Parse index name and intial value + if(node->getInit()) + { + TIntermAggregate *init = node->getInit()->getAsAggregate(); + + if(init) + { + TIntermSequence &sequence = init->getSequence(); + TIntermTyped *variable = sequence[0]->getAsTyped(); + + if(variable && variable->getQualifier() == EvqTemporary) + { + TIntermBinary *assign = variable->getAsBinaryNode(); + + if(assign->getOp() == EOpInitialize) + { + TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode(); + TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion(); + + if(symbol && constant) + { + if(constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + { + index = symbol; + initial = constant->getUnionArrayPointer()[0].getIConst(); + } + } + } + } + } + } + + // Parse comparator and limit value + if(index && node->getCondition()) + { + TIntermBinary *test = node->getCondition()->getAsBinaryNode(); + + if(test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) + { + TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); + + if(constant) + { + if(constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + { + comparator = test->getOp(); + limit = constant->getUnionArrayPointer()[0].getIConst(); + } + } + } + } + + // Parse increment + if(index && comparator != EOpNull && node->getExpression()) + { + TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); + TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); + + if(binaryTerminal) + { + TOperator op = binaryTerminal->getOp(); + TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion(); + + if(constant) + { + if(constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + { + int value = constant->getUnionArrayPointer()[0].getIConst(); + + switch(op) + { + case EOpAddAssign: increment = value; break; + case EOpSubAssign: increment = -value; break; + default: UNIMPLEMENTED(); + } + } + } + } + else if(unaryTerminal) + { + TOperator op = unaryTerminal->getOp(); + + switch(op) + { + case EOpPostIncrement: increment = 1; break; + case EOpPostDecrement: increment = -1; break; + case EOpPreIncrement: increment = 1; break; + case EOpPreDecrement: increment = -1; break; + default: UNIMPLEMENTED(); + } + } + } + + if(index && comparator != EOpNull && increment != 0) + { + if(comparator == EOpLessThanEqual) + { + comparator = EOpLessThan; + limit += 1; + } + + if(comparator == EOpLessThan) + { + int iterations = (limit - initial) / increment; + + if(iterations <= 0) + { + iterations = 0; + } + + return iterations; + } + else UNIMPLEMENTED(); // Falls through + } + + return ~0u; + } + + bool LoopUnrollable::traverse(TIntermNode *node) + { + loopDepth = 0; + loopUnrollable = true; + + node->traverse(this); + + return loopUnrollable; + } + + bool LoopUnrollable::visitLoop(Visit visit, TIntermLoop *loop) + { + if(visit == PreVisit) + { + loopDepth++; + } + else if(visit == PostVisit) + { + loopDepth++; + } + + return true; + } + + bool LoopUnrollable::visitBranch(Visit visit, TIntermBranch *node) + { + if(!loopUnrollable) + { + return false; + } + + if(!loopDepth) + { + return true; + } + + switch(node->getFlowOp()) + { + case EOpKill: + case EOpReturn: + break; + case EOpBreak: + case EOpContinue: + loopUnrollable = false; + break; + default: UNREACHABLE(node->getFlowOp()); + } + + return loopUnrollable; + } + + bool LoopUnrollable::visitAggregate(Visit visit, TIntermAggregate *node) + { + return loopUnrollable; + } +}
diff --git a/src/OpenGL/compiler/OutputASM.h b/src/OpenGL/compiler/OutputASM.h index 854c262..eff3c78 100644 --- a/src/OpenGL/compiler/OutputASM.h +++ b/src/OpenGL/compiler/OutputASM.h
@@ -1,365 +1,368 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -#ifndef COMPILER_OUTPUTASM_H_ -#define COMPILER_OUTPUTASM_H_ - -#include "intermediate.h" -#include "ParseHelper.h" -#include "Shader/PixelShader.hpp" -#include "Shader/VertexShader.hpp" - -#include <list> -#include <set> -#include <map> - -namespace es2 -{ - class Shader; -} - -typedef unsigned int GLenum; - -namespace glsl -{ - struct BlockMemberInfo - { - BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {} - - BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) - : offset(offset), - arrayStride(arrayStride), - matrixStride(matrixStride), - isRowMajorMatrix(isRowMajorMatrix) - {} - - static BlockMemberInfo getDefaultBlockInfo() - { - return BlockMemberInfo(-1, -1, -1, false); - } - - int offset; - int arrayStride; - int matrixStride; - bool isRowMajorMatrix; - }; - - struct Uniform - { - Uniform(GLenum type, GLenum precision, const std::string &name, int arraySize, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo); - - GLenum type; - GLenum precision; - std::string name; - int arraySize; - - int registerIndex; - - int blockId; - BlockMemberInfo blockInfo; - }; - - typedef std::vector<Uniform> ActiveUniforms; - - struct UniformBlock - { - UniformBlock(const std::string& name, unsigned int dataSize, unsigned int arraySize, - TLayoutBlockStorage layout, bool isRowMajorLayout, int registerIndex, int blockId); - - std::string name; - unsigned int dataSize; - unsigned int arraySize; - TLayoutBlockStorage layout; - bool isRowMajorLayout; - std::vector<int> fields; - - int registerIndex; - - int blockId; - }; - - class BlockLayoutEncoder - { - public: - BlockLayoutEncoder(bool rowMajor); - virtual ~BlockLayoutEncoder() {} - - BlockMemberInfo encodeType(const TType &type); - - size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } - - virtual void enterAggregateType() = 0; - virtual void exitAggregateType() = 0; - - static const size_t BytesPerComponent = 4u; - static const unsigned int ComponentsPerRegister = 4u; - - static size_t getBlockRegister(const BlockMemberInfo &info); - static size_t getBlockRegisterElement(const BlockMemberInfo &info); - - protected: - size_t mCurrentOffset; - bool isRowMajor; - - void nextRegister(); - - virtual void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0; - virtual void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0; - }; - - // Block layout according to the std140 block layout - // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification - class Std140BlockEncoder : public BlockLayoutEncoder - { - public: - Std140BlockEncoder(bool rowMajor); - - void enterAggregateType() override; - void exitAggregateType() override; - - protected: - void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override; - void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) override; - }; - - typedef std::vector<UniformBlock> ActiveUniformBlocks; - - struct Attribute - { - Attribute(); - Attribute(GLenum type, const std::string &name, int arraySize, int location, int registerIndex); - - GLenum type; - std::string name; - int arraySize; - int location; - - int registerIndex; - }; - - typedef std::vector<Attribute> ActiveAttributes; - - struct Varying - { - Varying(GLenum type, const std::string &name, int arraySize, int reg = -1, int col = -1) - : type(type), name(name), arraySize(arraySize), reg(reg), col(col) - { - } - - bool isArray() const - { - return arraySize >= 1; - } - - int size() const // Unify with es2::Uniform? - { - return arraySize > 0 ? arraySize : 1; - } - - GLenum type; - std::string name; - int arraySize; - - int reg; // First varying register, assigned during link - int col; // First register element, assigned during link - }; - - typedef std::list<Varying> VaryingList; - - class Shader - { - friend class OutputASM; - public: - virtual ~Shader() {}; - virtual sw::Shader *getShader() const = 0; - virtual sw::PixelShader *getPixelShader() const; - virtual sw::VertexShader *getVertexShader() const; - - protected: - VaryingList varyings; - ActiveUniforms activeUniforms; - ActiveAttributes activeAttributes; - ActiveUniformBlocks activeUniformBlocks; - }; - - struct Function - { - Function(int label, const char *name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret) - { - } - - Function(int label, const TString &name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret) - { - } - - int label; - TString name; - TIntermSequence *arg; - TIntermTyped *ret; - }; - - typedef sw::Shader::Instruction Instruction; - - class Temporary; - - class OutputASM : public TIntermTraverser - { - public: - explicit OutputASM(TParseContext &context, Shader *shaderObject); - ~OutputASM(); - - void output(); - - void freeTemporary(Temporary *temporary); - - private: - enum Scope - { - GLOBAL, - FUNCTION - }; - - struct TextureFunction - { - TextureFunction(const TString& name); - - enum Method - { - IMPLICIT, // Mipmap LOD determined implicitly (standard lookup) - LOD, - SIZE, // textureSize() - FETCH, - GRAD - }; - - Method method; - bool proj; - bool offset; - }; - - void emitShader(Scope scope); - - // Visit AST nodes and output their code to the body stream - virtual void visitSymbol(TIntermSymbol*); - virtual bool visitBinary(Visit visit, TIntermBinary*); - virtual bool visitUnary(Visit visit, TIntermUnary*); - virtual bool visitSelection(Visit visit, TIntermSelection*); - virtual bool visitAggregate(Visit visit, TIntermAggregate*); - virtual bool visitLoop(Visit visit, TIntermLoop*); - virtual bool visitBranch(Visit visit, TIntermBranch*); - - sw::Shader::Opcode getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const; - Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, TIntermNode *src3 = 0, TIntermNode *src4 = 0); - Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0 = 0, int index0 = 0, TIntermNode *src1 = 0, int index1 = 0, - TIntermNode *src2 = 0, int index2 = 0, TIntermNode *src3 = 0, int index3 = 0, TIntermNode *src4 = 0, int index4 = 0); - Instruction *emitCast(TIntermTyped *dst, TIntermTyped *src); - Instruction *emitCast(TIntermTyped *dst, int dstIndex, TIntermTyped *src, int srcIndex); - void emitBinary(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0); - void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0); - void emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index = 0); - void emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col = -1, int row = -1, int outCol = 0, int outRow = 0); - void argument(sw::Shader::SourceParameter ¶meter, TIntermNode *argument, int index = 0); - void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0); - void assignLvalue(TIntermTyped *dst, TIntermTyped *src); - int lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node); - sw::Shader::ParameterType registerType(TIntermTyped *operand); - unsigned int registerIndex(TIntermTyped *operand); - int writeMask(TIntermTyped *destination, int index = 0); - int readSwizzle(TIntermTyped *argument, int size); - bool trivial(TIntermTyped *expression, int budget); // Fast to compute and no side effects - int cost(TIntermNode *expression, int budget); - const Function *findFunction(const TString &name); - - int temporaryRegister(TIntermTyped *temporary); - int varyingRegister(TIntermTyped *varying); - void declareVarying(TIntermTyped *varying, int reg); - int uniformRegister(TIntermTyped *uniform); - int attributeRegister(TIntermTyped *attribute); - int fragmentOutputRegister(TIntermTyped *fragmentOutput); - int samplerRegister(TIntermTyped *sampler); - int samplerRegister(TIntermSymbol *sampler); - bool isSamplerRegister(TIntermTyped *operand); - - typedef std::vector<TIntermTyped*> VariableArray; - - int lookup(VariableArray &list, TIntermTyped *variable); - int lookup(VariableArray &list, TInterfaceBlock *block); - int blockMemberLookup(const TType &type, const TString &name, int registerIndex); - int allocate(VariableArray &list, TIntermTyped *variable); - void free(VariableArray &list, TIntermTyped *variable); - - void declareUniform(const TType &type, const TString &name, int registerIndex, int blockId = -1, BlockLayoutEncoder* encoder = nullptr); - GLenum glVariableType(const TType &type); - GLenum glVariablePrecision(const TType &type); - - static int dim(TIntermNode *v); - static int dim2(TIntermNode *m); - static unsigned int loopCount(TIntermLoop *node); - - Shader *const shaderObject; - sw::Shader *shader; - sw::PixelShader *pixelShader; - sw::VertexShader *vertexShader; - - VariableArray temporaries; - VariableArray uniforms; - VariableArray varyings; - VariableArray attributes; - VariableArray samplers; - VariableArray fragmentOutputs; - - struct TypedMemberInfo : public BlockMemberInfo - { - TypedMemberInfo() {} - TypedMemberInfo(const BlockMemberInfo& b, const TType& t) : BlockMemberInfo(b), type(t) {} - TType type; - }; - struct ArgumentInfo - { - ArgumentInfo(const BlockMemberInfo& b, const TType& t, int clampedIndex, int bufferIndex) : - typedMemberInfo(b, t), clampedIndex(clampedIndex), bufferIndex(bufferIndex) {} - TypedMemberInfo typedMemberInfo; - int clampedIndex; - int bufferIndex; - }; - int getBlockId(TIntermTyped *argument); - ArgumentInfo getArgumentInfo(TIntermTyped *argument, int index); - - typedef std::map<int, TypedMemberInfo> BlockDefinitionIndexMap; - std::vector<BlockDefinitionIndexMap> blockDefinitions; - - Scope emitScope; - Scope currentScope; - - int currentFunction; - std::vector<Function> functionArray; - - TQualifier outputQualifier; - - TParseContext &mContext; - }; - - class LoopUnrollable : public TIntermTraverser - { - public: - bool traverse(TIntermNode *node); - - private: - bool visitBranch(Visit visit, TIntermBranch *node); - bool visitLoop(Visit visit, TIntermLoop *loop); - bool visitAggregate(Visit visit, TIntermAggregate *node); - - int loopDepth; - bool loopUnrollable; - }; -} - -#endif // COMPILER_OUTPUTASM_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_OUTPUTASM_H_ +#define COMPILER_OUTPUTASM_H_ + +#include "intermediate.h" +#include "ParseHelper.h" +#include "Shader/PixelShader.hpp" +#include "Shader/VertexShader.hpp" + +#include <list> +#include <set> +#include <map> + +namespace es2 +{ + class Shader; +} + +typedef unsigned int GLenum; + +namespace glsl +{ + struct BlockMemberInfo + { + BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {} + + BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) + : offset(offset), + arrayStride(arrayStride), + matrixStride(matrixStride), + isRowMajorMatrix(isRowMajorMatrix) + {} + + static BlockMemberInfo getDefaultBlockInfo() + { + return BlockMemberInfo(-1, -1, -1, false); + } + + int offset; + int arrayStride; + int matrixStride; + bool isRowMajorMatrix; + }; + + struct Uniform + { + Uniform(GLenum type, GLenum precision, const std::string &name, int arraySize, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo); + + GLenum type; + GLenum precision; + std::string name; + int arraySize; + + int registerIndex; + + int blockId; + BlockMemberInfo blockInfo; + }; + + typedef std::vector<Uniform> ActiveUniforms; + + struct UniformBlock + { + UniformBlock(const std::string& name, unsigned int dataSize, unsigned int arraySize, + TLayoutBlockStorage layout, bool isRowMajorLayout, int registerIndex, int blockId); + + std::string name; + unsigned int dataSize; + unsigned int arraySize; + TLayoutBlockStorage layout; + bool isRowMajorLayout; + std::vector<int> fields; + + int registerIndex; + + int blockId; + }; + + class BlockLayoutEncoder + { + public: + BlockLayoutEncoder(bool rowMajor); + virtual ~BlockLayoutEncoder() {} + + BlockMemberInfo encodeType(const TType &type); + + size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } + + virtual void enterAggregateType() = 0; + virtual void exitAggregateType() = 0; + + static const size_t BytesPerComponent = 4u; + static const unsigned int ComponentsPerRegister = 4u; + + static size_t getBlockRegister(const BlockMemberInfo &info); + static size_t getBlockRegisterElement(const BlockMemberInfo &info); + + protected: + size_t mCurrentOffset; + bool isRowMajor; + + void nextRegister(); + + virtual void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0; + virtual void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0; + }; + + // Block layout according to the std140 block layout + // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification + class Std140BlockEncoder : public BlockLayoutEncoder + { + public: + Std140BlockEncoder(bool rowMajor); + + void enterAggregateType() override; + void exitAggregateType() override; + + protected: + void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override; + void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) override; + }; + + typedef std::vector<UniformBlock> ActiveUniformBlocks; + + struct Attribute + { + Attribute(); + Attribute(GLenum type, const std::string &name, int arraySize, int location, int registerIndex); + + GLenum type; + std::string name; + int arraySize; + int location; + + int registerIndex; + }; + + typedef std::vector<Attribute> ActiveAttributes; + + struct Varying + { + Varying(GLenum type, const std::string &name, int arraySize, int reg = -1, int col = -1) + : type(type), name(name), arraySize(arraySize), reg(reg), col(col) + { + } + + bool isArray() const + { + return arraySize >= 1; + } + + int size() const // Unify with es2::Uniform? + { + return arraySize > 0 ? arraySize : 1; + } + + GLenum type; + std::string name; + int arraySize; + + int reg; // First varying register, assigned during link + int col; // First register element, assigned during link + }; + + typedef std::list<Varying> VaryingList; + + class Shader + { + friend class OutputASM; + public: + virtual ~Shader() {}; + virtual sw::Shader *getShader() const = 0; + virtual sw::PixelShader *getPixelShader() const; + virtual sw::VertexShader *getVertexShader() const; + + protected: + VaryingList varyings; + ActiveUniforms activeUniforms; + ActiveAttributes activeAttributes; + ActiveUniformBlocks activeUniformBlocks; + }; + + struct Function + { + Function(int label, const char *name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret) + { + } + + Function(int label, const TString &name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret) + { + } + + int label; + TString name; + TIntermSequence *arg; + TIntermTyped *ret; + }; + + typedef sw::Shader::Instruction Instruction; + + class Temporary; + + class OutputASM : public TIntermTraverser + { + public: + explicit OutputASM(TParseContext &context, Shader *shaderObject); + ~OutputASM(); + + void output(); + + void freeTemporary(Temporary *temporary); + + private: + enum Scope + { + GLOBAL, + FUNCTION + }; + + struct TextureFunction + { + TextureFunction(const TString& name); + + enum Method + { + IMPLICIT, // Mipmap LOD determined implicitly (standard lookup) + LOD, + SIZE, // textureSize() + FETCH, + GRAD + }; + + Method method; + bool proj; + bool offset; + }; + + void emitShader(Scope scope); + + // Visit AST nodes and output their code to the body stream + virtual void visitSymbol(TIntermSymbol*); + virtual bool visitBinary(Visit visit, TIntermBinary*); + virtual bool visitUnary(Visit visit, TIntermUnary*); + virtual bool visitSelection(Visit visit, TIntermSelection*); + virtual bool visitAggregate(Visit visit, TIntermAggregate*); + virtual bool visitLoop(Visit visit, TIntermLoop*); + virtual bool visitBranch(Visit visit, TIntermBranch*); + + sw::Shader::Opcode getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const; + Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, TIntermNode *src3 = 0, TIntermNode *src4 = 0); + Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0 = 0, int index0 = 0, TIntermNode *src1 = 0, int index1 = 0, + TIntermNode *src2 = 0, int index2 = 0, TIntermNode *src3 = 0, int index3 = 0, TIntermNode *src4 = 0, int index4 = 0); + Instruction *emitCast(TIntermTyped *dst, TIntermTyped *src); + Instruction *emitCast(TIntermTyped *dst, int dstIndex, TIntermTyped *src, int srcIndex); + void emitBinary(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0); + void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0); + void emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index = 0); + void emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col = -1, int row = -1, int outCol = 0, int outRow = 0); + void argument(sw::Shader::SourceParameter ¶meter, TIntermNode *argument, int index = 0); + void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0); + void assignLvalue(TIntermTyped *dst, TIntermTyped *src); + int lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node); + sw::Shader::ParameterType registerType(TIntermTyped *operand); + unsigned int registerIndex(TIntermTyped *operand); + int writeMask(TIntermTyped *destination, int index = 0); + int readSwizzle(TIntermTyped *argument, int size); + bool trivial(TIntermTyped *expression, int budget); // Fast to compute and no side effects + int cost(TIntermNode *expression, int budget); + const Function *findFunction(const TString &name); + + int temporaryRegister(TIntermTyped *temporary); + int varyingRegister(TIntermTyped *varying); + void declareVarying(TIntermTyped *varying, int reg); + int uniformRegister(TIntermTyped *uniform); + int attributeRegister(TIntermTyped *attribute); + int fragmentOutputRegister(TIntermTyped *fragmentOutput); + int samplerRegister(TIntermTyped *sampler); + int samplerRegister(TIntermSymbol *sampler); + bool isSamplerRegister(TIntermTyped *operand); + + typedef std::vector<TIntermTyped*> VariableArray; + + int lookup(VariableArray &list, TIntermTyped *variable); + int lookup(VariableArray &list, TInterfaceBlock *block); + int blockMemberLookup(const TType &type, const TString &name, int registerIndex); + int allocate(VariableArray &list, TIntermTyped *variable); + void free(VariableArray &list, TIntermTyped *variable); + + void declareUniform(const TType &type, const TString &name, int registerIndex, int blockId = -1, BlockLayoutEncoder* encoder = nullptr); + GLenum glVariableType(const TType &type); + GLenum glVariablePrecision(const TType &type); + + static int dim(TIntermNode *v); + static int dim2(TIntermNode *m); + static unsigned int loopCount(TIntermLoop *node); + + Shader *const shaderObject; + sw::Shader *shader; + sw::PixelShader *pixelShader; + sw::VertexShader *vertexShader; + + VariableArray temporaries; + VariableArray uniforms; + VariableArray varyings; + VariableArray attributes; + VariableArray samplers; + VariableArray fragmentOutputs; + + struct TypedMemberInfo : public BlockMemberInfo + { + TypedMemberInfo() {} + TypedMemberInfo(const BlockMemberInfo& b, const TType& t) : BlockMemberInfo(b), type(t) {} + TType type; + }; + struct ArgumentInfo + { + ArgumentInfo(const BlockMemberInfo& b, const TType& t, int clampedIndex, int bufferIndex) : + typedMemberInfo(b, t), clampedIndex(clampedIndex), bufferIndex(bufferIndex) {} + TypedMemberInfo typedMemberInfo; + int clampedIndex; + int bufferIndex; + }; + int getBlockId(TIntermTyped *argument); + ArgumentInfo getArgumentInfo(TIntermTyped *argument, int index); + + typedef std::map<int, TypedMemberInfo> BlockDefinitionIndexMap; + std::vector<BlockDefinitionIndexMap> blockDefinitions; + + Scope emitScope; + Scope currentScope; + + int currentFunction; + std::vector<Function> functionArray; + + TQualifier outputQualifier; + + TParseContext &mContext; + }; + + class LoopUnrollable : public TIntermTraverser + { + public: + bool traverse(TIntermNode *node); + + private: + bool visitBranch(Visit visit, TIntermBranch *node); + bool visitLoop(Visit visit, TIntermLoop *loop); + bool visitAggregate(Visit visit, TIntermAggregate *node); + + int loopDepth; + bool loopUnrollable; + }; +} + +#endif // COMPILER_OUTPUTASM_H_
diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp index 87f1e2d..9d8d6a2 100644 --- a/src/OpenGL/compiler/ParseHelper.cpp +++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "ParseHelper.h" @@ -26,89 +34,89 @@ // bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc &line) { - fields.num = (int) compString.size(); - if (fields.num > 4) { - error(line, "illegal vector field selection", compString.c_str()); - return false; - } + fields.num = (int) compString.size(); + if (fields.num > 4) { + error(line, "illegal vector field selection", compString.c_str()); + return false; + } - enum { - exyzw, - ergba, - estpq - } fieldSet[4]; + enum { + exyzw, + ergba, + estpq + } fieldSet[4]; - for (int i = 0; i < fields.num; ++i) { - switch (compString[i]) { - case 'x': - fields.offsets[i] = 0; - fieldSet[i] = exyzw; - break; - case 'r': - fields.offsets[i] = 0; - fieldSet[i] = ergba; - break; - case 's': - fields.offsets[i] = 0; - fieldSet[i] = estpq; - break; - case 'y': - fields.offsets[i] = 1; - fieldSet[i] = exyzw; - break; - case 'g': - fields.offsets[i] = 1; - fieldSet[i] = ergba; - break; - case 't': - fields.offsets[i] = 1; - fieldSet[i] = estpq; - break; - case 'z': - fields.offsets[i] = 2; - fieldSet[i] = exyzw; - break; - case 'b': - fields.offsets[i] = 2; - fieldSet[i] = ergba; - break; - case 'p': - fields.offsets[i] = 2; - fieldSet[i] = estpq; - break; - case 'w': - fields.offsets[i] = 3; - fieldSet[i] = exyzw; - break; - case 'a': - fields.offsets[i] = 3; - fieldSet[i] = ergba; - break; - case 'q': - fields.offsets[i] = 3; - fieldSet[i] = estpq; - break; - default: - error(line, "illegal vector field selection", compString.c_str()); - return false; - } - } + for (int i = 0; i < fields.num; ++i) { + switch (compString[i]) { + case 'x': + fields.offsets[i] = 0; + fieldSet[i] = exyzw; + break; + case 'r': + fields.offsets[i] = 0; + fieldSet[i] = ergba; + break; + case 's': + fields.offsets[i] = 0; + fieldSet[i] = estpq; + break; + case 'y': + fields.offsets[i] = 1; + fieldSet[i] = exyzw; + break; + case 'g': + fields.offsets[i] = 1; + fieldSet[i] = ergba; + break; + case 't': + fields.offsets[i] = 1; + fieldSet[i] = estpq; + break; + case 'z': + fields.offsets[i] = 2; + fieldSet[i] = exyzw; + break; + case 'b': + fields.offsets[i] = 2; + fieldSet[i] = ergba; + break; + case 'p': + fields.offsets[i] = 2; + fieldSet[i] = estpq; + break; + case 'w': + fields.offsets[i] = 3; + fieldSet[i] = exyzw; + break; + case 'a': + fields.offsets[i] = 3; + fieldSet[i] = ergba; + break; + case 'q': + fields.offsets[i] = 3; + fieldSet[i] = estpq; + break; + default: + error(line, "illegal vector field selection", compString.c_str()); + return false; + } + } - for (int i = 0; i < fields.num; ++i) { - if (fields.offsets[i] >= vecSize) { - error(line, "vector field selection out of range", compString.c_str()); - return false; - } + for (int i = 0; i < fields.num; ++i) { + if (fields.offsets[i] >= vecSize) { + error(line, "vector field selection out of range", compString.c_str()); + return false; + } - if (i > 0) { - if (fieldSet[i] != fieldSet[i-1]) { - error(line, "illegal - vector component fields not from the same set", compString.c_str()); - return false; - } - } - } + if (i > 0) { + if (fieldSet[i] != fieldSet[i-1]) { + error(line, "illegal - vector component fields not from the same set", compString.c_str()); + return false; + } + } + } - return true; + return true; } @@ -118,46 +126,46 @@ // bool TParseContext::parseMatrixFields(const TString& compString, int matCols, int matRows, TMatrixFields& fields, const TSourceLoc &line) { - fields.wholeRow = false; - fields.wholeCol = false; - fields.row = -1; - fields.col = -1; + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = -1; + fields.col = -1; - if (compString.size() != 2) { - error(line, "illegal length of matrix field selection", compString.c_str()); - return false; - } + if (compString.size() != 2) { + error(line, "illegal length of matrix field selection", compString.c_str()); + return false; + } - if (compString[0] == '_') { - if (compString[1] < '0' || compString[1] > '3') { - error(line, "illegal matrix field selection", compString.c_str()); - return false; - } - fields.wholeCol = true; - fields.col = compString[1] - '0'; - } else if (compString[1] == '_') { - if (compString[0] < '0' || compString[0] > '3') { - error(line, "illegal matrix field selection", compString.c_str()); - return false; - } - fields.wholeRow = true; - fields.row = compString[0] - '0'; - } else { - if (compString[0] < '0' || compString[0] > '3' || - compString[1] < '0' || compString[1] > '3') { - error(line, "illegal matrix field selection", compString.c_str()); - return false; - } - fields.row = compString[0] - '0'; - fields.col = compString[1] - '0'; - } + if (compString[0] == '_') { + if (compString[1] < '0' || compString[1] > '3') { + error(line, "illegal matrix field selection", compString.c_str()); + return false; + } + fields.wholeCol = true; + fields.col = compString[1] - '0'; + } else if (compString[1] == '_') { + if (compString[0] < '0' || compString[0] > '3') { + error(line, "illegal matrix field selection", compString.c_str()); + return false; + } + fields.wholeRow = true; + fields.row = compString[0] - '0'; + } else { + if (compString[0] < '0' || compString[0] > '3' || + compString[1] < '0' || compString[1] > '3') { + error(line, "illegal matrix field selection", compString.c_str()); + return false; + } + fields.row = compString[0] - '0'; + fields.col = compString[1] - '0'; + } - if (fields.row >= matRows || fields.col >= matCols) { - error(line, "matrix field selection out of range", compString.c_str()); - return false; - } + if (fields.row >= matRows || fields.col >= matCols) { + error(line, "matrix field selection out of range", compString.c_str()); + return false; + } - return true; + return true; } /////////////////////////////////////////////////////////////////////// @@ -177,26 +185,26 @@ // Used by flex/bison to output all syntax and parsing errors. // void TParseContext::error(const TSourceLoc& loc, - const char* reason, const char* token, - const char* extraInfo) + const char* reason, const char* token, + const char* extraInfo) { - pp::SourceLocation srcLoc(loc.first_file, loc.first_line); - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, - srcLoc, reason, token, extraInfo); + pp::SourceLocation srcLoc(loc.first_file, loc.first_line); + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, + srcLoc, reason, token, extraInfo); } void TParseContext::warning(const TSourceLoc& loc, - const char* reason, const char* token, - const char* extraInfo) { - pp::SourceLocation srcLoc(loc.first_file, loc.first_line); - mDiagnostics.writeInfo(pp::Diagnostics::PP_WARNING, - srcLoc, reason, token, extraInfo); + const char* reason, const char* token, + const char* extraInfo) { + pp::SourceLocation srcLoc(loc.first_file, loc.first_line); + mDiagnostics.writeInfo(pp::Diagnostics::PP_WARNING, + srcLoc, reason, token, extraInfo); } void TParseContext::trace(const char* str) { - mDiagnostics.writeDebug(str); + mDiagnostics.writeDebug(str); } // @@ -204,10 +212,10 @@ // void TParseContext::assignError(const TSourceLoc &line, const char* op, TString left, TString right) { - std::stringstream extraInfoStream; - extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", op, extraInfo.c_str()); + std::stringstream extraInfoStream; + extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", op, extraInfo.c_str()); } // @@ -215,11 +223,11 @@ // 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 - << " (or there is no acceptable conversion)"; - std::string extraInfo = extraInfoStream.str(); - error(line, " wrong operand type", op, extraInfo.c_str()); + std::stringstream extraInfoStream; + extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand + << " (or there is no acceptable conversion)"; + std::string extraInfo = extraInfoStream.str(); + error(line, " wrong operand type", op, extraInfo.c_str()); } // @@ -227,33 +235,33 @@ // 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 - << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)"; - std::string extraInfo = extraInfoStream.str(); - error(line, " wrong operand types ", op, extraInfo.c_str()); + std::stringstream extraInfoStream; + extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left + << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)"; + std::string extraInfo = extraInfoStream.str(); + error(line, " wrong operand types ", op, extraInfo.c_str()); } bool TParseContext::precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type){ - if (!mChecksPrecisionErrors) - return false; - switch( type ){ - case EbtFloat: - if( precision == EbpUndefined ){ - error( line, "No precision specified for (float)", "" ); - return true; - } - break; - case EbtInt: - if( precision == EbpUndefined ){ - error( line, "No precision specified (int)", "" ); - return true; - } - break; - default: - return false; - } - return false; + if (!mChecksPrecisionErrors) + return false; + switch( type ){ + case EbtFloat: + if( precision == EbpUndefined ){ + error( line, "No precision specified for (float)", "" ); + return true; + } + break; + case EbtInt: + if( precision == EbpUndefined ){ + error( line, "No precision specified (int)", "" ); + return true; + } + break; + default: + return false; + } + return false; } // @@ -264,113 +272,113 @@ // bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char* op, TIntermTyped* node) { - TIntermSymbol* symNode = node->getAsSymbolNode(); - TIntermBinary* binaryNode = node->getAsBinaryNode(); + TIntermSymbol* symNode = node->getAsSymbolNode(); + TIntermBinary* binaryNode = node->getAsBinaryNode(); - if (binaryNode) { - bool errorReturn; + if (binaryNode) { + bool errorReturn; - switch(binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - return lValueErrorCheck(line, op, binaryNode->getLeft()); - case EOpVectorSwizzle: - errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); - if (!errorReturn) { - int offset[4] = {0,0,0,0}; + switch(binaryNode->getOp()) { + case EOpIndexDirect: + case EOpIndexIndirect: + case EOpIndexDirectStruct: + return lValueErrorCheck(line, op, binaryNode->getLeft()); + case EOpVectorSwizzle: + errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); + if (!errorReturn) { + int offset[4] = {0,0,0,0}; - TIntermTyped* rightNode = binaryNode->getRight(); - TIntermAggregate *aggrNode = rightNode->getAsAggregate(); + TIntermTyped* rightNode = binaryNode->getRight(); + TIntermAggregate *aggrNode = rightNode->getAsAggregate(); - for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); - p != aggrNode->getSequence().end(); p++) { - int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); - offset[value]++; - if (offset[value] > 1) { - error(line, " l-value of swizzle cannot have duplicate components", op); + for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); + p != aggrNode->getSequence().end(); p++) { + int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); + offset[value]++; + if (offset[value] > 1) { + error(line, " l-value of swizzle cannot have duplicate components", op); - return true; - } - } - } + return true; + } + } + } - return errorReturn; - default: - break; - } - error(line, " l-value required", op); + return errorReturn; + default: + break; + } + error(line, " l-value required", op); - return true; - } + return true; + } - const char* symbol = 0; - if (symNode != 0) - symbol = symNode->getSymbol().c_str(); + const char* symbol = 0; + if (symNode != 0) + symbol = symNode->getSymbol().c_str(); - const char* message = 0; - switch (node->getQualifier()) { - case EvqConstExpr: message = "can't modify a const"; break; - case EvqConstReadOnly: message = "can't modify a const"; break; - case EvqAttribute: message = "can't modify an attribute"; break; - case EvqFragmentIn: message = "can't modify an input"; break; - case EvqVertexIn: message = "can't modify an input"; break; - case EvqUniform: message = "can't modify a uniform"; break; - case EvqSmoothIn: - case EvqFlatIn: - case EvqCentroidIn: - 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; - case EvqInstanceID: message = "can't modify gl_InstanceID"; break; - default: + const char* message = 0; + switch (node->getQualifier()) { + case EvqConstExpr: message = "can't modify a const"; break; + case EvqConstReadOnly: message = "can't modify a const"; break; + case EvqAttribute: message = "can't modify an attribute"; break; + case EvqFragmentIn: message = "can't modify an input"; break; + case EvqVertexIn: message = "can't modify an input"; break; + case EvqUniform: message = "can't modify a uniform"; break; + case EvqSmoothIn: + case EvqFlatIn: + case EvqCentroidIn: + 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; + case EvqInstanceID: message = "can't modify gl_InstanceID"; break; + default: - // - // Type that can't be written to? - // - if(IsSampler(node->getBasicType())) - { - message = "can't modify a sampler"; - } - else if(node->getBasicType() == EbtVoid) - { - message = "can't modify void"; - } - } + // + // Type that can't be written to? + // + if(IsSampler(node->getBasicType())) + { + message = "can't modify a sampler"; + } + else if(node->getBasicType() == EbtVoid) + { + message = "can't modify void"; + } + } - if (message == 0 && binaryNode == 0 && symNode == 0) { - error(line, " l-value required", op); + if (message == 0 && binaryNode == 0 && symNode == 0) { + error(line, " l-value required", op); - return true; - } + return true; + } - // - // Everything else is okay, no error. - // - if (message == 0) - return false; + // + // Everything else is okay, no error. + // + if (message == 0) + return false; - // - // If we get here, we have an error and a message. - // - if (symNode) { - std::stringstream extraInfoStream; - extraInfoStream << "\"" << symbol << "\" (" << message << ")"; - std::string extraInfo = extraInfoStream.str(); - error(line, " l-value required", op, extraInfo.c_str()); - } - else { - std::stringstream extraInfoStream; - extraInfoStream << "(" << message << ")"; - std::string extraInfo = extraInfoStream.str(); - error(line, " l-value required", op, extraInfo.c_str()); - } + // + // If we get here, we have an error and a message. + // + if (symNode) { + std::stringstream extraInfoStream; + extraInfoStream << "\"" << symbol << "\" (" << message << ")"; + std::string extraInfo = extraInfoStream.str(); + error(line, " l-value required", op, extraInfo.c_str()); + } + else { + std::stringstream extraInfoStream; + extraInfoStream << "(" << message << ")"; + std::string extraInfo = extraInfoStream.str(); + error(line, " l-value required", op, extraInfo.c_str()); + } - return true; + return true; } // @@ -381,12 +389,12 @@ // bool TParseContext::constErrorCheck(TIntermTyped* node) { - if (node->getQualifier() == EvqConstExpr) - return false; + if (node->getQualifier() == EvqConstExpr) + return false; - error(node->getLine(), "constant expression required", ""); + error(node->getLine(), "constant expression required", ""); - return true; + return true; } // @@ -397,12 +405,12 @@ // bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) { - if (node->isScalarInt()) - return false; + if (node->isScalarInt()) + return false; - error(node->getLine(), "integer expression required", token); + error(node->getLine(), "integer expression required", token); - return true; + return true; } // @@ -413,12 +421,12 @@ // bool TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char* token) { - if (global) - return false; + if (global) + return false; - error(line, "only allowed at global scope", token); + error(line, "only allowed at global scope", token); - return true; + return true; } // @@ -432,19 +440,19 @@ // bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString& identifier) { - static const char* reservedErrMsg = "reserved built-in name"; - if (!symbolTable.atBuiltInLevel()) { - if (identifier.compare(0, 3, "gl_") == 0) { - error(line, reservedErrMsg, "gl_"); - return true; - } - if (identifier.find("__") != TString::npos) { - error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str()); - return true; - } - } + static const char* reservedErrMsg = "reserved built-in name"; + if (!symbolTable.atBuiltInLevel()) { + if (identifier.compare(0, 3, "gl_") == 0) { + error(line, reservedErrMsg, "gl_"); + return true; + } + if (identifier.find("__") != TString::npos) { + error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str()); + return true; + } + } - return false; + return false; } // @@ -456,104 +464,104 @@ // bool TParseContext::constructorErrorCheck(const TSourceLoc &line, TIntermNode* node, TFunction& function, TOperator op, TType* type) { - *type = function.getReturnType(); + *type = function.getReturnType(); - bool constructingMatrix = false; - switch(op) { - case EOpConstructMat2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4: - constructingMatrix = true; - break; - default: - break; - } + bool constructingMatrix = false; + switch(op) { + case EOpConstructMat2: + case EOpConstructMat2x3: + case EOpConstructMat2x4: + case EOpConstructMat3x2: + case EOpConstructMat3: + case EOpConstructMat3x4: + case EOpConstructMat4x2: + case EOpConstructMat4x3: + case EOpConstructMat4: + constructingMatrix = true; + break; + default: + break; + } - // - // Note: It's okay to have too many components available, but not okay to have unused - // arguments. 'full' will go to true when enough args have been seen. If we loop - // again, there is an extra argument, so 'overfull' will become true. - // + // + // Note: It's okay to have too many components available, but not okay to have unused + // arguments. 'full' will go to true when enough args have been seen. If we loop + // again, there is an extra argument, so 'overfull' will become true. + // - size_t size = 0; - bool full = false; - bool overFull = false; - bool matrixInMatrix = false; - bool arrayArg = false; - for (size_t i = 0; i < function.getParamCount(); ++i) { - const TParameter& param = function.getParam(i); - size += param.type->getObjectSize(); + size_t size = 0; + bool full = false; + bool overFull = false; + bool matrixInMatrix = false; + bool arrayArg = false; + for (size_t i = 0; i < function.getParamCount(); ++i) { + const TParameter& param = function.getParam(i); + size += param.type->getObjectSize(); - if (constructingMatrix && param.type->isMatrix()) - matrixInMatrix = true; - if (full) - overFull = true; - if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) - full = true; - if (param.type->isArray()) - arrayArg = true; - } + if (constructingMatrix && param.type->isMatrix()) + matrixInMatrix = true; + if (full) + overFull = true; + if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) + full = true; + if (param.type->isArray()) + arrayArg = true; + } - if(type->isArray()) { - if(type->getArraySize() == 0) { - type->setArraySize(function.getParamCount()); - } else if(type->getArraySize() != (int)function.getParamCount()) { - error(line, "array constructor needs one argument per array element", "constructor"); - return true; - } - } + if(type->isArray()) { + if(type->getArraySize() == 0) { + type->setArraySize(function.getParamCount()); + } else if(type->getArraySize() != (int)function.getParamCount()) { + error(line, "array constructor needs one argument per array element", "constructor"); + return true; + } + } - if (arrayArg && op != EOpConstructStruct) { - error(line, "constructing from a non-dereferenced array", "constructor"); - return true; - } + if (arrayArg && op != EOpConstructStruct) { + error(line, "constructing from a non-dereferenced array", "constructor"); + return true; + } - if (matrixInMatrix && !type->isArray()) { - if (function.getParamCount() != 1) { - error(line, "constructing matrix from matrix can only take one argument", "constructor"); - return true; - } - } + if (matrixInMatrix && !type->isArray()) { + if (function.getParamCount() != 1) { + error(line, "constructing matrix from matrix can only take one argument", "constructor"); + return true; + } + } - if (overFull) { - error(line, "too many arguments", "constructor"); - return true; - } + if (overFull) { + error(line, "too many arguments", "constructor"); + return true; + } - if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) { - error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); - return true; - } + if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) { + error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); + return true; + } - if (!type->isMatrix() || !matrixInMatrix) { - if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || - (op == EOpConstructStruct && size < type->getObjectSize())) { - error(line, "not enough data provided for construction", "constructor"); - return true; - } - } + if (!type->isMatrix() || !matrixInMatrix) { + if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || + (op == EOpConstructStruct && size < type->getObjectSize())) { + error(line, "not enough data provided for construction", "constructor"); + return true; + } + } - TIntermTyped *typed = node ? node->getAsTyped() : 0; - if (typed == 0) { - error(line, "constructor argument does not have a type", "constructor"); - return true; - } - if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { - error(line, "cannot convert a sampler", "constructor"); - return true; - } - if (typed->getBasicType() == EbtVoid) { - error(line, "cannot convert a void", "constructor"); - return true; - } + TIntermTyped *typed = node ? node->getAsTyped() : 0; + if (typed == 0) { + error(line, "constructor argument does not have a type", "constructor"); + return true; + } + if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) { + error(line, "cannot convert a sampler", "constructor"); + return true; + } + if (typed->getBasicType() == EbtVoid) { + error(line, "cannot convert a void", "constructor"); + return true; + } - return false; + return false; } // This function checks to see if a void variable has been declared and raise an error message for such a case @@ -562,12 +570,12 @@ // bool TParseContext::voidErrorCheck(const TSourceLoc &line, const TString& identifier, const TBasicType& type) { - if(type == EbtVoid) { - error(line, "illegal use of type 'void'", identifier.c_str()); - return true; - } + if(type == EbtVoid) { + error(line, "illegal use of type 'void'", identifier.c_str()); + return true; + } - return false; + return false; } // This function checks to see if the node (for the expression) contains a scalar boolean expression or not @@ -576,12 +584,12 @@ // bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped* type) { - if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { - error(line, "boolean expression expected", ""); - return true; - } + if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { + error(line, "boolean expression expected", ""); + return true; + } - return false; + return false; } // This function checks to see if the node (for the expression) contains a scalar boolean expression or not @@ -590,31 +598,31 @@ // bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType& pType) { - if (pType.type != EbtBool || pType.array || (pType.primarySize > 1) || (pType.secondarySize > 1)) { - error(line, "boolean expression expected", ""); - return true; - } + if (pType.type != EbtBool || pType.array || (pType.primarySize > 1) || (pType.secondarySize > 1)) { + error(line, "boolean expression expected", ""); + return true; + } - return false; + return false; } bool TParseContext::samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason) { - if (pType.type == EbtStruct) { - if (containsSampler(*pType.userDef)) { - error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); + if (pType.type == EbtStruct) { + if (containsSampler(*pType.userDef)) { + error(line, reason, getBasicString(pType.type), "(structure contains a sampler)"); - return true; - } + return true; + } - return false; - } else if (IsSampler(pType.type)) { - error(line, reason, getBasicString(pType.type)); + return false; + } else if (IsSampler(pType.type)) { + error(line, reason, getBasicString(pType.type)); - return true; - } + return true; + } - return false; + return false; } bool TParseContext::structQualifierErrorCheck(const TSourceLoc &line, const TPublicType& pType) @@ -643,19 +651,19 @@ break; } - if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) - return true; + if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) + return true; // check for layout qualifier issues const TLayoutQualifier layoutQualifier = pType.layoutQualifier; if (pType.qualifier != EvqVertexIn && pType.qualifier != EvqFragmentOut && - layoutLocationErrorCheck(line, pType.layoutQualifier)) + layoutLocationErrorCheck(line, pType.layoutQualifier)) { return true; } - return false; + return false; } // These checks are common for all declarations starting a declarator list, and declarators that follow an empty @@ -736,29 +744,29 @@ bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType& type) { - if ((qualifier == EvqOut || qualifier == EvqInOut) && - type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { - error(line, "samplers cannot be output parameters", type.getBasicString()); - return true; - } + if ((qualifier == EvqOut || qualifier == EvqInOut) && + type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { + error(line, "samplers cannot be output parameters", type.getBasicString()); + return true; + } - return false; + return false; } bool TParseContext::containsSampler(TType& type) { - if (IsSampler(type.getBasicType())) - return true; + if (IsSampler(type.getBasicType())) + return true; - if (type.getBasicType() == EbtStruct) { - const TFieldList& fields = type.getStruct()->fields(); - for(unsigned int i = 0; i < fields.size(); ++i) { - if (containsSampler(*fields[i]->type())) - return true; - } - } + if (type.getBasicType() == EbtStruct) { + const TFieldList& fields = type.getStruct()->fields(); + for(unsigned int i = 0; i < fields.size(); ++i) { + if (containsSampler(*fields[i]->type())) + return true; + } + } - return false; + return false; } // @@ -768,39 +776,39 @@ // bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped* expr, int& size) { - TIntermConstantUnion* constant = expr->getAsConstantUnion(); + TIntermConstantUnion* constant = expr->getAsConstantUnion(); - if (constant == 0 || !constant->isScalarInt()) - { - error(line, "array size must be a constant integer expression", ""); - return true; - } + if (constant == 0 || !constant->isScalarInt()) + { + error(line, "array size must be a constant integer expression", ""); + return true; + } - if (constant->getBasicType() == EbtUInt) - { - unsigned int uintSize = constant->getUConst(0); - if (uintSize > static_cast<unsigned int>(std::numeric_limits<int>::max())) - { - error(line, "array size too large", ""); - size = 1; - return true; - } + if (constant->getBasicType() == EbtUInt) + { + unsigned int uintSize = constant->getUConst(0); + if (uintSize > static_cast<unsigned int>(std::numeric_limits<int>::max())) + { + error(line, "array size too large", ""); + size = 1; + return true; + } - size = static_cast<int>(uintSize); - } - else - { - size = constant->getIConst(0); + size = static_cast<int>(uintSize); + } + else + { + size = constant->getIConst(0); - if (size <= 0) - { - error(line, "array size must be a positive integer", ""); - size = 1; - return true; - } - } + if (size <= 0) + { + error(line, "array size must be a positive integer", ""); + size = 1; + return true; + } + } - return false; + return false; } // @@ -810,12 +818,12 @@ // bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type) { - if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConstExpr)) { - error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); - return true; - } + if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConstExpr)) { + error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); + return true; + } - return false; + return false; } // @@ -825,59 +833,59 @@ // bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type) { - // - // Can the type be an array? - // - if (type.array) { - error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str()); - return true; - } + // + // Can the type be an array? + // + if (type.array) { + error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str()); + return true; + } - return false; + return false; } bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, const TSourceLoc &line) { - bool builtIn = false; - TSymbol* symbol = symbolTable.find(node->getSymbol(), mShaderVersion, &builtIn); - if (symbol == 0) { - error(line, " undeclared identifier", node->getSymbol().c_str()); - return true; - } - TVariable* variable = static_cast<TVariable*>(symbol); + bool builtIn = false; + TSymbol* symbol = symbolTable.find(node->getSymbol(), mShaderVersion, &builtIn); + if (symbol == 0) { + error(line, " undeclared identifier", node->getSymbol().c_str()); + return true; + } + TVariable* variable = static_cast<TVariable*>(symbol); - type->setArrayInformationType(variable->getArrayInformationType()); - variable->updateArrayInformationType(type); + 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", mShaderVersion, &builtIn); - ASSERT(fragData); + // 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", mShaderVersion, &builtIn); + ASSERT(fragData); - int fragDataValue = static_cast<TVariable*>(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; - } - } + int fragDataValue = static_cast<TVariable*>(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; + // 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; + size++; + variable->getType().setMaxArraySize(size); + type->setMaxArraySize(size); + TType* tt = type; - while(tt->getArrayInformationType() != 0) { - tt = tt->getArrayInformationType(); - tt->setMaxArraySize(size); - } + while(tt->getArrayInformationType() != 0) { + tt = tt->getArrayInformationType(); + tt->setMaxArraySize(size); + } - return false; + return false; } // @@ -887,28 +895,28 @@ // bool TParseContext::nonInitConstErrorCheck(const TSourceLoc &line, TString& identifier, TPublicType& type, bool array) { - if (type.qualifier == EvqConstExpr) - { - // Make the qualifier make sense. - type.qualifier = EvqTemporary; + if (type.qualifier == EvqConstExpr) + { + // Make the qualifier make sense. + type.qualifier = EvqTemporary; - if (array) - { - error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str()); - } - else if (type.isStructureContainingArrays()) - { - error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str()); - } - else - { - error(line, "variables with qualifier 'const' must be initialized", identifier.c_str()); - } + if (array) + { + error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str()); + } + else if (type.isStructureContainingArrays()) + { + error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str()); + } + else + { + error(line, "variables with qualifier 'const' must be initialized", identifier.c_str()); + } - return true; - } + return true; + } - return false; + return false; } // @@ -989,42 +997,42 @@ bool TParseContext::paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type) { - if (qualifier != EvqConstReadOnly && qualifier != EvqTemporary) { - error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); - return true; - } - if (qualifier == EvqConstReadOnly && paramQualifier != EvqIn) { - error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier)); - return true; - } + if (qualifier != EvqConstReadOnly && qualifier != EvqTemporary) { + error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); + return true; + } + if (qualifier == EvqConstReadOnly && paramQualifier != EvqIn) { + error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier)); + return true; + } - if (qualifier == EvqConstReadOnly) - type->setQualifier(EvqConstReadOnly); - else - type->setQualifier(paramQualifier); + if (qualifier == EvqConstReadOnly) + type->setQualifier(EvqConstReadOnly); + else + type->setQualifier(paramQualifier); - return false; + return false; } bool TParseContext::extensionErrorCheck(const TSourceLoc &line, const TString& extension) { - const TExtensionBehavior& extBehavior = extensionBehavior(); - TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); - if (iter == extBehavior.end()) { - error(line, "extension", extension.c_str(), "is not supported"); - return true; - } - // In GLSL ES, an extension's default behavior is "disable". - if (iter->second == EBhDisable || iter->second == EBhUndefined) { - error(line, "extension", extension.c_str(), "is disabled"); - return true; - } - if (iter->second == EBhWarn) { - warning(line, "extension", extension.c_str(), "is being used"); - return false; - } + const TExtensionBehavior& extBehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); + if (iter == extBehavior.end()) { + error(line, "extension", extension.c_str(), "is not supported"); + return true; + } + // In GLSL ES, an extension's default behavior is "disable". + if (iter->second == EBhDisable || iter->second == EBhUndefined) { + error(line, "extension", extension.c_str(), "is disabled"); + return true; + } + if (iter->second == EBhWarn) { + warning(line, "extension", extension.c_str(), "is being used"); + return false; + } - return false; + return false; } bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate) @@ -1067,21 +1075,21 @@ bool TParseContext::supportsExtension(const char* extension) { - const TExtensionBehavior& extbehavior = extensionBehavior(); - TExtensionBehavior::const_iterator iter = extbehavior.find(extension); - return (iter != extbehavior.end()); + const TExtensionBehavior& extbehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extbehavior.find(extension); + return (iter != extbehavior.end()); } void TParseContext::handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior) { - pp::SourceLocation loc(line.first_file, line.first_line); - mDirectiveHandler.handleExtension(loc, extName, behavior); + pp::SourceLocation loc(line.first_file, line.first_line); + mDirectiveHandler.handleExtension(loc, extName, behavior); } void TParseContext::handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value) { - pp::SourceLocation loc(line.first_file, line.first_line); - mDirectiveHandler.handlePragma(loc, name, value); + pp::SourceLocation loc(line.first_file, line.first_line); + mDirectiveHandler.handlePragma(loc, name, value); } ///////////////////////////////////////////////////////////////////////////////// @@ -1094,7 +1102,7 @@ const TString *name, const TSymbol *symbol) { - const TVariable *variable = NULL; + const TVariable *variable = nullptr; if(!symbol) { @@ -1155,24 +1163,24 @@ // 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. - const TSymbol* symbol = symbolTable.find(call->getName(), mShaderVersion, builtIn); - if (symbol == 0) { - symbol = symbolTable.find(call->getMangledName(), mShaderVersion, builtIn); - } + // First find by unmangled name to check whether the function name has been + // hidden by a variable name or struct typename. + const TSymbol* symbol = symbolTable.find(call->getName(), mShaderVersion, builtIn); + if (symbol == 0) { + symbol = symbolTable.find(call->getMangledName(), mShaderVersion, builtIn); + } - if (symbol == 0) { - error(line, "no matching overloaded function found", call->getName().c_str()); - return 0; - } + if (symbol == 0) { + error(line, "no matching overloaded function found", call->getName().c_str()); + return 0; + } - if (!symbol->isFunction()) { - error(line, "function name expected", call->getName().c_str()); - return 0; - } + if (!symbol->isFunction()) { + error(line, "function name expected", call->getName().c_str()); + return 0; + } - return static_cast<const TFunction*>(symbol); + return static_cast<const TFunction*>(symbol); } // @@ -1180,7 +1188,7 @@ // code to handle them here. // bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, const TPublicType& pType, - TIntermTyped *initializer, TIntermNode **intermNode) + TIntermTyped *initializer, TIntermNode **intermNode) { ASSERT(intermNode != nullptr); TType type = TType(pType); @@ -1208,59 +1216,59 @@ { warning(line, "global variable initializers should be constant expressions " "(uniforms and globals are allowed in global initializers for legacy compatibility)", "="); - } + } - // - // identifier must be of type constant, a global, or a temporary - // - TQualifier qualifier = type.getQualifier(); - if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) { - error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString()); - return true; - } - // - // test for and propagate constant - // + // + // identifier must be of type constant, a global, or a temporary + // + TQualifier qualifier = type.getQualifier(); + if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) { + error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString()); + return true; + } + // + // test for and propagate constant + // - if (qualifier == EvqConstExpr) { - if (qualifier != initializer->getQualifier()) { - std::stringstream extraInfoStream; - extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, " assigning non-constant to", "=", extraInfo.c_str()); - variable->getType().setQualifier(EvqTemporary); - return true; - } + if (qualifier == EvqConstExpr) { + if (qualifier != initializer->getQualifier()) { + std::stringstream extraInfoStream; + extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, " assigning non-constant to", "=", extraInfo.c_str()); + variable->getType().setQualifier(EvqTemporary); + return true; + } - if (type != initializer->getType()) { - error(line, " non-matching types for const initializer ", - variable->getType().getQualifierString()); - variable->getType().setQualifier(EvqTemporary); - return true; - } + if (type != initializer->getType()) { + error(line, " non-matching types for const initializer ", + variable->getType().getQualifierString()); + variable->getType().setQualifier(EvqTemporary); + return true; + } - if (initializer->getAsConstantUnion()) { - variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - } else if (initializer->getAsSymbolNode()) { - const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0); - const TVariable* tVar = static_cast<const TVariable*>(symbol); + if (initializer->getAsConstantUnion()) { + variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); + } else if (initializer->getAsSymbolNode()) { + const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0); + const TVariable* tVar = static_cast<const TVariable*>(symbol); - ConstantUnion* constArray = tVar->getConstPointer(); - variable->shareConstPointer(constArray); - } - } + ConstantUnion* constArray = tVar->getConstPointer(); + variable->shareConstPointer(constArray); + } + } - if (!variable->isConstant()) { - TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); - *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line); - if(*intermNode == nullptr) { - assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); - return true; - } - } else - *intermNode = nullptr; + if (!variable->isConstant()) { + TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); + *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line); + if(*intermNode == nullptr) { + assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); + return true; + } + } else + *intermNode = nullptr; - return false; + return false; } TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier) @@ -2062,61 +2070,61 @@ // TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc &line) { - TIntermAggregate *aggregateArguments = arguments->getAsAggregate(); + TIntermAggregate *aggregateArguments = arguments->getAsAggregate(); - if(!aggregateArguments) - { - aggregateArguments = new TIntermAggregate; - aggregateArguments->getSequence().push_back(arguments); - } + if(!aggregateArguments) + { + aggregateArguments = new TIntermAggregate; + aggregateArguments->getSequence().push_back(arguments); + } - if(op == EOpConstructStruct) - { - const TFieldList &fields = type->getStruct()->fields(); - TIntermSequence &args = aggregateArguments->getSequence(); + if(op == EOpConstructStruct) + { + const TFieldList &fields = type->getStruct()->fields(); + TIntermSequence &args = aggregateArguments->getSequence(); - for(size_t i = 0; i < fields.size(); i++) - { - if(args[i]->getAsTyped()->getType() != *fields[i]->type()) - { - error(line, "Structure constructor arguments do not match structure fields", "Error"); - recover(); + for(size_t i = 0; i < fields.size(); i++) + { + if(args[i]->getAsTyped()->getType() != *fields[i]->type()) + { + error(line, "Structure constructor arguments do not match structure fields", "Error"); + recover(); - return 0; - } - } - } + return 0; + } + } + } - // Turn the argument list itself into a constructor - TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); - TIntermTyped *constConstructor = foldConstConstructor(constructor, *type); - if(constConstructor) - { - return constConstructor; - } + // Turn the argument list itself into a constructor + TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); + TIntermTyped *constConstructor = foldConstConstructor(constructor, *type); + if(constConstructor) + { + return constConstructor; + } - return constructor; + return constructor; } TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) { - aggrNode->setType(type); - if (aggrNode->isConstantFoldable()) { - bool returnVal = false; - ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; - if (aggrNode->getSequence().size() == 1) { - returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true); - } - else { - returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type); - } - if (returnVal) - return 0; + aggrNode->setType(type); + if (aggrNode->isConstantFoldable()) { + bool returnVal = false; + ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; + if (aggrNode->getSequence().size() == 1) { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true); + } + else { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type); + } + if (returnVal) + return 0; - return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); - } + return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); + } - return 0; + return 0; } // @@ -2128,40 +2136,40 @@ // TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc &line) { - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); - ConstantUnion *unionArray; - if (tempConstantNode) { - unionArray = tempConstantNode->getUnionArrayPointer(); + ConstantUnion *unionArray; + if (tempConstantNode) { + unionArray = tempConstantNode->getUnionArrayPointer(); - if (!unionArray) { - return node; - } - } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error - error(line, "Cannot offset into the vector", "Error"); - recover(); + if (!unionArray) { + return node; + } + } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error + error(line, "Cannot offset into the vector", "Error"); + recover(); - return 0; - } + return 0; + } - ConstantUnion* constArray = new ConstantUnion[fields.num]; + ConstantUnion* constArray = new ConstantUnion[fields.num]; - for (int i = 0; i < fields.num; i++) { - if (fields.offsets[i] >= node->getType().getObjectSize()) { - std::stringstream extraInfoStream; - extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "[", extraInfo.c_str()); - recover(); - fields.offsets[i] = 0; - } + for (int i = 0; i < fields.num; i++) { + if (fields.offsets[i] >= node->getType().getObjectSize()) { + std::stringstream extraInfoStream; + extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "[", extraInfo.c_str()); + recover(); + fields.offsets[i] = 0; + } - constArray[i] = unionArray[fields.offsets[i]]; + constArray[i] = unionArray[fields.offsets[i]]; - } - typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); - return typedNode; + } + typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); + return typedNode; } // @@ -2172,30 +2180,30 @@ // TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc &line) { - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); - if (index >= node->getType().getNominalSize()) { - std::stringstream extraInfoStream; - extraInfoStream << "matrix field selection out of range '" << index << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "[", extraInfo.c_str()); - recover(); - index = 0; - } + if (index >= node->getType().getNominalSize()) { + std::stringstream extraInfoStream; + extraInfoStream << "matrix field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "[", extraInfo.c_str()); + recover(); + index = 0; + } - if (tempConstantNode) { - ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); - int size = tempConstantNode->getType().getNominalSize(); - typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); - } else { - error(line, "Cannot offset into the matrix", "Error"); - recover(); + if (tempConstantNode) { + ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); + int size = tempConstantNode->getType().getNominalSize(); + typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); + } else { + error(line, "Cannot offset into the matrix", "Error"); + recover(); - return 0; - } + return 0; + } - return typedNode; + return typedNode; } @@ -2207,33 +2215,33 @@ // TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line) { - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); - TType arrayElementType = node->getType(); - arrayElementType.clearArrayness(); + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + TType arrayElementType = node->getType(); + arrayElementType.clearArrayness(); - if (index >= node->getType().getArraySize()) { - std::stringstream extraInfoStream; - extraInfoStream << "array field selection out of range '" << index << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "[", extraInfo.c_str()); - recover(); - index = 0; - } + if (index >= node->getType().getArraySize()) { + std::stringstream extraInfoStream; + extraInfoStream << "array field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "[", extraInfo.c_str()); + recover(); + index = 0; + } - size_t arrayElementSize = arrayElementType.getObjectSize(); + size_t arrayElementSize = arrayElementType.getObjectSize(); - if (tempConstantNode) { - ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); - typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); - } else { - error(line, "Cannot offset into the array", "Error"); - recover(); + if (tempConstantNode) { + ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); + typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); + } else { + error(line, "Cannot offset into the array", "Error"); + recover(); - return 0; - } + return 0; + } - return typedNode; + return typedNode; } @@ -2244,38 +2252,38 @@ // TIntermTyped* TParseContext::addConstStruct(const TString& identifier, TIntermTyped* node, const TSourceLoc &line) { - const TFieldList &fields = node->getType().getStruct()->fields(); - TIntermTyped *typedNode; - size_t instanceSize = 0; - TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); + const TFieldList &fields = node->getType().getStruct()->fields(); + TIntermTyped *typedNode; + size_t instanceSize = 0; + TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); - for(size_t index = 0; index < fields.size(); ++index) { - if (fields[index]->name() == identifier) { - break; - } else { - instanceSize += fields[index]->type()->getObjectSize(); - } - } + for(size_t index = 0; index < fields.size(); ++index) { + if (fields[index]->name() == identifier) { + break; + } else { + instanceSize += fields[index]->type()->getObjectSize(); + } + } - if (tempConstantNode) { - ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); + if (tempConstantNode) { + ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); - typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function - } else { - error(line, "Cannot offset into the structure", "Error"); - recover(); + typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function + } else { + error(line, "Cannot offset into the structure", "Error"); + recover(); - return 0; - } + return 0; + } - return typedNode; + return typedNode; } // // Interface/uniform blocks // TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList, - const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine) + const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine) { if(reservedErrorCheck(nameLine, blockName)) recover(); @@ -2357,7 +2365,7 @@ // add array index int arraySize = 0; - if(arrayIndex != NULL) + if(arrayIndex) { if(arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize)) recover(); @@ -2416,7 +2424,7 @@ // TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, TIntermTyped *indexExpression) { - TIntermTyped *indexedExpression = NULL; + TIntermTyped *indexedExpression = nullptr; if(!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) { @@ -2576,7 +2584,7 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation, const TString &fieldString, const TSourceLoc &fieldLocation) { - TIntermTyped *indexedExpression = NULL; + TIntermTyped *indexedExpression = nullptr; if(baseExpression->isArray()) { @@ -2769,9 +2777,9 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine) { - TLayoutQualifier qualifier; + TLayoutQualifier qualifier; - qualifier.location = -1; + qualifier.location = -1; qualifier.matrixPacking = EmpUnspecified; qualifier.blockStorage = EbsUnspecified; @@ -2796,57 +2804,57 @@ qualifier.matrixPacking = EmpColumnMajor; } else if(qualifierType == "location") - { - error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument"); - recover(); - } - else - { - error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); - recover(); - } + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument"); + recover(); + } + else + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); + recover(); + } - return qualifier; + return qualifier; } TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine) { - TLayoutQualifier qualifier; + TLayoutQualifier qualifier; - qualifier.location = -1; - qualifier.matrixPacking = EmpUnspecified; - qualifier.blockStorage = EbsUnspecified; + qualifier.location = -1; + qualifier.matrixPacking = EmpUnspecified; + qualifier.blockStorage = EbsUnspecified; - if (qualifierType != "location") - { - error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments"); - recover(); - } - else - { - // must check that location is non-negative - if (intValue < 0) - { - error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative"); - recover(); - } - else - { - qualifier.location = intValue; - } - } + if (qualifierType != "location") + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments"); + recover(); + } + else + { + // must check that location is non-negative + if (intValue < 0) + { + error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative"); + recover(); + } + else + { + qualifier.location = intValue; + } + } - return qualifier; + return qualifier; } TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier) { - TLayoutQualifier joinedQualifier = leftQualifier; + TLayoutQualifier joinedQualifier = leftQualifier; - if (rightQualifier.location != -1) - { - joinedQualifier.location = rightQualifier.location; - } + if (rightQualifier.location != -1) + { + joinedQualifier.location = rightQualifier.location; + } if(rightQualifier.matrixPacking != EmpUnspecified) { joinedQualifier.matrixPacking = rightQualifier.matrixPacking; @@ -2856,7 +2864,7 @@ joinedQualifier.blockStorage = rightQualifier.blockStorage; } - return joinedQualifier; + return joinedQualifier; } @@ -2999,22 +3007,22 @@ bool TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString& identifier) { - ++mStructNestingLevel; + ++mStructNestingLevel; - // Embedded structure definitions are not supported per GLSL ES spec. - // They aren't allowed in GLSL either, but we need to detect this here - // so we don't rely on the GLSL compiler to catch it. - if (mStructNestingLevel > 1) { - error(line, "", "Embedded struct definitions are not allowed"); - return true; - } + // Embedded structure definitions are not supported per GLSL ES spec. + // They aren't allowed in GLSL either, but we need to detect this here + // so we don't rely on the GLSL compiler to catch it. + if (mStructNestingLevel > 1) { + error(line, "", "Embedded struct definitions are not allowed"); + return true; + } - return false; + return false; } void TParseContext::exitStructDeclaration() { - --mStructNestingLevel; + --mStructNestingLevel; } bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField &field) @@ -3663,20 +3671,20 @@ // Returns 0 for success. // int PaParseStrings(int count, const char* const string[], const int length[], - TParseContext* context) { - if ((count == 0) || (string == NULL)) - return 1; + TParseContext* context) { + if ((count == 0) || !string) + return 1; - if (glslang_initialize(context)) - return 1; + if (glslang_initialize(context)) + return 1; - int error = glslang_scan(count, string, length, context); - if (!error) - error = glslang_parse(context); + int error = glslang_scan(count, string, length, context); + if (!error) + error = glslang_parse(context); - glslang_finalize(context); + glslang_finalize(context); - return (error == 0) && (context->numErrors() == 0) ? 0 : 1; + return (error == 0) && (context->numErrors() == 0) ? 0 : 1; }
diff --git a/src/OpenGL/compiler/ParseHelper.h b/src/OpenGL/compiler/ParseHelper.h index d6b08b3..8733ef5 100644 --- a/src/OpenGL/compiler/ParseHelper.h +++ b/src/OpenGL/compiler/ParseHelper.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _PARSER_HELPER_INCLUDED_ #define _PARSER_HELPER_INCLUDED_ @@ -14,10 +22,10 @@ #include "SymbolTable.h" struct TMatrixFields { - bool wholeRow; - bool wholeCol; - int row; - int col; + bool wholeRow; + bool wholeCol; + int row; + int col; }; // @@ -26,129 +34,129 @@ // class TParseContext { public: - TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, GLenum type, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : - intermediate(interm), - symbolTable(symt), - compileOptions(options), - sourcePath(sourcePath), - lexAfterType(false), - inTypeParen(false), - AfterEOF(false), - mDeferredSingleDeclarationErrorCheck(false), - mShaderType(type), - mShaderVersion(100), - mTreeRoot(0), - mLoopNestingLevel(0), - mSwitchNestingLevel(0), - mStructNestingLevel(0), - mCurrentFunctionType(NULL), - mFunctionReturnsValue(false), - mChecksPrecisionErrors(checksPrecErrors), - mDefaultMatrixPacking(EmpColumnMajor), - mDefaultBlockStorage(EbsShared), - mDiagnostics(is), - mDirectiveHandler(ext, mDiagnostics, mShaderVersion), - mPreprocessor(&mDiagnostics, &mDirectiveHandler), - mScanner(NULL), - mUsesFragData(false), - mUsesFragColor(false) { } - TIntermediate& intermediate; // to hold and build a parse tree - TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed - int compileOptions; - const char* sourcePath; // Path of source file or NULL. - bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier - bool inTypeParen; // true if in parentheses, looking only for an identifier - bool AfterEOF; + TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, GLenum type, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : + intermediate(interm), + symbolTable(symt), + compileOptions(options), + sourcePath(sourcePath), + lexAfterType(false), + inTypeParen(false), + AfterEOF(false), + mDeferredSingleDeclarationErrorCheck(false), + mShaderType(type), + mShaderVersion(100), + mTreeRoot(0), + mLoopNestingLevel(0), + mSwitchNestingLevel(0), + mStructNestingLevel(0), + mCurrentFunctionType(nullptr), + mFunctionReturnsValue(false), + mChecksPrecisionErrors(checksPrecErrors), + mDefaultMatrixPacking(EmpColumnMajor), + mDefaultBlockStorage(EbsShared), + mDiagnostics(is), + mDirectiveHandler(ext, mDiagnostics, mShaderVersion), + mPreprocessor(&mDiagnostics, &mDirectiveHandler), + mScanner(nullptr), + mUsesFragData(false), + mUsesFragColor(false) { } + TIntermediate& intermediate; // to hold and build a parse tree + TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed + int compileOptions; + const char* sourcePath; // Path of source file or null. + bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier + bool inTypeParen; // true if in parentheses, looking only for an identifier + bool AfterEOF; - const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } - pp::Preprocessor &getPreprocessor() { return mPreprocessor; } - void *getScanner() const { return mScanner; } - void setScanner(void *scanner) { mScanner = scanner; } - int getShaderVersion() const { return mShaderVersion; } - GLenum getShaderType() const { return mShaderType; } - int numErrors() const { return mDiagnostics.numErrors(); } - TInfoSink &infoSink() { return mDiagnostics.infoSink(); } - void error(const TSourceLoc &loc, const char *reason, const char* token, - const char* extraInfo=""); - void warning(const TSourceLoc &loc, const char* reason, const char* token, - const char* extraInfo=""); - void trace(const char* str); - void recover(); - TIntermNode *getTreeRoot() const { return mTreeRoot; } - void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; } + const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } + pp::Preprocessor &getPreprocessor() { return mPreprocessor; } + void *getScanner() const { return mScanner; } + void setScanner(void *scanner) { mScanner = scanner; } + int getShaderVersion() const { return mShaderVersion; } + GLenum getShaderType() const { return mShaderType; } + int numErrors() const { return mDiagnostics.numErrors(); } + TInfoSink &infoSink() { return mDiagnostics.infoSink(); } + void error(const TSourceLoc &loc, const char *reason, const char* token, + const char* extraInfo=""); + void warning(const TSourceLoc &loc, const char* reason, const char* token, + const char* extraInfo=""); + void trace(const char* str); + void recover(); + TIntermNode *getTreeRoot() const { return mTreeRoot; } + void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; } - bool getFunctionReturnsValue() const { return mFunctionReturnsValue; } - void setFunctionReturnsValue(bool functionReturnsValue) - { - mFunctionReturnsValue = functionReturnsValue; - } + bool getFunctionReturnsValue() const { return mFunctionReturnsValue; } + void setFunctionReturnsValue(bool functionReturnsValue) + { + mFunctionReturnsValue = functionReturnsValue; + } - void setLoopNestingLevel(int loopNestintLevel) - { - mLoopNestingLevel = loopNestintLevel; - } + void setLoopNestingLevel(int loopNestintLevel) + { + mLoopNestingLevel = loopNestintLevel; + } - const TType *getCurrentFunctionType() const { return mCurrentFunctionType; } - void setCurrentFunctionType(const TType *currentFunctionType) - { - mCurrentFunctionType = currentFunctionType; - } + const TType *getCurrentFunctionType() const { return mCurrentFunctionType; } + void setCurrentFunctionType(const TType *currentFunctionType) + { + mCurrentFunctionType = currentFunctionType; + } - void incrLoopNestingLevel() { ++mLoopNestingLevel; } - void decrLoopNestingLevel() { --mLoopNestingLevel; } + void incrLoopNestingLevel() { ++mLoopNestingLevel; } + void decrLoopNestingLevel() { --mLoopNestingLevel; } - void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } - void decrSwitchNestingLevel() { --mSwitchNestingLevel; } + void incrSwitchNestingLevel() { ++mSwitchNestingLevel; } + void decrSwitchNestingLevel() { --mSwitchNestingLevel; } // This method is guaranteed to succeed, even if no variable with 'name' exists. const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol); - bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line); - bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc &line); + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line); + bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc &line); - 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(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 voidErrorCheck(const TSourceLoc&, const TString&, const TBasicType&); - bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); - bool boolErrorCheck(const TSourceLoc&, const TPublicType&); - bool samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason); + 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(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 voidErrorCheck(const TSourceLoc&, const TString&, const TBasicType&); + bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); + bool boolErrorCheck(const TSourceLoc&, const TPublicType&); + bool samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason); bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType); - 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, const TString& identifier, TPublicType& type); - bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type); - bool extensionErrorCheck(const TSourceLoc &line, const TString&); + 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, const TString& identifier, TPublicType& type); + bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type); + bool extensionErrorCheck(const TSourceLoc &line, const TString&); bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation); - bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier); - bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); + bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier); + bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation); - const TExtensionBehavior& extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); } - bool supportsExtension(const char* extension); - void handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior); + const TExtensionBehavior& extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); } + bool supportsExtension(const char* extension); + void handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior); - const TPragma& pragma() const { return mDirectiveHandler.pragma(); } - void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value); + const TPragma& pragma() const { return mDirectiveHandler.pragma(); } + void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value); - bool containsSampler(TType& type); - const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0); - bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType, - TIntermTyped *initializer, TIntermNode **intermNode); + bool containsSampler(TType& type); + const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0); + bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType, + TIntermTyped *initializer, TIntermNode **intermNode); - TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier); - bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&); + TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier); + bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&); TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, const TSourceLoc &identifierOrTypeLocation, const TString &identifier); TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier, @@ -177,37 +185,37 @@ const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression, const TSourceLoc &initLocation, TIntermTyped *initializer); - void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); + void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location); TIntermAggregate *addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location); void parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut); TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function); TFunction *addConstructorFunc(const TPublicType &publicType); - TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); - TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); - TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); - TIntermTyped* addConstMatrixNode(int, TIntermTyped*, const TSourceLoc&); - TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line); - TIntermTyped* addConstStruct(const TString&, TIntermTyped*, const TSourceLoc&); - TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); - TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation, const TString &fieldString, const TSourceLoc &fieldLocation); + TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); + TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); + TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstMatrixNode(int, TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line); + TIntermTyped* addConstStruct(const TString&, TIntermTyped*, const TSourceLoc&); + TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); + TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation, const TString &fieldString, const TSourceLoc &fieldLocation); - TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); - TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList); + TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); + TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList); - TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList, - const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine); + TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList, + const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine); - TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine); - TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine); - TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier); - TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, const TSourceLoc &storageLoc, TQualifier storageQualifier); + TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine); + TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine); + TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier); + TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, const TSourceLoc &storageLoc, TQualifier storageQualifier); - // Performs an error check for embedded struct declarations. - // Returns true if an error was raised due to the declaration of - // this struct. - bool enterStructDeclaration(const TSourceLoc &line, const TString& identifier); - void exitStructDeclaration(); + // Performs an error check for embedded struct declarations. + // Returns true if an error was raised due to the declaration of + // this struct. + bool enterStructDeclaration(const TSourceLoc &line, const TString& identifier); + void exitStructDeclaration(); bool structNestingErrorCheck(const TSourceLoc &line, const TField &field);
diff --git a/src/OpenGL/compiler/PoolAlloc.cpp b/src/OpenGL/compiler/PoolAlloc.cpp index a8347c2..f3d19eb 100644 --- a/src/OpenGL/compiler/PoolAlloc.cpp +++ b/src/OpenGL/compiler/PoolAlloc.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "PoolAlloc.h" @@ -18,98 +26,98 @@ bool InitializePoolIndex() { - assert(PoolIndex == OS_INVALID_TLS_INDEX); + assert(PoolIndex == OS_INVALID_TLS_INDEX); - PoolIndex = OS_AllocTLSIndex(); - return PoolIndex != OS_INVALID_TLS_INDEX; + PoolIndex = OS_AllocTLSIndex(); + return PoolIndex != OS_INVALID_TLS_INDEX; } void FreePoolIndex() { - assert(PoolIndex != OS_INVALID_TLS_INDEX); + assert(PoolIndex != OS_INVALID_TLS_INDEX); - OS_FreeTLSIndex(PoolIndex); - PoolIndex = OS_INVALID_TLS_INDEX; + OS_FreeTLSIndex(PoolIndex); + PoolIndex = OS_INVALID_TLS_INDEX; } TPoolAllocator* GetGlobalPoolAllocator() { - assert(PoolIndex != OS_INVALID_TLS_INDEX); - return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex)); + assert(PoolIndex != OS_INVALID_TLS_INDEX); + return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex)); } void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { - assert(PoolIndex != OS_INVALID_TLS_INDEX); - OS_SetTLSValue(PoolIndex, poolAllocator); + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(PoolIndex, poolAllocator); } // // Implement the functionality of the TPoolAllocator class, which // is documented in PoolAlloc.h. // -TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : - pageSize(growthIncrement), - alignment(allocationAlignment), - freeList(0), - inUseList(0), - numCalls(0), - totalBytes(0) +TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : + pageSize(growthIncrement), + alignment(allocationAlignment), + freeList(0), + inUseList(0), + numCalls(0), + totalBytes(0) { - // - // Don't allow page sizes we know are smaller than all common - // OS page sizes. - // - if (pageSize < 4*1024) - pageSize = 4*1024; + // + // Don't allow page sizes we know are smaller than all common + // OS page sizes. + // + if (pageSize < 4*1024) + pageSize = 4*1024; - // - // A large currentPageOffset indicates a new page needs to - // be obtained to allocate memory. - // - currentPageOffset = pageSize; + // + // A large currentPageOffset indicates a new page needs to + // be obtained to allocate memory. + // + currentPageOffset = pageSize; - // - // Adjust alignment to be at least pointer aligned and - // power of 2. - // - size_t minAlign = sizeof(void*); - alignment &= ~(minAlign - 1); - if (alignment < minAlign) - alignment = minAlign; - size_t a = 1; - while (a < alignment) - a <<= 1; - alignment = a; - alignmentMask = a - 1; + // + // Adjust alignment to be at least pointer aligned and + // power of 2. + // + size_t minAlign = sizeof(void*); + alignment &= ~(minAlign - 1); + if (alignment < minAlign) + alignment = minAlign; + size_t a = 1; + while (a < alignment) + a <<= 1; + alignment = a; + alignmentMask = a - 1; - // - // Align header skip - // - headerSkip = minAlign; - if (headerSkip < sizeof(tHeader)) { - headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; - } + // + // Align header skip + // + headerSkip = minAlign; + if (headerSkip < sizeof(tHeader)) { + headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; + } } TPoolAllocator::~TPoolAllocator() { - while (inUseList) { - tHeader* next = inUseList->nextPage; - inUseList->~tHeader(); - delete [] reinterpret_cast<char*>(inUseList); - inUseList = next; - } + while (inUseList) { + tHeader* next = inUseList->nextPage; + inUseList->~tHeader(); + delete [] reinterpret_cast<char*>(inUseList); + inUseList = next; + } - // We should not check the guard blocks - // here, because we did it already when the block was - // placed into the free list. - // - while (freeList) { - tHeader* next = freeList->nextPage; - delete [] reinterpret_cast<char*>(freeList); - freeList = next; - } + // We should not check the guard blocks + // here, because we did it already when the block was + // placed into the free list. + // + while (freeList) { + tHeader* next = freeList->nextPage; + delete [] reinterpret_cast<char*>(freeList); + freeList = next; + } } // Support MSVC++ 6.0 @@ -118,9 +126,9 @@ const unsigned char TAllocation::userDataFill = 0xcd; #ifdef GUARD_BLOCKS - const size_t TAllocation::guardBlockSize = 16; + const size_t TAllocation::guardBlockSize = 16; #else - const size_t TAllocation::guardBlockSize = 0; + const size_t TAllocation::guardBlockSize = 0; #endif // @@ -129,35 +137,35 @@ void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const { #ifdef GUARD_BLOCKS - for (size_t x = 0; x < guardBlockSize; x++) { - if (blockMem[x] != val) { - char assertMsg[80]; + for (size_t x = 0; x < guardBlockSize; x++) { + if (blockMem[x] != val) { + char assertMsg[80]; - // We don't print the assert message. It's here just to be helpful. - #if defined(_MSC_VER) - _snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", - locText, size, data()); - #else - snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", - locText, size, data()); - #endif - assert(0 && "PoolAlloc: Damage in guard block"); - } - } + // We don't print the assert message. It's here just to be helpful. + #if defined(_MSC_VER) + _snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", + locText, size, data()); + #else + snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", + locText, size, data()); + #endif + assert(0 && "PoolAlloc: Damage in guard block"); + } + } #endif } void TPoolAllocator::push() { - tAllocState state = { currentPageOffset, inUseList }; + tAllocState state = { currentPageOffset, inUseList }; - stack.push_back(state); - - // - // Indicate there is no current page to allocate from. - // - currentPageOffset = pageSize; + stack.push_back(state); + + // + // Indicate there is no current page to allocate from. + // + currentPageOffset = pageSize; } // @@ -169,27 +177,27 @@ // void TPoolAllocator::pop() { - if (stack.size() < 1) - return; + if (stack.size() < 1) + return; - tHeader* page = stack.back().page; - currentPageOffset = stack.back().offset; + tHeader* page = stack.back().page; + currentPageOffset = stack.back().offset; - while (inUseList != page) { - // invoke destructor to free allocation list - inUseList->~tHeader(); - - tHeader* nextInUse = inUseList->nextPage; - if (inUseList->pageCount > 1) - delete [] reinterpret_cast<char*>(inUseList); - else { - inUseList->nextPage = freeList; - freeList = inUseList; - } - inUseList = nextInUse; - } + while (inUseList != page) { + // invoke destructor to free allocation list + inUseList->~tHeader(); - stack.pop_back(); + tHeader* nextInUse = inUseList->nextPage; + if (inUseList->pageCount > 1) + delete [] reinterpret_cast<char*>(inUseList); + else { + inUseList->nextPage = freeList; + freeList = inUseList; + } + inUseList = nextInUse; + } + + stack.pop_back(); } // @@ -198,88 +206,88 @@ // void TPoolAllocator::popAll() { - while (stack.size() > 0) - pop(); + while (stack.size() > 0) + pop(); } void* TPoolAllocator::allocate(size_t numBytes) { - // - // Just keep some interesting statistics. - // - ++numCalls; - totalBytes += 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); - // Detect integer overflow. - if (allocationSize < numBytes) - return 0; + // 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); + // 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 (allocationSize <= pageSize - currentPageOffset) { - // - // Safe to allocate from currentPageOffset. - // - unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset; - currentPageOffset += allocationSize; - currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; + // + // Do the allocation, most likely case first, for efficiency. + // This step could be moved to be inline sometime. + // + if (allocationSize <= pageSize - currentPageOffset) { + // + // Safe to allocate from currentPageOffset. + // + unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset; + currentPageOffset += allocationSize; + currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; - return initializeAllocation(inUseList, memory, numBytes); - } + return initializeAllocation(inUseList, memory, numBytes); + } - 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; + 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<tHeader*>(::new char[numBytesToAlloc]); - if (memory == 0) - return 0; + tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]); + if (memory == 0) + return 0; - // Use placement-new to initialize header - new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); - inUseList = memory; + // Use placement-new to initialize header + new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); + inUseList = memory; - currentPageOffset = pageSize; // make next allocation come from a new page + currentPageOffset = pageSize; // make next allocation come from a new page - // No guard blocks for multi-page allocations (yet) - return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip); - } + // No guard blocks for multi-page allocations (yet) + return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip); + } - // - // Need a simple page to allocate from. - // - tHeader* memory; - if (freeList) { - memory = freeList; - freeList = freeList->nextPage; - } else { - memory = reinterpret_cast<tHeader*>(::new char[pageSize]); - if (memory == 0) - return 0; - } + // + // Need a simple page to allocate from. + // + tHeader* memory; + if (freeList) { + memory = freeList; + freeList = freeList->nextPage; + } else { + memory = reinterpret_cast<tHeader*>(::new char[pageSize]); + if (memory == 0) + return 0; + } - // Use placement-new to initialize header - new(memory) tHeader(inUseList, 1); - inUseList = memory; - - unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip; - currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; + // Use placement-new to initialize header + new(memory) tHeader(inUseList, 1); + inUseList = memory; - return initializeAllocation(inUseList, ret, numBytes); + unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip; + currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; + + return initializeAllocation(inUseList, ret, numBytes); } @@ -288,6 +296,6 @@ // void TAllocation::checkAllocList() const { - for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc) - alloc->check(); + for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc) + alloc->check(); }
diff --git a/src/OpenGL/compiler/PoolAlloc.h b/src/OpenGL/compiler/PoolAlloc.h index b032c47..1aca1c9 100644 --- a/src/OpenGL/compiler/PoolAlloc.h +++ b/src/OpenGL/compiler/PoolAlloc.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _POOLALLOC_INCLUDED_ #define _POOLALLOC_INCLUDED_ @@ -13,8 +21,8 @@ // // This header defines an allocator that can be used to efficiently -// allocate a large number of small requests for heap memory, with the -// intention that they are not individually deallocated, but rather +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather // collectively deallocated at one time. // // This simultaneously @@ -38,70 +46,70 @@ // If we are using guard blocks, we must track each indivual // allocation. If we aren't using guard blocks, these // never get instantiated, so won't have any impact. -// +// class TAllocation { public: - TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : - size(size), mem(mem), prevAlloc(prev) { - // Allocations are bracketed: - // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] - // This would be cleaner with if (guardBlockSize)..., but that - // makes the compiler print warnings about 0 length memsets, - // even with the if() protecting them. + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. #ifdef GUARD_BLOCKS - memset(preGuard(), guardBlockBeginVal, guardBlockSize); - memset(data(), userDataFill, size); - memset(postGuard(), guardBlockEndVal, guardBlockSize); + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); #endif - } + } - void check() const { - checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); - checkGuardBlock(postGuard(), guardBlockEndVal, "after"); - } + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } - void checkAllocList() const; + void checkAllocList() const; - // Return total size needed to accomodate user buffer of 'size', - // plus our tracking data. - inline static size_t allocationSize(size_t size) { - return size + 2 * guardBlockSize + headerSize(); - } + // Return total size needed to accomodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } - // Offset from surrounding buffer to get to user data buffer. - inline static unsigned char* offsetAllocation(unsigned char* m) { - return m + guardBlockSize + headerSize(); - } + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } private: - void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; + void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; - // Find offsets to pre and post guard blocks, and user data buffer - unsigned char* preGuard() const { return mem + headerSize(); } - unsigned char* data() const { return preGuard() + guardBlockSize; } - unsigned char* postGuard() const { return data() + size; } + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } - size_t size; // size of the user data area - unsigned char* mem; // beginning of our allocation (pts to header) - TAllocation* prevAlloc; // prior allocation in the chain + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain - // Support MSVC++ 6.0 - const static unsigned char guardBlockBeginVal; - const static unsigned char guardBlockEndVal; - const static unsigned char userDataFill; + // Support MSVC++ 6.0 + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; - const static size_t guardBlockSize; + const static size_t guardBlockSize; #ifdef GUARD_BLOCKS - inline static size_t headerSize() { return sizeof(TAllocation); } + inline static size_t headerSize() { return sizeof(TAllocation); } #else - inline static size_t headerSize() { return 0; } + inline static size_t headerSize() { return 0; } #endif }; // // There are several stacks. One is to track the pushing and popping -// of the user, and not yet implemented. The others are simply a +// of the user, and not yet implemented. The others are simply a // repositories of free pages or used pages. // // Page stacks are linked together with a simple header at the beginning @@ -110,107 +118,107 @@ // re-use. // // The "page size" used is not, nor must it match, the underlying OS -// page size. But, having it be about that size or equal to a set of +// page size. But, having it be about that size or equal to a set of // pages is likely most optimal. // class TPoolAllocator { public: - TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); - // - // Don't call the destructor just to free up the memory, call pop() - // - ~TPoolAllocator(); + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); - // - // Call push() to establish a new place to pop memory too. Does not - // have to be called to get things started. - // - void push(); + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); - // - // Call pop() to free all memory allocated since the last call to push(), - // or if no last call to push, frees all memory since first allocation. - // - void pop(); + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); - // - // Call popAll() to free all memory allocated. - // - void popAll(); + // + // Call popAll() to free all memory allocated. + // + void popAll(); - // - // Call allocate() to actually acquire memory. Returns 0 if no memory - // available, otherwise a properly aligned pointer to 'numBytes' of memory. - // - void* allocate(size_t numBytes); + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); - // - // There is no deallocate. The point of this class is that - // deallocation can be skipped by the user of it, as the model - // of use is to simultaneously deallocate everything at once - // by calling pop(), and to not have to solve memory leak problems. - // + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // protected: - friend struct tHeader; - - struct tHeader { - tHeader(tHeader* nextPage, size_t pageCount) : - nextPage(nextPage), - pageCount(pageCount) + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : + nextPage(nextPage), + pageCount(pageCount) #ifdef GUARD_BLOCKS - , lastAllocation(0) + , lastAllocation(0) #endif - { } + { } - ~tHeader() { + ~tHeader() { #ifdef GUARD_BLOCKS - if (lastAllocation) - lastAllocation->checkAllocList(); + if (lastAllocation) + lastAllocation->checkAllocList(); #endif - } + } - tHeader* nextPage; - size_t pageCount; + tHeader* nextPage; + size_t pageCount; #ifdef GUARD_BLOCKS - TAllocation* lastAllocation; + TAllocation* lastAllocation; #endif - }; + }; - struct tAllocState { - size_t offset; - tHeader* page; - }; - typedef std::vector<tAllocState> tAllocStack; + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector<tAllocState> tAllocStack; - // Track allocations if and only if we're using guard blocks - void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { + // Track allocations if and only if we're using guard blocks + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { #ifdef GUARD_BLOCKS - new(memory) TAllocation(numBytes, memory, block->lastAllocation); - block->lastAllocation = reinterpret_cast<TAllocation*>(memory); + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast<TAllocation*>(memory); #endif - // This is optimized entirely away if GUARD_BLOCKS is not defined. - return TAllocation::offsetAllocation(memory); - } + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } - size_t pageSize; // granularity of allocation from the OS - size_t alignment; // all returned allocations will be aligned at - // this granularity, which will be a power of 2 - size_t alignmentMask; - size_t headerSkip; // amount of memory to skip to make room for the - // header (basically, size of header, rounded - // up to make it aligned - size_t currentPageOffset; // next offset in top of inUseList to allocate from - tHeader* freeList; // list of popped memory - tHeader* inUseList; // list of all memory currently being used - tAllocStack stack; // stack of where to allocate from, to partition pool + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool - int numCalls; // just an interesting statistic - size_t totalBytes; // just an interesting statistic + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic private: - TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator - TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor + TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator + TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor }; @@ -232,69 +240,69 @@ template<class T> class pool_allocator { public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; - template<class Other> - struct rebind { - typedef pool_allocator<Other> other; - }; - pointer address(reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } + template<class Other> + struct rebind { + typedef pool_allocator<Other> other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } - pool_allocator() : allocator(GetGlobalPoolAllocator()) { } - pool_allocator(TPoolAllocator& a) : allocator(&a) { } - pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { } + pool_allocator() : allocator(GetGlobalPoolAllocator()) { } + pool_allocator(TPoolAllocator& a) : allocator(&a) { } + pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { } - template <class Other> - pool_allocator<T>& operator=(const pool_allocator<Other>& p) { - allocator = p.allocator; - return *this; - } + template <class Other> + pool_allocator<T>& operator=(const pool_allocator<Other>& p) { + allocator = p.allocator; + return *this; + } - template<class Other> - pool_allocator(const pool_allocator<Other>& p) : allocator(&p.getAllocator()) { } + template<class Other> + pool_allocator(const pool_allocator<Other>& p) : allocator(&p.getAllocator()) { } #if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR) - // libCStd on some platforms have a different allocate/deallocate interface. - // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be - // allocated, not the number of elements. - void* allocate(size_type n) { - return getAllocator().allocate(n); - } - void* allocate(size_type n, const void*) { - return getAllocator().allocate(n); - } - void deallocate(void*, size_type) {} + // libCStd on some platforms have a different allocate/deallocate interface. + // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be + // allocated, not the number of elements. + void* allocate(size_type n) { + return getAllocator().allocate(n); + } + void* allocate(size_type n, const void*) { + return getAllocator().allocate(n); + } + void deallocate(void*, size_type) {} #else - pointer allocate(size_type n) { - return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); - } - pointer allocate(size_type n, const void*) { - return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); - } - void deallocate(pointer, size_type) {} + pointer allocate(size_type n) { + return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); + } + pointer allocate(size_type n, const void*) { + return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); + } + void deallocate(pointer, size_type) {} #endif // _RWSTD_ALLOCATOR - void construct(pointer p, const T& val) { new ((void *)p) T(val); } - void destroy(pointer p) { p->T::~T(); } + void construct(pointer p, const T& val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } - bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } - bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } - size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); } - size_type max_size(int size) const { return static_cast<size_type>(-1) / size; } + size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast<size_type>(-1) / size; } - void setAllocator(TPoolAllocator *a) { allocator = a; } - TPoolAllocator& getAllocator() const { return *allocator; } + void setAllocator(TPoolAllocator *a) { allocator = a; } + TPoolAllocator& getAllocator() const { return *allocator; } protected: - TPoolAllocator *allocator; + TPoolAllocator *allocator; }; #endif // _POOLALLOC_INCLUDED_
diff --git a/src/OpenGL/compiler/Pragma.h b/src/OpenGL/compiler/Pragma.h index 2f74412..04df5b1 100644 --- a/src/OpenGL/compiler/Pragma.h +++ b/src/OpenGL/compiler/Pragma.h
@@ -1,19 +1,27 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef COMPILER_PRAGMA_H_ #define COMPILER_PRAGMA_H_ struct TPragma { - // By default optimization is turned on and debug is turned off. - TPragma() : optimize(true), debug(false) { } - TPragma(bool o, bool d) : optimize(o), debug(d) { } + // By default optimization is turned on and debug is turned off. + TPragma() : optimize(true), debug(false) { } + TPragma(bool o, bool d) : optimize(o), debug(d) { } - bool optimize; - bool debug; + bool optimize; + bool debug; }; #endif // COMPILER_PRAGMA_H_
diff --git a/src/OpenGL/compiler/SymbolTable.cpp b/src/OpenGL/compiler/SymbolTable.cpp index 0d449d9..39023ae 100644 --- a/src/OpenGL/compiler/SymbolTable.cpp +++ b/src/OpenGL/compiler/SymbolTable.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // // Symbol table for parsing. Most functionaliy and main ideas @@ -26,15 +34,15 @@ int TSymbolTableLevel::uniqueId = 0; TType::TType(const TPublicType &p) : - type(p.type), precision(p.precision), qualifier(p.qualifier), invariant(false), layoutQualifier(TLayoutQualifier::create()), - primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), maxArraySize(0), - arrayInformationType(0), interfaceBlock(0), structure(0), deepestStructNesting(0), mangled(0) + type(p.type), precision(p.precision), qualifier(p.qualifier), invariant(false), layoutQualifier(TLayoutQualifier::create()), + primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), maxArraySize(0), + arrayInformationType(0), interfaceBlock(0), structure(0), deepestStructNesting(0), mangled(0) { - if (p.userDef) - { - structure = p.userDef->getStruct(); - computeDeepestStructNesting(); - } + if (p.userDef) + { + structure = p.userDef->getStruct(); + computeDeepestStructNesting(); + } } // @@ -42,17 +50,17 @@ // void TType::buildMangledName(TString& mangledName) { - if (isMatrix()) - mangledName += 'm'; - else if (isVector()) - mangledName += 'v'; + if (isMatrix()) + mangledName += 'm'; + else if (isVector()) + mangledName += 'v'; - switch (type) { - case EbtFloat: mangledName += 'f'; break; - case EbtInt: mangledName += 'i'; break; - case EbtUInt: mangledName += 'u'; break; - case EbtBool: mangledName += 'b'; break; - case EbtSampler2D: mangledName += "s2"; break; + switch (type) { + case EbtFloat: mangledName += 'f'; break; + case EbtInt: mangledName += 'i'; break; + case EbtUInt: mangledName += 'u'; break; + case EbtBool: mangledName += 'b'; break; + case EbtSampler2D: mangledName += "s2"; break; case EbtSampler3D: mangledName += "s3"; break; case EbtSamplerCube: mangledName += "sC"; break; case EbtSampler2DArray: mangledName += "s2a"; break; @@ -70,31 +78,31 @@ case EbtSampler2DArrayShadow: mangledName += "s2as"; break; case EbtStruct: mangledName += structure->mangledName(); break; case EbtInterfaceBlock: mangledName += interfaceBlock->mangledName(); break; - default: - break; - } + default: + break; + } - mangledName += static_cast<char>('0' + getNominalSize()); - if(isMatrix()) { - mangledName += static_cast<char>('0' + getSecondarySize()); - } - if (isArray()) { - char buf[20]; - snprintf(buf, sizeof(buf), "%d", arraySize); - mangledName += '['; - mangledName += buf; - mangledName += ']'; - } + mangledName += static_cast<char>('0' + getNominalSize()); + if(isMatrix()) { + mangledName += static_cast<char>('0' + getSecondarySize()); + } + if (isArray()) { + char buf[20]; + snprintf(buf, sizeof(buf), "%d", arraySize); + mangledName += '['; + mangledName += buf; + mangledName += ']'; + } } size_t TType::getStructSize() const { - if (!getStruct()) { - assert(false && "Not a struct"); - return 0; - } + if (!getStruct()) { + assert(false && "Not a struct"); + return 0; + } - return getStruct()->objectSize(); + return getStruct()->objectSize(); } void TType::computeDeepestStructNesting() @@ -163,8 +171,8 @@ // TFunction::~TFunction() { - for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) - delete (*i).type; + for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) + delete (*i).type; } // @@ -172,62 +180,62 @@ // TSymbolTableLevel::~TSymbolTableLevel() { - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - delete (*it).second; + for (tLevel::iterator it = level.begin(); it != level.end(); ++it) + delete (*it).second; } TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) const { - int level = currentLevel(); - TSymbol *symbol = nullptr; + int level = currentLevel(); + TSymbol *symbol = nullptr; - do - { - while((level == ESSL3_BUILTINS && shaderVersion != 300) || - (level == ESSL1_BUILTINS && shaderVersion != 100)) // Skip version specific levels - { - --level; - } + do + { + while((level == ESSL3_BUILTINS && shaderVersion != 300) || + (level == ESSL1_BUILTINS && shaderVersion != 100)) // Skip version specific levels + { + --level; + } - symbol = table[level]->find(name); - } - while(!symbol && --level >= 0); // Doesn't decrement level when a symbol was found + symbol = table[level]->find(name); + } + while(!symbol && --level >= 0); // Doesn't decrement level when a symbol was found - if(builtIn) - { - *builtIn = (level <= LAST_BUILTIN_LEVEL); - } + if(builtIn) + { + *builtIn = (level <= LAST_BUILTIN_LEVEL); + } - if(sameScope) - { - *sameScope = (level == currentLevel()); - } + if(sameScope) + { + *sameScope = (level == currentLevel()); + } - return symbol; + return symbol; } TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const { - for(int level = LAST_BUILTIN_LEVEL; level >= 0; --level) - { - while((level == ESSL3_BUILTINS && shaderVersion != 300) || - (level == ESSL1_BUILTINS && shaderVersion != 100)) // Skip version specific levels - { - --level; - } + for(int level = LAST_BUILTIN_LEVEL; level >= 0; --level) + { + while((level == ESSL3_BUILTINS && shaderVersion != 300) || + (level == ESSL1_BUILTINS && shaderVersion != 100)) // Skip version specific levels + { + --level; + } - TSymbol *symbol = table[level]->find(name); + TSymbol *symbol = table[level]->find(name); - if(symbol) - { - return symbol; - } - } + if(symbol) + { + return symbol; + } + } - return 0; + return 0; } TSymbol::TSymbol(const TSymbol& copyOf) { - name = NewPoolTString(copyOf.name->c_str()); + name = NewPoolTString(copyOf.name->c_str()); }
diff --git a/src/OpenGL/compiler/SymbolTable.h b/src/OpenGL/compiler/SymbolTable.h index 153e814..d8c6029 100644 --- a/src/OpenGL/compiler/SymbolTable.h +++ b/src/OpenGL/compiler/SymbolTable.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _SYMBOL_TABLE_INCLUDED_ #define _SYMBOL_TABLE_INCLUDED_ @@ -46,21 +54,21 @@ class TSymbol { public: - POOL_ALLOCATOR_NEW_DELETE(); - TSymbol(const TString *n) : name(n) { } - virtual ~TSymbol() { /* don't delete name, it's from the pool */ } + POOL_ALLOCATOR_NEW_DELETE(); + TSymbol(const TString *n) : 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; } - TSymbol(const TSymbol&); + 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; } + TSymbol(const TSymbol&); protected: - const TString *name; - unsigned int uniqueId; // For real comparing during code generation + const TString *name; + unsigned int uniqueId; // For real comparing during code generation }; // @@ -76,43 +84,43 @@ 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) { } - 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; } + TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(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; } - ConstantUnion* getConstPointer() - { - if (!unionArray) - unionArray = new ConstantUnion[type.getObjectSize()]; + ConstantUnion* getConstPointer() + { + if (!unionArray) + unionArray = new ConstantUnion[type.getObjectSize()]; - return unionArray; - } + return unionArray; + } - ConstantUnion* getConstPointer() const { return unionArray; } + ConstantUnion* getConstPointer() const { return unionArray; } bool isConstant() const { return unionArray != nullptr; } - void shareConstPointer( ConstantUnion *constArray) - { - if (unionArray == constArray) - return; + void shareConstPointer( ConstantUnion *constArray) + { + if (unionArray == constArray) + return; - delete[] unionArray; - unionArray = constArray; - } + delete[] unionArray; + unionArray = constArray; + } protected: - 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 + 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 }; // @@ -121,8 +129,8 @@ // struct TParameter { - TString *name; - TType *type; + TString *name; + TType *type; }; // @@ -131,57 +139,57 @@ class TFunction : public TSymbol { public: - TFunction(TOperator o) : - TSymbol(0), - returnType(TType(EbtVoid, EbpUndefined)), - op(o), - defined(false), - prototypeDeclaration(false) { } - TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull, const char *ext = "") : - TSymbol(name), - returnType(retType), - mangledName(TFunction::mangleName(*name)), - op(tOp), - extension(ext), + TFunction(TOperator o) : + TSymbol(0), + returnType(TType(EbtVoid, EbpUndefined)), + op(o), defined(false), prototypeDeclaration(false) { } - virtual ~TFunction(); - virtual bool isFunction() const { return true; } + TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull, const char *ext = "") : + TSymbol(name), + returnType(retType), + mangledName(TFunction::mangleName(*name)), + op(tOp), + extension(ext), + defined(false), + prototypeDeclaration(false) { } + virtual ~TFunction(); + virtual bool isFunction() const { return true; } - static TString mangleName(const TString& name) { return name + '('; } - static TString unmangleName(const TString& mangledName) - { - return TString(mangledName.c_str(), mangledName.find_first_of('(')); - } + static TString mangleName(const TString& name) { return name + '('; } + static TString unmangleName(const TString& mangledName) + { + return TString(mangledName.c_str(), mangledName.find_first_of('(')); + } - void addParameter(TParameter& p) - { - parameters.push_back(p); - mangledName = mangledName + p.type->getMangledName(); - } + void addParameter(TParameter& p) + { + parameters.push_back(p); + mangledName = mangledName + p.type->getMangledName(); + } - const TString& getMangledName() const { return mangledName; } - const TType& getReturnType() const { return returnType; } + const TString& getMangledName() const { return mangledName; } + const TType& getReturnType() const { return returnType; } - TOperator getBuiltInOp() const { return op; } - const TString& getExtension() const { return extension; } + TOperator getBuiltInOp() const { return op; } + const TString& getExtension() const { return extension; } - void setDefined() { defined = true; } - bool isDefined() { return defined; } + void setDefined() { defined = true; } + bool isDefined() { return defined; } void setHasPrototypeDeclaration() { prototypeDeclaration = true; } bool hasPrototypeDeclaration() const { return prototypeDeclaration; } - size_t getParamCount() const { return parameters.size(); } - const TParameter& getParam(int i) const { return parameters[i]; } + size_t getParamCount() const { return parameters.size(); } + const TParameter& getParam(int i) const { return parameters[i]; } protected: - typedef TVector<TParameter> TParamList; - TParamList parameters; - TType returnType; - TString mangledName; - TOperator op; - TString extension; - bool defined; + typedef TVector<TParameter> TParamList; + TParamList parameters; + TType returnType; + TString mangledName; + TOperator op; + TString extension; + bool defined; bool prototypeDeclaration; }; @@ -189,36 +197,36 @@ class TSymbolTableLevel { public: - typedef TMap<TString, TSymbol*> tLevel; - typedef tLevel::const_iterator const_iterator; - typedef const tLevel::value_type tLevelPair; - typedef std::pair<tLevel::iterator, bool> tInsertResult; + typedef TMap<TString, TSymbol*> tLevel; + typedef tLevel::const_iterator const_iterator; + typedef const tLevel::value_type tLevelPair; + typedef std::pair<tLevel::iterator, bool> tInsertResult; - POOL_ALLOCATOR_NEW_DELETE(); - TSymbolTableLevel() { } - ~TSymbolTableLevel(); + POOL_ALLOCATOR_NEW_DELETE(); + TSymbolTableLevel() { } + ~TSymbolTableLevel(); - bool insert(TSymbol &symbol) - { + bool insert(TSymbol &symbol) + { symbol.setUniqueId(nextUniqueId()); - // - // returning true means symbol was added to the table - // - tInsertResult result; - result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); + // + // returning true means symbol was added to the table + // + tInsertResult result; + result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); - return result.second; - } + return result.second; + } - TSymbol* find(const TString& name) const - { - tLevel::const_iterator it = level.find(name); - if (it == level.end()) - return 0; - else - return (*it).second; - } + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } static int nextUniqueId() { @@ -226,17 +234,17 @@ } protected: - tLevel level; + tLevel level; static int uniqueId; // for unique identification in code generation }; enum ESymbolLevel { - COMMON_BUILTINS, - ESSL1_BUILTINS, - ESSL3_BUILTINS, - LAST_BUILTIN_LEVEL = ESSL3_BUILTINS, - GLOBAL_LEVEL + COMMON_BUILTINS, + ESSL1_BUILTINS, + ESSL3_BUILTINS, + LAST_BUILTIN_LEVEL = ESSL3_BUILTINS, + GLOBAL_LEVEL }; inline bool IsGenType(const TType *type) @@ -306,49 +314,49 @@ class TSymbolTable { public: - TSymbolTable() - : mGlobalInvariant(false) - { - // - // The symbol table cannot be used until push() is called, but - // the lack of an initial call to push() can be used to detect - // that the symbol table has not been preloaded with built-ins. - // - } + TSymbolTable() + : mGlobalInvariant(false) + { + // + // The symbol table cannot be used until push() is called, but + // the lack of an initial call to push() can be used to detect + // that the symbol table has not been preloaded with built-ins. + // + } - ~TSymbolTable() - { + ~TSymbolTable() + { while(currentLevel() > LAST_BUILTIN_LEVEL) { pop(); } - } + } - bool isEmpty() { return table.empty(); } - bool atBuiltInLevel() { return currentLevel() <= LAST_BUILTIN_LEVEL; } - bool atGlobalLevel() { return currentLevel() <= GLOBAL_LEVEL; } - void push() - { - table.push_back(new TSymbolTableLevel); - precisionStack.push_back( PrecisionStackLevel() ); - } + bool isEmpty() { return table.empty(); } + bool atBuiltInLevel() { return currentLevel() <= LAST_BUILTIN_LEVEL; } + bool atGlobalLevel() { return currentLevel() <= GLOBAL_LEVEL; } + void push() + { + table.push_back(new TSymbolTableLevel); + precisionStack.push_back( PrecisionStackLevel() ); + } - void pop() - { - delete table[currentLevel()]; - table.pop_back(); - precisionStack.pop_back(); - } + void pop() + { + delete table[currentLevel()]; + table.pop_back(); + precisionStack.pop_back(); + } - bool declare(TSymbol &symbol) - { - return insert(currentLevel(), symbol); - } + bool declare(TSymbol &symbol) + { + return insert(currentLevel(), symbol); + } - bool insert(ESymbolLevel level, TSymbol &symbol) - { - return table[level]->insert(symbol); - } + bool insert(ESymbolLevel level, TSymbol &symbol) + { + return table[level]->insert(symbol); + } bool insertConstInt(ESymbolLevel level, const char *name, int value) { @@ -435,61 +443,61 @@ insert(level, *function); } - } + } void insertBuiltIn(ESymbolLevel level, TOperator op, TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) { insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); - } + } void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) { insertBuiltIn(level, EOpNull, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); - } + } - TSymbol *find(const TString &name, int shaderVersion, bool *builtIn = nullptr, bool *sameScope = nullptr) const; - TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; + TSymbol *find(const TString &name, int shaderVersion, bool *builtIn = nullptr, bool *sameScope = nullptr) const; + TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; - TSymbolTableLevel *getOuterLevel() const - { - assert(currentLevel() >= 1); - return table[currentLevel() - 1]; - } + TSymbolTableLevel *getOuterLevel() const + { + assert(currentLevel() >= 1); + return table[currentLevel() - 1]; + } - 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 - if (type.primarySize > 1 || type.secondarySize > 1 || type.array) - return false; // Not allowed to set for aggregate types - int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; - precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value - return true; - } + 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 + if (type.primarySize > 1 || type.secondarySize > 1 || type.array) + return false; // Not allowed to set for aggregate types + int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; + 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) - { - // unsigned integers use the same precision as signed - if (type == EbtUInt) type = EbtInt; + // Searches down the precisionStack for a precision qualifier for the specified TBasicType + TPrecision getDefaultPrecision( TBasicType type) + { + // unsigned integers use the same precision as signed + if (type == EbtUInt) type = EbtInt; - if( type != EbtFloat && type != EbtInt ) return EbpUndefined; - int level = static_cast<int>(precisionStack.size()) - 1; - 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() ){ - prec = (*it).second; - break; - } - level--; - } - return prec; - } + if( type != EbtFloat && type != EbtInt ) return EbpUndefined; + int level = static_cast<int>(precisionStack.size()) - 1; + 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() ){ + prec = (*it).second; + break; + } + level--; + } + return prec; + } // This records invariant varyings declared through // "invariant varying_name;". @@ -511,11 +519,11 @@ bool getGlobalInvariant() const { return mGlobalInvariant; } protected: - ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); } + ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); } - std::vector<TSymbolTableLevel*> table; - typedef std::map< TBasicType, TPrecision > PrecisionStackLevel; - std::vector< PrecisionStackLevel > precisionStack; + std::vector<TSymbolTableLevel*> table; + typedef std::map< TBasicType, TPrecision > PrecisionStackLevel; + std::vector< PrecisionStackLevel > precisionStack; std::set<std::string> mInvariantVaryings; bool mGlobalInvariant;
diff --git a/src/OpenGL/compiler/TranslatorASM.cpp b/src/OpenGL/compiler/TranslatorASM.cpp index e1a8bda..05ea246 100644 --- a/src/OpenGL/compiler/TranslatorASM.cpp +++ b/src/OpenGL/compiler/TranslatorASM.cpp
@@ -1,28 +1,31 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -#include "TranslatorASM.h" - -#include "InitializeParseContext.h" - -TranslatorASM::TranslatorASM(glsl::Shader *shaderObject, GLenum shaderType) : TCompiler(shaderType), shaderObject(shaderObject) -{ -} - -bool TranslatorASM::translate(TIntermNode* root) -{ - TParseContext& parseContext = *GetGlobalParseContext(); - glsl::OutputASM outputASM(parseContext, shaderObject); - - outputASM.output(); - - return parseContext.numErrors() == 0; -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "TranslatorASM.h" + +#include "InitializeParseContext.h" + +TranslatorASM::TranslatorASM(glsl::Shader *shaderObject, GLenum shaderType) : TCompiler(shaderType), shaderObject(shaderObject) +{ +} + +bool TranslatorASM::translate(TIntermNode* root) +{ + TParseContext& parseContext = *GetGlobalParseContext(); + glsl::OutputASM outputASM(parseContext, shaderObject); + + outputASM.output(); + + return parseContext.numErrors() == 0; +}
diff --git a/src/OpenGL/compiler/TranslatorASM.h b/src/OpenGL/compiler/TranslatorASM.h index 41f911e..c31df96 100644 --- a/src/OpenGL/compiler/TranslatorASM.h +++ b/src/OpenGL/compiler/TranslatorASM.h
@@ -1,35 +1,38 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -#ifndef COMPILER_TRANSLATORASM_H_ -#define COMPILER_TRANSLATORASM_H_ - -#include "Compiler.h" -#include "OutputASM.h" - -namespace glsl -{ - class Shader; -} - -class TranslatorASM : public TCompiler -{ -public: - TranslatorASM(glsl::Shader *shaderObject, GLenum type); - -protected: - virtual bool translate(TIntermNode* root); - -private: - glsl::Shader *const shaderObject; -}; - -#endif // COMPILER_TRANSLATORASM_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_TRANSLATORASM_H_ +#define COMPILER_TRANSLATORASM_H_ + +#include "Compiler.h" +#include "OutputASM.h" + +namespace glsl +{ + class Shader; +} + +class TranslatorASM : public TCompiler +{ +public: + TranslatorASM(glsl::Shader *shaderObject, GLenum type); + +protected: + virtual bool translate(TIntermNode* root); + +private: + glsl::Shader *const shaderObject; +}; + +#endif // COMPILER_TRANSLATORASM_H_
diff --git a/src/OpenGL/compiler/Types.h b/src/OpenGL/compiler/Types.h index 0131343..f24f9e6 100644 --- a/src/OpenGL/compiler/Types.h +++ b/src/OpenGL/compiler/Types.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _TYPES_INCLUDED #define _TYPES_INCLUDED @@ -191,7 +199,7 @@ } bool hasInstanceName() const { - return mInstanceName != NULL; + return mInstanceName != nullptr; } bool isArray() const { @@ -228,27 +236,27 @@ class TType { public: - POOL_ALLOCATOR_NEW_DELETE(); - TType() {} + POOL_ALLOCATOR_NEW_DELETE(); + TType() {} TType(TBasicType t, int s0 = 1, int s1 = 1) : type(t), precision(EbpUndefined), qualifier(EvqGlobal), invariant(false), layoutQualifier(TLayoutQualifier::create()), primarySize(s0), secondarySize(s1), array(false), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), structure(0), deepestStructNesting(0), mangled(0) - { - } - TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s0 = 1, int s1 = 1, bool a = false) : + { + } + TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s0 = 1, int s1 = 1, bool a = false) : type(t), precision(p), qualifier(q), invariant(false), layoutQualifier(TLayoutQualifier::create()), primarySize(s0), secondarySize(s1), array(a), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), structure(0), deepestStructNesting(0), mangled(0) - { - } - explicit TType(const TPublicType &p); + { + } + explicit TType(const TPublicType &p); TType(TStructure* userDef, TPrecision p = EbpUndefined) : type(EbtStruct), precision(p), qualifier(EvqTemporary), invariant(false), layoutQualifier(TLayoutQualifier::create()), primarySize(1), secondarySize(1), array(false), arraySize(0), maxArraySize(0), arrayInformationType(0), interfaceBlock(0), structure(userDef), deepestStructNesting(0), mangled(0) - { - } + { + } TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn, TLayoutQualifier layoutQualifierIn, int arraySizeIn) @@ -259,24 +267,24 @@ { } - TBasicType getBasicType() const { return type; } - void setBasicType(TBasicType t) { type = t; } + TBasicType getBasicType() const { return type; } + void setBasicType(TBasicType t) { type = t; } - TPrecision getPrecision() const { return precision; } - void setPrecision(TPrecision p) { precision = p; } + TPrecision getPrecision() const { return precision; } + void setPrecision(TPrecision p) { precision = p; } - TQualifier getQualifier() const { return qualifier; } - void setQualifier(TQualifier q) { qualifier = q; } + TQualifier getQualifier() const { return qualifier; } + void setQualifier(TQualifier q) { qualifier = q; } bool isInvariant() const { return invariant; } TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; } void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; } - // One-dimensional size of single instance type + // One-dimensional size of single instance type int getNominalSize() const { return primarySize; } void setNominalSize(int s) { primarySize = s; } - // Full size of single instance of type + // Full size of single instance of type size_t getObjectSize() const { if(isArray()) @@ -372,14 +380,14 @@ void setSecondarySize(int s1) { secondarySize = s1; } int getSecondarySize() const { return secondarySize; } - 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; } + 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; } TInterfaceBlock *getInterfaceBlock() const { return interfaceBlock; } void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) { interfaceBlock = interfaceBlockIn; } @@ -395,100 +403,100 @@ TStructure* getStruct() const { return structure; } void setStruct(TStructure* s) { structure = s; computeDeepestStructNesting(); } - TString& getMangledName() { - if (!mangled) { - mangled = NewPoolTString(""); - buildMangledName(*mangled); - *mangled += ';' ; - } + TString& getMangledName() { + if (!mangled) { + mangled = NewPoolTString(""); + buildMangledName(*mangled); + *mangled += ';' ; + } - return *mangled; - } + return *mangled; + } - bool sameElementType(const TType& right) const { - return type == right.type && + bool sameElementType(const TType& right) const { + return type == right.type && primarySize == right.primarySize && secondarySize == right.secondarySize && - structure == right.structure; - } - bool operator==(const TType& right) const { - return type == right.type && + structure == right.structure; + } + bool operator==(const TType& right) const { + return type == right.type && primarySize == right.primarySize && secondarySize == right.secondarySize && array == right.array && (!array || arraySize == right.arraySize) && - structure == right.structure; - // don't check the qualifier, it's not ever what's being sought after - } - bool operator!=(const TType& right) const { - return !operator==(right); - } - bool operator<(const TType& right) const { - if (type != right.type) return type < right.type; + structure == right.structure; + // don't check the qualifier, it's not ever what's being sought after + } + bool operator!=(const TType& right) const { + return !operator==(right); + } + bool operator<(const TType& right) const { + if (type != right.type) return type < right.type; if(primarySize != right.primarySize) return (primarySize * secondarySize) < (right.primarySize * right.secondarySize); if(secondarySize != right.secondarySize) return secondarySize < right.secondarySize; - if (array != right.array) return array < right.array; - if (arraySize != right.arraySize) return arraySize < right.arraySize; - if (structure != right.structure) return structure < right.structure; + if (array != right.array) return array < right.array; + if (arraySize != right.arraySize) return arraySize < right.arraySize; + if (structure != right.structure) return structure < right.structure; - return false; - } + return false; + } - const char* getBasicString() const { return ::getBasicString(type); } - const char* getPrecisionString() const { return ::getPrecisionString(precision); } - const char* getQualifierString() const { return ::getQualifierString(qualifier); } - TString getCompleteString() const; + const char* getBasicString() const { return ::getBasicString(type); } + const char* getPrecisionString() const { return ::getPrecisionString(precision); } + const char* getQualifierString() const { return ::getQualifierString(qualifier); } + TString getCompleteString() const; - // If this type is a struct, returns the deepest struct nesting of - // any field in the struct. For example: - // struct nesting1 { - // vec4 position; - // }; - // struct nesting2 { - // nesting1 field1; - // vec4 field2; - // }; - // 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 structure ? structure->deepestNesting() : 0; - } + // If this type is a struct, returns the deepest struct nesting of + // any field in the struct. For example: + // struct nesting1 { + // vec4 position; + // }; + // struct nesting2 { + // nesting1 field1; + // vec4 field2; + // }; + // 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 structure ? structure->deepestNesting() : 0; + } - bool isStructureContainingArrays() const - { - return structure ? structure->containsArrays() : false; - } + bool isStructureContainingArrays() const + { + return structure ? structure->containsArrays() : false; + } - bool isStructureContainingSamplers() const - { - return structure ? structure->containsSamplers() : false; - } + bool isStructureContainingSamplers() const + { + return structure ? structure->containsSamplers() : false; + } protected: - void buildMangledName(TString&); - size_t getStructSize() const; - void computeDeepestStructNesting(); + void buildMangledName(TString&); + size_t getStructSize() const; + void computeDeepestStructNesting(); - TBasicType type; - TPrecision precision; - TQualifier qualifier; + TBasicType type; + TPrecision precision; + TQualifier qualifier; bool invariant; TLayoutQualifier layoutQualifier; - unsigned char primarySize; // size of vector or matrix, not size of array + unsigned char primarySize; // size of vector or matrix, not size of array unsigned char secondarySize; // secondarySize: 1 for vectors, >1 for matrices - bool array; - int arraySize; - int maxArraySize; - TType *arrayInformationType; + bool array; + int arraySize; + int maxArraySize; + TType *arrayInformationType; // 0 unless this is an interface block, or interface block member variable TInterfaceBlock *interfaceBlock; TStructure *structure; // 0 unless this is a struct - int deepestStructNesting; + int deepestStructNesting; - TString *mangled; + TString *mangled; }; // @@ -502,38 +510,38 @@ // struct TPublicType { - TBasicType type; - TLayoutQualifier layoutQualifier; - TQualifier qualifier; - bool invariant; - TPrecision precision; - int primarySize; // size of vector or matrix, not size of array + TBasicType type; + TLayoutQualifier layoutQualifier; + TQualifier qualifier; + bool invariant; + TPrecision precision; + int primarySize; // size of vector or matrix, not size of array int secondarySize; // 1 for scalars/vectors, >1 for matrices - bool array; - int arraySize; - TType* userDef; - TSourceLoc line; + bool array; + int arraySize; + TType* userDef; + TSourceLoc line; - void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln) - { - type = bt; - layoutQualifier = TLayoutQualifier::create(); - qualifier = q; - invariant = false; - precision = EbpUndefined; + void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln) + { + type = bt; + layoutQualifier = TLayoutQualifier::create(); + qualifier = q; + invariant = false; + precision = EbpUndefined; primarySize = 1; secondarySize = 1; - array = false; - arraySize = 0; - userDef = 0; - line = ln; - } + array = false; + arraySize = 0; + userDef = 0; + line = ln; + } - void setAggregate(int s) - { + void setAggregate(int s) + { primarySize = s; secondarySize = 1; - } + } void setMatrix(int s0, int s1) { @@ -546,11 +554,11 @@ return array && arraySize == 0; } - void setArray(bool a, int s = 0) - { - array = a; - arraySize = s; - } + void setArray(bool a, int s = 0) + { + array = a; + arraySize = s; + } void clearArrayness() { @@ -558,15 +566,15 @@ arraySize = 0; } - bool isStructureContainingArrays() const - { - if (!userDef) - { - return false; - } + bool isStructureContainingArrays() const + { + if (!userDef) + { + return false; + } - return userDef->isStructureContainingArrays(); - } + return userDef->isStructureContainingArrays(); + } bool isMatrix() const {
diff --git a/src/OpenGL/compiler/ValidateGlobalInitializer.cpp b/src/OpenGL/compiler/ValidateGlobalInitializer.cpp index af2c6d3..6c5fa86 100644 --- a/src/OpenGL/compiler/ValidateGlobalInitializer.cpp +++ b/src/OpenGL/compiler/ValidateGlobalInitializer.cpp
@@ -1,80 +1,88 @@ -// -// Copyright (c) 2002-2015 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 "ValidateGlobalInitializer.h" - -#include "ParseHelper.h" - -namespace -{ - -class ValidateGlobalInitializerTraverser : public TIntermTraverser -{ - public: - ValidateGlobalInitializerTraverser(const TParseContext *context); - - void visitSymbol(TIntermSymbol *node) override; - - bool isValid() const { return mIsValid; } - bool issueWarning() const { return mIssueWarning; } - - private: - const TParseContext *mContext; - bool mIsValid; - bool mIssueWarning; -}; - -void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) -{ - const TSymbol *sym = mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion()); - if (sym->isVariable()) - { - // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): - // Global initializers must be constant expressions. - const TVariable *var = static_cast<const TVariable *>(sym); - switch (var->getType().getQualifier()) - { - case EvqConstExpr: - break; - case EvqGlobal: - case EvqTemporary: - case EvqUniform: - // We allow these cases to be compatible with legacy ESSL 1.00 content. - // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal with. - if (mContext->getShaderVersion() >= 300) - { - mIsValid = false; - } - else - { - mIssueWarning = true; - } - break; - default: - mIsValid = false; - } - } -} - -ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context) - : TIntermTraverser(true, false, false), - mContext(context), - mIsValid(true), - mIssueWarning(false) -{ -} - -} // namespace - -bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning) -{ - ValidateGlobalInitializerTraverser validate(context); - initializer->traverse(&validate); - ASSERT(warning != nullptr); - *warning = validate.issueWarning(); - return validate.isValid(); -} - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "ValidateGlobalInitializer.h" + +#include "ParseHelper.h" + +namespace +{ + +class ValidateGlobalInitializerTraverser : public TIntermTraverser +{ +public: + ValidateGlobalInitializerTraverser(const TParseContext *context); + + void visitSymbol(TIntermSymbol *node) override; + + bool isValid() const { return mIsValid; } + bool issueWarning() const { return mIssueWarning; } + +private: + const TParseContext *mContext; + bool mIsValid; + bool mIssueWarning; +}; + +void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) +{ + const TSymbol *sym = mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion()); + if (sym->isVariable()) + { + // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): + // Global initializers must be constant expressions. + const TVariable *var = static_cast<const TVariable *>(sym); + switch (var->getType().getQualifier()) + { + case EvqConstExpr: + break; + case EvqGlobal: + case EvqTemporary: + case EvqUniform: + // We allow these cases to be compatible with legacy ESSL 1.00 content. + // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal with. + if (mContext->getShaderVersion() >= 300) + { + mIsValid = false; + } + else + { + mIssueWarning = true; + } + break; + default: + mIsValid = false; + } + } +} + +ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context) + : TIntermTraverser(true, false, false), + mContext(context), + mIsValid(true), + mIssueWarning(false) +{ +} + +} // namespace + +bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning) +{ + ValidateGlobalInitializerTraverser validate(context); + initializer->traverse(&validate); + ASSERT(warning != nullptr); + *warning = validate.issueWarning(); + return validate.isValid(); +} +
diff --git a/src/OpenGL/compiler/ValidateGlobalInitializer.h b/src/OpenGL/compiler/ValidateGlobalInitializer.h index debc33c..28c1293 100644 --- a/src/OpenGL/compiler/ValidateGlobalInitializer.h +++ b/src/OpenGL/compiler/ValidateGlobalInitializer.h
@@ -1,16 +1,24 @@ -// -// Copyright (c) 2002-2015 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_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ -#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ - -class TIntermTyped; -class TParseContext; - -// Returns true if the initializer is valid. -bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning); - -#endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ +#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_ + +class TIntermTyped; +class TParseContext; + +// Returns true if the initializer is valid. +bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning); + +#endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
diff --git a/src/OpenGL/compiler/ValidateLimitations.cpp b/src/OpenGL/compiler/ValidateLimitations.cpp index 1bba3c7..a685d5b 100644 --- a/src/OpenGL/compiler/ValidateLimitations.cpp +++ b/src/OpenGL/compiler/ValidateLimitations.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "ValidateLimitations.h" #include "InfoSink.h" @@ -11,22 +19,22 @@ namespace { bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) { - for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) { - if (i->index.id == symbol->getId()) - return true; - } - return false; + for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) { + if (i->index.id == symbol->getId()) + return true; + } + return false; } void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) { - for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) { - if (i->index.id == symbol->getId()) { - ASSERT(i->loop != NULL); - i->loop->setUnrollFlag(true); - return; - } - } - UNREACHABLE(0); + for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) { + if (i->index.id == symbol->getId()) { + ASSERT(i->loop); + i->loop->setUnrollFlag(true); + return; + } + } + UNREACHABLE(0); } // Traverses a node to check if it represents a constant index expression. @@ -40,24 +48,24 @@ // - Expressions composed of both of the above class ValidateConstIndexExpr : public TIntermTraverser { public: - ValidateConstIndexExpr(const TLoopStack& stack) - : mValid(true), mLoopStack(stack) {} + ValidateConstIndexExpr(const TLoopStack& stack) + : mValid(true), mLoopStack(stack) {} - // Returns true if the parsed node represents a constant index expression. - bool isValid() const { return mValid; } + // Returns true if the parsed node represents a constant index expression. + bool isValid() const { return mValid; } - virtual void visitSymbol(TIntermSymbol* symbol) { - // Only constants and loop indices are allowed in a - // constant index expression. - if (mValid) { - mValid = (symbol->getQualifier() == EvqConstExpr) || - IsLoopIndex(symbol, mLoopStack); - } - } + virtual void visitSymbol(TIntermSymbol* symbol) { + // Only constants and loop indices are allowed in a + // constant index expression. + if (mValid) { + mValid = (symbol->getQualifier() == EvqConstExpr) || + IsLoopIndex(symbol, mLoopStack); + } + } private: - bool mValid; - const TLoopStack& mLoopStack; + bool mValid; + const TLoopStack& mLoopStack; }; // Traverses a node to check if it uses a loop index. @@ -65,452 +73,433 @@ // mark the loop for unroll. class ValidateLoopIndexExpr : public TIntermTraverser { public: - ValidateLoopIndexExpr(TLoopStack& stack) - : mUsesFloatLoopIndex(false), - mUsesIntLoopIndex(false), - mLoopStack(stack) {} + ValidateLoopIndexExpr(TLoopStack& stack) + : mUsesFloatLoopIndex(false), + mUsesIntLoopIndex(false), + mLoopStack(stack) {} - bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; } - bool usesIntLoopIndex() const { return mUsesIntLoopIndex; } + bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; } + bool usesIntLoopIndex() const { return mUsesIntLoopIndex; } - virtual void visitSymbol(TIntermSymbol* symbol) { - if (IsLoopIndex(symbol, mLoopStack)) { - switch (symbol->getBasicType()) { - case EbtFloat: - mUsesFloatLoopIndex = true; - break; - case EbtUInt: - mUsesIntLoopIndex = true; - MarkLoopForUnroll(symbol, mLoopStack); - break; - case EbtInt: - mUsesIntLoopIndex = true; - MarkLoopForUnroll(symbol, mLoopStack); - break; - default: - UNREACHABLE(symbol->getBasicType()); - } - } - } + virtual void visitSymbol(TIntermSymbol* symbol) { + if (IsLoopIndex(symbol, mLoopStack)) { + switch (symbol->getBasicType()) { + case EbtFloat: + mUsesFloatLoopIndex = true; + break; + case EbtUInt: + mUsesIntLoopIndex = true; + MarkLoopForUnroll(symbol, mLoopStack); + break; + case EbtInt: + mUsesIntLoopIndex = true; + MarkLoopForUnroll(symbol, mLoopStack); + break; + default: + UNREACHABLE(symbol->getBasicType()); + } + } + } private: - bool mUsesFloatLoopIndex; - bool mUsesIntLoopIndex; - TLoopStack& mLoopStack; + bool mUsesFloatLoopIndex; + bool mUsesIntLoopIndex; + TLoopStack& mLoopStack; }; } // namespace ValidateLimitations::ValidateLimitations(GLenum shaderType, TInfoSinkBase& sink) - : mShaderType(shaderType), - mSink(sink), - mNumErrors(0) + : mShaderType(shaderType), + mSink(sink), + mNumErrors(0) { } bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node) { - // Check if loop index is modified in the loop body. - validateOperation(node, node->getLeft()); + // Check if loop index is modified in the loop body. + validateOperation(node, node->getLeft()); - // Check indexing. - switch (node->getOp()) { - case EOpIndexDirect: - validateIndexing(node); - break; - case EOpIndexIndirect: -#if defined(__APPLE__) - // Loop unrolling is a work-around for a Mac Cg compiler bug where it - // crashes when a sampler array's index is also the loop index. - // Once Apple fixes this bug, we should remove the code in this CL. - // See http://codereview.appspot.com/4331048/. - if ((node->getLeft() != NULL) && (node->getRight() != NULL) && - (node->getLeft()->getAsSymbolNode())) { - TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode(); - if (IsSampler(symbol->getBasicType()) && symbol->isArray()) { - ValidateLoopIndexExpr validate(mLoopStack); - node->getRight()->traverse(&validate); - if (validate.usesFloatLoopIndex()) { - error(node->getLine(), - "sampler array index is float loop index", - "for"); - } - } - } -#endif - validateIndexing(node); - break; - default: break; - } - return true; + // Check indexing. + switch (node->getOp()) { + case EOpIndexDirect: + validateIndexing(node); + break; + case EOpIndexIndirect: + validateIndexing(node); + break; + default: break; + } + return true; } bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node) { - // Check if loop index is modified in the loop body. - validateOperation(node, node->getOperand()); + // Check if loop index is modified in the loop body. + validateOperation(node, node->getOperand()); - return true; + return true; } bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node) { - switch (node->getOp()) { - case EOpFunctionCall: - validateFunctionCall(node); - break; - default: - break; - } - return true; + switch (node->getOp()) { + case EOpFunctionCall: + validateFunctionCall(node); + break; + default: + break; + } + return true; } bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node) { - if (!validateLoopType(node)) - return false; + if (!validateLoopType(node)) + return false; - TLoopInfo info; - memset(&info, 0, sizeof(TLoopInfo)); - info.loop = node; - if (!validateForLoopHeader(node, &info)) - return false; + TLoopInfo info; + memset(&info, 0, sizeof(TLoopInfo)); + info.loop = node; + if (!validateForLoopHeader(node, &info)) + return false; - TIntermNode* body = node->getBody(); - if (body != NULL) { - mLoopStack.push_back(info); - body->traverse(this); - mLoopStack.pop_back(); - } + TIntermNode* body = node->getBody(); + if (body) { + mLoopStack.push_back(info); + body->traverse(this); + mLoopStack.pop_back(); + } - // The loop is fully processed - no need to visit children. - return false; + // The loop is fully processed - no need to visit children. + return false; } void ValidateLimitations::error(TSourceLoc loc, const char *reason, const char* token) { - mSink.prefix(EPrefixError); - mSink.location(loc); - mSink << "'" << token << "' : " << reason << "\n"; - ++mNumErrors; + mSink.prefix(EPrefixError); + mSink.location(loc); + mSink << "'" << token << "' : " << reason << "\n"; + ++mNumErrors; } bool ValidateLimitations::withinLoopBody() const { - return !mLoopStack.empty(); + return !mLoopStack.empty(); } bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const { - return IsLoopIndex(symbol, mLoopStack); + return IsLoopIndex(symbol, mLoopStack); } bool ValidateLimitations::validateLoopType(TIntermLoop* node) { - TLoopType type = node->getType(); - if (type == ELoopFor) - return true; + TLoopType type = node->getType(); + if (type == ELoopFor) + return true; - // Reject while and do-while loops. - error(node->getLine(), - "This type of loop is not allowed", - type == ELoopWhile ? "while" : "do"); - return false; + // Reject while and do-while loops. + error(node->getLine(), + "This type of loop is not allowed", + type == ELoopWhile ? "while" : "do"); + return false; } bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node, TLoopInfo* info) { - ASSERT(node->getType() == ELoopFor); + ASSERT(node->getType() == ELoopFor); - // - // The for statement has the form: - // for ( init-declaration ; condition ; expression ) statement - // - if (!validateForLoopInit(node, info)) - return false; - if (!validateForLoopCond(node, info)) - return false; - if (!validateForLoopExpr(node, info)) - return false; + // + // The for statement has the form: + // for ( init-declaration ; condition ; expression ) statement + // + if (!validateForLoopInit(node, info)) + return false; + if (!validateForLoopCond(node, info)) + return false; + if (!validateForLoopExpr(node, info)) + return false; - return true; + return true; } bool ValidateLimitations::validateForLoopInit(TIntermLoop* node, TLoopInfo* info) { - TIntermNode* init = node->getInit(); - if (init == NULL) { - error(node->getLine(), "Missing init declaration", "for"); - return false; - } + TIntermNode* init = node->getInit(); + if (!init) { + error(node->getLine(), "Missing init declaration", "for"); + return false; + } - // - // init-declaration has the form: - // type-specifier identifier = constant-expression - // - TIntermAggregate* decl = init->getAsAggregate(); - if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) { - error(init->getLine(), "Invalid init declaration", "for"); - return false; - } - // To keep things simple do not allow declaration list. - TIntermSequence& declSeq = decl->getSequence(); - if (declSeq.size() != 1) { - error(decl->getLine(), "Invalid init declaration", "for"); - return false; - } - TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); - if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) { - error(decl->getLine(), "Invalid init declaration", "for"); - return false; - } - TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); - if (symbol == NULL) { - error(declInit->getLine(), "Invalid init declaration", "for"); - return false; - } - // The loop index has type int or float. - TBasicType type = symbol->getBasicType(); - if (!IsInteger(type) && (type != EbtFloat)) { - error(symbol->getLine(), - "Invalid type for loop index", getBasicString(type)); - return false; - } - // The loop index is initialized with constant expression. - if (!isConstExpr(declInit->getRight())) { - error(declInit->getLine(), - "Loop index cannot be initialized with non-constant expression", - symbol->getSymbol().c_str()); - return false; - } + // + // init-declaration has the form: + // type-specifier identifier = constant-expression + // + TIntermAggregate* decl = init->getAsAggregate(); + if (!decl || (decl->getOp() != EOpDeclaration)) { + error(init->getLine(), "Invalid init declaration", "for"); + return false; + } + // To keep things simple do not allow declaration list. + TIntermSequence& declSeq = decl->getSequence(); + if (declSeq.size() != 1) { + error(decl->getLine(), "Invalid init declaration", "for"); + return false; + } + TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); + if (!declInit || (declInit->getOp() != EOpInitialize)) { + error(decl->getLine(), "Invalid init declaration", "for"); + return false; + } + TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); + if (!symbol) { + error(declInit->getLine(), "Invalid init declaration", "for"); + return false; + } + // The loop index has type int or float. + TBasicType type = symbol->getBasicType(); + if (!IsInteger(type) && (type != EbtFloat)) { + error(symbol->getLine(), + "Invalid type for loop index", getBasicString(type)); + return false; + } + // The loop index is initialized with constant expression. + if (!isConstExpr(declInit->getRight())) { + error(declInit->getLine(), + "Loop index cannot be initialized with non-constant expression", + symbol->getSymbol().c_str()); + return false; + } - info->index.id = symbol->getId(); - return true; + info->index.id = symbol->getId(); + return true; } bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, TLoopInfo* info) { - TIntermNode* cond = node->getCondition(); - if (cond == NULL) { - error(node->getLine(), "Missing condition", "for"); - return false; - } - // - // condition has the form: - // loop_index relational_operator constant_expression - // - TIntermBinary* binOp = cond->getAsBinaryNode(); - if (binOp == NULL) { - error(node->getLine(), "Invalid condition", "for"); - return false; - } - // Loop index should be to the left of relational operator. - TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode(); - if (symbol == NULL) { - error(binOp->getLine(), "Invalid condition", "for"); - return false; - } - if (symbol->getId() != info->index.id) { - error(symbol->getLine(), - "Expected loop index", symbol->getSymbol().c_str()); - return false; - } - // Relational operator is one of: > >= < <= == or !=. - switch (binOp->getOp()) { - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - break; - default: - error(binOp->getLine(), - "Invalid relational operator", - getOperatorString(binOp->getOp())); - break; - } - // Loop index must be compared with a constant. - if (!isConstExpr(binOp->getRight())) { - error(binOp->getLine(), - "Loop index cannot be compared with non-constant expression", - symbol->getSymbol().c_str()); - return false; - } + TIntermNode* cond = node->getCondition(); + if (!cond) { + error(node->getLine(), "Missing condition", "for"); + return false; + } + // + // condition has the form: + // loop_index relational_operator constant_expression + // + TIntermBinary* binOp = cond->getAsBinaryNode(); + if (!binOp) { + error(node->getLine(), "Invalid condition", "for"); + return false; + } + // Loop index should be to the left of relational operator. + TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode(); + if (!symbol) { + error(binOp->getLine(), "Invalid condition", "for"); + return false; + } + if (symbol->getId() != info->index.id) { + error(symbol->getLine(), + "Expected loop index", symbol->getSymbol().c_str()); + return false; + } + // Relational operator is one of: > >= < <= == or !=. + switch (binOp->getOp()) { + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + break; + default: + error(binOp->getLine(), + "Invalid relational operator", + getOperatorString(binOp->getOp())); + break; + } + // Loop index must be compared with a constant. + if (!isConstExpr(binOp->getRight())) { + error(binOp->getLine(), + "Loop index cannot be compared with non-constant expression", + symbol->getSymbol().c_str()); + return false; + } - return true; + return true; } bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node, TLoopInfo* info) { - TIntermNode* expr = node->getExpression(); - if (expr == NULL) { - error(node->getLine(), "Missing expression", "for"); - return false; - } + TIntermNode* expr = node->getExpression(); + if (!expr) { + error(node->getLine(), "Missing expression", "for"); + return false; + } - // for expression has one of the following forms: - // loop_index++ - // loop_index-- - // loop_index += constant_expression - // loop_index -= constant_expression - // ++loop_index - // --loop_index - // The last two forms are not specified in the spec, but I am assuming - // its an oversight. - TIntermUnary* unOp = expr->getAsUnaryNode(); - TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); + // for expression has one of the following forms: + // loop_index++ + // loop_index-- + // loop_index += constant_expression + // loop_index -= constant_expression + // ++loop_index + // --loop_index + // The last two forms are not specified in the spec, but I am assuming + // its an oversight. + TIntermUnary* unOp = expr->getAsUnaryNode(); + TIntermBinary* binOp = unOp ? nullptr : expr->getAsBinaryNode(); - TOperator op = EOpNull; - TIntermSymbol* symbol = NULL; - if (unOp != NULL) { - op = unOp->getOp(); - symbol = unOp->getOperand()->getAsSymbolNode(); - } else if (binOp != NULL) { - op = binOp->getOp(); - symbol = binOp->getLeft()->getAsSymbolNode(); - } + TOperator op = EOpNull; + TIntermSymbol* symbol = nullptr; + if (unOp) { + op = unOp->getOp(); + symbol = unOp->getOperand()->getAsSymbolNode(); + } else if (binOp) { + op = binOp->getOp(); + symbol = binOp->getLeft()->getAsSymbolNode(); + } - // The operand must be loop index. - if (symbol == NULL) { - error(expr->getLine(), "Invalid expression", "for"); - return false; - } - if (symbol->getId() != info->index.id) { - error(symbol->getLine(), - "Expected loop index", symbol->getSymbol().c_str()); - return false; - } + // The operand must be loop index. + if (!symbol) { + error(expr->getLine(), "Invalid expression", "for"); + return false; + } + if (symbol->getId() != info->index.id) { + error(symbol->getLine(), + "Expected loop index", symbol->getSymbol().c_str()); + return false; + } - // The operator is one of: ++ -- += -=. - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - ASSERT((unOp != NULL) && (binOp == NULL)); - break; - case EOpAddAssign: - case EOpSubAssign: - ASSERT((unOp == NULL) && (binOp != NULL)); - break; - default: - error(expr->getLine(), "Invalid operator", getOperatorString(op)); - return false; - } + // The operator is one of: ++ -- += -=. + switch (op) { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + ASSERT((unOp != NULL) && (binOp == NULL)); + break; + case EOpAddAssign: + case EOpSubAssign: + ASSERT((unOp == NULL) && (binOp != NULL)); + break; + default: + error(expr->getLine(), "Invalid operator", getOperatorString(op)); + return false; + } - // Loop index must be incremented/decremented with a constant. - if (binOp != NULL) { - if (!isConstExpr(binOp->getRight())) { - error(binOp->getLine(), - "Loop index cannot be modified by non-constant expression", - symbol->getSymbol().c_str()); - return false; - } - } + // Loop index must be incremented/decremented with a constant. + if (binOp != NULL) { + if (!isConstExpr(binOp->getRight())) { + error(binOp->getLine(), + "Loop index cannot be modified by non-constant expression", + symbol->getSymbol().c_str()); + return false; + } + } - return true; + return true; } bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) { - ASSERT(node->getOp() == EOpFunctionCall); + ASSERT(node->getOp() == EOpFunctionCall); - // If not within loop body, there is nothing to check. - if (!withinLoopBody()) - return true; + // If not within loop body, there is nothing to check. + if (!withinLoopBody()) + return true; - // List of param indices for which loop indices are used as argument. - typedef std::vector<int> ParamIndex; - ParamIndex pIndex; - TIntermSequence& params = node->getSequence(); - for (TIntermSequence::size_type i = 0; i < params.size(); ++i) { - TIntermSymbol* symbol = params[i]->getAsSymbolNode(); - if (symbol && isLoopIndex(symbol)) - pIndex.push_back(i); - } - // If none of the loop indices are used as arguments, - // there is nothing to check. - if (pIndex.empty()) - return true; + // List of param indices for which loop indices are used as argument. + typedef std::vector<int> ParamIndex; + ParamIndex pIndex; + TIntermSequence& params = node->getSequence(); + for (TIntermSequence::size_type i = 0; i < params.size(); ++i) { + TIntermSymbol* symbol = params[i]->getAsSymbolNode(); + if (symbol && isLoopIndex(symbol)) + pIndex.push_back(i); + } + // If none of the loop indices are used as arguments, + // there is nothing to check. + if (pIndex.empty()) + return true; - bool valid = true; - TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable; - TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->getShaderVersion()); - ASSERT(symbol && symbol->isFunction()); - TFunction* function = static_cast<TFunction*>(symbol); - for (ParamIndex::const_iterator i = pIndex.begin(); - i != pIndex.end(); ++i) { - const TParameter& param = function->getParam(*i); - TQualifier qual = param.type->getQualifier(); - if ((qual == EvqOut) || (qual == EvqInOut)) { - error(params[*i]->getLine(), - "Loop index cannot be used as argument to a function out or inout parameter", - params[*i]->getAsSymbolNode()->getSymbol().c_str()); - valid = false; - } - } + bool valid = true; + TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable; + TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->getShaderVersion()); + ASSERT(symbol && symbol->isFunction()); + TFunction* function = static_cast<TFunction*>(symbol); + for (ParamIndex::const_iterator i = pIndex.begin(); + i != pIndex.end(); ++i) { + const TParameter& param = function->getParam(*i); + TQualifier qual = param.type->getQualifier(); + if ((qual == EvqOut) || (qual == EvqInOut)) { + error(params[*i]->getLine(), + "Loop index cannot be used as argument to a function out or inout parameter", + params[*i]->getAsSymbolNode()->getSymbol().c_str()); + valid = false; + } + } - return valid; + return valid; } bool ValidateLimitations::validateOperation(TIntermOperator* node, TIntermNode* operand) { - // Check if loop index is modified in the loop body. - if (!withinLoopBody() || !node->modifiesState()) - return true; + // Check if loop index is modified in the loop body. + if (!withinLoopBody() || !node->modifiesState()) + return true; - const TIntermSymbol* symbol = operand->getAsSymbolNode(); - if (symbol && isLoopIndex(symbol)) { - error(node->getLine(), - "Loop index cannot be statically assigned to within the body of the loop", - symbol->getSymbol().c_str()); - } - return true; + const TIntermSymbol* symbol = operand->getAsSymbolNode(); + if (symbol && isLoopIndex(symbol)) { + error(node->getLine(), + "Loop index cannot be statically assigned to within the body of the loop", + symbol->getSymbol().c_str()); + } + return true; } bool ValidateLimitations::isConstExpr(TIntermNode* node) { - ASSERT(node != NULL); - return node->getAsConstantUnion() != NULL; + ASSERT(node); + return node->getAsConstantUnion() != nullptr; } bool ValidateLimitations::isConstIndexExpr(TIntermNode* node) { - ASSERT(node != NULL); + ASSERT(node); - ValidateConstIndexExpr validate(mLoopStack); - node->traverse(&validate); - return validate.isValid(); + ValidateConstIndexExpr validate(mLoopStack); + node->traverse(&validate); + return validate.isValid(); } bool ValidateLimitations::validateIndexing(TIntermBinary* node) { - ASSERT((node->getOp() == EOpIndexDirect) || - (node->getOp() == EOpIndexIndirect)); + ASSERT((node->getOp() == EOpIndexDirect) || + (node->getOp() == EOpIndexIndirect)); - bool valid = true; - TIntermTyped* index = node->getRight(); - // The index expression must have integral type. - if (!index->isScalarInt()) { - error(index->getLine(), - "Index expression must have integral type", - index->getCompleteString().c_str()); - valid = false; - } - // The index expession must be a constant-index-expression unless - // the operand is a uniform in a vertex shader. - TIntermTyped* operand = node->getLeft(); - bool skip = (mShaderType == GL_VERTEX_SHADER) && - (operand->getQualifier() == EvqUniform); - if (!skip && !isConstIndexExpr(index)) { - error(index->getLine(), "Index expression must be constant", "[]"); - valid = false; - } - return valid; + bool valid = true; + TIntermTyped* index = node->getRight(); + // The index expression must have integral type. + if (!index->isScalarInt()) { + error(index->getLine(), + "Index expression must have integral type", + index->getCompleteString().c_str()); + valid = false; + } + // The index expession must be a constant-index-expression unless + // the operand is a uniform in a vertex shader. + TIntermTyped* operand = node->getLeft(); + bool skip = (mShaderType == GL_VERTEX_SHADER) && + (operand->getQualifier() == EvqUniform); + if (!skip && !isConstIndexExpr(index)) { + error(index->getLine(), "Index expression must be constant", "[]"); + valid = false; + } + return valid; }
diff --git a/src/OpenGL/compiler/ValidateLimitations.h b/src/OpenGL/compiler/ValidateLimitations.h index fa8adb1..6e43e0c 100644 --- a/src/OpenGL/compiler/ValidateLimitations.h +++ b/src/OpenGL/compiler/ValidateLimitations.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "Compiler.h" #include "intermediate.h" @@ -10,10 +18,10 @@ class TInfoSinkBase; struct TLoopInfo { - struct TIndex { - int id; // symbol id. - } index; - TIntermLoop* loop; + struct TIndex { + int id; // symbol id. + } index; + TIntermLoop* loop; }; typedef TVector<TLoopInfo> TLoopStack; @@ -21,39 +29,39 @@ // minimum functionality mandated in GLSL 1.0 spec, Appendix A. class ValidateLimitations : public TIntermTraverser { public: - ValidateLimitations(GLenum shaderType, TInfoSinkBase& sink); + ValidateLimitations(GLenum shaderType, TInfoSinkBase& sink); - int numErrors() const { return mNumErrors; } + int numErrors() const { return mNumErrors; } - virtual bool visitBinary(Visit, TIntermBinary*); - virtual bool visitUnary(Visit, TIntermUnary*); - virtual bool visitAggregate(Visit, TIntermAggregate*); - virtual bool visitLoop(Visit, TIntermLoop*); + virtual bool visitBinary(Visit, TIntermBinary*); + virtual bool visitUnary(Visit, TIntermUnary*); + virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual bool visitLoop(Visit, TIntermLoop*); private: - void error(TSourceLoc loc, const char *reason, const char* token); + void error(TSourceLoc loc, const char *reason, const char* token); - bool withinLoopBody() const; - bool isLoopIndex(const TIntermSymbol* symbol) const; - bool validateLoopType(TIntermLoop* node); - bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info); - // Returns true if none of the loop indices is used as the argument to - // the given function out or inout parameter. - bool validateFunctionCall(TIntermAggregate* node); - bool validateOperation(TIntermOperator* node, TIntermNode* operand); + bool withinLoopBody() const; + bool isLoopIndex(const TIntermSymbol* symbol) const; + bool validateLoopType(TIntermLoop* node); + bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info); + bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info); + // Returns true if none of the loop indices is used as the argument to + // the given function out or inout parameter. + bool validateFunctionCall(TIntermAggregate* node); + bool validateOperation(TIntermOperator* node, TIntermNode* operand); - // Returns true if indexing does not exceed the minimum functionality - // mandated in GLSL 1.0 spec, Appendix A, Section 5. - bool isConstExpr(TIntermNode* node); - bool isConstIndexExpr(TIntermNode* node); - bool validateIndexing(TIntermBinary* node); + // Returns true if indexing does not exceed the minimum functionality + // mandated in GLSL 1.0 spec, Appendix A, Section 5. + bool isConstExpr(TIntermNode* node); + bool isConstIndexExpr(TIntermNode* node); + bool validateIndexing(TIntermBinary* node); - GLenum mShaderType; - TInfoSinkBase& mSink; - int mNumErrors; - TLoopStack mLoopStack; + GLenum mShaderType; + TInfoSinkBase& mSink; + int mNumErrors; + TLoopStack mLoopStack; };
diff --git a/src/OpenGL/compiler/ValidateSwitch.cpp b/src/OpenGL/compiler/ValidateSwitch.cpp index 982cc51..edef69b 100644 --- a/src/OpenGL/compiler/ValidateSwitch.cpp +++ b/src/OpenGL/compiler/ValidateSwitch.cpp
@@ -1,200 +1,208 @@ -// -// Copyright (c) 2002-2015 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 "ValidateSwitch.h" - -#include "ParseHelper.h" - -bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context, - TIntermAggregate *statementList, const TSourceLoc &loc) -{ - ValidateSwitch validate(switchType, context); - ASSERT(statementList); - statementList->traverse(&validate); - return validate.validateInternal(loc); -} - -ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context) - : TIntermTraverser(true, false, true), - mSwitchType(switchType), - mContext(context), - mCaseTypeMismatch(false), - mFirstCaseFound(false), - mStatementBeforeCase(false), - mLastStatementWasCase(false), - mControlFlowDepth(0), - mCaseInsideControlFlow(false), - mDefaultCount(0), - mDuplicateCases(false) -{} - -void ValidateSwitch::visitSymbol(TIntermSymbol *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; -} - -void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) -{ - // Conditions of case labels are not traversed, so this is some other constant - // Could be just a statement like "0;" - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; -} - -bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *) -{ - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - // Don't go into nested switch statements - return false; -} - -bool ValidateSwitch::visitCase(Visit, TIntermCase *node) -{ - const char *nodeStr = node->hasCondition() ? "case" : "default"; - if (mControlFlowDepth > 0) - { - mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr); - mCaseInsideControlFlow = true; - } - mFirstCaseFound = true; - mLastStatementWasCase = true; - if (!node->hasCondition()) - { - ++mDefaultCount; - if (mDefaultCount > 1) - { - mContext->error(node->getLine(), "duplicate default label", nodeStr); - } - } - else - { - TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion(); - if (condition == nullptr) - { - // This can happen in error cases. - return false; - } - TBasicType conditionType = condition->getBasicType(); - if (conditionType != mSwitchType) - { - mContext->error(condition->getLine(), - "case label type does not match switch init-expression type", nodeStr); - mCaseTypeMismatch = true; - } - - if (conditionType == EbtInt) - { - int iConst = condition->getIConst(0); - if (mCasesSigned.find(iConst) != mCasesSigned.end()) - { - mContext->error(condition->getLine(), "duplicate case label", nodeStr); - mDuplicateCases = true; - } - else - { - mCasesSigned.insert(iConst); - } - } - else if (conditionType == EbtUInt) - { - unsigned int uConst = condition->getUConst(0); - if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) - { - mContext->error(condition->getLine(), "duplicate case label", nodeStr); - mDuplicateCases = true; - } - else - { - mCasesUnsigned.insert(uConst); - } - } - // Other types are possible only in error cases, where the error has already been generated - // when parsing the case statement. - } - // Don't traverse the condition of the case statement - return false; -} - -bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) -{ - if (getParentNode() != nullptr) - { - // This is not the statementList node, but some other node. - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - } - return true; -} - -bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) -{ - if (visit == PreVisit) - ++mControlFlowDepth; - if (visit == PostVisit) - --mControlFlowDepth; - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) -{ - if (!mFirstCaseFound) - mStatementBeforeCase = true; - mLastStatementWasCase = false; - return true; -} - -bool ValidateSwitch::validateInternal(const TSourceLoc &loc) -{ - if (mStatementBeforeCase) - { - mContext->error(loc, - "statement before the first label", "switch"); - } - if (mLastStatementWasCase) - { - mContext->error(loc, - "no statement between the last label and the end of the switch statement", "switch"); - } - return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow && - !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "ValidateSwitch.h" + +#include "ParseHelper.h" + +bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context, + TIntermAggregate *statementList, const TSourceLoc &loc) +{ + ValidateSwitch validate(switchType, context); + ASSERT(statementList); + statementList->traverse(&validate); + return validate.validateInternal(loc); +} + +ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context) + : TIntermTraverser(true, false, true), + mSwitchType(switchType), + mContext(context), + mCaseTypeMismatch(false), + mFirstCaseFound(false), + mStatementBeforeCase(false), + mLastStatementWasCase(false), + mControlFlowDepth(0), + mCaseInsideControlFlow(false), + mDefaultCount(0), + mDuplicateCases(false) +{} + +void ValidateSwitch::visitSymbol(TIntermSymbol *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; +} + +void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) +{ + // Conditions of case labels are not traversed, so this is some other constant + // Could be just a statement like "0;" + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; +} + +bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *) +{ + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + // Don't go into nested switch statements + return false; +} + +bool ValidateSwitch::visitCase(Visit, TIntermCase *node) +{ + const char *nodeStr = node->hasCondition() ? "case" : "default"; + if (mControlFlowDepth > 0) + { + mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr); + mCaseInsideControlFlow = true; + } + mFirstCaseFound = true; + mLastStatementWasCase = true; + if (!node->hasCondition()) + { + ++mDefaultCount; + if (mDefaultCount > 1) + { + mContext->error(node->getLine(), "duplicate default label", nodeStr); + } + } + else + { + TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion(); + if (condition == nullptr) + { + // This can happen in error cases. + return false; + } + TBasicType conditionType = condition->getBasicType(); + if (conditionType != mSwitchType) + { + mContext->error(condition->getLine(), + "case label type does not match switch init-expression type", nodeStr); + mCaseTypeMismatch = true; + } + + if (conditionType == EbtInt) + { + int iConst = condition->getIConst(0); + if (mCasesSigned.find(iConst) != mCasesSigned.end()) + { + mContext->error(condition->getLine(), "duplicate case label", nodeStr); + mDuplicateCases = true; + } + else + { + mCasesSigned.insert(iConst); + } + } + else if (conditionType == EbtUInt) + { + unsigned int uConst = condition->getUConst(0); + if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) + { + mContext->error(condition->getLine(), "duplicate case label", nodeStr); + mDuplicateCases = true; + } + else + { + mCasesUnsigned.insert(uConst); + } + } + // Other types are possible only in error cases, where the error has already been generated + // when parsing the case statement. + } + // Don't traverse the condition of the case statement + return false; +} + +bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) +{ + if (getParentNode() != nullptr) + { + // This is not the statementList node, but some other node. + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + } + return true; +} + +bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) +{ + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::validateInternal(const TSourceLoc &loc) +{ + if (mStatementBeforeCase) + { + mContext->error(loc, + "statement before the first label", "switch"); + } + if (mLastStatementWasCase) + { + mContext->error(loc, + "no statement between the last label and the end of the switch statement", "switch"); + } + return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow && + !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; +}
diff --git a/src/OpenGL/compiler/ValidateSwitch.h b/src/OpenGL/compiler/ValidateSwitch.h index 7dcc5e5..1c36e33 100644 --- a/src/OpenGL/compiler/ValidateSwitch.h +++ b/src/OpenGL/compiler/ValidateSwitch.h
@@ -1,53 +1,61 @@ -// -// Copyright (c) 2002-2015 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_TRANSLATOR_VALIDATESWITCH_H_ -#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_ - -#include "intermediate.h" -#include <set> - -class TParseContext; - -class ValidateSwitch : public TIntermTraverser -{ - public: - // Check for errors and output messages any remaining errors on the context. - // Returns true if there are no errors. - static bool validate(TBasicType switchType, TParseContext *context, - TIntermAggregate *statementList, const TSourceLoc &loc); - - void visitSymbol(TIntermSymbol *) override; - void visitConstantUnion(TIntermConstantUnion *) override; - bool visitBinary(Visit, TIntermBinary *) override; - bool visitUnary(Visit, TIntermUnary *) override; - bool visitSelection(Visit visit, TIntermSelection *) override; - bool visitSwitch(Visit, TIntermSwitch *) override; - bool visitCase(Visit, TIntermCase *) override; - bool visitAggregate(Visit, TIntermAggregate *) override; - bool visitLoop(Visit visit, TIntermLoop *) override; - bool visitBranch(Visit, TIntermBranch *) override; - - private: - ValidateSwitch(TBasicType switchType, TParseContext *context); - - bool validateInternal(const TSourceLoc &loc); - - TBasicType mSwitchType; - TParseContext *mContext; - bool mCaseTypeMismatch; - bool mFirstCaseFound; - bool mStatementBeforeCase; - bool mLastStatementWasCase; - int mControlFlowDepth; - bool mCaseInsideControlFlow; - int mDefaultCount; - std::set<int> mCasesSigned; - std::set<unsigned int> mCasesUnsigned; - bool mDuplicateCases; -}; - -#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_TRANSLATOR_VALIDATESWITCH_H_ +#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_ + +#include "intermediate.h" +#include <set> + +class TParseContext; + +class ValidateSwitch : public TIntermTraverser +{ +public: + // Check for errors and output messages any remaining errors on the context. + // Returns true if there are no errors. + static bool validate(TBasicType switchType, TParseContext *context, + TIntermAggregate *statementList, const TSourceLoc &loc); + + void visitSymbol(TIntermSymbol *) override; + void visitConstantUnion(TIntermConstantUnion *) override; + bool visitBinary(Visit, TIntermBinary *) override; + bool visitUnary(Visit, TIntermUnary *) override; + bool visitSelection(Visit visit, TIntermSelection *) override; + bool visitSwitch(Visit, TIntermSwitch *) override; + bool visitCase(Visit, TIntermCase *) override; + bool visitAggregate(Visit, TIntermAggregate *) override; + bool visitLoop(Visit visit, TIntermLoop *) override; + bool visitBranch(Visit, TIntermBranch *) override; + +private: + ValidateSwitch(TBasicType switchType, TParseContext *context); + + bool validateInternal(const TSourceLoc &loc); + + TBasicType mSwitchType; + TParseContext *mContext; + bool mCaseTypeMismatch; + bool mFirstCaseFound; + bool mStatementBeforeCase; + bool mLastStatementWasCase; + int mControlFlowDepth; + bool mCaseInsideControlFlow; + int mDefaultCount; + std::set<int> mCasesSigned; + std::set<unsigned int> mCasesUnsigned; + bool mDuplicateCases; +}; + +#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_
diff --git a/src/OpenGL/compiler/debug.cpp b/src/OpenGL/compiler/debug.cpp index e507ff6..b30632d 100644 --- a/src/OpenGL/compiler/debug.cpp +++ b/src/OpenGL/compiler/debug.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // debug.cpp: Debugging utilities. @@ -19,18 +27,18 @@ #ifdef TRACE_ENABLED extern "C" { void Trace(const char *format, ...) { - if (!format) return; + if (!format) return; - TParseContext* parseContext = GetGlobalParseContext(); - if (parseContext) { - char buf[kTraceBufferLen]; - va_list args; - va_start(args, format); - vsnprintf(buf, kTraceBufferLen, format, args); - va_end(args); + TParseContext* parseContext = GetGlobalParseContext(); + if (parseContext) { + char buf[kTraceBufferLen]; + va_list args; + va_start(args, format); + vsnprintf(buf, kTraceBufferLen, format, args); + va_end(args); - parseContext->trace(buf); - } + parseContext->trace(buf); + } } } // extern "C" #endif // TRACE_ENABLED
diff --git a/src/OpenGL/compiler/debug.h b/src/OpenGL/compiler/debug.h index 1b4a69b..2755d23 100644 --- a/src/OpenGL/compiler/debug.h +++ b/src/OpenGL/compiler/debug.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // debug.h: Debugging utilities. @@ -41,21 +49,21 @@ // A macro asserting a condition and outputting failures to the debug log #undef ASSERT #define ASSERT(expression) do { \ - if(!(expression)) \ - Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \ - assert(expression); \ + if(!(expression)) \ + Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \ + assert(expression); \ } while(0) #undef UNIMPLEMENTED #define UNIMPLEMENTED() do { \ - Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \ - assert(false); \ + Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \ + assert(false); \ } while(0) #undef UNREACHABLE #define UNREACHABLE(value) do { \ - Trace("Unreachable reached: %s(%d). %s: %d\n", __FUNCTION__, __LINE__, #value, value); \ - assert(false); \ + Trace("Unreachable reached: %s(%d). %s: %d\n", __FUNCTION__, __LINE__, #value, value); \ + assert(false); \ } while(0) #endif // __ANDROID__
diff --git a/src/OpenGL/compiler/generate_parser.sh b/src/OpenGL/compiler/generate_parser.sh index e472191..428b79b 100644 --- a/src/OpenGL/compiler/generate_parser.sh +++ b/src/OpenGL/compiler/generate_parser.sh
@@ -1,7 +1,17 @@ #!/bin/bash -# Copyright (c) 2010 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. +# Copyright 2016 The SwiftShader Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # Generates GLSL ES parser - glslang_lex.cpp, glslang_tab.h, and glslang_tab.cpp
diff --git a/src/OpenGL/compiler/glslang.h b/src/OpenGL/compiler/glslang.h index 98f760b..656ba18 100644 --- a/src/OpenGL/compiler/glslang.h +++ b/src/OpenGL/compiler/glslang.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. class TParseContext; extern int glslang_initialize(TParseContext* context);
diff --git a/src/OpenGL/compiler/glslang.l b/src/OpenGL/compiler/glslang.l index 0c51a97..9acc29a 100644 --- a/src/OpenGL/compiler/glslang.l +++ b/src/OpenGL/compiler/glslang.l
@@ -1,9 +1,17 @@ /* +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2015 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. This file contains the Lex specification for GLSL ES. Based on ANSI C grammar, Lex specification: @@ -14,11 +22,19 @@ */ %top{ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012-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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
diff --git a/src/OpenGL/compiler/glslang.y b/src/OpenGL/compiler/glslang.y index 3030144..c7e8f28 100644 --- a/src/OpenGL/compiler/glslang.y +++ b/src/OpenGL/compiler/glslang.y
@@ -1,9 +1,17 @@ /* +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2015 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. This file contains the Yacc grammar for GLSL ES. Based on ANSI C Yacc grammar: @@ -14,11 +22,19 @@ */ %{ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2015 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
diff --git a/src/OpenGL/compiler/glslang_lex.cpp b/src/OpenGL/compiler/glslang_lex.cpp index 91c1310..155605c 100644 --- a/src/OpenGL/compiler/glslang_lex.cpp +++ b/src/OpenGL/compiler/glslang_lex.cpp
@@ -1,9 +1,17 @@ #line 17 "./glslang.l" +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012-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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT! @@ -1019,11 +1027,19 @@ #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET /* +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2015 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. This file contains the Lex specification for GLSL ES. Based on ANSI C grammar, Lex specification:
diff --git a/src/OpenGL/compiler/glslang_tab.cpp b/src/OpenGL/compiler/glslang_tab.cpp index 2e23afe..e4f4952 100644 --- a/src/OpenGL/compiler/glslang_tab.cpp +++ b/src/OpenGL/compiler/glslang_tab.cpp
@@ -64,11 +64,19 @@ /* Copy the first part of user declarations. */ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2015 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
diff --git a/src/OpenGL/compiler/intermOut.cpp b/src/OpenGL/compiler/intermOut.cpp index 0b219b9..704f40e 100644 --- a/src/OpenGL/compiler/intermOut.cpp +++ b/src/OpenGL/compiler/intermOut.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "localintermediate.h" #include "SymbolTable.h" @@ -22,35 +30,35 @@ // class TOutputTraverser : public TIntermTraverser { public: - TOutputTraverser(TInfoSinkBase& i) : sink(i) { } - TInfoSinkBase& sink; + TOutputTraverser(TInfoSinkBase& i) : sink(i) { } + TInfoSinkBase& sink; protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); + void visitSymbol(TIntermSymbol*); + void visitConstantUnion(TIntermConstantUnion*); + bool visitBinary(Visit visit, TIntermBinary*); + bool visitUnary(Visit visit, TIntermUnary*); + bool visitSelection(Visit visit, TIntermSelection*); + bool visitAggregate(Visit visit, TIntermAggregate*); + bool visitLoop(Visit visit, TIntermLoop*); + bool visitBranch(Visit visit, TIntermBranch*); }; TString TType::getCompleteString() const { - TStringStream stream; + TStringStream stream; - if (qualifier != EvqTemporary && qualifier != EvqGlobal) - stream << getQualifierString() << " " << getPrecisionString() << " "; - if (array) - stream << "array of "; - if (isMatrix()) + if (qualifier != EvqTemporary && qualifier != EvqGlobal) + stream << getQualifierString() << " " << getPrecisionString() << " "; + if (array) + stream << "array of "; + if (isMatrix()) stream << static_cast<int>(primarySize) << "X" << static_cast<int>(secondarySize) << " matrix of "; else if(primarySize > 1) stream << static_cast<int>(primarySize) << "-component vector of "; - stream << getBasicString(); - return stream.str(); + stream << getBasicString(); + return stream.str(); } // @@ -59,12 +67,12 @@ void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) { - int i; + int i; - sink.location(node->getLine()); + sink.location(node->getLine()); - for (i = 0; i < depth; ++i) - sink << " "; + for (i = 0; i < depth; ++i) + sink << " "; } // @@ -78,372 +86,372 @@ void TOutputTraverser::visitSymbol(TIntermSymbol* node) { - OutputTreeText(sink, node, mDepth); + OutputTreeText(sink, node, mDepth); - sink << "'" << node->getSymbol() << "' "; - sink << "(" << node->getCompleteString() << ")\n"; + sink << "'" << node->getSymbol() << "' "; + sink << "(" << node->getCompleteString() << ")\n"; } bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) { - TInfoSinkBase& out = sink; + TInfoSinkBase& out = sink; - OutputTreeText(out, node, mDepth); + OutputTreeText(out, node, mDepth); - switch (node->getOp()) { - case EOpAssign: out << "move second child to first child"; break; - case EOpInitialize: out << "initialize first child with second child"; break; - case EOpAddAssign: out << "add second child into first child"; break; - case EOpSubAssign: out << "subtract second child into first child"; break; - case EOpMulAssign: out << "multiply second child into first child"; break; - case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break; - case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break; - case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break; - case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break; - case EOpDivAssign: out << "divide second child into first child"; break; - case EOpIModAssign: out << "modulo second child into first child"; break; - case EOpBitShiftLeftAssign: out << "bit-wise shift first child left by second child"; break; - case EOpBitShiftRightAssign: out << "bit-wise shift first child right by second child"; break; - case EOpBitwiseAndAssign: out << "bit-wise and second child into first child"; break; - case EOpBitwiseXorAssign: out << "bit-wise xor second child into first child"; break; - case EOpBitwiseOrAssign: out << "bit-wise or second child into first child"; break; - case EOpIndexDirect: out << "direct index"; break; - case EOpIndexIndirect: out << "indirect index"; break; - case EOpIndexDirectStruct: out << "direct index for structure"; break; - case EOpVectorSwizzle: out << "vector swizzle"; break; + switch (node->getOp()) { + case EOpAssign: out << "move second child to first child"; break; + case EOpInitialize: out << "initialize first child with second child"; break; + case EOpAddAssign: out << "add second child into first child"; break; + case EOpSubAssign: out << "subtract second child into first child"; break; + case EOpMulAssign: out << "multiply second child into first child"; break; + case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break; + case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break; + case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break; + case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break; + case EOpDivAssign: out << "divide second child into first child"; break; + case EOpIModAssign: out << "modulo second child into first child"; break; + case EOpBitShiftLeftAssign: out << "bit-wise shift first child left by second child"; break; + case EOpBitShiftRightAssign: out << "bit-wise shift first child right by second child"; break; + case EOpBitwiseAndAssign: out << "bit-wise and second child into first child"; break; + case EOpBitwiseXorAssign: out << "bit-wise xor second child into first child"; break; + case EOpBitwiseOrAssign: out << "bit-wise or second child into first child"; break; + case EOpIndexDirect: out << "direct index"; break; + case EOpIndexIndirect: out << "indirect index"; break; + case EOpIndexDirectStruct: out << "direct index for structure"; break; + case EOpVectorSwizzle: out << "vector swizzle"; break; - case EOpAdd: out << "add"; break; - case EOpSub: out << "subtract"; break; - case EOpMul: out << "component-wise multiply"; break; - case EOpDiv: out << "divide"; break; - case EOpIMod: out << "modulo"; break; - case EOpBitShiftLeft: out << "bit-wise shift left"; break; - case EOpBitShiftRight: out << "bit-wise shift right"; break; - case EOpBitwiseAnd: out << "bit-wise and"; break; - case EOpBitwiseXor: out << "bit-wise xor"; break; - case EOpBitwiseOr: out << "bit-wise or"; break; - case EOpEqual: out << "Compare Equal"; break; - case EOpNotEqual: out << "Compare Not Equal"; break; - case EOpLessThan: out << "Compare Less Than"; break; - case EOpGreaterThan: out << "Compare Greater Than"; break; - case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + case EOpAdd: out << "add"; break; + case EOpSub: out << "subtract"; break; + case EOpMul: out << "component-wise multiply"; break; + case EOpDiv: out << "divide"; break; + case EOpIMod: out << "modulo"; break; + case EOpBitShiftLeft: out << "bit-wise shift left"; break; + case EOpBitShiftRight: out << "bit-wise shift right"; break; + case EOpBitwiseAnd: out << "bit-wise and"; break; + case EOpBitwiseXor: out << "bit-wise xor"; break; + case EOpBitwiseOr: out << "bit-wise or"; break; + case EOpEqual: out << "Compare Equal"; break; + case EOpNotEqual: out << "Compare Not Equal"; break; + case EOpLessThan: out << "Compare Less Than"; break; + case EOpGreaterThan: out << "Compare Greater Than"; break; + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; - case EOpVectorTimesScalar: out << "vector-scale"; break; - case EOpVectorTimesMatrix: out << "vector-times-matrix"; break; - case EOpMatrixTimesVector: out << "matrix-times-vector"; break; - case EOpMatrixTimesScalar: out << "matrix-scale"; break; - case EOpMatrixTimesMatrix: out << "matrix-multiply"; break; + case EOpVectorTimesScalar: out << "vector-scale"; break; + case EOpVectorTimesMatrix: out << "vector-times-matrix"; break; + case EOpMatrixTimesVector: out << "matrix-times-vector"; break; + case EOpMatrixTimesScalar: out << "matrix-scale"; break; + case EOpMatrixTimesMatrix: out << "matrix-multiply"; break; - case EOpLogicalOr: out << "logical-or"; break; - case EOpLogicalXor: out << "logical-xor"; break; - case EOpLogicalAnd: out << "logical-and"; break; - default: out << "<unknown op>"; - } + case EOpLogicalOr: out << "logical-or"; break; + case EOpLogicalXor: out << "logical-xor"; break; + case EOpLogicalAnd: out << "logical-and"; break; + default: out << "<unknown op>"; + } - out << " (" << node->getCompleteString() << ")"; + out << " (" << node->getCompleteString() << ")"; - out << "\n"; + out << "\n"; - return true; + return true; } bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) { - TInfoSinkBase& out = sink; + TInfoSinkBase& out = sink; - OutputTreeText(out, node, mDepth); + OutputTreeText(out, node, mDepth); - switch (node->getOp()) { - case EOpNegative: out << "Negate value"; break; - case EOpVectorLogicalNot: - case EOpLogicalNot: out << "Negate conditional"; break; - case EOpBitwiseNot: out << "bit-wise not"; break; + switch (node->getOp()) { + case EOpNegative: out << "Negate value"; break; + case EOpVectorLogicalNot: + case EOpLogicalNot: out << "Negate conditional"; break; + case EOpBitwiseNot: out << "bit-wise not"; break; - case EOpPostIncrement: out << "Post-Increment"; break; - case EOpPostDecrement: out << "Post-Decrement"; break; - case EOpPreIncrement: out << "Pre-Increment"; break; - case EOpPreDecrement: out << "Pre-Decrement"; break; + case EOpPostIncrement: out << "Post-Increment"; break; + case EOpPostDecrement: out << "Post-Decrement"; break; + case EOpPreIncrement: out << "Pre-Increment"; break; + case EOpPreDecrement: out << "Pre-Decrement"; break; - case EOpRadians: out << "radians"; break; - case EOpDegrees: out << "degrees"; break; - case EOpSin: out << "sine"; break; - case EOpCos: out << "cosine"; break; - case EOpTan: out << "tangent"; break; - case EOpAsin: out << "arc sine"; break; - case EOpAcos: out << "arc cosine"; break; - case EOpAtan: out << "arc tangent"; break; - case EOpSinh: out << "hyperbolic sine"; break; - case EOpCosh: out << "hyperbolic cosine"; break; - case EOpTanh: out << "hyperbolic tangent"; break; - case EOpAsinh: out << "arc hyperbolic sine"; break; - case EOpAcosh: out << "arc hyperbolic cosine"; break; - case EOpAtanh: out << "arc hyperbolic tangent"; break; + case EOpRadians: out << "radians"; break; + case EOpDegrees: out << "degrees"; break; + case EOpSin: out << "sine"; break; + case EOpCos: out << "cosine"; break; + case EOpTan: out << "tangent"; break; + case EOpAsin: out << "arc sine"; break; + case EOpAcos: out << "arc cosine"; break; + case EOpAtan: out << "arc tangent"; break; + case EOpSinh: out << "hyperbolic sine"; break; + case EOpCosh: out << "hyperbolic cosine"; break; + case EOpTanh: out << "hyperbolic tangent"; break; + case EOpAsinh: out << "arc hyperbolic sine"; break; + case EOpAcosh: out << "arc hyperbolic cosine"; break; + case EOpAtanh: out << "arc hyperbolic tangent"; break; - case EOpExp: out << "exp"; break; - case EOpLog: out << "log"; break; - case EOpExp2: out << "exp2"; break; - case EOpLog2: out << "log2"; break; - case EOpSqrt: out << "sqrt"; break; - case EOpInverseSqrt: out << "inverse sqrt"; break; + case EOpExp: out << "exp"; break; + case EOpLog: out << "log"; break; + case EOpExp2: out << "exp2"; break; + case EOpLog2: out << "log2"; break; + case EOpSqrt: out << "sqrt"; break; + case EOpInverseSqrt: out << "inverse sqrt"; break; - case EOpAbs: out << "Absolute value"; break; - case EOpSign: out << "Sign"; break; - case EOpFloor: out << "Floor"; break; - case EOpTrunc: out << "Trunc"; break; - case EOpRound: out << "Round"; break; - case EOpRoundEven: out << "RoundEven"; break; - case EOpCeil: out << "Ceiling"; break; - case EOpFract: out << "Fraction"; break; - case EOpIsNan: out << "Is not a number"; break; - case EOpIsInf: out << "Is infinity"; break; + case EOpAbs: out << "Absolute value"; break; + case EOpSign: out << "Sign"; break; + case EOpFloor: out << "Floor"; break; + case EOpTrunc: out << "Trunc"; break; + case EOpRound: out << "Round"; break; + case EOpRoundEven: out << "RoundEven"; break; + case EOpCeil: out << "Ceiling"; break; + case EOpFract: out << "Fraction"; break; + case EOpIsNan: out << "Is not a number"; break; + case EOpIsInf: out << "Is infinity"; break; - case EOpFloatBitsToInt: out << "float bits to int"; break; - case EOpFloatBitsToUint: out << "float bits to uint"; break; - case EOpIntBitsToFloat: out << "int bits to float"; break; - case EOpUintBitsToFloat: out << "uint bits to float"; break; + case EOpFloatBitsToInt: out << "float bits to int"; break; + case EOpFloatBitsToUint: out << "float bits to uint"; break; + case EOpIntBitsToFloat: out << "int bits to float"; break; + case EOpUintBitsToFloat: out << "uint bits to float"; break; - case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break; - case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break; - case EOpPackHalf2x16: out << "pack half 2x16"; break; + case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break; + case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break; + case EOpPackHalf2x16: out << "pack half 2x16"; break; - case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break; - case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break; - case EOpUnpackHalf2x16: out << "unpack half 2x16"; break; + case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break; + case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break; + case EOpUnpackHalf2x16: out << "unpack half 2x16"; break; - case EOpLength: out << "length"; break; - case EOpNormalize: out << "normalize"; break; - // case EOpDPdx: out << "dPdx"; break; - // case EOpDPdy: out << "dPdy"; break; - // case EOpFwidth: out << "fwidth"; break; + case EOpLength: out << "length"; break; + case EOpNormalize: out << "normalize"; break; + // case EOpDPdx: out << "dPdx"; break; + // case EOpDPdy: out << "dPdy"; break; + // case EOpFwidth: out << "fwidth"; break; - case EOpDeterminant: out << "determinant"; break; - case EOpTranspose: out << "transpose"; break; - case EOpInverse: out << "inverse"; break; + case EOpDeterminant: out << "determinant"; break; + case EOpTranspose: out << "transpose"; break; + case EOpInverse: out << "inverse"; break; - case EOpAny: out << "any"; break; - case EOpAll: out << "all"; break; + case EOpAny: out << "any"; break; + case EOpAll: out << "all"; break; - default: out.message(EPrefixError, "Bad unary op"); - } + default: out.message(EPrefixError, "Bad unary op"); + } - out << " (" << node->getCompleteString() << ")"; + out << " (" << node->getCompleteString() << ")"; - out << "\n"; + out << "\n"; - return true; + return true; } bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) { - TInfoSinkBase& out = sink; + TInfoSinkBase& out = sink; - if (node->getOp() == EOpNull) { - out.message(EPrefixError, "node is still EOpNull!"); - return true; - } + if (node->getOp() == EOpNull) { + out.message(EPrefixError, "node is still EOpNull!"); + return true; + } - OutputTreeText(out, node, mDepth); + OutputTreeText(out, node, mDepth); - switch (node->getOp()) { - case EOpSequence: out << "Sequence\n"; return true; - case EOpComma: out << "Comma\n"; return true; - case EOpFunction: out << "Function Definition: " << node->getName(); break; - case EOpFunctionCall: out << "Function Call: " << node->getName(); break; - case EOpParameters: out << "Function Parameters: "; break; + switch (node->getOp()) { + case EOpSequence: out << "Sequence\n"; return true; + case EOpComma: out << "Comma\n"; return true; + case EOpFunction: out << "Function Definition: " << node->getName(); break; + case EOpFunctionCall: out << "Function Call: " << node->getName(); break; + case EOpParameters: out << "Function Parameters: "; break; - case EOpConstructFloat: out << "Construct float"; break; - case EOpConstructVec2: out << "Construct vec2"; break; - case EOpConstructVec3: out << "Construct vec3"; break; - case EOpConstructVec4: out << "Construct vec4"; break; - case EOpConstructBool: out << "Construct bool"; break; - case EOpConstructBVec2: out << "Construct bvec2"; break; - case EOpConstructBVec3: out << "Construct bvec3"; break; - case EOpConstructBVec4: out << "Construct bvec4"; break; - case EOpConstructInt: out << "Construct int"; break; - case EOpConstructIVec2: out << "Construct ivec2"; break; - case EOpConstructIVec3: out << "Construct ivec3"; break; - case EOpConstructIVec4: out << "Construct ivec4"; break; - case EOpConstructUInt: out << "Construct uint"; break; - case EOpConstructUVec2: out << "Construct uvec2"; break; - case EOpConstructUVec3: out << "Construct uvec3"; break; - case EOpConstructUVec4: out << "Construct uvec4"; break; - case EOpConstructMat2: out << "Construct mat2"; break; - case EOpConstructMat3: out << "Construct mat3"; break; - case EOpConstructMat4: out << "Construct mat4"; break; - case EOpConstructStruct: out << "Construct structure"; break; + case EOpConstructFloat: out << "Construct float"; break; + case EOpConstructVec2: out << "Construct vec2"; break; + case EOpConstructVec3: out << "Construct vec3"; break; + case EOpConstructVec4: out << "Construct vec4"; break; + case EOpConstructBool: out << "Construct bool"; break; + case EOpConstructBVec2: out << "Construct bvec2"; break; + case EOpConstructBVec3: out << "Construct bvec3"; break; + case EOpConstructBVec4: out << "Construct bvec4"; break; + case EOpConstructInt: out << "Construct int"; break; + case EOpConstructIVec2: out << "Construct ivec2"; break; + case EOpConstructIVec3: out << "Construct ivec3"; break; + case EOpConstructIVec4: out << "Construct ivec4"; break; + case EOpConstructUInt: out << "Construct uint"; break; + case EOpConstructUVec2: out << "Construct uvec2"; break; + case EOpConstructUVec3: out << "Construct uvec3"; break; + case EOpConstructUVec4: out << "Construct uvec4"; break; + case EOpConstructMat2: out << "Construct mat2"; break; + case EOpConstructMat3: out << "Construct mat3"; break; + case EOpConstructMat4: out << "Construct mat4"; break; + case EOpConstructStruct: out << "Construct structure"; break; - case EOpLessThan: out << "Compare Less Than"; break; - case EOpGreaterThan: out << "Compare Greater Than"; break; - case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out << "Equal"; break; - case EOpVectorNotEqual: out << "NotEqual"; break; + case EOpLessThan: out << "Compare Less Than"; break; + case EOpGreaterThan: out << "Compare Greater Than"; break; + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + case EOpVectorEqual: out << "Equal"; break; + case EOpVectorNotEqual: out << "NotEqual"; break; - case EOpMod: out << "mod"; break; - case EOpModf: out << "modf"; break; - case EOpPow: out << "pow"; break; + case EOpMod: out << "mod"; break; + case EOpModf: out << "modf"; break; + case EOpPow: out << "pow"; break; - case EOpAtan: out << "arc tangent"; break; + case EOpAtan: out << "arc tangent"; break; - case EOpMin: out << "min"; break; - case EOpMax: out << "max"; break; - case EOpClamp: out << "clamp"; break; - case EOpMix: out << "mix"; break; - case EOpStep: out << "step"; break; - case EOpSmoothStep: out << "smoothstep"; break; + case EOpMin: out << "min"; break; + case EOpMax: out << "max"; break; + case EOpClamp: out << "clamp"; break; + case EOpMix: out << "mix"; break; + case EOpStep: out << "step"; break; + case EOpSmoothStep: out << "smoothstep"; break; - case EOpDistance: out << "distance"; break; - case EOpDot: out << "dot-product"; break; - case EOpCross: out << "cross-product"; break; - case EOpFaceForward: out << "face-forward"; break; - case EOpReflect: out << "reflect"; break; - case EOpRefract: out << "refract"; break; - case EOpMul: out << "component-wise multiply"; break; - case EOpOuterProduct: out << "outer product"; break; + case EOpDistance: out << "distance"; break; + case EOpDot: out << "dot-product"; break; + case EOpCross: out << "cross-product"; break; + case EOpFaceForward: out << "face-forward"; break; + case EOpReflect: out << "reflect"; break; + case EOpRefract: out << "refract"; break; + case EOpMul: out << "component-wise multiply"; break; + case EOpOuterProduct: out << "outer product"; break; - default: out.message(EPrefixError, "Bad aggregation op"); - } + default: out.message(EPrefixError, "Bad aggregation op"); + } - if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) - out << " (" << node->getCompleteString() << ")"; + if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) + out << " (" << node->getCompleteString() << ")"; - out << "\n"; + out << "\n"; - return true; + return true; } bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) { - TInfoSinkBase& out = sink; + TInfoSinkBase& out = sink; - OutputTreeText(out, node, mDepth); + OutputTreeText(out, node, mDepth); - out << "Test condition and select"; - out << " (" << node->getCompleteString() << ")\n"; + out << "Test condition and select"; + out << " (" << node->getCompleteString() << ")\n"; - ++mDepth; + ++mDepth; - OutputTreeText(sink, node, mDepth); - out << "Condition\n"; - node->getCondition()->traverse(this); + OutputTreeText(sink, node, mDepth); + out << "Condition\n"; + node->getCondition()->traverse(this); - OutputTreeText(sink, node, mDepth); - if (node->getTrueBlock()) { - out << "true case\n"; - node->getTrueBlock()->traverse(this); - } else - out << "true case is null\n"; + OutputTreeText(sink, node, mDepth); + if (node->getTrueBlock()) { + out << "true case\n"; + node->getTrueBlock()->traverse(this); + } else + out << "true case is null\n"; - if (node->getFalseBlock()) { - OutputTreeText(sink, node, mDepth); - out << "false case\n"; - node->getFalseBlock()->traverse(this); - } + if (node->getFalseBlock()) { + OutputTreeText(sink, node, mDepth); + out << "false case\n"; + node->getFalseBlock()->traverse(this); + } - --mDepth; + --mDepth; - return false; + return false; } void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) { - TInfoSinkBase& out = sink; + TInfoSinkBase& out = sink; - size_t size = node->getType().getObjectSize(); + size_t size = node->getType().getObjectSize(); - for(size_t i = 0; i < size; i++) { - OutputTreeText(out, node, mDepth); - switch (node->getUnionArrayPointer()[i].getType()) { - case EbtBool: - if (node->getUnionArrayPointer()[i].getBConst()) - out << "true"; - else - out << "false"; + for(size_t i = 0; i < size; i++) { + OutputTreeText(out, node, mDepth); + switch (node->getUnionArrayPointer()[i].getType()) { + case EbtBool: + if (node->getUnionArrayPointer()[i].getBConst()) + out << "true"; + else + out << "false"; - out << " (" << "const bool" << ")"; - out << "\n"; - break; - case EbtFloat: - out << node->getUnionArrayPointer()[i].getFConst(); - out << " (const float)\n"; - break; - case EbtInt: - out << node->getUnionArrayPointer()[i].getIConst(); - out << " (const int)\n"; - break; - case EbtUInt: - out << node->getUnionArrayPointer()[i].getUConst(); - out << " (const uint)\n"; - break; - default: - out.message(EPrefixInternalError, "Unknown constant", node->getLine()); - break; - } - } + out << " (" << "const bool" << ")"; + out << "\n"; + break; + case EbtFloat: + out << node->getUnionArrayPointer()[i].getFConst(); + out << " (const float)\n"; + break; + case EbtInt: + out << node->getUnionArrayPointer()[i].getIConst(); + out << " (const int)\n"; + break; + case EbtUInt: + out << node->getUnionArrayPointer()[i].getUConst(); + out << " (const uint)\n"; + break; + default: + out.message(EPrefixInternalError, "Unknown constant", node->getLine()); + break; + } + } } bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) { - TInfoSinkBase& out = sink; + TInfoSinkBase& out = sink; - OutputTreeText(out, node, mDepth); + OutputTreeText(out, node, mDepth); - out << "Loop with condition "; - if (node->getType() == ELoopDoWhile) - out << "not "; - out << "tested first\n"; + out << "Loop with condition "; + if (node->getType() == ELoopDoWhile) + out << "not "; + out << "tested first\n"; - ++mDepth; + ++mDepth; - OutputTreeText(sink, node, mDepth); - if (node->getCondition()) { - out << "Loop Condition\n"; - node->getCondition()->traverse(this); - } else - out << "No loop condition\n"; + OutputTreeText(sink, node, mDepth); + if (node->getCondition()) { + out << "Loop Condition\n"; + node->getCondition()->traverse(this); + } else + out << "No loop condition\n"; - OutputTreeText(sink, node, mDepth); - if (node->getBody()) { - out << "Loop Body\n"; - node->getBody()->traverse(this); - } else - out << "No loop body\n"; + OutputTreeText(sink, node, mDepth); + if (node->getBody()) { + out << "Loop Body\n"; + node->getBody()->traverse(this); + } else + out << "No loop body\n"; - if (node->getExpression()) { - OutputTreeText(sink, node, mDepth); - out << "Loop Terminal Expression\n"; - node->getExpression()->traverse(this); - } + if (node->getExpression()) { + OutputTreeText(sink, node, mDepth); + out << "Loop Terminal Expression\n"; + node->getExpression()->traverse(this); + } - --mDepth; + --mDepth; - return false; + return false; } bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) { - TInfoSinkBase& out = sink; + TInfoSinkBase& out = sink; - OutputTreeText(out, node, mDepth); + OutputTreeText(out, node, mDepth); - switch (node->getFlowOp()) { - case EOpKill: out << "Branch: Kill"; break; - case EOpBreak: out << "Branch: Break"; break; - case EOpContinue: out << "Branch: Continue"; break; - case EOpReturn: out << "Branch: Return"; break; - default: out << "Branch: Unknown Branch"; break; - } + switch (node->getFlowOp()) { + case EOpKill: out << "Branch: Kill"; break; + case EOpBreak: out << "Branch: Break"; break; + case EOpContinue: out << "Branch: Continue"; break; + case EOpReturn: out << "Branch: Return"; break; + default: out << "Branch: Unknown Branch"; break; + } - if (node->getExpression()) { - out << " with expression\n"; - ++mDepth; - node->getExpression()->traverse(this); - --mDepth; - } else - out << "\n"; + if (node->getExpression()) { + out << " with expression\n"; + ++mDepth; + node->getExpression()->traverse(this); + --mDepth; + } else + out << "\n"; - return false; + return false; } // @@ -453,10 +461,10 @@ // void TIntermediate::outputTree(TIntermNode* root) { - if (root == 0) - return; + if (root == 0) + return; - TOutputTraverser it(infoSink.info); + TOutputTraverser it(infoSink.info); - root->traverse(&it); + root->traverse(&it); }
diff --git a/src/OpenGL/compiler/intermediate.h b/src/OpenGL/compiler/intermediate.h index 7db04f4..3e0d876 100644 --- a/src/OpenGL/compiler/intermediate.h +++ b/src/OpenGL/compiler/intermediate.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // // Definition of the in-memory high-level intermediate representation @@ -24,210 +32,210 @@ // Operators used by the high-level (parse tree) representation. // enum TOperator { - EOpNull, // if in a node, should only mean a node is still being built - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function - EOpDeclaration, - EOpInvariantDeclaration, // Specialized declarations for attributing invariance - EOpPrototype, + EOpDeclaration, + EOpInvariantDeclaration, // Specialized declarations for attributing invariance + EOpPrototype, - // - // Unary operators - // + // + // Unary operators + // - EOpNegative, - EOpLogicalNot, - EOpVectorLogicalNot, - EOpBitwiseNot, + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, - // - // binary operations - // + // + // binary operations + // - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpEqual, - EOpNotEqual, - EOpVectorEqual, - EOpVectorNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - EOpComma, + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, - EOpOuterProduct, - EOpTranspose, - EOpDeterminant, - EOpInverse, + EOpOuterProduct, + EOpTranspose, + EOpDeterminant, + EOpInverse, - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, - EOpIMod, - EOpBitShiftLeft, - EOpBitShiftRight, - EOpBitwiseAnd, - EOpBitwiseXor, - EOpBitwiseOr, + EOpIMod, + EOpBitShiftLeft, + EOpBitShiftRight, + EOpBitwiseAnd, + EOpBitwiseXor, + EOpBitwiseOr, - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - EOpIndexDirectInterfaceBlock, + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + EOpIndexDirectInterfaceBlock, - EOpVectorSwizzle, + EOpVectorSwizzle, - // - // Built-in functions potentially mapped to operators - // + // + // Built-in functions potentially mapped to operators + // - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - EOpSinh, - EOpCosh, - EOpTanh, - EOpAsinh, - EOpAcosh, - EOpAtanh, + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + EOpSinh, + EOpCosh, + EOpTanh, + EOpAsinh, + EOpAcosh, + EOpAtanh, - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, - EOpAbs, - EOpSign, - EOpFloor, - EOpTrunc, - EOpRound, - EOpRoundEven, - EOpCeil, - EOpFract, - EOpMod, - EOpModf, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - EOpIsNan, - EOpIsInf, - EOpFloatBitsToInt, - EOpFloatBitsToUint, - EOpIntBitsToFloat, - EOpUintBitsToFloat, - EOpPackSnorm2x16, - EOpPackUnorm2x16, - EOpPackHalf2x16, - EOpUnpackSnorm2x16, - EOpUnpackUnorm2x16, - EOpUnpackHalf2x16, + EOpAbs, + EOpSign, + EOpFloor, + EOpTrunc, + EOpRound, + EOpRoundEven, + EOpCeil, + EOpFract, + EOpMod, + EOpModf, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + EOpIsNan, + EOpIsInf, + EOpFloatBitsToInt, + EOpFloatBitsToUint, + EOpIntBitsToFloat, + EOpUintBitsToFloat, + EOpPackSnorm2x16, + EOpPackUnorm2x16, + EOpPackHalf2x16, + EOpUnpackSnorm2x16, + EOpUnpackUnorm2x16, + EOpUnpackHalf2x16, - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceForward, - EOpReflect, - EOpRefract, + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, - EOpDFdx, // Fragment only, OES_standard_derivatives extension - EOpDFdy, // Fragment only, OES_standard_derivatives extension - EOpFwidth, // Fragment only, OES_standard_derivatives extension + EOpDFdx, // Fragment only, OES_standard_derivatives extension + EOpDFdy, // Fragment only, OES_standard_derivatives extension + EOpFwidth, // Fragment only, OES_standard_derivatives extension - EOpMatrixTimesMatrix, + EOpMatrixTimesMatrix, - EOpAny, - EOpAll, + EOpAny, + EOpAll, - // - // Branch - // + // + // Branch + // - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, - // - // Constructors - // + // + // Constructors + // - EOpConstructInt, - EOpConstructUInt, - EOpConstructBool, - EOpConstructFloat, - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructUVec2, - EOpConstructUVec3, - EOpConstructUVec4, - EOpConstructMat2, - EOpConstructMat2x3, - EOpConstructMat2x4, - EOpConstructMat3x2, - EOpConstructMat3, - EOpConstructMat3x4, - EOpConstructMat4x2, - EOpConstructMat4x3, - EOpConstructMat4, - EOpConstructStruct, + EOpConstructInt, + EOpConstructUInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructMat2, + EOpConstructMat2x3, + EOpConstructMat2x4, + EOpConstructMat3x2, + EOpConstructMat3, + EOpConstructMat3x4, + EOpConstructMat4x2, + EOpConstructMat4x3, + EOpConstructMat4, + EOpConstructStruct, - // - // moves - // + // + // moves + // - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign, - EOpIModAssign, - EOpBitShiftLeftAssign, - EOpBitShiftRightAssign, - EOpBitwiseAndAssign, - EOpBitwiseXorAssign, - EOpBitwiseOrAssign + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign, + EOpIModAssign, + EOpBitShiftLeftAssign, + EOpBitShiftRightAssign, + EOpBitwiseAndAssign, + EOpBitwiseXorAssign, + EOpBitwiseOrAssign }; extern const char* getOperatorString(TOperator op); @@ -251,43 +259,43 @@ // class TIntermNode { public: - POOL_ALLOCATOR_NEW_DELETE(); + 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; - } + 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; + } - const TSourceLoc& getLine() const { return line; } - void setLine(const 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; } - virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } - virtual TIntermAggregate* getAsAggregate() { return 0; } - virtual TIntermBinary* getAsBinaryNode() { return 0; } - virtual TIntermUnary* getAsUnaryNode() { return 0; } - virtual TIntermSelection* getAsSelectionNode() { return 0; } - virtual TIntermSymbol* getAsSymbolNode() { return 0; } - virtual TIntermLoop* getAsLoopNode() { return 0; } + virtual void traverse(TIntermTraverser*) = 0; + virtual TIntermTyped* getAsTyped() { return 0; } + virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual TIntermAggregate* getAsAggregate() { return 0; } + virtual TIntermBinary* getAsBinaryNode() { return 0; } + virtual TIntermUnary* getAsUnaryNode() { return 0; } + virtual TIntermSelection* getAsSelectionNode() { return 0; } + virtual TIntermSymbol* getAsSymbolNode() { return 0; } + virtual TIntermLoop* getAsLoopNode() { return 0; } virtual TIntermBranch* getAsBranchNode() { return 0; } virtual TIntermSwitch *getAsSwitchNode() { return 0; } virtual TIntermCase *getAsCaseNode() { return 0; } - virtual ~TIntermNode() { } + virtual ~TIntermNode() { } protected: - TSourceLoc line; + TSourceLoc line; }; // // This is just to help yacc. // struct TIntermNodePair { - TIntermNode* node1; - TIntermNode* node2; + TIntermNode* node1; + TIntermNode* node2; }; // @@ -295,30 +303,30 @@ // class TIntermTyped : public TIntermNode { public: - TIntermTyped(const TType& t) : type(t) { } - virtual TIntermTyped* getAsTyped() { return this; } + TIntermTyped(const TType& t) : type(t) { } + virtual TIntermTyped* getAsTyped() { return this; } - virtual void setType(const TType& t) { type = t; } - const TType& getType() const { return type; } - TType* getTypePointer() { return &type; } + virtual void setType(const TType& t) { type = t; } + const TType& getType() const { return type; } + TType* getTypePointer() { return &type; } - TBasicType getBasicType() const { return type.getBasicType(); } - TQualifier getQualifier() const { return type.getQualifier(); } - TPrecision getPrecision() const { return type.getPrecision(); } - int getNominalSize() const { return type.getNominalSize(); } + TBasicType getBasicType() const { return type.getBasicType(); } + TQualifier getQualifier() const { return type.getQualifier(); } + TPrecision getPrecision() const { return type.getPrecision(); } + int getNominalSize() const { return type.getNominalSize(); } int getSecondarySize() const { return type.getSecondarySize(); } bool isInterfaceBlock() const { return type.isInterfaceBlock(); } - bool isMatrix() const { return type.isMatrix(); } - bool isArray() const { return type.isArray(); } - bool isVector() const { return type.isVector(); } - bool isScalar() const { return type.isScalar(); } - bool isScalarInt() const { return type.isScalarInt(); } + bool isMatrix() const { return type.isMatrix(); } + bool isArray() const { return type.isArray(); } + bool isVector() const { return type.isVector(); } + bool isScalar() const { return type.isScalar(); } + bool isScalarInt() const { return type.isScalarInt(); } bool isRegister() const { return type.isRegister(); } // Fits in a 4-element register bool isStruct() const { return type.isStruct(); } - const char* getBasicString() const { return type.getBasicString(); } - const char* getQualifierString() const { return type.getQualifierString(); } - TString getCompleteString() const { return type.getCompleteString(); } + const char* getBasicString() const { return type.getBasicString(); } + const char* getQualifierString() const { return type.getQualifierString(); } + TString getCompleteString() const { return type.getCompleteString(); } int totalRegisterCount() const { return type.totalRegisterCount(); } int blockRegisterCount() const { return type.blockRegisterCount(); } @@ -327,50 +335,50 @@ int getArraySize() const { return type.getArraySize(); } protected: - TType type; + TType type; }; // // Handle for, do-while, and while loops. // enum TLoopType { - ELoopFor, - ELoopWhile, - ELoopDoWhile + ELoopFor, + ELoopWhile, + ELoopDoWhile }; class TIntermLoop : public TIntermNode { public: - TIntermLoop(TLoopType aType, - TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, - TIntermNode* aBody) : - type(aType), - init(aInit), - cond(aCond), - expr(aExpr), - body(aBody), - unrollFlag(false) { } + TIntermLoop(TLoopType aType, + TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, + TIntermNode* aBody) : + type(aType), + init(aInit), + cond(aCond), + expr(aExpr), + body(aBody), + unrollFlag(false) { } - virtual TIntermLoop* getAsLoopNode() { return this; } - virtual void traverse(TIntermTraverser*); + virtual TIntermLoop* getAsLoopNode() { return this; } + virtual void traverse(TIntermTraverser*); - TLoopType getType() const { return type; } - TIntermNode* getInit() { return init; } - TIntermTyped* getCondition() { return cond; } - TIntermTyped* getExpression() { return expr; } - TIntermNode* getBody() { return body; } + TLoopType getType() const { return type; } + TIntermNode* getInit() { return init; } + TIntermTyped* getCondition() { return cond; } + TIntermTyped* getExpression() { return expr; } + TIntermNode* getBody() { return body; } - void setUnrollFlag(bool flag) { unrollFlag = flag; } - bool getUnrollFlag() { return unrollFlag; } + void setUnrollFlag(bool flag) { unrollFlag = flag; } + bool getUnrollFlag() { return unrollFlag; } protected: - TLoopType type; - TIntermNode* init; // for-loop initialization - TIntermTyped* cond; // loop exit condition - TIntermTyped* expr; // for-loop expression - TIntermNode* body; // loop body + TLoopType type; + TIntermNode* init; // for-loop initialization + TIntermTyped* cond; // loop exit condition + TIntermTyped* expr; // for-loop expression + TIntermNode* body; // loop body - bool unrollFlag; // Whether the loop should be unrolled or not. + bool unrollFlag; // Whether the loop should be unrolled or not. }; // @@ -378,19 +386,19 @@ // class TIntermBranch : public TIntermNode { public: - TIntermBranch(TOperator op, TIntermTyped* e) : - flowOp(op), - expression(e) { } + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } virtual TIntermBranch* getAsBranchNode() { return this; } - virtual void traverse(TIntermTraverser*); + virtual void traverse(TIntermTraverser*); - TOperator getFlowOp() { return flowOp; } - TIntermTyped* getExpression() { return expression; } + TOperator getFlowOp() { return flowOp; } + TIntermTyped* getExpression() { return expression; } protected: - TOperator flowOp; - TIntermTyped* expression; // non-zero except for "return exp;" statements + TOperator flowOp; + TIntermTyped* expression; // non-zero except for "return exp;" statements }; // @@ -398,49 +406,49 @@ // class TIntermSymbol : public TIntermTyped { public: - // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from - // per process globalpoolallocator, then it causes increased memory usage per compile - // it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int i, const TString& sym, const TType& t) : - TIntermTyped(t), id(i) { symbol = sym; } + // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from + // per process globalpoolallocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& sym, const TType& t) : + TIntermTyped(t), id(i) { symbol = sym; } - int getId() const { return id; } - const TString& getSymbol() const { return symbol; } + int getId() const { return id; } + const TString& getSymbol() const { return symbol; } - void setId(int newId) { id = newId; } + void setId(int newId) { id = newId; } - virtual void traverse(TIntermTraverser*); - virtual TIntermSymbol* getAsSymbolNode() { return this; } + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } protected: - int id; - TString symbol; + int id; + TString symbol; }; class TIntermConstantUnion : public TIntermTyped { public: - TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) + TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { getTypePointer()->setQualifier(EvqConstExpr); } - ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } + ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } - int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } - int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; } - float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } - bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } + int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } + int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; } + float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } + bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } // Previous union pointer freed on pool deallocation. void replaceConstantUnion(ConstantUnion *safeConstantUnion) { unionArrayPointer = safeConstantUnion; } - virtual TIntermConstantUnion* getAsConstantUnion() { return this; } - virtual void traverse(TIntermTraverser*); + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual void traverse(TIntermTraverser*); - TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); + TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); protected: - ConstantUnion *unionArrayPointer; + ConstantUnion *unionArrayPointer; }; // @@ -448,16 +456,16 @@ // class TIntermOperator : public TIntermTyped { public: - TOperator getOp() const { return op; } - void setOp(TOperator o) { op = o; } + TOperator getOp() const { return op; } + void setOp(TOperator o) { op = o; } - bool modifiesState() const; - bool isConstructor() const; + bool modifiesState() const; + bool isConstructor() const; protected: - TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} - TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} - TOperator op; + TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} + TOperator op; }; // @@ -465,10 +473,10 @@ // class TIntermBinary : public TIntermOperator { public: - TIntermBinary(TOperator o) : TIntermOperator(o) {} + TIntermBinary(TOperator o) : TIntermOperator(o) {} - virtual TIntermBinary* getAsBinaryNode() { return this; } - virtual void traverse(TIntermTraverser*); + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual void traverse(TIntermTraverser*); void setType(const TType &t) override { @@ -480,15 +488,15 @@ } } - void setLeft(TIntermTyped* n) { left = n; } - void setRight(TIntermTyped* n) { right = n; } - TIntermTyped* getLeft() const { return left; } - TIntermTyped* getRight() const { return right; } - bool promote(TInfoSink&); + void setLeft(TIntermTyped* n) { left = n; } + void setRight(TIntermTyped* n) { right = n; } + TIntermTyped* getLeft() const { return left; } + TIntermTyped* getRight() const { return right; } + bool promote(TInfoSink&); protected: - TIntermTyped* left; - TIntermTyped* right; + TIntermTyped* left; + TIntermTyped* right; }; // @@ -496,8 +504,8 @@ // class TIntermUnary : public TIntermOperator { public: - TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} - TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} void setType(const TType &t) override { @@ -509,15 +517,15 @@ } } - virtual void traverse(TIntermTraverser*); - virtual TIntermUnary* getAsUnaryNode() { return this; } + virtual void traverse(TIntermTraverser*); + virtual TIntermUnary* getAsUnaryNode() { return this; } - void setOperand(TIntermTyped* o) { operand = o; } - TIntermTyped* getOperand() { return operand; } - bool promote(TInfoSink&, const TType *funcReturnType); + void setOperand(TIntermTyped* o) { operand = o; } + TIntermTyped* getOperand() { return operand; } + bool promote(TInfoSink&, const TType *funcReturnType); protected: - TIntermTyped* operand; + TIntermTyped* operand; }; typedef TVector<TIntermNode*> TIntermSequence; @@ -528,14 +536,14 @@ // class TIntermAggregate : public TIntermOperator { public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false) { endLine = { 0, 0, 0, 0 }; } - TIntermAggregate(TOperator o) : TIntermOperator(o) { } - ~TIntermAggregate() { } + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false) { endLine = { 0, 0, 0, 0 }; } + TIntermAggregate(TOperator o) : TIntermOperator(o) { } + ~TIntermAggregate() { } - virtual TIntermAggregate* getAsAggregate() { return this; } - virtual void traverse(TIntermTraverser*); + virtual TIntermAggregate* getAsAggregate() { return this; } + virtual void traverse(TIntermTraverser*); - TIntermSequence& getSequence() { return sequence; } + TIntermSequence& getSequence() { return sequence; } void setType(const TType &t) override { @@ -555,19 +563,19 @@ } } - void setName(const TString& n) { name = n; } - const TString& getName() const { return name; } + void setName(const TString& n) { name = n; } + const TString& getName() const { return name; } - void setUserDefined() { userDefined = true; } - bool isUserDefined() const { return userDefined; } + void setUserDefined() { userDefined = true; } + bool isUserDefined() const { return userDefined; } - void setOptimize(bool o) { optimize = o; } - bool getOptimize() { return optimize; } - void setDebug(bool d) { debug = d; } - bool getDebug() { return debug; } + void setOptimize(bool o) { optimize = o; } + bool getOptimize() { return optimize; } + void setDebug(bool d) { debug = d; } + bool getDebug() { return debug; } - void setEndLine(const TSourceLoc& line) { endLine = line; } - const TSourceLoc& getEndLine() const { return endLine; } + void setEndLine(const TSourceLoc& line) { endLine = line; } + const TSourceLoc& getEndLine() const { return endLine; } bool isConstantFoldable() { @@ -583,15 +591,15 @@ } protected: - TIntermAggregate(const TIntermAggregate&); // disallow copy constructor - TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator - TIntermSequence sequence; - TString name; - bool userDefined; // used for user defined function names + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TString name; + bool userDefined; // used for user defined function names - bool optimize; - bool debug; - TSourceLoc endLine; + bool optimize; + bool debug; + TSourceLoc endLine; }; // @@ -599,26 +607,26 @@ // class TIntermSelection : public TIntermTyped { public: - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : - TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : - TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) { this->type.setQualifier(EvqTemporary); } - virtual void traverse(TIntermTraverser*); + virtual void traverse(TIntermTraverser*); - bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } - TIntermTyped* getCondition() const { return condition; } - TIntermNode* getTrueBlock() const { return trueBlock; } - TIntermNode* getFalseBlock() const { return falseBlock; } - TIntermSelection* getAsSelectionNode() { return this; } + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } + TIntermTyped* getCondition() const { return condition; } + TIntermNode* getTrueBlock() const { return trueBlock; } + TIntermNode* getFalseBlock() const { return falseBlock; } + TIntermSelection* getAsSelectionNode() { return this; } protected: - TIntermTyped* condition; - TIntermNode* trueBlock; - TIntermNode* falseBlock; + TIntermTyped* condition; + TIntermNode* trueBlock; + TIntermNode* falseBlock; }; // @@ -666,9 +674,9 @@ enum Visit { - PreVisit, - InVisit, - PostVisit + PreVisit, + InVisit, + PostVisit }; // @@ -682,23 +690,23 @@ class TIntermTraverser { public: - 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), - mDepth(0) {} - virtual ~TIntermTraverser() {}; + 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), + mDepth(0) {} + virtual ~TIntermTraverser() {}; - virtual void visitSymbol(TIntermSymbol*) {} - virtual void visitConstantUnion(TIntermConstantUnion*) {} - virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} - virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} - virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} - virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} - virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} - virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} + virtual void visitSymbol(TIntermSymbol*) {} + virtual void visitConstantUnion(TIntermConstantUnion*) {} + virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} + virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} + virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} + virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} + virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} + virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} virtual bool visitSwitch(Visit, TIntermSwitch*) { return true; } virtual bool visitCase(Visit, TIntermCase*) { return true; } @@ -716,13 +724,13 @@ TIntermNode *getParentNode() { - return mPath.size() == 0 ? NULL : mPath.back(); + return mPath.size() == 0 ? nullptr : mPath.back(); } - const bool preVisit; - const bool inVisit; - const bool postVisit; - const bool rightToLeft; + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; protected: int mDepth;
diff --git a/src/OpenGL/compiler/localintermediate.h b/src/OpenGL/compiler/localintermediate.h index 4d6ed79..5210451 100644 --- a/src/OpenGL/compiler/localintermediate.h +++ b/src/OpenGL/compiler/localintermediate.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef _LOCAL_INTERMEDIATE_INCLUDED_ #define _LOCAL_INTERMEDIATE_INCLUDED_ @@ -10,8 +18,8 @@ #include "intermediate.h" struct TVectorFields { - int offsets[4]; - int num; + int offsets[4]; + int num; }; // @@ -20,37 +28,37 @@ class TInfoSink; class TIntermediate { public: - POOL_ALLOCATOR_NEW_DELETE(); + POOL_ALLOCATOR_NEW_DELETE(); - TIntermediate(TInfoSink& i) : infoSink(i) { } - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); - TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); - TIntermTyped* addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType*); - 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&); - TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line); - TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &line); - TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&); - TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*); - bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, 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 outputTree(TIntermNode*); + TIntermediate(TInfoSink& i) : infoSink(i) { } + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); + TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); + TIntermTyped* addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType*); + 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&); + TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line); + TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &line); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&); + TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*); + bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, 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 outputTree(TIntermNode*); protected: - TInfoSink& infoSink; + TInfoSink& infoSink; private: - void operator=(TIntermediate&); // prevent assignments + void operator=(TIntermediate&); // prevent assignments }; #endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/src/OpenGL/compiler/osinclude.h b/src/OpenGL/compiler/osinclude.h index 8349a4a..650f871 100644 --- a/src/OpenGL/compiler/osinclude.h +++ b/src/OpenGL/compiler/osinclude.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef __OSINCLUDE_H #define __OSINCLUDE_H
diff --git a/src/OpenGL/compiler/ossource_posix.cpp b/src/OpenGL/compiler/ossource_posix.cpp index f8ed83b..0e12fda 100644 --- a/src/OpenGL/compiler/ossource_posix.cpp +++ b/src/OpenGL/compiler/ossource_posix.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // // This file contains the posix specific functions @@ -18,47 +26,47 @@ // OS_TLSIndex OS_AllocTLSIndex() { - pthread_key_t pPoolIndex; + pthread_key_t pPoolIndex; - // - // Create global pool key. - // - if ((pthread_key_create(&pPoolIndex, NULL)) != 0) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return false; - } - else { - return pPoolIndex; - } + // + // Create global pool key. + // + if ((pthread_key_create(&pPoolIndex, NULL)) != 0) { + assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); + return false; + } + else { + return pPoolIndex; + } } bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) { - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } - if (pthread_setspecific(nIndex, lpvValue) == 0) - return true; - else - return false; + if (pthread_setspecific(nIndex, lpvValue) == 0) + return true; + else + return false; } bool OS_FreeTLSIndex(OS_TLSIndex nIndex) { - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } + if (nIndex == OS_INVALID_TLS_INDEX) { + assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); + return false; + } - // - // Delete the global pool key. - // - if (pthread_key_delete(nIndex) == 0) - return true; - else - return false; + // + // Delete the global pool key. + // + if (pthread_key_delete(nIndex) == 0) + return true; + else + return false; }
diff --git a/src/OpenGL/compiler/ossource_win.cpp b/src/OpenGL/compiler/ossource_win.cpp index 71fda7a..a442167 100644 --- a/src/OpenGL/compiler/ossource_win.cpp +++ b/src/OpenGL/compiler/ossource_win.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "osinclude.h" //
diff --git a/src/OpenGL/compiler/parseConst.cpp b/src/OpenGL/compiler/parseConst.cpp index 59b39b4..c3e0b0c 100644 --- a/src/OpenGL/compiler/parseConst.cpp +++ b/src/OpenGL/compiler/parseConst.cpp
@@ -1,51 +1,59 @@ +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "ParseHelper.h" // -// Use this class to carry along data from node to node in +// Use this class to carry along data from node to node in // the traversal // class TConstTraverser : public TIntermTraverser { public: - TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t) - : error(false), - index(0), - unionArray(cUnion), - type(t), - constructorType(constructType), - singleConstantParam(singleConstParam), - infoSink(sink), - size(0), - isMatrix(false), - matrixSize(0) { - } + TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t) + : error(false), + index(0), + unionArray(cUnion), + type(t), + constructorType(constructType), + singleConstantParam(singleConstParam), + infoSink(sink), + size(0), + isMatrix(false), + matrixSize(0) { + } - bool error; + bool error; protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); + void visitSymbol(TIntermSymbol*); + void visitConstantUnion(TIntermConstantUnion*); + bool visitBinary(Visit visit, TIntermBinary*); + bool visitUnary(Visit visit, TIntermUnary*); + bool visitSelection(Visit visit, TIntermSelection*); + bool visitAggregate(Visit visit, TIntermAggregate*); + bool visitLoop(Visit visit, TIntermLoop*); + bool visitBranch(Visit visit, TIntermBranch*); - size_t index; - ConstantUnion *unionArray; - TType type; - TOperator constructorType; - bool singleConstantParam; - TInfoSink& infoSink; - 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 index; + ConstantUnion *unionArray; + TType type; + TOperator constructorType; + bool singleConstantParam; + TInfoSink& infoSink; + 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) }; // @@ -59,168 +67,168 @@ void TConstTraverser::visitSymbol(TIntermSymbol* node) { - infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine()); - return; + infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine()); + return; } bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) { - TQualifier qualifier = node->getType().getQualifier(); + TQualifier qualifier = node->getType().getQualifier(); - if (qualifier != EvqConstExpr) { - TString buf; - buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); - error = true; - return false; - } + if (qualifier != EvqConstExpr) { + TString buf; + buf.append("'constructor' : assigning non-constant to "); + buf.append(type.getCompleteString()); + infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + error = true; + return false; + } - infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine()); + infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine()); - return false; + return false; } 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()); - error = true; - return false; + TString buf; + buf.append("'constructor' : assigning non-constant to "); + buf.append(type.getCompleteString()); + infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + error = true; + return false; } bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) { - if (!node->isConstructor() && node->getOp() != EOpComma) { - TString buf; - buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); - error = true; - return false; - } + if (!node->isConstructor() && node->getOp() != EOpComma) { + TString buf; + buf.append("'constructor' : assigning non-constant to "); + buf.append(type.getCompleteString()); + infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); + error = true; + return false; + } - if (node->getSequence().size() == 0) { - error = true; - return false; - } + if (node->getSequence().size() == 0) { + error = true; + return false; + } - bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); - if (flag) - { - singleConstantParam = true; - constructorType = node->getOp(); - size = node->getType().getObjectSize(); + bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); + if (flag) + { + singleConstantParam = true; + constructorType = node->getOp(); + size = node->getType().getObjectSize(); - if (node->getType().isMatrix()) { - isMatrix = true; - matrixSize = node->getType().getNominalSize(); - } - } + if (node->getType().isMatrix()) { + isMatrix = true; + matrixSize = node->getType().getNominalSize(); + } + } - for (TIntermSequence::iterator p = node->getSequence().begin(); - p != node->getSequence().end(); p++) { + for (TIntermSequence::iterator p = node->getSequence().begin(); + p != node->getSequence().end(); p++) { - if (node->getOp() == EOpComma) - index = 0; + if (node->getOp() == EOpComma) + index = 0; - (*p)->traverse(this); - } - if (flag) - { - singleConstantParam = false; - constructorType = EOpNull; - size = 0; - isMatrix = false; - matrixSize = 0; - } - return false; + (*p)->traverse(this); + } + if (flag) + { + singleConstantParam = false; + constructorType = EOpNull; + size = 0; + isMatrix = false; + matrixSize = 0; + } + return false; } bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) { - infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine()); - error = true; - return false; + infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine()); + error = true; + return false; } void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) { - if (!node->getUnionArrayPointer()) - { - // The constant was not initialized, this should already have been logged - assert(infoSink.info.size() != 0); - return; - } + if (!node->getUnionArrayPointer()) + { + // The constant was not initialized, this should already have been logged + assert(infoSink.info.size() != 0); + return; + } - ConstantUnion* leftUnionArray = unionArray; - size_t instanceSize = type.getObjectSize(); - TBasicType basicType = type.getBasicType(); + ConstantUnion* leftUnionArray = unionArray; + size_t instanceSize = type.getObjectSize(); + TBasicType basicType = type.getBasicType(); - if (index >= instanceSize) - return; + if (index >= instanceSize) + return; - if (!singleConstantParam) { - size_t size = node->getType().getObjectSize(); + if (!singleConstantParam) { + size_t size = node->getType().getObjectSize(); - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - for(size_t i = 0; i < size; i++) { - if (index >= instanceSize) - return; - leftUnionArray[index].cast(basicType, rightUnionArray[i]); + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + for(size_t i = 0; i < size; i++) { + if (index >= instanceSize) + return; + leftUnionArray[index].cast(basicType, rightUnionArray[i]); - (index)++; - } - } else { - size_t totalSize = index + size; - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - if (!isMatrix) { - int count = 0; - for(size_t i = index; i < totalSize; i++) { - if (i >= instanceSize) - return; + (index)++; + } + } else { + size_t totalSize = index + size; + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + if (!isMatrix) { + int count = 0; + for(size_t i = index; i < totalSize; i++) { + if (i >= instanceSize) + return; - leftUnionArray[i].cast(basicType, rightUnionArray[count]); + leftUnionArray[i].cast(basicType, rightUnionArray[count]); - (index)++; + (index)++; - if (node->getType().getObjectSize() > 1) - count++; - } - } else { // for matrix constructors - int count = 0; - int element = index; - for(size_t i = index; i < totalSize; i++) { - if (i >= instanceSize) - return; - if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) - leftUnionArray[i].cast(basicType, rightUnionArray[0]); - else - leftUnionArray[i].setFConst(0.0f); + if (node->getType().getObjectSize() > 1) + count++; + } + } else { // for matrix constructors + int count = 0; + int element = index; + for(size_t i = index; i < totalSize; i++) { + if (i >= instanceSize) + return; + if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) + leftUnionArray[i].cast(basicType, rightUnionArray[0]); + else + leftUnionArray[i].setFConst(0.0f); - (index)++; + (index)++; - if (node->getType().getObjectSize() > 1) - count++; - } - } - } + if (node->getType().getObjectSize() > 1) + count++; + } + } + } } bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) { - infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine()); - error = true; - return false; + infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine()); + error = true; + return false; } bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) { - infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine()); - error = true; - return false; + infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine()); + error = true; + return false; } // @@ -230,14 +238,14 @@ // bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam) { - if (root == 0) - return false; + if (root == 0) + return false; - TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t); + TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t); - root->traverse(&it); - if (it.error) - return true; - else - return false; + root->traverse(&it); + if (it.error) + return true; + else + return false; }
diff --git a/src/OpenGL/compiler/preprocessor/Diagnostics.cpp b/src/OpenGL/compiler/preprocessor/Diagnostics.cpp index b6888b9..767edd9 100644 --- a/src/OpenGL/compiler/preprocessor/Diagnostics.cpp +++ b/src/OpenGL/compiler/preprocessor/Diagnostics.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "Diagnostics.h" @@ -19,113 +27,113 @@ const SourceLocation& loc, const std::string& text) { - // TODO(alokp): Keep a count of errors and warnings. - print(id, loc, text); + // TODO(alokp): Keep a count of errors and warnings. + print(id, loc, text); } Diagnostics::Severity Diagnostics::severity(ID id) { - if ((id > ERROR_BEGIN) && (id < ERROR_END)) - return PP_ERROR; + if ((id > ERROR_BEGIN) && (id < ERROR_END)) + return PP_ERROR; - if ((id > WARNING_BEGIN) && (id < WARNING_END)) - return PP_WARNING; + if ((id > WARNING_BEGIN) && (id < WARNING_END)) + return PP_WARNING; - assert(false); - return PP_ERROR; + assert(false); + return PP_ERROR; } std::string Diagnostics::message(ID id) { - switch (id) - { - // Errors begin. - case INTERNAL_ERROR: - return "internal error"; - case OUT_OF_MEMORY: - return "out of memory"; - case INVALID_CHARACTER: - return "invalid character"; - case INVALID_NUMBER: - return "invalid number"; - case INTEGER_OVERFLOW: - return "integer overflow"; - case FLOAT_OVERFLOW: - return "float overflow"; - case TOKEN_TOO_LONG: - return "token too long"; - case INVALID_EXPRESSION: - return "invalid expression"; - case DIVISION_BY_ZERO: - return "division by zero"; - case EOF_IN_COMMENT: - return "unexpected end of file found in comment"; - case UNEXPECTED_TOKEN: - return "unexpected token"; - case DIRECTIVE_INVALID_NAME: - return "invalid directive name"; - case MACRO_NAME_RESERVED: - return "macro name is reserved"; - case MACRO_REDEFINED: - return "macro redefined"; - case MACRO_PREDEFINED_REDEFINED: - return "predefined macro redefined"; - case MACRO_PREDEFINED_UNDEFINED: - return "predefined macro undefined"; - case MACRO_UNTERMINATED_INVOCATION: - return "unterminated macro invocation"; - case MACRO_TOO_FEW_ARGS: - return "Not enough arguments for macro"; - case MACRO_TOO_MANY_ARGS: - return "Too many arguments for macro"; - case MACRO_DUPLICATE_PARAMETER_NAMES: - return "duplicate macro parameter name"; - case CONDITIONAL_ENDIF_WITHOUT_IF: - return "unexpected #endif found without a matching #if"; - case CONDITIONAL_ELSE_WITHOUT_IF: - return "unexpected #else found without a matching #if"; - case CONDITIONAL_ELSE_AFTER_ELSE: - return "unexpected #else found after another #else"; - case CONDITIONAL_ELIF_WITHOUT_IF: - return "unexpected #elif found without a matching #if"; - case CONDITIONAL_ELIF_AFTER_ELSE: - return "unexpected #elif found after #else"; - case CONDITIONAL_UNTERMINATED: - return "unexpected end of file found in conditional block"; - case INVALID_EXTENSION_NAME: - return "invalid extension name"; - case INVALID_EXTENSION_BEHAVIOR: - return "invalid extension behavior"; - case INVALID_EXTENSION_DIRECTIVE: - return "invalid extension directive"; - case INVALID_VERSION_NUMBER: - return "invalid version number"; - case INVALID_VERSION_DIRECTIVE: - return "invalid version directive"; - case VERSION_NOT_FIRST_STATEMENT: - return "#version directive must occur before anything else, " - "except for comments and white space"; - case INVALID_LINE_NUMBER: - return "invalid line number"; - case INVALID_FILE_NUMBER: - return "invalid file number"; - case INVALID_LINE_DIRECTIVE: - return "invalid line directive"; - case UNDEFINED_IDENTIFIER: - return "undefined identifier"; - // Errors end. - // Warnings begin. - case EOF_IN_DIRECTIVE: - return "unexpected end of file found in directive"; - case CONDITIONAL_UNEXPECTED_TOKEN: - return "unexpected token after conditional expression"; - case UNRECOGNIZED_PRAGMA: - return "unrecognized pragma"; - // Warnings end. - default: - assert(false); - return ""; - } + switch (id) + { + // Errors begin. + case INTERNAL_ERROR: + return "internal error"; + case OUT_OF_MEMORY: + return "out of memory"; + case INVALID_CHARACTER: + return "invalid character"; + case INVALID_NUMBER: + return "invalid number"; + case INTEGER_OVERFLOW: + return "integer overflow"; + case FLOAT_OVERFLOW: + return "float overflow"; + case TOKEN_TOO_LONG: + return "token too long"; + case INVALID_EXPRESSION: + return "invalid expression"; + case DIVISION_BY_ZERO: + return "division by zero"; + case EOF_IN_COMMENT: + return "unexpected end of file found in comment"; + case UNEXPECTED_TOKEN: + return "unexpected token"; + case DIRECTIVE_INVALID_NAME: + return "invalid directive name"; + case MACRO_NAME_RESERVED: + return "macro name is reserved"; + case MACRO_REDEFINED: + return "macro redefined"; + case MACRO_PREDEFINED_REDEFINED: + return "predefined macro redefined"; + case MACRO_PREDEFINED_UNDEFINED: + return "predefined macro undefined"; + case MACRO_UNTERMINATED_INVOCATION: + return "unterminated macro invocation"; + case MACRO_TOO_FEW_ARGS: + return "Not enough arguments for macro"; + case MACRO_TOO_MANY_ARGS: + return "Too many arguments for macro"; + case MACRO_DUPLICATE_PARAMETER_NAMES: + return "duplicate macro parameter name"; + case CONDITIONAL_ENDIF_WITHOUT_IF: + return "unexpected #endif found without a matching #if"; + case CONDITIONAL_ELSE_WITHOUT_IF: + return "unexpected #else found without a matching #if"; + case CONDITIONAL_ELSE_AFTER_ELSE: + return "unexpected #else found after another #else"; + case CONDITIONAL_ELIF_WITHOUT_IF: + return "unexpected #elif found without a matching #if"; + case CONDITIONAL_ELIF_AFTER_ELSE: + return "unexpected #elif found after #else"; + case CONDITIONAL_UNTERMINATED: + return "unexpected end of file found in conditional block"; + case INVALID_EXTENSION_NAME: + return "invalid extension name"; + case INVALID_EXTENSION_BEHAVIOR: + return "invalid extension behavior"; + case INVALID_EXTENSION_DIRECTIVE: + return "invalid extension directive"; + case INVALID_VERSION_NUMBER: + return "invalid version number"; + case INVALID_VERSION_DIRECTIVE: + return "invalid version directive"; + case VERSION_NOT_FIRST_STATEMENT: + return "#version directive must occur before anything else, " + "except for comments and white space"; + case INVALID_LINE_NUMBER: + return "invalid line number"; + case INVALID_FILE_NUMBER: + return "invalid file number"; + case INVALID_LINE_DIRECTIVE: + return "invalid line directive"; + case UNDEFINED_IDENTIFIER: + return "undefined identifier"; + // Errors end. + // Warnings begin. + case EOF_IN_DIRECTIVE: + return "unexpected end of file found in directive"; + case CONDITIONAL_UNEXPECTED_TOKEN: + return "unexpected token after conditional expression"; + case UNRECOGNIZED_PRAGMA: + return "unrecognized pragma"; + // Warnings end. + default: + assert(false); + return ""; + } } } // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/Diagnostics.h b/src/OpenGL/compiler/preprocessor/Diagnostics.h index 0516c2b..1f4cfc4 100644 --- a/src/OpenGL/compiler/preprocessor/Diagnostics.h +++ b/src/OpenGL/compiler/preprocessor/Diagnostics.h
@@ -1,89 +1,97 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_DIAGNOSTICS_H_ -#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ - -#include <string> - -namespace pp -{ - -struct SourceLocation; - -// Base class for reporting diagnostic messages. -// Derived classes are responsible for formatting and printing the messages. -class Diagnostics -{ - public: - enum Severity - { - PP_ERROR, - PP_WARNING - }; - enum ID - { - ERROR_BEGIN, - INTERNAL_ERROR, - OUT_OF_MEMORY, - INVALID_CHARACTER, - INVALID_NUMBER, - INTEGER_OVERFLOW, - FLOAT_OVERFLOW, - TOKEN_TOO_LONG, - INVALID_EXPRESSION, - DIVISION_BY_ZERO, - EOF_IN_COMMENT, - UNEXPECTED_TOKEN, - DIRECTIVE_INVALID_NAME, - MACRO_NAME_RESERVED, - MACRO_REDEFINED, - MACRO_PREDEFINED_REDEFINED, - MACRO_PREDEFINED_UNDEFINED, - MACRO_UNTERMINATED_INVOCATION, - MACRO_TOO_FEW_ARGS, - MACRO_TOO_MANY_ARGS, - MACRO_DUPLICATE_PARAMETER_NAMES, - CONDITIONAL_ENDIF_WITHOUT_IF, - CONDITIONAL_ELSE_WITHOUT_IF, - CONDITIONAL_ELSE_AFTER_ELSE, - CONDITIONAL_ELIF_WITHOUT_IF, - CONDITIONAL_ELIF_AFTER_ELSE, - CONDITIONAL_UNTERMINATED, - CONDITIONAL_UNEXPECTED_TOKEN, - INVALID_EXTENSION_NAME, - INVALID_EXTENSION_BEHAVIOR, - INVALID_EXTENSION_DIRECTIVE, - INVALID_VERSION_NUMBER, - INVALID_VERSION_DIRECTIVE, - VERSION_NOT_FIRST_STATEMENT, - INVALID_LINE_NUMBER, - INVALID_FILE_NUMBER, - INVALID_LINE_DIRECTIVE, - UNDEFINED_IDENTIFIER, - ERROR_END, - - WARNING_BEGIN, - EOF_IN_DIRECTIVE, - UNRECOGNIZED_PRAGMA, - WARNING_END - }; - - virtual ~Diagnostics(); - - void report(ID id, const SourceLocation& loc, const std::string& text); - - protected: - Severity severity(ID id); - std::string message(ID id); - - virtual void print(ID id, - const SourceLocation& loc, - const std::string& text) = 0; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ +#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ + +#include <string> + +namespace pp +{ + +struct SourceLocation; + +// Base class for reporting diagnostic messages. +// Derived classes are responsible for formatting and printing the messages. +class Diagnostics +{ +public: + enum Severity + { + PP_ERROR, + PP_WARNING + }; + enum ID + { + ERROR_BEGIN, + INTERNAL_ERROR, + OUT_OF_MEMORY, + INVALID_CHARACTER, + INVALID_NUMBER, + INTEGER_OVERFLOW, + FLOAT_OVERFLOW, + TOKEN_TOO_LONG, + INVALID_EXPRESSION, + DIVISION_BY_ZERO, + EOF_IN_COMMENT, + UNEXPECTED_TOKEN, + DIRECTIVE_INVALID_NAME, + MACRO_NAME_RESERVED, + MACRO_REDEFINED, + MACRO_PREDEFINED_REDEFINED, + MACRO_PREDEFINED_UNDEFINED, + MACRO_UNTERMINATED_INVOCATION, + MACRO_TOO_FEW_ARGS, + MACRO_TOO_MANY_ARGS, + MACRO_DUPLICATE_PARAMETER_NAMES, + CONDITIONAL_ENDIF_WITHOUT_IF, + CONDITIONAL_ELSE_WITHOUT_IF, + CONDITIONAL_ELSE_AFTER_ELSE, + CONDITIONAL_ELIF_WITHOUT_IF, + CONDITIONAL_ELIF_AFTER_ELSE, + CONDITIONAL_UNTERMINATED, + CONDITIONAL_UNEXPECTED_TOKEN, + INVALID_EXTENSION_NAME, + INVALID_EXTENSION_BEHAVIOR, + INVALID_EXTENSION_DIRECTIVE, + INVALID_VERSION_NUMBER, + INVALID_VERSION_DIRECTIVE, + VERSION_NOT_FIRST_STATEMENT, + INVALID_LINE_NUMBER, + INVALID_FILE_NUMBER, + INVALID_LINE_DIRECTIVE, + UNDEFINED_IDENTIFIER, + ERROR_END, + + WARNING_BEGIN, + EOF_IN_DIRECTIVE, + UNRECOGNIZED_PRAGMA, + WARNING_END + }; + + virtual ~Diagnostics(); + + void report(ID id, const SourceLocation& loc, const std::string& text); + +protected: + Severity severity(ID id); + std::string message(ID id); + + virtual void print(ID id, + const SourceLocation& loc, + const std::string& text) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveHandler.cpp b/src/OpenGL/compiler/preprocessor/DirectiveHandler.cpp index d67bee3..ac26c83 100644 --- a/src/OpenGL/compiler/preprocessor/DirectiveHandler.cpp +++ b/src/OpenGL/compiler/preprocessor/DirectiveHandler.cpp
@@ -1,16 +1,24 @@ -// -// Copyright (c) 2012 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 "DirectiveHandler.h" - -namespace pp -{ - -DirectiveHandler::~DirectiveHandler() -{ -} - -} // namespace pp +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "DirectiveHandler.h" + +namespace pp +{ + +DirectiveHandler::~DirectiveHandler() +{ +} + +} // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveHandler.h b/src/OpenGL/compiler/preprocessor/DirectiveHandler.h index 572b897..f7b3784 100644 --- a/src/OpenGL/compiler/preprocessor/DirectiveHandler.h +++ b/src/OpenGL/compiler/preprocessor/DirectiveHandler.h
@@ -1,43 +1,51 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_DIRECTIVE_HANDLER_H_ -#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ - -#include <string> - -namespace pp -{ - -struct SourceLocation; - -// Base class for handling directives. -// Preprocessor uses this class to notify the clients about certain -// preprocessor directives. Derived classes are responsible for -// handling them in an appropriate manner. -class DirectiveHandler -{ - public: - virtual ~DirectiveHandler(); - - virtual void handleError(const SourceLocation& loc, - const std::string& msg) = 0; - - // Handle pragma of form: #pragma name[(value)] - virtual void handlePragma(const SourceLocation& loc, - const std::string& name, - const std::string& value) = 0; - - virtual void handleExtension(const SourceLocation& loc, - const std::string& name, - const std::string& behavior) = 0; - - virtual void handleVersion(const SourceLocation& loc, - int version) = 0; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ + +#include <string> + +namespace pp +{ + +struct SourceLocation; + +// Base class for handling directives. +// Preprocessor uses this class to notify the clients about certain +// preprocessor directives. Derived classes are responsible for +// handling them in an appropriate manner. +class DirectiveHandler +{ +public: + virtual ~DirectiveHandler(); + + virtual void handleError(const SourceLocation& loc, + const std::string& msg) = 0; + + // Handle pragma of form: #pragma name[(value)] + virtual void handlePragma(const SourceLocation& loc, + const std::string& name, + const std::string& value) = 0; + + virtual void handleExtension(const SourceLocation& loc, + const std::string& name, + const std::string& behavior) = 0; + + virtual void handleVersion(const SourceLocation& loc, + int version) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveParser.cpp b/src/OpenGL/compiler/preprocessor/DirectiveParser.cpp index 8e6dcbd..ec77c21 100644 --- a/src/OpenGL/compiler/preprocessor/DirectiveParser.cpp +++ b/src/OpenGL/compiler/preprocessor/DirectiveParser.cpp
@@ -1,891 +1,899 @@ -// -// Copyright (c) 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 "DirectiveParser.h" - -#include <cassert> -#include <cstdlib> -#include <sstream> - -#include "Diagnostics.h" -#include "DirectiveHandler.h" -#include "ExpressionParser.h" -#include "MacroExpander.h" -#include "Token.h" -#include "Tokenizer.h" - -namespace { -enum DirectiveType -{ - DIRECTIVE_NONE, - DIRECTIVE_DEFINE, - DIRECTIVE_UNDEF, - DIRECTIVE_IF, - DIRECTIVE_IFDEF, - DIRECTIVE_IFNDEF, - DIRECTIVE_ELSE, - DIRECTIVE_ELIF, - DIRECTIVE_ENDIF, - DIRECTIVE_ERROR, - DIRECTIVE_PRAGMA, - DIRECTIVE_EXTENSION, - DIRECTIVE_VERSION, - DIRECTIVE_LINE -}; -} // namespace - -static DirectiveType getDirective(const pp::Token* token) -{ - static const std::string kDirectiveDefine("define"); - static const std::string kDirectiveUndef("undef"); - static const std::string kDirectiveIf("if"); - static const std::string kDirectiveIfdef("ifdef"); - static const std::string kDirectiveIfndef("ifndef"); - static const std::string kDirectiveElse("else"); - static const std::string kDirectiveElif("elif"); - static const std::string kDirectiveEndif("endif"); - static const std::string kDirectiveError("error"); - static const std::string kDirectivePragma("pragma"); - static const std::string kDirectiveExtension("extension"); - static const std::string kDirectiveVersion("version"); - static const std::string kDirectiveLine("line"); - - if (token->type != pp::Token::IDENTIFIER) - return DIRECTIVE_NONE; - - if (token->text == kDirectiveDefine) - return DIRECTIVE_DEFINE; - else if (token->text == kDirectiveUndef) - return DIRECTIVE_UNDEF; - else if (token->text == kDirectiveIf) - return DIRECTIVE_IF; - else if (token->text == kDirectiveIfdef) - return DIRECTIVE_IFDEF; - else if (token->text == kDirectiveIfndef) - return DIRECTIVE_IFNDEF; - else if (token->text == kDirectiveElse) - return DIRECTIVE_ELSE; - else if (token->text == kDirectiveElif) - return DIRECTIVE_ELIF; - else if (token->text == kDirectiveEndif) - return DIRECTIVE_ENDIF; - else if (token->text == kDirectiveError) - return DIRECTIVE_ERROR; - else if (token->text == kDirectivePragma) - return DIRECTIVE_PRAGMA; - else if (token->text == kDirectiveExtension) - return DIRECTIVE_EXTENSION; - else if (token->text == kDirectiveVersion) - return DIRECTIVE_VERSION; - else if (token->text == kDirectiveLine) - return DIRECTIVE_LINE; - - return DIRECTIVE_NONE; -} - -static bool isConditionalDirective(DirectiveType directive) -{ - switch (directive) - { - case DIRECTIVE_IF: - case DIRECTIVE_IFDEF: - case DIRECTIVE_IFNDEF: - case DIRECTIVE_ELSE: - case DIRECTIVE_ELIF: - case DIRECTIVE_ENDIF: - return true; - default: - return false; - } -} - -// Returns true if the token represents End Of Directive. -static bool isEOD(const pp::Token* token) -{ - return (token->type == '\n') || (token->type == pp::Token::LAST); -} - -static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token) -{ - while(!isEOD(token)) - { - lexer->lex(token); - } -} - -static bool isMacroNameReserved(const std::string& name) -{ - // Names prefixed with "GL_" are reserved. - if (name.substr(0, 3) == "GL_") - return true; - - // Names containing two consecutive underscores are reserved. - if (name.find("__") != std::string::npos) - return true; - - return false; -} - -static bool isMacroPredefined(const std::string& name, - const pp::MacroSet& macroSet) -{ - pp::MacroSet::const_iterator iter = macroSet.find(name); - return iter != macroSet.end() ? iter->second.predefined : false; -} - -namespace pp -{ - -DirectiveParser::DirectiveParser(Tokenizer* tokenizer, - MacroSet* macroSet, - Diagnostics* diagnostics, - DirectiveHandler* directiveHandler) : - mPastFirstStatement(false), - mTokenizer(tokenizer), - mMacroSet(macroSet), - mDiagnostics(diagnostics), - mDirectiveHandler(directiveHandler) -{ -} - -void DirectiveParser::lex(Token* token) -{ - do - { - mTokenizer->lex(token); - - if (token->type == Token::PP_HASH) - { - parseDirective(token); - mPastFirstStatement = true; - } - - if (token->type == Token::LAST) - { - if (!mConditionalStack.empty()) - { - const ConditionalBlock& block = mConditionalStack.back(); - mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED, - block.location, block.type); - } - break; - } - - } while (skipping() || (token->type == '\n')); - - mPastFirstStatement = true; -} - -void DirectiveParser::parseDirective(Token* token) -{ - assert(token->type == Token::PP_HASH); - - mTokenizer->lex(token); - if (isEOD(token)) - { - // Empty Directive. - return; - } - - DirectiveType directive = getDirective(token); - - // While in an excluded conditional block/group, - // we only parse conditional directives. - if (skipping() && !isConditionalDirective(directive)) - { - skipUntilEOD(mTokenizer, token); - return; - } - - switch(directive) - { - case DIRECTIVE_NONE: - mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - break; - case DIRECTIVE_DEFINE: - parseDefine(token); - break; - case DIRECTIVE_UNDEF: - parseUndef(token); - break; - case DIRECTIVE_IF: - parseIf(token); - break; - case DIRECTIVE_IFDEF: - parseIfdef(token); - break; - case DIRECTIVE_IFNDEF: - parseIfndef(token); - break; - case DIRECTIVE_ELSE: - parseElse(token); - break; - case DIRECTIVE_ELIF: - parseElif(token); - break; - case DIRECTIVE_ENDIF: - parseEndif(token); - break; - case DIRECTIVE_ERROR: - parseError(token); - break; - case DIRECTIVE_PRAGMA: - parsePragma(token); - break; - case DIRECTIVE_EXTENSION: - parseExtension(token); - break; - case DIRECTIVE_VERSION: - parseVersion(token); - break; - case DIRECTIVE_LINE: - parseLine(token); - break; - default: - assert(false); - break; - } - - skipUntilEOD(mTokenizer, token); - if (token->type == Token::LAST) - { - mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE, - token->location, token->text); - } -} - -void DirectiveParser::parseDefine(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_DEFINE); - - mTokenizer->lex(token); - if (token->type != Token::IDENTIFIER) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - return; - } - if (isMacroPredefined(token->text, *mMacroSet)) - { - mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED, - token->location, token->text); - return; - } - if (isMacroNameReserved(token->text)) - { - mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED, - token->location, token->text); - return; - } - - Macro macro; - macro.type = Macro::kTypeObj; - macro.name = token->text; - - mTokenizer->lex(token); - if (token->type == '(' && !token->hasLeadingSpace()) - { - // Function-like macro. Collect arguments. - macro.type = Macro::kTypeFunc; - do { - mTokenizer->lex(token); - if (token->type != Token::IDENTIFIER) - break; - - if (std::find(macro.parameters.begin(), macro.parameters.end(), token->text) != macro.parameters.end()) - { - mDiagnostics->report(Diagnostics::MACRO_DUPLICATE_PARAMETER_NAMES, - token->location, token->text); - return; - } - - macro.parameters.push_back(token->text); - - mTokenizer->lex(token); // Get ','. - } while (token->type == ','); - - if (token->type != ')') - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, - token->text); - return; - } - mTokenizer->lex(token); // Get ')'. - } - - while ((token->type != '\n') && (token->type != Token::LAST)) - { - // Reset the token location because it is unnecessary in replacement - // list. Resetting it also allows us to reuse Token::equals() to - // compare macros. - token->location = SourceLocation(); - macro.replacements.push_back(*token); - mTokenizer->lex(token); - } - if (!macro.replacements.empty()) - { - // Whitespace preceding the replacement list is not considered part of - // the replacement list for either form of macro. - macro.replacements.front().setHasLeadingSpace(false); - } - - // Check for macro redefinition. - MacroSet::const_iterator iter = mMacroSet->find(macro.name); - if (iter != mMacroSet->end() && !macro.equals(iter->second)) - { - mDiagnostics->report(Diagnostics::MACRO_REDEFINED, - token->location, - macro.name); - return; - } - mMacroSet->insert(std::make_pair(macro.name, macro)); -} - -void DirectiveParser::parseUndef(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_UNDEF); - - mTokenizer->lex(token); - if (token->type != Token::IDENTIFIER) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - return; - } - - MacroSet::iterator iter = mMacroSet->find(token->text); - if (iter != mMacroSet->end()) - { - if (iter->second.predefined) - { - mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED, - token->location, token->text); - } - else - { - mMacroSet->erase(iter); - } - } - - mTokenizer->lex(token); -} - -void DirectiveParser::parseIf(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_IF); - parseConditionalIf(token); -} - -void DirectiveParser::parseIfdef(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_IFDEF); - parseConditionalIf(token); -} - -void DirectiveParser::parseIfndef(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_IFNDEF); - parseConditionalIf(token); -} - -void DirectiveParser::parseElse(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_ELSE); - - if (mConditionalStack.empty()) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - ConditionalBlock& block = mConditionalStack.back(); - if (block.skipBlock) - { - // No diagnostics. Just skip the whole line. - skipUntilEOD(mTokenizer, token); - return; - } - if (block.foundElseGroup) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - block.foundElseGroup = true; - block.skipGroup = block.foundValidGroup; - block.foundValidGroup = true; - - // Check if there are extra tokens after #else. - mTokenizer->lex(token); - if (!isEOD(token)) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - } -} - -void DirectiveParser::parseElif(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_ELIF); - - if (mConditionalStack.empty()) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - ConditionalBlock& block = mConditionalStack.back(); - if (block.skipBlock) - { - // No diagnostics. Just skip the whole line. - skipUntilEOD(mTokenizer, token); - return; - } - if (block.foundElseGroup) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - if (block.foundValidGroup) - { - // Do not parse the expression. - // Also be careful not to emit a diagnostic. - block.skipGroup = true; - skipUntilEOD(mTokenizer, token); - return; - } - - int expression = parseExpressionIf(token); - block.skipGroup = expression == 0; - block.foundValidGroup = expression != 0; -} - -void DirectiveParser::parseEndif(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_ENDIF); - - if (mConditionalStack.empty()) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - mConditionalStack.pop_back(); - - // Check if there are tokens after #endif. - mTokenizer->lex(token); - if (!isEOD(token)) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - } -} - -void DirectiveParser::parseError(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_ERROR); - - std::ostringstream stream; - mTokenizer->lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - stream << *token; - mTokenizer->lex(token); - } - mDirectiveHandler->handleError(token->location, stream.str()); -} - -// Parses pragma of form: #pragma name[(value)]. -void DirectiveParser::parsePragma(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_PRAGMA); - - enum State - { - PRAGMA_NAME, - LEFT_PAREN, - PRAGMA_VALUE, - RIGHT_PAREN - }; - - bool valid = true; - std::string name, value; - int state = PRAGMA_NAME; - - mTokenizer->lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - switch(state++) - { - case PRAGMA_NAME: - name = token->text; - valid = valid && (token->type == Token::IDENTIFIER); - break; - case LEFT_PAREN: - valid = valid && (token->type == '('); - break; - case PRAGMA_VALUE: - value = token->text; - valid = valid && (token->type == Token::IDENTIFIER); - break; - case RIGHT_PAREN: - valid = valid && (token->type == ')'); - break; - default: - valid = false; - break; - } - mTokenizer->lex(token); - } - - valid = valid && ((state == PRAGMA_NAME) || // Empty pragma. - (state == LEFT_PAREN) || // Without value. - (state == RIGHT_PAREN + 1)); // With value. - if (!valid) - { - mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA, - token->location, name); - } - else if (state > PRAGMA_NAME) // Do not notify for empty pragma. - { - mDirectiveHandler->handlePragma(token->location, name, value); - } -} - -void DirectiveParser::parseExtension(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_EXTENSION); - - enum State - { - EXT_NAME, - COLON, - EXT_BEHAVIOR - }; - - bool valid = true; - std::string name, behavior; - int state = EXT_NAME; - - mTokenizer->lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - switch (state++) - { - case EXT_NAME: - if (valid && (token->type != Token::IDENTIFIER)) - { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME, - token->location, token->text); - valid = false; - } - if (valid) name = token->text; - break; - case COLON: - if (valid && (token->type != ':')) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - valid = false; - } - break; - case EXT_BEHAVIOR: - if (valid && (token->type != Token::IDENTIFIER)) - { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR, - token->location, token->text); - valid = false; - } - if (valid) behavior = token->text; - break; - default: - if (valid) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - valid = false; - } - break; - } - mTokenizer->lex(token); - } - if (valid && (state != EXT_BEHAVIOR + 1)) - { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE, - token->location, token->text); - valid = false; - } - if (valid) - mDirectiveHandler->handleExtension(token->location, name, behavior); -} - -void DirectiveParser::parseVersion(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_VERSION); - - if (mPastFirstStatement) - { - mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - enum State - { - VERSION_NUMBER, - VERSION_PROFILE, - VERSION_ENDLINE - }; - - bool valid = true; - int version = 0; - int state = VERSION_NUMBER; - - mTokenizer->lex(token); - while (valid && (token->type != '\n') && (token->type != Token::LAST)) - { - switch (state) - { - case VERSION_NUMBER: - if (token->type != Token::CONST_INT) - { - mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER, - token->location, token->text); - valid = false; - } - if (valid && !token->iValue(&version)) - { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - valid = false; - } - if (valid) - { - state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE; - } - break; - case VERSION_PROFILE: - if (token->type != Token::IDENTIFIER || token->text != "es") - { - mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, - token->location, token->text); - valid = false; - } - state = VERSION_ENDLINE; - break; - default: - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - valid = false; - break; - } - - mTokenizer->lex(token); - } - - if (valid && (state != VERSION_ENDLINE)) - { - mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, - token->location, token->text); - valid = false; - } - - if (valid) - { - mDirectiveHandler->handleVersion(token->location, version); - } -} - -void DirectiveParser::parseLine(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_LINE); - - enum State - { - LINE_NUMBER, - FILE_NUMBER - }; - - bool valid = true; - int line = 0, file = 0; - int state = LINE_NUMBER; - - MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false); - macroExpander.lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - switch (state++) - { - case LINE_NUMBER: - if (valid && (token->type != Token::CONST_INT)) - { - mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER, - token->location, token->text); - valid = false; - } - if (valid && !token->iValue(&line)) - { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - valid = false; - } - break; - case FILE_NUMBER: - if (valid && (token->type != Token::CONST_INT)) - { - mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER, - token->location, token->text); - valid = false; - } - if (valid && !token->iValue(&file)) - { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - valid = false; - } - break; - default: - if (valid) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - valid = false; - } - break; - } - macroExpander.lex(token); - } - - if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1)) - { - mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE, - token->location, token->text); - valid = false; - } - if (valid) - { - mTokenizer->setLineNumber(line); - if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file); - } -} - -bool DirectiveParser::skipping() const -{ - if (mConditionalStack.empty()) return false; - - const ConditionalBlock& block = mConditionalStack.back(); - return block.skipBlock || block.skipGroup; -} - -void DirectiveParser::parseConditionalIf(Token* token) -{ - ConditionalBlock block; - block.type = token->text; - block.location = token->location; - - if (skipping()) - { - // This conditional block is inside another conditional group - // which is skipped. As a consequence this whole block is skipped. - // Be careful not to parse the conditional expression that might - // emit a diagnostic. - skipUntilEOD(mTokenizer, token); - block.skipBlock = true; - } - else - { - DirectiveType directive = getDirective(token); - - int expression = 0; - switch (directive) - { - case DIRECTIVE_IF: - expression = parseExpressionIf(token); - break; - case DIRECTIVE_IFDEF: - expression = parseExpressionIfdef(token); - break; - case DIRECTIVE_IFNDEF: - expression = parseExpressionIfdef(token) == 0 ? 1 : 0; - break; - default: - assert(false); - break; - } - block.skipGroup = expression == 0; - block.foundValidGroup = expression != 0; - } - mConditionalStack.push_back(block); -} - -int DirectiveParser::parseExpressionIf(Token* token) -{ - assert((getDirective(token) == DIRECTIVE_IF) || - (getDirective(token) == DIRECTIVE_ELIF)); - - MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true); - ExpressionParser expressionParser(¯oExpander, mDiagnostics); - - int expression = 0; - macroExpander.lex(token); - expressionParser.parse(token, &expression); - - // Check if there are tokens after #if expression. - if (!isEOD(token)) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - } - - return expression; -} - -int DirectiveParser::parseExpressionIfdef(Token* token) -{ - assert((getDirective(token) == DIRECTIVE_IFDEF) || - (getDirective(token) == DIRECTIVE_IFNDEF)); - - mTokenizer->lex(token); - if (token->type != Token::IDENTIFIER) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return 0; - } - - MacroSet::const_iterator iter = mMacroSet->find(token->text); - int expression = iter != mMacroSet->end() ? 1 : 0; - - // Check if there are tokens after #ifdef expression. - mTokenizer->lex(token); - if (!isEOD(token)) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - } - return expression; -} - -} // namespace pp +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "DirectiveParser.h" + +#include <cassert> +#include <cstdlib> +#include <sstream> + +#include "Diagnostics.h" +#include "DirectiveHandler.h" +#include "ExpressionParser.h" +#include "MacroExpander.h" +#include "Token.h" +#include "Tokenizer.h" + +namespace { +enum DirectiveType +{ + DIRECTIVE_NONE, + DIRECTIVE_DEFINE, + DIRECTIVE_UNDEF, + DIRECTIVE_IF, + DIRECTIVE_IFDEF, + DIRECTIVE_IFNDEF, + DIRECTIVE_ELSE, + DIRECTIVE_ELIF, + DIRECTIVE_ENDIF, + DIRECTIVE_ERROR, + DIRECTIVE_PRAGMA, + DIRECTIVE_EXTENSION, + DIRECTIVE_VERSION, + DIRECTIVE_LINE +}; +} // namespace + +static DirectiveType getDirective(const pp::Token* token) +{ + static const std::string kDirectiveDefine("define"); + static const std::string kDirectiveUndef("undef"); + static const std::string kDirectiveIf("if"); + static const std::string kDirectiveIfdef("ifdef"); + static const std::string kDirectiveIfndef("ifndef"); + static const std::string kDirectiveElse("else"); + static const std::string kDirectiveElif("elif"); + static const std::string kDirectiveEndif("endif"); + static const std::string kDirectiveError("error"); + static const std::string kDirectivePragma("pragma"); + static const std::string kDirectiveExtension("extension"); + static const std::string kDirectiveVersion("version"); + static const std::string kDirectiveLine("line"); + + if (token->type != pp::Token::IDENTIFIER) + return DIRECTIVE_NONE; + + if (token->text == kDirectiveDefine) + return DIRECTIVE_DEFINE; + else if (token->text == kDirectiveUndef) + return DIRECTIVE_UNDEF; + else if (token->text == kDirectiveIf) + return DIRECTIVE_IF; + else if (token->text == kDirectiveIfdef) + return DIRECTIVE_IFDEF; + else if (token->text == kDirectiveIfndef) + return DIRECTIVE_IFNDEF; + else if (token->text == kDirectiveElse) + return DIRECTIVE_ELSE; + else if (token->text == kDirectiveElif) + return DIRECTIVE_ELIF; + else if (token->text == kDirectiveEndif) + return DIRECTIVE_ENDIF; + else if (token->text == kDirectiveError) + return DIRECTIVE_ERROR; + else if (token->text == kDirectivePragma) + return DIRECTIVE_PRAGMA; + else if (token->text == kDirectiveExtension) + return DIRECTIVE_EXTENSION; + else if (token->text == kDirectiveVersion) + return DIRECTIVE_VERSION; + else if (token->text == kDirectiveLine) + return DIRECTIVE_LINE; + + return DIRECTIVE_NONE; +} + +static bool isConditionalDirective(DirectiveType directive) +{ + switch (directive) + { + case DIRECTIVE_IF: + case DIRECTIVE_IFDEF: + case DIRECTIVE_IFNDEF: + case DIRECTIVE_ELSE: + case DIRECTIVE_ELIF: + case DIRECTIVE_ENDIF: + return true; + default: + return false; + } +} + +// Returns true if the token represents End Of Directive. +static bool isEOD(const pp::Token* token) +{ + return (token->type == '\n') || (token->type == pp::Token::LAST); +} + +static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token) +{ + while(!isEOD(token)) + { + lexer->lex(token); + } +} + +static bool isMacroNameReserved(const std::string& name) +{ + // Names prefixed with "GL_" are reserved. + if (name.substr(0, 3) == "GL_") + return true; + + // Names containing two consecutive underscores are reserved. + if (name.find("__") != std::string::npos) + return true; + + return false; +} + +static bool isMacroPredefined(const std::string& name, + const pp::MacroSet& macroSet) +{ + pp::MacroSet::const_iterator iter = macroSet.find(name); + return iter != macroSet.end() ? iter->second.predefined : false; +} + +namespace pp +{ + +DirectiveParser::DirectiveParser(Tokenizer* tokenizer, + MacroSet* macroSet, + Diagnostics* diagnostics, + DirectiveHandler* directiveHandler) : + mPastFirstStatement(false), + mTokenizer(tokenizer), + mMacroSet(macroSet), + mDiagnostics(diagnostics), + mDirectiveHandler(directiveHandler) +{ +} + +void DirectiveParser::lex(Token* token) +{ + do + { + mTokenizer->lex(token); + + if (token->type == Token::PP_HASH) + { + parseDirective(token); + mPastFirstStatement = true; + } + + if (token->type == Token::LAST) + { + if (!mConditionalStack.empty()) + { + const ConditionalBlock& block = mConditionalStack.back(); + mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED, + block.location, block.type); + } + break; + } + + } while (skipping() || (token->type == '\n')); + + mPastFirstStatement = true; +} + +void DirectiveParser::parseDirective(Token* token) +{ + assert(token->type == Token::PP_HASH); + + mTokenizer->lex(token); + if (isEOD(token)) + { + // Empty Directive. + return; + } + + DirectiveType directive = getDirective(token); + + // While in an excluded conditional block/group, + // we only parse conditional directives. + if (skipping() && !isConditionalDirective(directive)) + { + skipUntilEOD(mTokenizer, token); + return; + } + + switch(directive) + { + case DIRECTIVE_NONE: + mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + break; + case DIRECTIVE_DEFINE: + parseDefine(token); + break; + case DIRECTIVE_UNDEF: + parseUndef(token); + break; + case DIRECTIVE_IF: + parseIf(token); + break; + case DIRECTIVE_IFDEF: + parseIfdef(token); + break; + case DIRECTIVE_IFNDEF: + parseIfndef(token); + break; + case DIRECTIVE_ELSE: + parseElse(token); + break; + case DIRECTIVE_ELIF: + parseElif(token); + break; + case DIRECTIVE_ENDIF: + parseEndif(token); + break; + case DIRECTIVE_ERROR: + parseError(token); + break; + case DIRECTIVE_PRAGMA: + parsePragma(token); + break; + case DIRECTIVE_EXTENSION: + parseExtension(token); + break; + case DIRECTIVE_VERSION: + parseVersion(token); + break; + case DIRECTIVE_LINE: + parseLine(token); + break; + default: + assert(false); + break; + } + + skipUntilEOD(mTokenizer, token); + if (token->type == Token::LAST) + { + mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE, + token->location, token->text); + } +} + +void DirectiveParser::parseDefine(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_DEFINE); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + return; + } + if (isMacroPredefined(token->text, *mMacroSet)) + { + mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED, + token->location, token->text); + return; + } + if (isMacroNameReserved(token->text)) + { + mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED, + token->location, token->text); + return; + } + + Macro macro; + macro.type = Macro::kTypeObj; + macro.name = token->text; + + mTokenizer->lex(token); + if (token->type == '(' && !token->hasLeadingSpace()) + { + // Function-like macro. Collect arguments. + macro.type = Macro::kTypeFunc; + do { + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + break; + + if (std::find(macro.parameters.begin(), macro.parameters.end(), token->text) != macro.parameters.end()) + { + mDiagnostics->report(Diagnostics::MACRO_DUPLICATE_PARAMETER_NAMES, + token->location, token->text); + return; + } + + macro.parameters.push_back(token->text); + + mTokenizer->lex(token); // Get ','. + } while (token->type == ','); + + if (token->type != ')') + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, + token->text); + return; + } + mTokenizer->lex(token); // Get ')'. + } + + while ((token->type != '\n') && (token->type != Token::LAST)) + { + // Reset the token location because it is unnecessary in replacement + // list. Resetting it also allows us to reuse Token::equals() to + // compare macros. + token->location = SourceLocation(); + macro.replacements.push_back(*token); + mTokenizer->lex(token); + } + if (!macro.replacements.empty()) + { + // Whitespace preceding the replacement list is not considered part of + // the replacement list for either form of macro. + macro.replacements.front().setHasLeadingSpace(false); + } + + // Check for macro redefinition. + MacroSet::const_iterator iter = mMacroSet->find(macro.name); + if (iter != mMacroSet->end() && !macro.equals(iter->second)) + { + mDiagnostics->report(Diagnostics::MACRO_REDEFINED, + token->location, + macro.name); + return; + } + mMacroSet->insert(std::make_pair(macro.name, macro)); +} + +void DirectiveParser::parseUndef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_UNDEF); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + return; + } + + MacroSet::iterator iter = mMacroSet->find(token->text); + if (iter != mMacroSet->end()) + { + if (iter->second.predefined) + { + mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED, + token->location, token->text); + } + else + { + mMacroSet->erase(iter); + } + } + + mTokenizer->lex(token); +} + +void DirectiveParser::parseIf(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IF); + parseConditionalIf(token); +} + +void DirectiveParser::parseIfdef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IFDEF); + parseConditionalIf(token); +} + +void DirectiveParser::parseIfndef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IFNDEF); + parseConditionalIf(token); +} + +void DirectiveParser::parseElse(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ELSE); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + ConditionalBlock& block = mConditionalStack.back(); + if (block.skipBlock) + { + // No diagnostics. Just skip the whole line. + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundElseGroup) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + block.foundElseGroup = true; + block.skipGroup = block.foundValidGroup; + block.foundValidGroup = true; + + // Check if there are extra tokens after #else. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } +} + +void DirectiveParser::parseElif(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ELIF); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + ConditionalBlock& block = mConditionalStack.back(); + if (block.skipBlock) + { + // No diagnostics. Just skip the whole line. + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundElseGroup) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundValidGroup) + { + // Do not parse the expression. + // Also be careful not to emit a diagnostic. + block.skipGroup = true; + skipUntilEOD(mTokenizer, token); + return; + } + + int expression = parseExpressionIf(token); + block.skipGroup = expression == 0; + block.foundValidGroup = expression != 0; +} + +void DirectiveParser::parseEndif(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ENDIF); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + mConditionalStack.pop_back(); + + // Check if there are tokens after #endif. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } +} + +void DirectiveParser::parseError(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ERROR); + + std::ostringstream stream; + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + stream << *token; + mTokenizer->lex(token); + } + mDirectiveHandler->handleError(token->location, stream.str()); +} + +// Parses pragma of form: #pragma name[(value)]. +void DirectiveParser::parsePragma(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_PRAGMA); + + enum State + { + PRAGMA_NAME, + LEFT_PAREN, + PRAGMA_VALUE, + RIGHT_PAREN + }; + + bool valid = true; + std::string name, value; + int state = PRAGMA_NAME; + + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch(state++) + { + case PRAGMA_NAME: + name = token->text; + valid = valid && (token->type == Token::IDENTIFIER); + break; + case LEFT_PAREN: + valid = valid && (token->type == '('); + break; + case PRAGMA_VALUE: + value = token->text; + valid = valid && (token->type == Token::IDENTIFIER); + break; + case RIGHT_PAREN: + valid = valid && (token->type == ')'); + break; + default: + valid = false; + break; + } + mTokenizer->lex(token); + } + + valid = valid && ((state == PRAGMA_NAME) || // Empty pragma. + (state == LEFT_PAREN) || // Without value. + (state == RIGHT_PAREN + 1)); // With value. + if (!valid) + { + mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA, + token->location, name); + } + else if (state > PRAGMA_NAME) // Do not notify for empty pragma. + { + mDirectiveHandler->handlePragma(token->location, name, value); + } +} + +void DirectiveParser::parseExtension(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_EXTENSION); + + enum State + { + EXT_NAME, + COLON, + EXT_BEHAVIOR + }; + + bool valid = true; + std::string name, behavior; + int state = EXT_NAME; + + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch (state++) + { + case EXT_NAME: + if (valid && (token->type != Token::IDENTIFIER)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME, + token->location, token->text); + valid = false; + } + if (valid) name = token->text; + break; + case COLON: + if (valid && (token->type != ':')) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + case EXT_BEHAVIOR: + if (valid && (token->type != Token::IDENTIFIER)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR, + token->location, token->text); + valid = false; + } + if (valid) behavior = token->text; + break; + default: + if (valid) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + } + mTokenizer->lex(token); + } + if (valid && (state != EXT_BEHAVIOR + 1)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE, + token->location, token->text); + valid = false; + } + if (valid) + mDirectiveHandler->handleExtension(token->location, name, behavior); +} + +void DirectiveParser::parseVersion(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_VERSION); + + if (mPastFirstStatement) + { + mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + enum State + { + VERSION_NUMBER, + VERSION_PROFILE, + VERSION_ENDLINE + }; + + bool valid = true; + int version = 0; + int state = VERSION_NUMBER; + + mTokenizer->lex(token); + while (valid && (token->type != '\n') && (token->type != Token::LAST)) + { + switch (state) + { + case VERSION_NUMBER: + if (token->type != Token::CONST_INT) + { + mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&version)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + if (valid) + { + state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE; + } + break; + case VERSION_PROFILE: + if (token->type != Token::IDENTIFIER || token->text != "es") + { + mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, + token->location, token->text); + valid = false; + } + state = VERSION_ENDLINE; + break; + default: + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + break; + } + + mTokenizer->lex(token); + } + + if (valid && (state != VERSION_ENDLINE)) + { + mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, + token->location, token->text); + valid = false; + } + + if (valid) + { + mDirectiveHandler->handleVersion(token->location, version); + } +} + +void DirectiveParser::parseLine(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_LINE); + + enum State + { + LINE_NUMBER, + FILE_NUMBER + }; + + bool valid = true; + int line = 0, file = 0; + int state = LINE_NUMBER; + + MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false); + macroExpander.lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch (state++) + { + case LINE_NUMBER: + if (valid && (token->type != Token::CONST_INT)) + { + mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&line)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + break; + case FILE_NUMBER: + if (valid && (token->type != Token::CONST_INT)) + { + mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&file)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + break; + default: + if (valid) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + } + macroExpander.lex(token); + } + + if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1)) + { + mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE, + token->location, token->text); + valid = false; + } + if (valid) + { + mTokenizer->setLineNumber(line); + if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file); + } +} + +bool DirectiveParser::skipping() const +{ + if (mConditionalStack.empty()) return false; + + const ConditionalBlock& block = mConditionalStack.back(); + return block.skipBlock || block.skipGroup; +} + +void DirectiveParser::parseConditionalIf(Token* token) +{ + ConditionalBlock block; + block.type = token->text; + block.location = token->location; + + if (skipping()) + { + // This conditional block is inside another conditional group + // which is skipped. As a consequence this whole block is skipped. + // Be careful not to parse the conditional expression that might + // emit a diagnostic. + skipUntilEOD(mTokenizer, token); + block.skipBlock = true; + } + else + { + DirectiveType directive = getDirective(token); + + int expression = 0; + switch (directive) + { + case DIRECTIVE_IF: + expression = parseExpressionIf(token); + break; + case DIRECTIVE_IFDEF: + expression = parseExpressionIfdef(token); + break; + case DIRECTIVE_IFNDEF: + expression = parseExpressionIfdef(token) == 0 ? 1 : 0; + break; + default: + assert(false); + break; + } + block.skipGroup = expression == 0; + block.foundValidGroup = expression != 0; + } + mConditionalStack.push_back(block); +} + +int DirectiveParser::parseExpressionIf(Token* token) +{ + assert((getDirective(token) == DIRECTIVE_IF) || + (getDirective(token) == DIRECTIVE_ELIF)); + + MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true); + ExpressionParser expressionParser(¯oExpander, mDiagnostics); + + int expression = 0; + macroExpander.lex(token); + expressionParser.parse(token, &expression); + + // Check if there are tokens after #if expression. + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } + + return expression; +} + +int DirectiveParser::parseExpressionIfdef(Token* token) +{ + assert((getDirective(token) == DIRECTIVE_IFDEF) || + (getDirective(token) == DIRECTIVE_IFNDEF)); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return 0; + } + + MacroSet::const_iterator iter = mMacroSet->find(token->text); + int expression = iter != mMacroSet->end() ? 1 : 0; + + // Check if there are tokens after #ifdef expression. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } + return expression; +} + +} // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/DirectiveParser.h b/src/OpenGL/compiler/preprocessor/DirectiveParser.h index 7b07392..b23a99e 100644 --- a/src/OpenGL/compiler/preprocessor/DirectiveParser.h +++ b/src/OpenGL/compiler/preprocessor/DirectiveParser.h
@@ -1,82 +1,90 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_DIRECTIVE_PARSER_H_ -#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ - -#include "Lexer.h" -#include "Macro.h" -#include "pp_utils.h" -#include "SourceLocation.h" - -namespace pp -{ - -class Diagnostics; -class DirectiveHandler; -class Tokenizer; - -class DirectiveParser : public Lexer -{ - public: - DirectiveParser(Tokenizer* tokenizer, - MacroSet* macroSet, - Diagnostics* diagnostics, - DirectiveHandler* directiveHandler); - - virtual void lex(Token* token); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser); - - void parseDirective(Token* token); - void parseDefine(Token* token); - void parseUndef(Token* token); - void parseIf(Token* token); - void parseIfdef(Token* token); - void parseIfndef(Token* token); - void parseElse(Token* token); - void parseElif(Token* token); - void parseEndif(Token* token); - void parseError(Token* token); - void parsePragma(Token* token); - void parseExtension(Token* token); - void parseVersion(Token* token); - void parseLine(Token* token); - - bool skipping() const; - void parseConditionalIf(Token* token); - int parseExpressionIf(Token* token); - int parseExpressionIfdef(Token* token); - - struct ConditionalBlock - { - std::string type; - SourceLocation location; - bool skipBlock; - bool skipGroup; - bool foundValidGroup; - bool foundElseGroup; - - ConditionalBlock() : - skipBlock(false), - skipGroup(false), - foundValidGroup(false), - foundElseGroup(false) - { - } - }; - bool mPastFirstStatement; - std::vector<ConditionalBlock> mConditionalStack; - Tokenizer* mTokenizer; - MacroSet* mMacroSet; - Diagnostics* mDiagnostics; - DirectiveHandler* mDirectiveHandler; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ + +#include "Lexer.h" +#include "Macro.h" +#include "pp_utils.h" +#include "SourceLocation.h" + +namespace pp +{ + +class Diagnostics; +class DirectiveHandler; +class Tokenizer; + +class DirectiveParser : public Lexer +{ +public: + DirectiveParser(Tokenizer* tokenizer, + MacroSet* macroSet, + Diagnostics* diagnostics, + DirectiveHandler* directiveHandler); + + virtual void lex(Token* token); + +private: + PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser); + + void parseDirective(Token* token); + void parseDefine(Token* token); + void parseUndef(Token* token); + void parseIf(Token* token); + void parseIfdef(Token* token); + void parseIfndef(Token* token); + void parseElse(Token* token); + void parseElif(Token* token); + void parseEndif(Token* token); + void parseError(Token* token); + void parsePragma(Token* token); + void parseExtension(Token* token); + void parseVersion(Token* token); + void parseLine(Token* token); + + bool skipping() const; + void parseConditionalIf(Token* token); + int parseExpressionIf(Token* token); + int parseExpressionIfdef(Token* token); + + struct ConditionalBlock + { + std::string type; + SourceLocation location; + bool skipBlock; + bool skipGroup; + bool foundValidGroup; + bool foundElseGroup; + + ConditionalBlock() : + skipBlock(false), + skipGroup(false), + foundValidGroup(false), + foundElseGroup(false) + { + } + }; + bool mPastFirstStatement; + std::vector<ConditionalBlock> mConditionalStack; + Tokenizer* mTokenizer; + MacroSet* mMacroSet; + Diagnostics* mDiagnostics; + DirectiveHandler* mDirectiveHandler; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ +
diff --git a/src/OpenGL/compiler/preprocessor/ExpressionParser.cpp b/src/OpenGL/compiler/preprocessor/ExpressionParser.cpp index 7a8892e..b2aa9d7 100644 --- a/src/OpenGL/compiler/preprocessor/ExpressionParser.cpp +++ b/src/OpenGL/compiler/preprocessor/ExpressionParser.cpp
@@ -70,11 +70,19 @@ /* Copy the first part of user declarations. */ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
diff --git a/src/OpenGL/compiler/preprocessor/ExpressionParser.h b/src/OpenGL/compiler/preprocessor/ExpressionParser.h index 3ee5b7a..c28f4bb 100644 --- a/src/OpenGL/compiler/preprocessor/ExpressionParser.h +++ b/src/OpenGL/compiler/preprocessor/ExpressionParser.h
@@ -1,34 +1,42 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_EXPRESSION_PARSER_H_ -#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ - -#include "pp_utils.h" - -namespace pp -{ - -class Diagnostics; -class Lexer; -struct Token; - -class ExpressionParser -{ - public: - ExpressionParser(Lexer* lexer, Diagnostics* diagnostics); - - bool parse(Token* token, int* result); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser); - - Lexer* mLexer; - Diagnostics* mDiagnostics; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ +#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ + +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; +class Lexer; +struct Token; + +class ExpressionParser +{ +public: + ExpressionParser(Lexer* lexer, Diagnostics* diagnostics); + + bool parse(Token* token, int* result); + +private: + PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser); + + Lexer* mLexer; + Diagnostics* mDiagnostics; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
diff --git a/src/OpenGL/compiler/preprocessor/ExpressionParser.y b/src/OpenGL/compiler/preprocessor/ExpressionParser.y index 1324288..09e86aa 100644 --- a/src/OpenGL/compiler/preprocessor/ExpressionParser.y +++ b/src/OpenGL/compiler/preprocessor/ExpressionParser.y
@@ -1,9 +1,17 @@ /* +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. This file contains the Yacc grammar for GLSL ES preprocessor expression. @@ -12,11 +20,19 @@ */ %{ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2012 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
diff --git a/src/OpenGL/compiler/preprocessor/Input.cpp b/src/OpenGL/compiler/preprocessor/Input.cpp index 5cbf138..c22622a 100644 --- a/src/OpenGL/compiler/preprocessor/Input.cpp +++ b/src/OpenGL/compiler/preprocessor/Input.cpp
@@ -1,55 +1,63 @@ -// -// Copyright (c) 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 "Input.h" - -#include <algorithm> -#include <cassert> -#include <cstring> - -namespace pp -{ - -Input::Input() : mCount(0), mString(0) -{ -} - -Input::Input(int count, const char* const string[], const int length[]) : - mCount(count), - mString(string) -{ - assert(mCount >= 0); - mLength.reserve(mCount); - for (int i = 0; i < mCount; ++i) - { - int len = length ? length[i] : -1; - mLength.push_back(len < 0 ? strlen(mString[i]) : len); - } -} - -int Input::read(char* buf, int maxSize) -{ - int nRead = 0; - while ((nRead < maxSize) && (mReadLoc.sIndex < mCount)) - { - int size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex; - size = std::min(size, maxSize); - memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size); - nRead += size; - mReadLoc.cIndex += size; - - // Advance string if we reached the end of current string. - if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) - { - ++mReadLoc.sIndex; - mReadLoc.cIndex = 0; - } - } - return nRead; -} - -} // namespace pp - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Input.h" + +#include <algorithm> +#include <cassert> +#include <cstring> + +namespace pp +{ + +Input::Input() : mCount(0), mString(0) +{ +} + +Input::Input(int count, const char* const string[], const int length[]) : + mCount(count), + mString(string) +{ + assert(mCount >= 0); + mLength.reserve(mCount); + for (int i = 0; i < mCount; ++i) + { + int len = length ? length[i] : -1; + mLength.push_back(len < 0 ? strlen(mString[i]) : len); + } +} + +int Input::read(char* buf, int maxSize) +{ + int nRead = 0; + while ((nRead < maxSize) && (mReadLoc.sIndex < mCount)) + { + int size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex; + size = std::min(size, maxSize); + memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size); + nRead += size; + mReadLoc.cIndex += size; + + // Advance string if we reached the end of current string. + if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) + { + ++mReadLoc.sIndex; + mReadLoc.cIndex = 0; + } + } + return nRead; +} + +} // namespace pp +
diff --git a/src/OpenGL/compiler/preprocessor/Input.h b/src/OpenGL/compiler/preprocessor/Input.h index 8e5b1e9..35776e7 100644 --- a/src/OpenGL/compiler/preprocessor/Input.h +++ b/src/OpenGL/compiler/preprocessor/Input.h
@@ -1,48 +1,56 @@ -// -// Copyright (c) 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_PREPROCESSOR_INPUT_H_ -#define COMPILER_PREPROCESSOR_INPUT_H_ - -#include <vector> - -namespace pp -{ - -// Holds and reads input for Lexer. -class Input -{ - public: - Input(); - Input(int count, const char* const string[], const int length[]); - - int count() const { return mCount; } - const char* string(int index) const { return mString[index]; } - int length(int index) const { return mLength[index]; } - - int read(char* buf, int maxSize); - - struct Location - { - int sIndex; // String index; - int cIndex; // Char index. - - Location() : sIndex(0), cIndex(0) { } - }; - const Location& readLoc() const { return mReadLoc; } - - private: - // Input. - int mCount; - const char* const* mString; - std::vector<int> mLength; - - Location mReadLoc; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_INPUT_H_ - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_INPUT_H_ +#define COMPILER_PREPROCESSOR_INPUT_H_ + +#include <vector> + +namespace pp +{ + +// Holds and reads input for Lexer. +class Input +{ +public: + Input(); + Input(int count, const char* const string[], const int length[]); + + int count() const { return mCount; } + const char* string(int index) const { return mString[index]; } + int length(int index) const { return mLength[index]; } + + int read(char* buf, int maxSize); + + struct Location + { + int sIndex; // String index; + int cIndex; // Char index. + + Location() : sIndex(0), cIndex(0) { } + }; + const Location& readLoc() const { return mReadLoc; } + +private: + // Input. + int mCount; + const char* const* mString; + std::vector<int> mLength; + + Location mReadLoc; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_INPUT_H_ +
diff --git a/src/OpenGL/compiler/preprocessor/Lexer.cpp b/src/OpenGL/compiler/preprocessor/Lexer.cpp index 231a906..157a998 100644 --- a/src/OpenGL/compiler/preprocessor/Lexer.cpp +++ b/src/OpenGL/compiler/preprocessor/Lexer.cpp
@@ -1,16 +1,24 @@ -// -// Copyright (c) 2012 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 "Lexer.h" - -namespace pp -{ - -Lexer::~Lexer() -{ -} - -} // namespace pp +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Lexer.h" + +namespace pp +{ + +Lexer::~Lexer() +{ +} + +} // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/Lexer.h b/src/OpenGL/compiler/preprocessor/Lexer.h index cb29a10..558fc98 100644 --- a/src/OpenGL/compiler/preprocessor/Lexer.h +++ b/src/OpenGL/compiler/preprocessor/Lexer.h
@@ -1,25 +1,33 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_LEXER_H_ -#define COMPILER_PREPROCESSOR_LEXER_H_ - -namespace pp -{ - -struct Token; - -class Lexer -{ - public: - virtual ~Lexer(); - - virtual void lex(Token* token) = 0; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_LEXER_H_ - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_LEXER_H_ +#define COMPILER_PREPROCESSOR_LEXER_H_ + +namespace pp +{ + +struct Token; + +class Lexer +{ +public: + virtual ~Lexer(); + + virtual void lex(Token* token) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_LEXER_H_ +
diff --git a/src/OpenGL/compiler/preprocessor/Macro.cpp b/src/OpenGL/compiler/preprocessor/Macro.cpp index 3c57afe..9024f8a 100644 --- a/src/OpenGL/compiler/preprocessor/Macro.cpp +++ b/src/OpenGL/compiler/preprocessor/Macro.cpp
@@ -1,23 +1,31 @@ -// -// Copyright (c) 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 "Macro.h" - -#include "Token.h" - -namespace pp -{ - -bool Macro::equals(const Macro& other) const -{ - return (type == other.type) && - (name == other.name) && - (parameters == other.parameters) && - (replacements == other.replacements); -} - -} // namespace pp - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Macro.h" + +#include "Token.h" + +namespace pp +{ + +bool Macro::equals(const Macro& other) const +{ + return (type == other.type) && + (name == other.name) && + (parameters == other.parameters) && + (replacements == other.replacements); +} + +} // namespace pp +
diff --git a/src/OpenGL/compiler/preprocessor/Macro.h b/src/OpenGL/compiler/preprocessor/Macro.h index 36faae9..bad8db3 100644 --- a/src/OpenGL/compiler/preprocessor/Macro.h +++ b/src/OpenGL/compiler/preprocessor/Macro.h
@@ -1,44 +1,52 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_MACRO_H_ -#define COMPILER_PREPROCESSOR_MACRO_H_ - -#include <map> -#include <string> -#include <vector> - -namespace pp -{ - -struct Token; - -struct Macro -{ - enum Type - { - kTypeObj, - kTypeFunc - }; - typedef std::vector<std::string> Parameters; - typedef std::vector<Token> Replacements; - - Macro() : predefined(false), disabled(false), type(kTypeObj) { } - bool equals(const Macro& other) const; - - bool predefined; - mutable bool disabled; - - Type type; - std::string name; - Parameters parameters; - Replacements replacements; -}; - -typedef std::map<std::string, Macro> MacroSet; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_MACRO_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_MACRO_H_ +#define COMPILER_PREPROCESSOR_MACRO_H_ + +#include <map> +#include <string> +#include <vector> + +namespace pp +{ + +struct Token; + +struct Macro +{ + enum Type + { + kTypeObj, + kTypeFunc + }; + typedef std::vector<std::string> Parameters; + typedef std::vector<Token> Replacements; + + Macro() : predefined(false), disabled(false), type(kTypeObj) { } + bool equals(const Macro& other) const; + + bool predefined; + mutable bool disabled; + + Type type; + std::string name; + Parameters parameters; + Replacements replacements; +}; + +typedef std::map<std::string, Macro> MacroSet; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_MACRO_H_
diff --git a/src/OpenGL/compiler/preprocessor/MacroExpander.cpp b/src/OpenGL/compiler/preprocessor/MacroExpander.cpp index 325daba..31c14e4 100644 --- a/src/OpenGL/compiler/preprocessor/MacroExpander.cpp +++ b/src/OpenGL/compiler/preprocessor/MacroExpander.cpp
@@ -1,410 +1,418 @@ -// -// Copyright (c) 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 "MacroExpander.h" - -#include <algorithm> -#include <sstream> - -#include "Diagnostics.h" -#include "Token.h" - -namespace pp -{ - -class TokenLexer : public Lexer -{ - public: - typedef std::vector<Token> TokenVector; - - TokenLexer(TokenVector* tokens) - { - tokens->swap(mTokens); - mIter = mTokens.begin(); - } - - virtual void lex(Token* token) - { - if (mIter == mTokens.end()) - { - token->reset(); - token->type = Token::LAST; - } - else - { - *token = *mIter++; - } - } - - private: - PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer); - - TokenVector mTokens; - TokenVector::const_iterator mIter; -}; - -MacroExpander::MacroExpander(Lexer* lexer, - MacroSet* macroSet, - Diagnostics* diagnostics, - bool parseDefined) : - mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined) -{ -} - -MacroExpander::~MacroExpander() -{ - for (size_t i = 0; i < mContextStack.size(); ++i) - { - delete mContextStack[i]; - } -} - -void MacroExpander::lex(Token* token) -{ - while (true) - { - getToken(token); - - if (token->type != Token::IDENTIFIER) - break; - - // Defined operator is parsed here since it may be generated by macro expansion. - // Defined operator produced by macro expansion has undefined behavior according to C++ - // spec, which the GLSL spec references (see C++14 draft spec section 16.1.4), but this - // behavior is needed for passing dEQP tests, which enforce stricter compatibility between - // implementations. - if (mParseDefined && token->text == "defined") - { - bool paren = false; - getToken(token); - if (token->type == '(') - { - paren = true; - getToken(token); - } - if (token->type != Token::IDENTIFIER) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location, - token->text); - break; - } - auto iter = mMacroSet->find(token->text); - std::string expression = iter != mMacroSet->end() ? "1" : "0"; - - if (paren) - { - getToken(token); - if (token->type != ')') - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location, - token->text); - break; - } - } - - // We have a valid defined operator. - // Convert the current token into a CONST_INT token. - token->type = Token::CONST_INT; - token->text = expression; - break; - } - - if (token->expansionDisabled()) - break; - - MacroSet::const_iterator iter = mMacroSet->find(token->text); - if (iter == mMacroSet->end()) - break; - - const Macro& macro = iter->second; - if (macro.disabled) - { - // If a particular token is not expanded, it is never expanded. - token->setExpansionDisabled(true); - break; - } - if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen()) - { - // If the token immediately after the macro name is not a '(', - // this macro should not be expanded. - break; - } - - pushMacro(macro, *token); - } -} - -void MacroExpander::getToken(Token* token) -{ - if (mReserveToken.get()) - { - *token = *mReserveToken; - mReserveToken.reset(); - return; - } - - // First pop all empty macro contexts. - while (!mContextStack.empty() && mContextStack.back()->empty()) - { - popMacro(); - } - - if (!mContextStack.empty()) - { - *token = mContextStack.back()->get(); - } - else - { - mLexer->lex(token); - } -} - -void MacroExpander::ungetToken(const Token& token) -{ - if (!mContextStack.empty()) - { - MacroContext* context = mContextStack.back(); - context->unget(); - assert(context->replacements[context->index] == token); - } - else - { - assert(!mReserveToken.get()); - mReserveToken.reset(new Token(token)); - } -} - -bool MacroExpander::isNextTokenLeftParen() -{ - Token token; - getToken(&token); - - bool lparen = token.type == '('; - ungetToken(token); - - return lparen; -} - -bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier) -{ - assert(!macro.disabled); - assert(!identifier.expansionDisabled()); - assert(identifier.type == Token::IDENTIFIER); - assert(identifier.text == macro.name); - - std::vector<Token> replacements; - if (!expandMacro(macro, identifier, &replacements)) - return false; - - // Macro is disabled for expansion until it is popped off the stack. - macro.disabled = true; - - MacroContext* context = new MacroContext; - context->macro = ¯o; - context->replacements.swap(replacements); - mContextStack.push_back(context); - return true; -} - -void MacroExpander::popMacro() -{ - assert(!mContextStack.empty()); - - MacroContext* context = mContextStack.back(); - mContextStack.pop_back(); - - assert(context->empty()); - assert(context->macro->disabled); - context->macro->disabled = false; - delete context; -} - -bool MacroExpander::expandMacro(const Macro& macro, - const Token& identifier, - std::vector<Token>* replacements) -{ - replacements->clear(); - if (macro.type == Macro::kTypeObj) - { - replacements->assign(macro.replacements.begin(), - macro.replacements.end()); - - if (macro.predefined) - { - static const std::string kLine = "__LINE__"; - static const std::string kFile = "__FILE__"; - - assert(replacements->size() == 1); - Token& repl = replacements->front(); - if (macro.name == kLine) - { - std::ostringstream stream; - stream << identifier.location.line; - repl.text = stream.str(); - } - else if (macro.name == kFile) - { - std::ostringstream stream; - stream << identifier.location.file; - repl.text = stream.str(); - } - } - } - else - { - assert(macro.type == Macro::kTypeFunc); - std::vector<MacroArg> args; - args.reserve(macro.parameters.size()); - if (!collectMacroArgs(macro, identifier, &args)) - return false; - - replaceMacroParams(macro, args, replacements); - } - - for (size_t i = 0; i < replacements->size(); ++i) - { - Token& repl = replacements->at(i); - if (i == 0) - { - // The first token in the replacement list inherits the padding - // properties of the identifier token. - repl.setAtStartOfLine(identifier.atStartOfLine()); - repl.setHasLeadingSpace(identifier.hasLeadingSpace()); - } - repl.location = identifier.location; - } - return true; -} - -bool MacroExpander::collectMacroArgs(const Macro& macro, - const Token& identifier, - std::vector<MacroArg>* args) -{ - Token token; - getToken(&token); - assert(token.type == '('); - - args->push_back(MacroArg()); - for (int openParens = 1; openParens != 0; ) - { - getToken(&token); - - if (token.type == Token::LAST) - { - mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION, - identifier.location, identifier.text); - // Do not lose EOF token. - ungetToken(token); - return false; - } - - bool isArg = false; // True if token is part of the current argument. - switch (token.type) - { - case '(': - ++openParens; - isArg = true; - break; - case ')': - --openParens; - isArg = openParens != 0; - break; - case ',': - // The individual arguments are separated by comma tokens, but - // the comma tokens between matching inner parentheses do not - // seperate arguments. - if (openParens == 1) args->push_back(MacroArg()); - isArg = openParens != 1; - break; - default: - isArg = true; - break; - } - if (isArg) - { - MacroArg& arg = args->back(); - // Initial whitespace is not part of the argument. - if (arg.empty()) token.setHasLeadingSpace(false); - arg.push_back(token); - } - } - - const Macro::Parameters& params = macro.parameters; - // If there is only one empty argument, it is equivalent to no argument. - if (params.empty() && (args->size() == 1) && args->front().empty()) - { - args->clear(); - } - // Validate the number of arguments. - if (args->size() != params.size()) - { - Diagnostics::ID id = args->size() < macro.parameters.size() ? - Diagnostics::MACRO_TOO_FEW_ARGS : - Diagnostics::MACRO_TOO_MANY_ARGS; - mDiagnostics->report(id, identifier.location, identifier.text); - return false; - } - - // Pre-expand each argument before substitution. - // This step expands each argument individually before they are - // inserted into the macro body. - for (size_t i = 0; i < args->size(); ++i) - { - MacroArg& arg = args->at(i); - TokenLexer lexer(&arg); - MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined); - - arg.clear(); - expander.lex(&token); - while (token.type != Token::LAST) - { - arg.push_back(token); - expander.lex(&token); - } - } - return true; -} - -void MacroExpander::replaceMacroParams(const Macro& macro, - const std::vector<MacroArg>& args, - std::vector<Token>* replacements) -{ - for (size_t i = 0; i < macro.replacements.size(); ++i) - { - const Token& repl = macro.replacements[i]; - if (repl.type != Token::IDENTIFIER) - { - replacements->push_back(repl); - continue; - } - - // TODO(alokp): Optimize this. - // There is no need to search for macro params every time. - // The param index can be cached with the replacement token. - Macro::Parameters::const_iterator iter = std::find( - macro.parameters.begin(), macro.parameters.end(), repl.text); - if (iter == macro.parameters.end()) - { - replacements->push_back(repl); - continue; - } - - size_t iArg = std::distance(macro.parameters.begin(), iter); - const MacroArg& arg = args[iArg]; - if (arg.empty()) - { - continue; - } - size_t iRepl = replacements->size(); - replacements->insert(replacements->end(), arg.begin(), arg.end()); - // The replacement token inherits padding properties from - // macro replacement token. - replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace()); - } -} - -} // namespace pp - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "MacroExpander.h" + +#include <algorithm> +#include <sstream> + +#include "Diagnostics.h" +#include "Token.h" + +namespace pp +{ + +class TokenLexer : public Lexer +{ + public: + typedef std::vector<Token> TokenVector; + + TokenLexer(TokenVector* tokens) + { + tokens->swap(mTokens); + mIter = mTokens.begin(); + } + + virtual void lex(Token* token) + { + if (mIter == mTokens.end()) + { + token->reset(); + token->type = Token::LAST; + } + else + { + *token = *mIter++; + } + } + + private: + PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer); + + TokenVector mTokens; + TokenVector::const_iterator mIter; +}; + +MacroExpander::MacroExpander(Lexer* lexer, + MacroSet* macroSet, + Diagnostics* diagnostics, + bool parseDefined) : + mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined) +{ +} + +MacroExpander::~MacroExpander() +{ + for (size_t i = 0; i < mContextStack.size(); ++i) + { + delete mContextStack[i]; + } +} + +void MacroExpander::lex(Token* token) +{ + while (true) + { + getToken(token); + + if (token->type != Token::IDENTIFIER) + break; + + // Defined operator is parsed here since it may be generated by macro expansion. + // Defined operator produced by macro expansion has undefined behavior according to C++ + // spec, which the GLSL spec references (see C++14 draft spec section 16.1.4), but this + // behavior is needed for passing dEQP tests, which enforce stricter compatibility between + // implementations. + if (mParseDefined && token->text == "defined") + { + bool paren = false; + getToken(token); + if (token->type == '(') + { + paren = true; + getToken(token); + } + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location, + token->text); + break; + } + auto iter = mMacroSet->find(token->text); + std::string expression = iter != mMacroSet->end() ? "1" : "0"; + + if (paren) + { + getToken(token); + if (token->type != ')') + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location, + token->text); + break; + } + } + + // We have a valid defined operator. + // Convert the current token into a CONST_INT token. + token->type = Token::CONST_INT; + token->text = expression; + break; + } + + if (token->expansionDisabled()) + break; + + MacroSet::const_iterator iter = mMacroSet->find(token->text); + if (iter == mMacroSet->end()) + break; + + const Macro& macro = iter->second; + if (macro.disabled) + { + // If a particular token is not expanded, it is never expanded. + token->setExpansionDisabled(true); + break; + } + if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen()) + { + // If the token immediately after the macro name is not a '(', + // this macro should not be expanded. + break; + } + + pushMacro(macro, *token); + } +} + +void MacroExpander::getToken(Token* token) +{ + if (mReserveToken.get()) + { + *token = *mReserveToken; + mReserveToken.reset(); + return; + } + + // First pop all empty macro contexts. + while (!mContextStack.empty() && mContextStack.back()->empty()) + { + popMacro(); + } + + if (!mContextStack.empty()) + { + *token = mContextStack.back()->get(); + } + else + { + mLexer->lex(token); + } +} + +void MacroExpander::ungetToken(const Token& token) +{ + if (!mContextStack.empty()) + { + MacroContext* context = mContextStack.back(); + context->unget(); + assert(context->replacements[context->index] == token); + } + else + { + assert(!mReserveToken.get()); + mReserveToken.reset(new Token(token)); + } +} + +bool MacroExpander::isNextTokenLeftParen() +{ + Token token; + getToken(&token); + + bool lparen = token.type == '('; + ungetToken(token); + + return lparen; +} + +bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier) +{ + assert(!macro.disabled); + assert(!identifier.expansionDisabled()); + assert(identifier.type == Token::IDENTIFIER); + assert(identifier.text == macro.name); + + std::vector<Token> replacements; + if (!expandMacro(macro, identifier, &replacements)) + return false; + + // Macro is disabled for expansion until it is popped off the stack. + macro.disabled = true; + + MacroContext* context = new MacroContext; + context->macro = ¯o; + context->replacements.swap(replacements); + mContextStack.push_back(context); + return true; +} + +void MacroExpander::popMacro() +{ + assert(!mContextStack.empty()); + + MacroContext* context = mContextStack.back(); + mContextStack.pop_back(); + + assert(context->empty()); + assert(context->macro->disabled); + context->macro->disabled = false; + delete context; +} + +bool MacroExpander::expandMacro(const Macro& macro, + const Token& identifier, + std::vector<Token>* replacements) +{ + replacements->clear(); + if (macro.type == Macro::kTypeObj) + { + replacements->assign(macro.replacements.begin(), + macro.replacements.end()); + + if (macro.predefined) + { + static const std::string kLine = "__LINE__"; + static const std::string kFile = "__FILE__"; + + assert(replacements->size() == 1); + Token& repl = replacements->front(); + if (macro.name == kLine) + { + std::ostringstream stream; + stream << identifier.location.line; + repl.text = stream.str(); + } + else if (macro.name == kFile) + { + std::ostringstream stream; + stream << identifier.location.file; + repl.text = stream.str(); + } + } + } + else + { + assert(macro.type == Macro::kTypeFunc); + std::vector<MacroArg> args; + args.reserve(macro.parameters.size()); + if (!collectMacroArgs(macro, identifier, &args)) + return false; + + replaceMacroParams(macro, args, replacements); + } + + for (size_t i = 0; i < replacements->size(); ++i) + { + Token& repl = replacements->at(i); + if (i == 0) + { + // The first token in the replacement list inherits the padding + // properties of the identifier token. + repl.setAtStartOfLine(identifier.atStartOfLine()); + repl.setHasLeadingSpace(identifier.hasLeadingSpace()); + } + repl.location = identifier.location; + } + return true; +} + +bool MacroExpander::collectMacroArgs(const Macro& macro, + const Token& identifier, + std::vector<MacroArg>* args) +{ + Token token; + getToken(&token); + assert(token.type == '('); + + args->push_back(MacroArg()); + for (int openParens = 1; openParens != 0; ) + { + getToken(&token); + + if (token.type == Token::LAST) + { + mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION, + identifier.location, identifier.text); + // Do not lose EOF token. + ungetToken(token); + return false; + } + + bool isArg = false; // True if token is part of the current argument. + switch (token.type) + { + case '(': + ++openParens; + isArg = true; + break; + case ')': + --openParens; + isArg = openParens != 0; + break; + case ',': + // The individual arguments are separated by comma tokens, but + // the comma tokens between matching inner parentheses do not + // seperate arguments. + if (openParens == 1) args->push_back(MacroArg()); + isArg = openParens != 1; + break; + default: + isArg = true; + break; + } + if (isArg) + { + MacroArg& arg = args->back(); + // Initial whitespace is not part of the argument. + if (arg.empty()) token.setHasLeadingSpace(false); + arg.push_back(token); + } + } + + const Macro::Parameters& params = macro.parameters; + // If there is only one empty argument, it is equivalent to no argument. + if (params.empty() && (args->size() == 1) && args->front().empty()) + { + args->clear(); + } + // Validate the number of arguments. + if (args->size() != params.size()) + { + Diagnostics::ID id = args->size() < macro.parameters.size() ? + Diagnostics::MACRO_TOO_FEW_ARGS : + Diagnostics::MACRO_TOO_MANY_ARGS; + mDiagnostics->report(id, identifier.location, identifier.text); + return false; + } + + // Pre-expand each argument before substitution. + // This step expands each argument individually before they are + // inserted into the macro body. + for (size_t i = 0; i < args->size(); ++i) + { + MacroArg& arg = args->at(i); + TokenLexer lexer(&arg); + MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined); + + arg.clear(); + expander.lex(&token); + while (token.type != Token::LAST) + { + arg.push_back(token); + expander.lex(&token); + } + } + return true; +} + +void MacroExpander::replaceMacroParams(const Macro& macro, + const std::vector<MacroArg>& args, + std::vector<Token>* replacements) +{ + for (size_t i = 0; i < macro.replacements.size(); ++i) + { + const Token& repl = macro.replacements[i]; + if (repl.type != Token::IDENTIFIER) + { + replacements->push_back(repl); + continue; + } + + // TODO(alokp): Optimize this. + // There is no need to search for macro params every time. + // The param index can be cached with the replacement token. + Macro::Parameters::const_iterator iter = std::find( + macro.parameters.begin(), macro.parameters.end(), repl.text); + if (iter == macro.parameters.end()) + { + replacements->push_back(repl); + continue; + } + + size_t iArg = std::distance(macro.parameters.begin(), iter); + const MacroArg& arg = args[iArg]; + if (arg.empty()) + { + continue; + } + size_t iRepl = replacements->size(); + replacements->insert(replacements->end(), arg.begin(), arg.end()); + // The replacement token inherits padding properties from + // macro replacement token. + replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace()); + } +} + +} // namespace pp +
diff --git a/src/OpenGL/compiler/preprocessor/MacroExpander.h b/src/OpenGL/compiler/preprocessor/MacroExpander.h index e1b049a..9d304a9 100644 --- a/src/OpenGL/compiler/preprocessor/MacroExpander.h +++ b/src/OpenGL/compiler/preprocessor/MacroExpander.h
@@ -1,76 +1,84 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_MACRO_EXPANDER_H_ -#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ - -#include <cassert> -#include <memory> -#include <vector> - -#include "Lexer.h" -#include "Macro.h" -#include "pp_utils.h" - -namespace pp -{ - -class Diagnostics; - -class MacroExpander : public Lexer -{ - public: - MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics, bool parseDefined); - virtual ~MacroExpander(); - - virtual void lex(Token* token); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander); - - void getToken(Token* token); - void ungetToken(const Token& token); - bool isNextTokenLeftParen(); - - bool pushMacro(const Macro& macro, const Token& identifier); - void popMacro(); - - bool expandMacro(const Macro& macro, - const Token& identifier, - std::vector<Token>* replacements); - - typedef std::vector<Token> MacroArg; - bool collectMacroArgs(const Macro& macro, - const Token& identifier, - std::vector<MacroArg>* args); - void replaceMacroParams(const Macro& macro, - const std::vector<MacroArg>& args, - std::vector<Token>* replacements); - - struct MacroContext - { - const Macro* macro; - size_t index; - std::vector<Token> replacements; - - MacroContext() : macro(0), index(0) { } - bool empty() const { return index == replacements.size(); } - const Token& get() { return replacements[index++]; } - void unget() { assert(index > 0); --index; } - }; - - Lexer* mLexer; - MacroSet* mMacroSet; - Diagnostics* mDiagnostics; - const bool mParseDefined; - - std::auto_ptr<Token> mReserveToken; - std::vector<MacroContext*> mContextStack; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ +#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ + +#include <cassert> +#include <memory> +#include <vector> + +#include "Lexer.h" +#include "Macro.h" +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; + +class MacroExpander : public Lexer +{ +public: + MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics, bool parseDefined); + virtual ~MacroExpander(); + + virtual void lex(Token* token); + +private: + PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander); + + void getToken(Token* token); + void ungetToken(const Token& token); + bool isNextTokenLeftParen(); + + bool pushMacro(const Macro& macro, const Token& identifier); + void popMacro(); + + bool expandMacro(const Macro& macro, + const Token& identifier, + std::vector<Token>* replacements); + + typedef std::vector<Token> MacroArg; + bool collectMacroArgs(const Macro& macro, + const Token& identifier, + std::vector<MacroArg>* args); + void replaceMacroParams(const Macro& macro, + const std::vector<MacroArg>& args, + std::vector<Token>* replacements); + + struct MacroContext + { + const Macro* macro; + size_t index; + std::vector<Token> replacements; + + MacroContext() : macro(0), index(0) { } + bool empty() const { return index == replacements.size(); } + const Token& get() { return replacements[index++]; } + void unget() { assert(index > 0); --index; } + }; + + Lexer* mLexer; + MacroSet* mMacroSet; + Diagnostics* mDiagnostics; + const bool mParseDefined; + + std::auto_ptr<Token> mReserveToken; + std::vector<MacroContext*> mContextStack; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ +
diff --git a/src/OpenGL/compiler/preprocessor/Preprocessor.cpp b/src/OpenGL/compiler/preprocessor/Preprocessor.cpp index 675b30b..4ce0bf4 100644 --- a/src/OpenGL/compiler/preprocessor/Preprocessor.cpp +++ b/src/OpenGL/compiler/preprocessor/Preprocessor.cpp
@@ -1,141 +1,149 @@ -// -// Copyright (c) 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 "Preprocessor.h" - -#include <cassert> -#include <sstream> - -#include "Diagnostics.h" -#include "DirectiveParser.h" -#include "Macro.h" -#include "MacroExpander.h" -#include "Token.h" -#include "Tokenizer.h" - -namespace pp -{ - -struct PreprocessorImpl -{ - Diagnostics* diagnostics; - MacroSet macroSet; - Tokenizer tokenizer; - DirectiveParser directiveParser; - MacroExpander macroExpander; - - PreprocessorImpl(Diagnostics* diag, DirectiveHandler* directiveHandler) : - diagnostics(diag), - tokenizer(diag), - directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), - macroExpander(&directiveParser, ¯oSet, diag, false) - { - } -}; - -Preprocessor::Preprocessor(Diagnostics* diagnostics, - DirectiveHandler* directiveHandler) -{ - mImpl = new PreprocessorImpl(diagnostics, directiveHandler); -} - -Preprocessor::~Preprocessor() -{ - delete mImpl; -} - -bool Preprocessor::init(int count, - const char* const string[], - const int length[]) -{ - static const int kGLSLVersion = 100; - - // Add standard pre-defined macros. - predefineMacro("__LINE__", 0); - predefineMacro("__FILE__", 0); - predefineMacro("__VERSION__", kGLSLVersion); - predefineMacro("GL_ES", 1); - - return mImpl->tokenizer.init(count, string, length); -} - -void Preprocessor::predefineMacro(const char* name, int value) -{ - std::ostringstream stream; - stream << value; - - Token token; - token.type = Token::CONST_INT; - token.text = stream.str(); - - Macro macro; - macro.predefined = true; - macro.type = Macro::kTypeObj; - macro.name = name; - macro.replacements.push_back(token); - - mImpl->macroSet[name] = macro; -} - -void Preprocessor::lex(Token* token) -{ - bool validToken = false; - while (!validToken) - { - mImpl->macroExpander.lex(token); - switch (token->type) - { - // We should not be returning internal preprocessing tokens. - // Convert preprocessing tokens to compiler tokens or report - // diagnostics. - 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); - break; - case Token::PP_OTHER: - mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER, - token->location, token->text); - break; - default: - validToken = true; - break; - } - } -} - -} // namespace pp - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Preprocessor.h" + +#include <cassert> +#include <sstream> + +#include "Diagnostics.h" +#include "DirectiveParser.h" +#include "Macro.h" +#include "MacroExpander.h" +#include "Token.h" +#include "Tokenizer.h" + +namespace pp +{ + +struct PreprocessorImpl +{ + Diagnostics* diagnostics; + MacroSet macroSet; + Tokenizer tokenizer; + DirectiveParser directiveParser; + MacroExpander macroExpander; + + PreprocessorImpl(Diagnostics* diag, DirectiveHandler* directiveHandler) : + diagnostics(diag), + tokenizer(diag), + directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), + macroExpander(&directiveParser, ¯oSet, diag, false) + { + } +}; + +Preprocessor::Preprocessor(Diagnostics* diagnostics, + DirectiveHandler* directiveHandler) +{ + mImpl = new PreprocessorImpl(diagnostics, directiveHandler); +} + +Preprocessor::~Preprocessor() +{ + delete mImpl; +} + +bool Preprocessor::init(int count, + const char* const string[], + const int length[]) +{ + static const int kGLSLVersion = 100; + + // Add standard pre-defined macros. + predefineMacro("__LINE__", 0); + predefineMacro("__FILE__", 0); + predefineMacro("__VERSION__", kGLSLVersion); + predefineMacro("GL_ES", 1); + + return mImpl->tokenizer.init(count, string, length); +} + +void Preprocessor::predefineMacro(const char* name, int value) +{ + std::ostringstream stream; + stream << value; + + Token token; + token.type = Token::CONST_INT; + token.text = stream.str(); + + Macro macro; + macro.predefined = true; + macro.type = Macro::kTypeObj; + macro.name = name; + macro.replacements.push_back(token); + + mImpl->macroSet[name] = macro; +} + +void Preprocessor::lex(Token* token) +{ + bool validToken = false; + while (!validToken) + { + mImpl->macroExpander.lex(token); + switch (token->type) + { + // We should not be returning internal preprocessing tokens. + // Convert preprocessing tokens to compiler tokens or report + // diagnostics. + 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); + break; + case Token::PP_OTHER: + mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER, + token->location, token->text); + break; + default: + validToken = true; + break; + } + } +} + +} // namespace pp +
diff --git a/src/OpenGL/compiler/preprocessor/Preprocessor.h b/src/OpenGL/compiler/preprocessor/Preprocessor.h index 7a54da0..62eca56 100644 --- a/src/OpenGL/compiler/preprocessor/Preprocessor.h +++ b/src/OpenGL/compiler/preprocessor/Preprocessor.h
@@ -1,49 +1,57 @@ -// -// Copyright (c) 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_PREPROCESSOR_PREPROCESSOR_H_ -#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_ - -#include "pp_utils.h" - -namespace pp -{ - -class Diagnostics; -class DirectiveHandler; -struct PreprocessorImpl; -struct Token; - -class Preprocessor -{ - public: - Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler); - ~Preprocessor(); - - // count: specifies the number of elements in the string and length arrays. - // string: specifies an array of pointers to strings. - // length: specifies an array of string lengths. - // If length is NULL, each string is assumed to be null terminated. - // If length is a value other than NULL, it points to an array containing - // a string length for each of the corresponding elements of string. - // Each element in the length array may contain the length of the - // corresponding string or a value less than 0 to indicate that the string - // is null terminated. - bool init(int count, const char* const string[], const int length[]); - // Adds a pre-defined macro. - void predefineMacro(const char* name, int value); - - void lex(Token* token); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor); - - PreprocessorImpl* mImpl; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_ - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_ +#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_ + +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; +class DirectiveHandler; +struct PreprocessorImpl; +struct Token; + +class Preprocessor +{ +public: + Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler); + ~Preprocessor(); + + // count: specifies the number of elements in the string and length arrays. + // string: specifies an array of pointers to strings. + // length: specifies an array of string lengths. + // If length is NULL, each string is assumed to be null terminated. + // If length is a value other than NULL, it points to an array containing + // a string length for each of the corresponding elements of string. + // Each element in the length array may contain the length of the + // corresponding string or a value less than 0 to indicate that the string + // is null terminated. + bool init(int count, const char* const string[], const int length[]); + // Adds a pre-defined macro. + void predefineMacro(const char* name, int value); + + void lex(Token* token); + +private: + PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor); + + PreprocessorImpl* mImpl; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_ +
diff --git a/src/OpenGL/compiler/preprocessor/SourceLocation.h b/src/OpenGL/compiler/preprocessor/SourceLocation.h index 9c0d1d3..b01e73b 100644 --- a/src/OpenGL/compiler/preprocessor/SourceLocation.h +++ b/src/OpenGL/compiler/preprocessor/SourceLocation.h
@@ -1,38 +1,46 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_SOURCE_LOCATION_H_ -#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ - -namespace pp -{ - -struct SourceLocation -{ - SourceLocation() : file(0), line(0) { } - SourceLocation(int f, int l) : file(f), line(l) { } - - bool equals(const SourceLocation& other) const - { - return (file == other.file) && (line == other.line); - } - - int file; - int line; -}; - -inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs) -{ - return lhs.equals(rhs); -} - -inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs) -{ - return !lhs.equals(rhs); -} - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ +#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ + +namespace pp +{ + +struct SourceLocation +{ + SourceLocation() : file(0), line(0) { } + SourceLocation(int f, int l) : file(f), line(l) { } + + bool equals(const SourceLocation& other) const + { + return (file == other.file) && (line == other.line); + } + + int file; + int line; +}; + +inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs) +{ + return lhs.equals(rhs); +} + +inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs) +{ + return !lhs.equals(rhs); +} + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
diff --git a/src/OpenGL/compiler/preprocessor/Token.cpp b/src/OpenGL/compiler/preprocessor/Token.cpp index a465aa1..28d6f8c 100644 --- a/src/OpenGL/compiler/preprocessor/Token.cpp +++ b/src/OpenGL/compiler/preprocessor/Token.cpp
@@ -1,83 +1,91 @@ -// -// Copyright (c) 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 "Token.h" - -#include <cassert> - -#include "numeric_lex.h" - -namespace pp -{ - -void Token::reset() -{ - type = 0; - flags = 0; - location = SourceLocation(); - text.clear(); -} - -bool Token::equals(const Token& other) const -{ - return (type == other.type) && - (flags == other.flags) && - (location == other.location) && - (text == other.text); -} - -void Token::setAtStartOfLine(bool start) -{ - if (start) - flags |= AT_START_OF_LINE; - else - flags &= ~AT_START_OF_LINE; -} - -void Token::setHasLeadingSpace(bool space) -{ - if (space) - flags |= HAS_LEADING_SPACE; - else - flags &= ~HAS_LEADING_SPACE; -} - -void Token::setExpansionDisabled(bool disable) -{ - if (disable) - flags |= EXPANSION_DISABLED; - else - flags &= ~EXPANSION_DISABLED; -} - -bool Token::iValue(int* value) const -{ - assert(type == CONST_INT); - return numeric_lex_int(text, value); -} - -bool Token::uValue(unsigned int* value) const -{ - assert(type == CONST_INT); - return numeric_lex_int(text, value); -} - -bool Token::fValue(float* value) const -{ - assert(type == CONST_FLOAT); - return numeric_lex_float(text, value); -} - -std::ostream& operator<<(std::ostream& out, const Token& token) -{ - if (token.hasLeadingSpace()) - out << " "; - - out << token.text; - return out; -} - -} // namespace pp +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Token.h" + +#include <cassert> + +#include "numeric_lex.h" + +namespace pp +{ + +void Token::reset() +{ + type = 0; + flags = 0; + location = SourceLocation(); + text.clear(); +} + +bool Token::equals(const Token& other) const +{ + return (type == other.type) && + (flags == other.flags) && + (location == other.location) && + (text == other.text); +} + +void Token::setAtStartOfLine(bool start) +{ + if (start) + flags |= AT_START_OF_LINE; + else + flags &= ~AT_START_OF_LINE; +} + +void Token::setHasLeadingSpace(bool space) +{ + if (space) + flags |= HAS_LEADING_SPACE; + else + flags &= ~HAS_LEADING_SPACE; +} + +void Token::setExpansionDisabled(bool disable) +{ + if (disable) + flags |= EXPANSION_DISABLED; + else + flags &= ~EXPANSION_DISABLED; +} + +bool Token::iValue(int* value) const +{ + assert(type == CONST_INT); + return numeric_lex_int(text, value); +} + +bool Token::uValue(unsigned int* value) const +{ + assert(type == CONST_INT); + return numeric_lex_int(text, value); +} + +bool Token::fValue(float* value) const +{ + assert(type == CONST_FLOAT); + return numeric_lex_float(text, value); +} + +std::ostream& operator<<(std::ostream& out, const Token& token) +{ + if (token.hasLeadingSpace()) + out << " "; + + out << token.text; + return out; +} + +} // namespace pp
diff --git a/src/OpenGL/compiler/preprocessor/Token.h b/src/OpenGL/compiler/preprocessor/Token.h index 45b1129..ddd3aac 100644 --- a/src/OpenGL/compiler/preprocessor/Token.h +++ b/src/OpenGL/compiler/preprocessor/Token.h
@@ -1,106 +1,114 @@ -// -// Copyright (c) 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_PREPROCESSOR_TOKEN_H_ -#define COMPILER_PREPROCESSOR_TOKEN_H_ - -#include <ostream> -#include <string> - -#include "SourceLocation.h" - -namespace pp -{ - -struct Token -{ - enum Type - { - LAST = 0, // EOF. - - IDENTIFIER = 258, - - CONST_INT, - CONST_FLOAT, - - OP_INC, - OP_DEC, - OP_LEFT, - OP_RIGHT, - OP_LE, - OP_GE, - OP_EQ, - OP_NE, - OP_AND, - OP_XOR, - OP_OR, - OP_ADD_ASSIGN, - OP_SUB_ASSIGN, - OP_MUL_ASSIGN, - OP_DIV_ASSIGN, - OP_MOD_ASSIGN, - OP_LEFT_ASSIGN, - OP_RIGHT_ASSIGN, - OP_AND_ASSIGN, - OP_XOR_ASSIGN, - OP_OR_ASSIGN, - - // Preprocessing token types. - // These types are used by the preprocessor internally. - // Preprocessor clients must not depend or check for them. - PP_HASH, - PP_NUMBER, - PP_OTHER - }; - enum Flags - { - AT_START_OF_LINE = 1 << 0, - HAS_LEADING_SPACE = 1 << 1, - EXPANSION_DISABLED = 1 << 2 - }; - - Token() : type(0), flags(0) { } - - void reset(); - bool equals(const Token& other) const; - - // Returns true if this is the first token on line. - // It disregards any leading whitespace. - bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; } - void setAtStartOfLine(bool start); - - bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; } - void setHasLeadingSpace(bool space); - - bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; } - void setExpansionDisabled(bool disable); - - // Converts text into numeric value for CONST_INT and CONST_FLOAT token. - // Returns false if the parsed value cannot fit into an int or float. - bool iValue(int* value) const; - bool uValue(unsigned int* value) const; - bool fValue(float* value) const; - - int type; - unsigned int flags; - SourceLocation location; - std::string text; -}; - -inline bool operator==(const Token& lhs, const Token& rhs) -{ - return lhs.equals(rhs); -} - -inline bool operator!=(const Token& lhs, const Token& rhs) -{ - return !lhs.equals(rhs); -} - -extern std::ostream& operator<<(std::ostream& out, const Token& token); - -} // namepsace pp -#endif // COMPILER_PREPROCESSOR_TOKEN_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_TOKEN_H_ +#define COMPILER_PREPROCESSOR_TOKEN_H_ + +#include <ostream> +#include <string> + +#include "SourceLocation.h" + +namespace pp +{ + +struct Token +{ + enum Type + { + LAST = 0, // EOF. + + IDENTIFIER = 258, + + CONST_INT, + CONST_FLOAT, + + OP_INC, + OP_DEC, + OP_LEFT, + OP_RIGHT, + OP_LE, + OP_GE, + OP_EQ, + OP_NE, + OP_AND, + OP_XOR, + OP_OR, + OP_ADD_ASSIGN, + OP_SUB_ASSIGN, + OP_MUL_ASSIGN, + OP_DIV_ASSIGN, + OP_MOD_ASSIGN, + OP_LEFT_ASSIGN, + OP_RIGHT_ASSIGN, + OP_AND_ASSIGN, + OP_XOR_ASSIGN, + OP_OR_ASSIGN, + + // Preprocessing token types. + // These types are used by the preprocessor internally. + // Preprocessor clients must not depend or check for them. + PP_HASH, + PP_NUMBER, + PP_OTHER + }; + enum Flags + { + AT_START_OF_LINE = 1 << 0, + HAS_LEADING_SPACE = 1 << 1, + EXPANSION_DISABLED = 1 << 2 + }; + + Token() : type(0), flags(0) { } + + void reset(); + bool equals(const Token& other) const; + + // Returns true if this is the first token on line. + // It disregards any leading whitespace. + bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; } + void setAtStartOfLine(bool start); + + bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; } + void setHasLeadingSpace(bool space); + + bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; } + void setExpansionDisabled(bool disable); + + // Converts text into numeric value for CONST_INT and CONST_FLOAT token. + // Returns false if the parsed value cannot fit into an int or float. + bool iValue(int* value) const; + bool uValue(unsigned int* value) const; + bool fValue(float* value) const; + + int type; + unsigned int flags; + SourceLocation location; + std::string text; +}; + +inline bool operator==(const Token& lhs, const Token& rhs) +{ + return lhs.equals(rhs); +} + +inline bool operator!=(const Token& lhs, const Token& rhs) +{ + return !lhs.equals(rhs); +} + +extern std::ostream& operator<<(std::ostream& out, const Token& token); + +} // namepsace pp +#endif // COMPILER_PREPROCESSOR_TOKEN_H_
diff --git a/src/OpenGL/compiler/preprocessor/Tokenizer.cpp b/src/OpenGL/compiler/preprocessor/Tokenizer.cpp index 02411ad..13e93ce 100644 --- a/src/OpenGL/compiler/preprocessor/Tokenizer.cpp +++ b/src/OpenGL/compiler/preprocessor/Tokenizer.cpp
@@ -1,9 +1,17 @@ #line 16 "./Tokenizer.l" +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2011-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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT! @@ -532,11 +540,19 @@ #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET /* +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. This file contains the Lex specification for GLSL ES preprocessor. Based on Microsoft Visual Studio 2010 Preprocessor Grammar:
diff --git a/src/OpenGL/compiler/preprocessor/Tokenizer.h b/src/OpenGL/compiler/preprocessor/Tokenizer.h index 6b40974..3bad966 100644 --- a/src/OpenGL/compiler/preprocessor/Tokenizer.h +++ b/src/OpenGL/compiler/preprocessor/Tokenizer.h
@@ -1,60 +1,68 @@ -// -// Copyright (c) 2012 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_PREPROCESSOR_TOKENIZER_H_ -#define COMPILER_PREPROCESSOR_TOKENIZER_H_ - -#include "Input.h" -#include "Lexer.h" -#include "pp_utils.h" - -#include <algorithm> - -namespace pp -{ - -class Diagnostics; - -class Tokenizer : public Lexer -{ - public: - struct Context - { - Diagnostics* diagnostics; - - Input input; - // The location where yytext points to. Token location should track - // scanLoc instead of Input::mReadLoc because they may not be the same - // if text is buffered up in the scanner input buffer. - Input::Location scanLoc; - - bool leadingSpace; - bool lineStart; - }; - static const size_t kMaxTokenLength; - - Tokenizer(Diagnostics* diagnostics); - ~Tokenizer(); - - bool init(int count, const char* const string[], const int length[]); - - void setFileNumber(int file); - void setLineNumber(int line); - - virtual void lex(Token* token); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer); - bool initScanner(); - void destroyScanner(); - - void* mHandle; // Scanner handle. - Context mContext; // Scanner extra. -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_ - +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_ +#define COMPILER_PREPROCESSOR_TOKENIZER_H_ + +#include "Input.h" +#include "Lexer.h" +#include "pp_utils.h" + +#include <algorithm> + +namespace pp +{ + +class Diagnostics; + +class Tokenizer : public Lexer +{ +public: + struct Context + { + Diagnostics* diagnostics; + + Input input; + // The location where yytext points to. Token location should track + // scanLoc instead of Input::mReadLoc because they may not be the same + // if text is buffered up in the scanner input buffer. + Input::Location scanLoc; + + bool leadingSpace; + bool lineStart; + }; + static const size_t kMaxTokenLength; + + Tokenizer(Diagnostics* diagnostics); + ~Tokenizer(); + + bool init(int count, const char* const string[], const int length[]); + + void setFileNumber(int file); + void setLineNumber(int line); + + virtual void lex(Token* token); + +private: + PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer); + bool initScanner(); + void destroyScanner(); + + void* mHandle; // Scanner handle. + Context mContext; // Scanner extra. +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_ +
diff --git a/src/OpenGL/compiler/preprocessor/Tokenizer.l b/src/OpenGL/compiler/preprocessor/Tokenizer.l index 5e5f26d..094627e 100644 --- a/src/OpenGL/compiler/preprocessor/Tokenizer.l +++ b/src/OpenGL/compiler/preprocessor/Tokenizer.l
@@ -1,9 +1,17 @@ /* +// Copyright 2016 The SwiftShader 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. This file contains the Lex specification for GLSL ES preprocessor. Based on Microsoft Visual Studio 2010 Preprocessor Grammar: @@ -13,11 +21,19 @@ */ %top{ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2011-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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT! } @@ -78,8 +94,8 @@ IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]* PUNCTUATOR [][<>(){}.+-/*%^|&~=!:;,?] -DECIMAL_CONSTANT [1-9][0-9]*[uU]? -OCTAL_CONSTANT 0[0-7]*[uU]? +DECIMAL_CONSTANT [1-9][0-9]*[uU]? +OCTAL_CONSTANT 0[0-7]*[uU]? HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+[uU]? DIGIT [0-9]
diff --git a/src/OpenGL/compiler/preprocessor/generate_parser.sh b/src/OpenGL/compiler/preprocessor/generate_parser.sh index 14ffa6a..36bd84e 100644 --- a/src/OpenGL/compiler/preprocessor/generate_parser.sh +++ b/src/OpenGL/compiler/preprocessor/generate_parser.sh
@@ -1,7 +1,17 @@ #!/bin/bash -# Copyright (c) 2012-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. +# Copyright 2016 The SwiftShader Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # Generates various components of GLSL ES preprocessor.
diff --git a/src/OpenGL/compiler/preprocessor/length_limits.h b/src/OpenGL/compiler/preprocessor/length_limits.h index 889d468..1c91447 100644 --- a/src/OpenGL/compiler/preprocessor/length_limits.h +++ b/src/OpenGL/compiler/preprocessor/length_limits.h
@@ -1,21 +1,29 @@ -// -// Copyright (c) 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. -// - -// -// length_limits.h -// - -#if !defined(__LENGTH_LIMITS_H) -#define __LENGTH_LIMITS_H 1 - -// These constants are factored out from the rest of the headers to -// make it easier to reference them from the compiler sources. - -// These lengths do not include the NULL terminator. -#define MAX_SYMBOL_NAME_LEN 256 -#define MAX_STRING_LEN 511 - -#endif // !(defined(__LENGTH_LIMITS_H) +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +// length_limits.h +// + +#if !defined(__LENGTH_LIMITS_H) +#define __LENGTH_LIMITS_H 1 + +// These constants are factored out from the rest of the headers to +// make it easier to reference them from the compiler sources. + +// These lengths do not include the NULL terminator. +#define MAX_SYMBOL_NAME_LEN 256 +#define MAX_STRING_LEN 511 + +#endif // !(defined(__LENGTH_LIMITS_H)
diff --git a/src/OpenGL/compiler/preprocessor/numeric_lex.h b/src/OpenGL/compiler/preprocessor/numeric_lex.h index 3cdf71f..f57410c 100644 --- a/src/OpenGL/compiler/preprocessor/numeric_lex.h +++ b/src/OpenGL/compiler/preprocessor/numeric_lex.h
@@ -1,61 +1,69 @@ -// -// Copyright (c) 2012 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. -// - -// numeric_lex.h: Functions to extract numeric values from string. - -#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ -#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ - -#include <sstream> - -namespace pp { - -inline std::ios::fmtflags numeric_base_int(const std::string& str) -{ - if ((str.size() >= 2) && - (str[0] == '0') && - (str[1] == 'x' || str[1] == 'X')) - { - return std::ios::hex; - } - else if ((str.size() >= 1) && (str[0] == '0')) - { - return std::ios::oct; - } - return std::ios::dec; -} - -// The following functions parse the given string to extract a numerical -// value of the given type. These functions assume that the string is -// of the correct form. They can only fail if the parsed value is too big, -// in which case false is returned. - -template<typename IntType> -bool numeric_lex_int(const std::string& str, IntType* value) -{ - std::istringstream stream(str); - // This should not be necessary, but MSVS has a buggy implementation. - // It returns incorrect results if the base is not specified. - stream.setf(numeric_base_int(str), std::ios::basefield); - - stream >> (*value); - return !stream.fail(); -} - -template<typename FloatType> -bool numeric_lex_float(const std::string& str, FloatType* value) -{ - std::istringstream stream(str); - // Force "C" locale so that decimal character is always '.', and - // not dependent on the current locale. - stream.imbue(std::locale::classic()); - - stream >> (*value); - return !stream.fail(); -} - -} // namespace pp. -#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// numeric_lex.h: Functions to extract numeric values from string. + +#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ +#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ + +#include <sstream> + +namespace pp { + +inline std::ios::fmtflags numeric_base_int(const std::string& str) +{ + if ((str.size() >= 2) && + (str[0] == '0') && + (str[1] == 'x' || str[1] == 'X')) + { + return std::ios::hex; + } + else if ((str.size() >= 1) && (str[0] == '0')) + { + return std::ios::oct; + } + return std::ios::dec; +} + +// The following functions parse the given string to extract a numerical +// value of the given type. These functions assume that the string is +// of the correct form. They can only fail if the parsed value is too big, +// in which case false is returned. + +template<typename IntType> +bool numeric_lex_int(const std::string& str, IntType* value) +{ + std::istringstream stream(str); + // This should not be necessary, but MSVS has a buggy implementation. + // It returns incorrect results if the base is not specified. + stream.setf(numeric_base_int(str), std::ios::basefield); + + stream >> (*value); + return !stream.fail(); +} + +template<typename FloatType> +bool numeric_lex_float(const std::string& str, FloatType* value) +{ + std::istringstream stream(str); + // Force "C" locale so that decimal character is always '.', and + // not dependent on the current locale. + stream.imbue(std::locale::classic()); + + stream >> (*value); + return !stream.fail(); +} + +} // namespace pp. +#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
diff --git a/src/OpenGL/compiler/preprocessor/pp_utils.h b/src/OpenGL/compiler/preprocessor/pp_utils.h index 9fed659..d0ea4c4 100644 --- a/src/OpenGL/compiler/preprocessor/pp_utils.h +++ b/src/OpenGL/compiler/preprocessor/pp_utils.h
@@ -1,18 +1,26 @@ -// -// Copyright (c) 2012 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. -// - -// pp_utils.h: Common preprocessor utilities - -#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_ -#define COMPILER_PREPROCESSOR_PPUTILS_H_ - -// A macro to disallow the copy constructor and operator= functions -// This must be used in the private: declarations for a class. -#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) - -#endif // COMPILER_PREPROCESSOR_PPUTILS_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// pp_utils.h: Common preprocessor utilities + +#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_ +#define COMPILER_PREPROCESSOR_PPUTILS_H_ + +// A macro to disallow the copy constructor and operator= functions +// This must be used in the private: declarations for a class. +#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#endif // COMPILER_PREPROCESSOR_PPUTILS_H_
diff --git a/src/OpenGL/compiler/util.cpp b/src/OpenGL/compiler/util.cpp index e20068b..2905c1d 100644 --- a/src/OpenGL/compiler/util.cpp +++ b/src/OpenGL/compiler/util.cpp
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include <limits>
diff --git a/src/OpenGL/compiler/util.h b/src/OpenGL/compiler/util.h index 61442be..a5c4842 100644 --- a/src/OpenGL/compiler/util.h +++ b/src/OpenGL/compiler/util.h
@@ -1,8 +1,16 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright (c) 2002-2010 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. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #ifndef COMPILER_UTIL_H #define COMPILER_UTIL_H