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