aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl
diff options
context:
space:
mode:
authorGravatar ethannicholas <ethannicholas@google.com>2016-10-10 10:09:00 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-10-10 10:09:00 -0700
commitdcfe6dba4a335e50e86ff68e3252065d4197432c (patch)
tree6953805849e283220d56f4feac3358b5efea3cc9 /src/sksl
parent95304e395c46bdd40decbb7ccd46939886cc1244 (diff)
Turned on SkSL->GLSL compiler
Diffstat (limited to 'src/sksl')
-rw-r--r--src/sksl/README35
-rw-r--r--src/sksl/SkSLCompiler.cpp38
-rw-r--r--src/sksl/SkSLCompiler.h5
-rw-r--r--src/sksl/SkSLContext.h2
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.cpp206
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.h16
-rw-r--r--src/sksl/SkSLIRGenerator.cpp82
-rw-r--r--src/sksl/SkSLIRGenerator.h4
-rw-r--r--src/sksl/SkSLMain.cpp52
-rw-r--r--src/sksl/SkSLParser.cpp72
-rw-r--r--src/sksl/SkSLParser.h3
-rw-r--r--src/sksl/SkSLSPIRVCodeGenerator.cpp25
-rw-r--r--src/sksl/SkSLSPIRVCodeGenerator.h2
-rw-r--r--src/sksl/SkSLToken.h6
-rw-r--r--src/sksl/SkSLUtil.cpp47
-rw-r--r--src/sksl/SkSLUtil.h14
-rw-r--r--src/sksl/ast/SkSLASTDeclaration.h4
-rw-r--r--src/sksl/ast/SkSLASTIndexSuffix.h16
-rw-r--r--src/sksl/ast/SkSLASTLayout.h17
-rw-r--r--src/sksl/ast/SkSLASTModifiersDeclaration.h37
-rw-r--r--src/sksl/ast/SkSLASTPrecision.h45
-rw-r--r--src/sksl/ir/SkSLIndexExpression.h6
-rw-r--r--src/sksl/ir/SkSLIntLiteral.h4
-rw-r--r--src/sksl/ir/SkSLLayout.h34
-rw-r--r--src/sksl/ir/SkSLModifiersDeclaration.h37
-rw-r--r--src/sksl/ir/SkSLProgram.h9
-rw-r--r--src/sksl/ir/SkSLProgramElement.h3
-rw-r--r--src/sksl/lex.sksl.c527
-rw-r--r--src/sksl/sksl.flex6
-rw-r--r--src/sksl/sksl.include3
-rw-r--r--src/sksl/sksl_frag.include14
31 files changed, 999 insertions, 372 deletions
diff --git a/src/sksl/README b/src/sksl/README
new file mode 100644
index 0000000000..1427c21926
--- /dev/null
+++ b/src/sksl/README
@@ -0,0 +1,35 @@
+Overview
+========
+
+SkSL ("Skia Shading Language") is a variant of GLSL which is used as Skia's
+internal shading language. SkSL is, at its heart, a single standardized version
+of GLSL which avoids all of the various version and dialect differences found
+in GLSL "in the wild", but it does bring a few of its own changes to the table.
+
+Skia uses the SkSL compiler to convert SkSL code to GLSL, GLSL ES, or SPIR-V
+before handing it over to the graphics driver.
+
+Differences from GLSL
+=====================
+
+SkSL is based on GLSL 4.5. For the most part, write SkSL exactly as you would
+desktop GLSL, and the SkSL compiler will take care of version and dialect
+differences (for instance, you always use "in" and "out", and skslc will handle
+translating them to "varying" and "attribute" as appropriate). Be aware of the
+following differences between SkSL and GLSL:
+
+* no #version or "precision" statement is required, and they will be ignored if
+ present
+* the output color is sk_FragColor (do not declare it)
+* lowp, mediump, and highp are always permitted (but will only be respected if
+ you run on a GLES device)
+* you do not need to include ".0" to make a number a float (meaning that
+ "vec2(x, y) * 4" is perfectly legal in SkSL, unlike GLSL where it would often
+ have to be expressed "vec2(x, y) * 4.0". There is no performance penalty for
+ this, as the number is converted to a float at compile time)
+* type suffixes on numbers (1.0f, 0xFFu) are both unnecessary and unsupported
+* some built-in functions and one or two rarely-used language features are not
+ yet supported (sorry!)
+
+SkSL is still under development, and is expected to diverge further from GLSL
+over time.
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index d2ad81223e..9eeacd082d 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -10,11 +10,13 @@
#include <fstream>
#include <streambuf>
+#include "ast/SkSLASTPrecision.h"
#include "SkSLIRGenerator.h"
#include "SkSLParser.h"
#include "SkSLSPIRVCodeGenerator.h"
#include "ir/SkSLExpression.h"
#include "ir/SkSLIntLiteral.h"
+#include "ir/SkSLModifiersDeclaration.h"
#include "ir/SkSLSymbolTable.h"
#include "ir/SkSLVarDeclaration.h"
#include "SkMutex.h"
@@ -23,15 +25,15 @@
// include the built-in shader symbols as static strings
-static std::string SKSL_INCLUDE =
+static const char* SKSL_INCLUDE =
#include "sksl.include"
;
-static std::string SKSL_VERT_INCLUDE =
+static const char* SKSL_VERT_INCLUDE =
#include "sksl_vert.include"
;
-static std::string SKSL_FRAG_INCLUDE =
+static const char* SKSL_FRAG_INCLUDE =
#include "sksl_frag.include"
;
@@ -97,6 +99,7 @@ Compiler::Compiler()
ADD_TYPE(Sampler1D);
ADD_TYPE(Sampler2D);
ADD_TYPE(Sampler3D);
+ ADD_TYPE(SamplerExternalOES);
ADD_TYPE(SamplerCube);
ADD_TYPE(Sampler2DRect);
ADD_TYPE(Sampler1DArray);
@@ -128,8 +131,9 @@ Compiler::Compiler()
ADD_TYPE(GSampler2DArrayShadow);
ADD_TYPE(GSamplerCubeArrayShadow);
- std::vector<std::unique_ptr<ProgramElement>> ignored;
- this->internalConvertProgram(SKSL_INCLUDE, &ignored);
+ Modifiers::Flag ignored1;
+ std::vector<std::unique_ptr<ProgramElement>> ignored2;
+ this->internalConvertProgram(SKSL_INCLUDE, &ignored1, &ignored2);
ASSERT(!fErrorCount);
}
@@ -138,12 +142,14 @@ Compiler::~Compiler() {
}
void Compiler::internalConvertProgram(std::string text,
+ Modifiers::Flag* defaultPrecision,
std::vector<std::unique_ptr<ProgramElement>>* result) {
Parser parser(text, *fTypes, *this);
std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
if (fErrorCount) {
return;
}
+ *defaultPrecision = Modifiers::kHighp_Flag;
for (size_t i = 0; i < parsed.size(); i++) {
ASTDeclaration& decl = *parsed[i];
switch (decl.fKind) {
@@ -164,6 +170,14 @@ void Compiler::internalConvertProgram(std::string text,
}
break;
}
+ case ASTDeclaration::kModifiers_Kind: {
+ std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration(
+ (ASTModifiersDeclaration&) decl);
+ if (f) {
+ result->push_back(std::move(f));
+ }
+ break;
+ }
case ASTDeclaration::kInterfaceBlock_Kind: {
std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
(ASTInterfaceBlock&) decl);
@@ -179,6 +193,10 @@ void Compiler::internalConvertProgram(std::string text,
}
break;
}
+ case ASTDeclaration::kPrecision_Kind: {
+ *defaultPrecision = ((ASTPrecision&) decl).fPrecision;
+ break;
+ }
default:
ABORT("unsupported declaration: %s\n", decl.description().c_str());
}
@@ -190,16 +208,18 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, std::strin
fErrorCount = 0;
fIRGenerator->pushSymbolTable();
std::vector<std::unique_ptr<ProgramElement>> elements;
+ Modifiers::Flag ignored;
switch (kind) {
case Program::kVertex_Kind:
- this->internalConvertProgram(SKSL_VERT_INCLUDE, &elements);
+ this->internalConvertProgram(SKSL_VERT_INCLUDE, &ignored, &elements);
break;
case Program::kFragment_Kind:
- this->internalConvertProgram(SKSL_FRAG_INCLUDE, &elements);
+ this->internalConvertProgram(SKSL_FRAG_INCLUDE, &ignored, &elements);
break;
}
- this->internalConvertProgram(text, &elements);
- auto result = std::unique_ptr<Program>(new Program(kind, std::move(elements),
+ Modifiers::Flag defaultPrecision;
+ this->internalConvertProgram(text, &defaultPrecision, &elements);
+ auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements),
fIRGenerator->fSymbolTable));;
fIRGenerator->popSymbolTable();
this->writeErrorCount();
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 9cd1eac3f9..96ae7d06bc 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -15,6 +15,8 @@
#include "SkSLErrorReporter.h"
#include "SkSLGLSLCodeGenerator.h"
+#define SK_FRAGCOLOR_BUILTIN 10001
+
namespace SkSL {
class IRGenerator;
@@ -24,6 +26,8 @@ class IRGenerator;
* file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
* produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
* compiled output.
+ *
+ * See the README for information about SkSL.
*/
class Compiler : public ErrorReporter {
public:
@@ -50,6 +54,7 @@ public:
private:
void internalConvertProgram(std::string text,
+ Modifiers::Flag* defaultPrecision,
std::vector<std::unique_ptr<ProgramElement>>* result);
std::shared_ptr<SymbolTable> fTypes;
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index 1f124d05eb..82c265bbb2 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -60,6 +60,7 @@ public:
, fSampler1D_Type(new Type("sampler1D", SpvDim1D, false, false, false, true))
, fSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true))
, fSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true))
+ , fSamplerExternalOES_Type(new Type("samplerExternalOES", SpvDim2D, false, false, false, true))
, fSamplerCube_Type(new Type("samplerCube"))
, fSampler2DRect_Type(new Type("sampler2DRect"))
, fSampler1DArray_Type(new Type("sampler1DArray"))
@@ -169,6 +170,7 @@ public:
const std::unique_ptr<Type> fSampler1D_Type;
const std::unique_ptr<Type> fSampler2D_Type;
const std::unique_ptr<Type> fSampler3D_Type;
+ const std::unique_ptr<Type> fSamplerExternalOES_Type;
const std::unique_ptr<Type> fSamplerCube_Type;
const std::unique_ptr<Type> fSampler2DRect_Type;
const std::unique_ptr<Type> fSampler1DArray_Type;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index da0bcb903c..58cf7d3c36 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -14,8 +14,11 @@
#include "ir/SkSLExpressionStatement.h"
#include "ir/SkSLExtension.h"
#include "ir/SkSLIndexExpression.h"
+#include "ir/SkSLModifiersDeclaration.h"
#include "ir/SkSLVariableReference.h"
+#define SK_FRAGCOLOR_BUILTIN 10001
+
namespace SkSL {
void GLSLCodeGenerator::write(const char* s) {
@@ -66,7 +69,7 @@ void GLSLCodeGenerator::writeType(const Type& type) {
this->writeLine("struct " + type.name() + " {");
fIndentation++;
for (const auto& f : type.fields()) {
- this->writeModifiers(f.fModifiers);
+ this->writeModifiers(f.fModifiers, false);
// sizes (which must be static in structs) are part of the type name here
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
@@ -124,7 +127,42 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren
}
}
+static bool is_abs(Expression& expr) {
+ if (expr.fKind != Expression::kFunctionCall_Kind) {
+ return false;
+ }
+ return ((FunctionCall&) expr).fFunction.fName == "abs";
+}
+
+// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
+// Tegra3 compiler bug.
+void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
+ ASSERT(!fCaps.fCanUseMinAndAbsTogether);
+ std::string tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
+ std::string tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
+ this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n";
+ this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n";
+ this->write("((" + tmpVar1 + " = ");
+ this->writeExpression(absExpr, kTopLevel_Precedence);
+ this->write(") < (" + tmpVar2 + " = ");
+ this->writeExpression(otherExpr, kAssignment_Precedence);
+ this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
+}
+
void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
+ if (!fCaps.fCanUseMinAndAbsTogether && c.fFunction.fName == "min") {
+ ASSERT(c.fArguments.size() == 2);
+ if (is_abs(*c.fArguments[0])) {
+ this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
+ return;
+ }
+ if (is_abs(*c.fArguments[1])) {
+ // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will
+ // ever end up mattering, but it's worth calling out.
+ this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]);
+ return;
+ }
+ }
this->write(c.fFunction.fName + "(");
const char* separator = "";
for (const auto& arg : c.fArguments) {
@@ -147,7 +185,15 @@ void GLSLCodeGenerator::writeConstructor(const Constructor& c) {
}
void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
- this->write(ref.fVariable.fName);
+ if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN) {
+ if (fCaps.fMustDeclareFragmentShaderOutput) {
+ this->write("sk_FragColor");
+ } else {
+ this->write("gl_FragColor");
+ }
+ } else {
+ this->write(ref.fVariable.fName);
+ }
}
void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
@@ -270,7 +316,11 @@ void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
}
void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) {
- this->write(to_string(i.fValue));
+ if (i.fType == *fContext.fUInt_Type) {
+ this->write(to_string(i.fValue & 0xffffffff) + "u");
+ } else {
+ this->write(to_string((int32_t) i.fValue));
+ }
}
void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
@@ -284,28 +334,99 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
for (const auto& param : f.fDeclaration.fParameters) {
this->write(separator);
separator = ", ";
- this->writeModifiers(param->fModifiers);
- this->writeType(param->fType);
+ this->writeModifiers(param->fModifiers, false);
+ std::vector<int> sizes;
+ const Type* type = &param->fType;
+ while (type->kind() == Type::kArray_Kind) {
+ sizes.push_back(type->columns());
+ type = &type->componentType();
+ }
+ this->writeType(*type);
this->write(" " + param->fName);
+ for (int s : sizes) {
+ if (s <= 0) {
+ this->write("[]");
+ } else {
+ this->write("[" + to_string(s) + "]");
+ }
+ }
}
- this->write(") ");
- this->writeBlock(*f.fBody);
- this->writeLine();
+ this->writeLine(") {");
+
+ fFunctionHeader = "";
+ std::ostream* oldOut = fOut;
+ std::stringstream buffer;
+ fOut = &buffer;
+ fIndentation++;
+ for (const auto& s : f.fBody->fStatements) {
+ this->writeStatement(*s);
+ this->writeLine();
+ }
+ fIndentation--;
+ this->writeLine("}");
+
+ fOut = oldOut;
+ this->write(fFunctionHeader);
+ this->write(buffer.str());
}
-void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) {
- this->write(modifiers.description());
+void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
+ bool globalContext) {
+ if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
+ this->write("noperspective ");
+ }
+ if (modifiers.fFlags & Modifiers::kFlat_Flag) {
+ this->write("flat ");
+ }
+ std::string layout = modifiers.fLayout.description();
+ if (layout.length()) {
+ this->write(layout + " ");
+ }
+ if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
+ (modifiers.fFlags & Modifiers::kOut_Flag)) {
+ this->write("inout ");
+ } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
+ if (globalContext && fCaps.fVersion < 130) {
+ this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
+ : "varying ");
+ } else {
+ this->write("in ");
+ }
+ } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
+ if (globalContext && fCaps.fVersion < 130) {
+ this->write("varying ");
+ } else {
+ this->write("out ");
+ }
+ }
+ if (modifiers.fFlags & Modifiers::kUniform_Flag) {
+ this->write("uniform ");
+ }
+ if (modifiers.fFlags & Modifiers::kConst_Flag) {
+ this->write("const ");
+ }
+ if (fCaps.fUsesPrecisionModifiers) {
+ if (modifiers.fFlags & Modifiers::kLowp_Flag) {
+ this->write("lowp ");
+ }
+ if (modifiers.fFlags & Modifiers::kMediump_Flag) {
+ this->write("mediump ");
+ }
+ if (modifiers.fFlags & Modifiers::kHighp_Flag) {
+ this->write("highp ");
+ }
+ }
}
void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
if (intf.fVariable.fName == "gl_PerVertex") {
return;
}
- this->writeModifiers(intf.fVariable.fModifiers);
+ this->writeModifiers(intf.fVariable.fModifiers, true);
this->writeLine(intf.fVariable.fType.name() + " {");
fIndentation++;
for (const auto& f : intf.fVariable.fType.fields()) {
- this->writeModifiers(f.fModifiers);
+ this->writeModifiers(f.fModifiers, false);
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
}
@@ -313,9 +434,9 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
this->writeLine("};");
}
-void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) {
+void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
ASSERT(decl.fVars.size() > 0);
- this->writeModifiers(decl.fVars[0].fVar->fModifiers);
+ this->writeModifiers(decl.fVars[0].fVar->fModifiers, global);
this->writeType(decl.fBaseType);
std::string separator = " ";
for (const auto& var : decl.fVars) {
@@ -325,7 +446,9 @@ void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) {
this->write(var.fVar->fName);
for (const auto& size : var.fSizes) {
this->write("[");
- this->writeExpression(*size, kTopLevel_Precedence);
+ if (size) {
+ this->writeExpression(*size, kTopLevel_Precedence);
+ }
this->write("]");
}
if (var.fValue) {
@@ -349,7 +472,7 @@ void GLSLCodeGenerator::writeStatement(const Statement& s) {
this->writeReturnStatement((ReturnStatement&) s);
break;
case Statement::kVarDeclarations_Kind:
- this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
+ this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
break;
case Statement::kIf_Kind:
this->writeIfStatement((IfStatement&) s);
@@ -444,22 +567,57 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) {
ASSERT(fOut == nullptr);
fOut = &out;
+ fProgramKind = program.fKind;
this->write("#version " + to_string(fCaps.fVersion));
- if (fCaps.fStandard == GLCaps::kGLES_Standard) {
+ if (fCaps.fStandard == GLCaps::kGLES_Standard && fCaps.fVersion >= 300) {
this->write(" es");
+ } else if (fCaps.fIsCoreProfile) {
+ this->write(" core");
}
this->writeLine();
for (const auto& e : program.fElements) {
+ if (e->fKind == ProgramElement::kExtension_Kind) {
+ this->writeExtension((Extension&) *e);
+ }
+ }
+ if (fCaps.fStandard == GLCaps::kGLES_Standard) {
+ this->write("precision ");
+ switch (program.fDefaultPrecision) {
+ case Modifiers::kLowp_Flag:
+ this->write("lowp");
+ break;
+ case Modifiers::kMediump_Flag:
+ this->write("mediump");
+ break;
+ case Modifiers::kHighp_Flag:
+ this->write("highp");
+ break;
+ default:
+ ASSERT(false);
+ this->write("<error>");
+ }
+ this->writeLine(" float;");
+ }
+ for (const auto& e : program.fElements) {
switch (e->fKind) {
case ProgramElement::kExtension_Kind:
- this->writeExtension((Extension&) *e);
break;
case ProgramElement::kVar_Kind: {
VarDeclarations& decl = (VarDeclarations&) *e;
- if (decl.fVars.size() > 0 &&
- decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin == -1) {
- this->writeVarDeclarations(decl);
- this->writeLine();
+ if (decl.fVars.size() > 0) {
+ int builtin = decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin;
+ if (builtin == -1) {
+ // normal var
+ this->writeVarDeclarations(decl, true);
+ this->writeLine();
+ } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
+ fCaps.fMustDeclareFragmentShaderOutput) {
+ this->write("out ");
+ if (fCaps.fUsesPrecisionModifiers) {
+ this->write("mediump ");
+ }
+ this->writeLine("vec4 sk_FragColor;");
+ }
}
break;
}
@@ -469,6 +627,10 @@ void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out)
case ProgramElement::kFunction_Kind:
this->writeFunction((FunctionDefinition&) *e);
break;
+ case ProgramElement::kModifiers_Kind:
+ this->writeModifiers(((ModifiersDeclaration&) *e).fModifiers, true);
+ this->writeLine(";");
+ break;
default:
printf("%s\n", e->description().c_str());
ABORT("unsupported program element");
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index 3534affccc..9851123708 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -50,6 +50,11 @@ struct GLCaps {
kGL_Standard,
kGLES_Standard
} fStandard;
+ bool fIsCoreProfile;
+ bool fUsesPrecisionModifiers;
+ bool fMustDeclareFragmentShaderOutput;
+ // The Tegra3 compiler will sometimes never return if we have min(abs(x), y)
+ bool fCanUseMinAndAbsTogether;
};
/**
@@ -81,6 +86,8 @@ public:
GLSLCodeGenerator(const Context* context, GLCaps caps)
: fContext(*context)
, fCaps(caps)
+ , fOut(nullptr)
+ , fVarCount(0)
, fIndentation(0)
, fAtLineStart(true) {}
@@ -111,11 +118,11 @@ private:
void writeLayout(const Layout& layout);
- void writeModifiers(const Modifiers& modifiers);
+ void writeModifiers(const Modifiers& modifiers, bool globalContext);
void writeGlobalVars(const VarDeclaration& vs);
- void writeVarDeclarations(const VarDeclarations& decl);
+ void writeVarDeclarations(const VarDeclarations& decl, bool global);
void writeVariableReference(const VariableReference& ref);
@@ -123,6 +130,8 @@ private:
void writeIntrinsicCall(const FunctionCall& c);
+ void writeMinAbsHack(Expression& absExpr, Expression& otherExpr);
+
void writeFunctionCall(const FunctionCall& c);
void writeConstructor(const Constructor& c);
@@ -164,6 +173,9 @@ private:
const Context& fContext;
const GLCaps fCaps;
std::ostream* fOut;
+ std::string fFunctionHeader;
+ Program::Kind fProgramKind;
+ int fVarCount;
int fIndentation;
bool fAtLineStart;
// Keeps track of which struct types we have written. Given that we are unlikely to ever write
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index c30cac17d7..d64684e62d 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -189,7 +189,11 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
}
value = this->coerce(std::move(value), *type);
}
- if ("gl_FragCoord" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) {
+ if ("sk_FragColor" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) {
+ // already defined, ignore
+ } else if ((*fSymbolTable)[varDecl.fName] &&
+ (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
+ ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
// already defined, just update the modifiers
Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
old->fModifiers = var->fModifiers;
@@ -203,6 +207,12 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
std::move(variables)));
}
+std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
+ const ASTModifiersDeclaration& m) {
+ Modifiers modifiers = this->convertModifiers(m.fModifiers);
+ return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
+}
+
std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
*fContext.fBool_Type);
@@ -419,8 +429,9 @@ std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti
for (size_t i = 0; i < parameters.size(); i++) {
if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
fErrors.error(f.fPosition, "modifiers on parameter " +
- to_string(i + 1) + " differ between " +
- "declaration and definition");
+ to_string((uint64_t) i + 1) +
+ " differ between declaration and "
+ "definition");
return nullptr;
}
}
@@ -616,8 +627,9 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
ASSERT(ctor);
return this->call(Position(), std::move(ctor), std::move(args));
}
- ABORT("cannot coerce %s to %s", expr->fType.description().c_str(),
- type.description().c_str());
+ std::vector<std::unique_ptr<Expression>> args;
+ args.push_back(std::move(expr));
+ return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
}
static bool is_matrix_multiply(const Type& left, const Type& right) {
@@ -832,12 +844,12 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
std::vector<std::unique_ptr<Expression>> arguments) {
if (function.fParameters.size() != arguments.size()) {
std::string msg = "call to '" + function.fName + "' expected " +
- to_string(function.fParameters.size()) +
+ to_string((uint64_t) function.fParameters.size()) +
" argument";
if (function.fParameters.size() != 1) {
msg += "s";
}
- msg += ", but found " + to_string(arguments.size());
+ msg += ", but found " + to_string((uint64_t) arguments.size());
fErrors.error(position, msg);
return nullptr;
}
@@ -921,7 +933,8 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
std::vector<std::unique_ptr<Expression>> args) {
// FIXME: add support for structs and arrays
Type::Kind kind = type.kind();
- if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind) {
+ if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind &&
+ kind != Type::kArray_Kind) {
fErrors.error(position, "cannot construct '" + type.description() + "'");
return nullptr;
}
@@ -938,7 +951,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
if (args.size() != 1) {
fErrors.error(position, "invalid arguments to '" + type.description() +
"' constructor, (expected exactly 1 argument, but found " +
- to_string(args.size()) + ")");
+ to_string((uint64_t) args.size()) + ")");
}
if (args[0]->fType == *fContext.fBool_Type) {
std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
@@ -953,6 +966,18 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
"' constructor (expected a number or bool, but found '" +
args[0]->fType.description() + "')");
}
+ if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
+ type == *fContext.fUInt_Type)) {
+ return std::unique_ptr<Expression>(new IntLiteral(fContext,
+ position,
+ ((IntLiteral&) *args[0]).fValue,
+ &type));
+ }
+ } else if (kind == Type::kArray_Kind) {
+ const Type& base = type.componentType();
+ for (size_t i = 0; i < args.size(); i++) {
+ args[i] = this->coerce(std::move(args[i]), base);
+ }
} else {
ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
int actual = 0;
@@ -1037,7 +1062,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
}
this->markWrittenTo(*base);
break;
- case Token::NOT:
+ case Token::LOGICALNOT:
if (base->fType != *fContext.fBool_Type) {
fErrors.error(expression.fPosition,
"'" + Token::OperatorName(expression.fOperator) +
@@ -1045,6 +1070,14 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
return nullptr;
}
break;
+ case Token::BITWISENOT:
+ if (base->fType != *fContext.fInt_Type) {
+ fErrors.error(expression.fPosition,
+ "'" + Token::OperatorName(expression.fOperator) +
+ "' cannot operate on '" + base->fType.description() + "'");
+ return nullptr;
+ }
+ break;
default:
ABORT("unsupported prefix operator\n");
}
@@ -1054,7 +1087,8 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
const ASTExpression& index) {
- if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind) {
+ if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
+ base->fType.kind() != Type::kVector_Kind) {
fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
"'");
return nullptr;
@@ -1063,9 +1097,11 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression
if (!converted) {
return nullptr;
}
- converted = this->coerce(std::move(converted), *fContext.fInt_Type);
- if (!converted) {
- return nullptr;
+ if (converted->fType != *fContext.fUInt_Type) {
+ converted = this->coerce(std::move(converted), *fContext.fInt_Type);
+ if (!converted) {
+ return nullptr;
+ }
}
return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
std::move(converted)));
@@ -1143,9 +1179,21 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
return nullptr;
}
switch (expression.fSuffix->fKind) {
- case ASTSuffix::kIndex_Kind:
- return this->convertIndex(std::move(base),
- *((ASTIndexSuffix&) *expression.fSuffix).fExpression);
+ case ASTSuffix::kIndex_Kind: {
+ const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get();
+ if (expr) {
+ return this->convertIndex(std::move(base), *expr);
+ } else if (base->fKind == Expression::kTypeReference_Kind) {
+ const Type& oldType = ((TypeReference&) *base).fValue;
+ Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
+ -1);
+ fSymbolTable->takeOwnership(newType);
+ return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
+ *newType));
+ } else {
+ fErrors.error(expression.fPosition, "'[]' must follow a type name");
+ }
+ }
case ASTSuffix::kCall_Kind: {
auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
std::vector<std::unique_ptr<Expression>> arguments;
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index a3ff210b45..834ed8de81 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -25,6 +25,7 @@
#include "ast/SkSLASTIfStatement.h"
#include "ast/SkSLASTInterfaceBlock.h"
#include "ast/SkSLASTModifiers.h"
+#include "ast/SkSLASTModifiersDeclaration.h"
#include "ast/SkSLASTPrefixExpression.h"
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTStatement.h"
@@ -39,6 +40,7 @@
#include "ir/SkSLFunctionDefinition.h"
#include "ir/SkSLInterfaceBlock.h"
#include "ir/SkSLModifiers.h"
+#include "ir/SkSLModifiersDeclaration.h"
#include "ir/SkSLSymbolTable.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLType.h"
@@ -61,6 +63,8 @@ public:
std::unique_ptr<FunctionDefinition> convertFunction(const ASTFunction& f);
std::unique_ptr<Statement> convertStatement(const ASTStatement& statement);
std::unique_ptr<Expression> convertExpression(const ASTExpression& expression);
+ std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration(
+ const ASTModifiersDeclaration& m);
private:
void pushSymbolTable();
diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp
index 24fbb6c260..de1b9819d5 100644
--- a/src/sksl/SkSLMain.cpp
+++ b/src/sksl/SkSLMain.cpp
@@ -9,6 +9,24 @@
#include <fstream>
#include "SkSLCompiler.h"
+bool endsWith(const std::string& s, const std::string& ending) {
+ if (s.length() >= ending.length()) {
+ return (0 == s.compare(s.length() - ending.length(), ending.length(), ending));
+ }
+ return false;
+}
+
+static SkSL::GLCaps default_caps() {
+ return {
+ 400,
+ SkSL::GLCaps::kGL_Standard,
+ false, // isCoreProfile
+ false, // usesPrecisionModifiers;
+ false, // mustDeclareFragmentShaderOutput
+ true // canUseMinAndAbsTogether
+ };
+}
+
/**
* Very simple standalone executable to facilitate testing.
*/
@@ -35,14 +53,30 @@ int main(int argc, const char** argv) {
printf("error reading '%s'\n", argv[1]);
exit(2);
}
- std::ofstream out(argv[2], std::ofstream::binary);
- SkSL::Compiler compiler;
- if (!compiler.toSPIRV(kind, text, out)) {
- printf("%s", compiler.errorText().c_str());
- exit(3);
- }
- if (out.rdstate()) {
- printf("error writing '%s'\n", argv[2]);
- exit(4);
+ std::string name(argv[2]);
+ if (endsWith(name, ".spirv")) {
+ std::ofstream out(argv[2], std::ofstream::binary);
+ SkSL::Compiler compiler;
+ if (!compiler.toSPIRV(kind, text, out)) {
+ printf("%s", compiler.errorText().c_str());
+ exit(3);
+ }
+ if (out.rdstate()) {
+ printf("error writing '%s'\n", argv[2]);
+ exit(4);
+ }
+ } else if (endsWith(name, ".glsl")) {
+ std::ofstream out(argv[2], std::ofstream::binary);
+ SkSL::Compiler compiler;
+ if (!compiler.toGLSL(kind, text, default_caps(), out)) {
+ printf("%s", compiler.errorText().c_str());
+ exit(3);
+ }
+ if (out.rdstate()) {
+ printf("error writing '%s'\n", argv[2]);
+ exit(4);
+ }
+ } else {
+ printf("expected output filename to end with '.spirv' or '.glsl'");
}
}
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index b240e4501e..29f1dbd178 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -56,7 +56,9 @@
#include "ast/SkSLASTIndexSuffix.h"
#include "ast/SkSLASTInterfaceBlock.h"
#include "ast/SkSLASTIntLiteral.h"
+#include "ast/SkSLASTModifiersDeclaration.h"
#include "ast/SkSLASTParameter.h"
+#include "ast/SkSLASTPrecision.h"
#include "ast/SkSLASTPrefixExpression.h"
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTStatement.h"
@@ -97,9 +99,13 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
switch (this->peek().fKind) {
case Token::END_OF_FILE:
return result;
- case Token::PRECISION:
- this->precision();
+ case Token::PRECISION: {
+ std::unique_ptr<ASTDeclaration> precision = this->precision();
+ if (precision) {
+ result.push_back(std::move(precision));
+ }
break;
+ }
case Token::DIRECTIVE: {
std::unique_ptr<ASTDeclaration> decl = this->directive();
if (decl) {
@@ -163,29 +169,37 @@ bool Parser::isType(std::string name) {
}
/* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */
-void Parser::precision() {
+std::unique_ptr<ASTDeclaration> Parser::precision() {
if (!this->expect(Token::PRECISION, "'precision'")) {
- return;
+ return nullptr;
}
+ Modifiers::Flag result;
Token p = this->nextToken();
switch (p.fKind) {
- case Token::LOWP: // fall through
- case Token::MEDIUMP: // fall through
+ case Token::LOWP:
+ result = Modifiers::kLowp_Flag;
+ break;
+ case Token::MEDIUMP:
+ result = Modifiers::kMediump_Flag;
+ break;
case Token::HIGHP:
- // ignored for now
+ result = Modifiers::kHighp_Flag;
break;
default:
this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
p.fText + "'");
- return;
+ return nullptr;
}
+ // FIXME handle the type
if (!this->type()) {
- return;
+ return nullptr;
}
this->expect(Token::SEMICOLON, "';'");
+ return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result));
}
-/* DIRECTIVE(#version) INT_LITERAL | DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
+/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
+ DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
std::unique_ptr<ASTDeclaration> Parser::directive() {
Token start;
if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
@@ -193,7 +207,12 @@ std::unique_ptr<ASTDeclaration> Parser::directive() {
}
if (start.fText == "#version") {
this->expect(Token::INT_LITERAL, "a version number");
- // ignored for now
+ Token next = this->peek();
+ if (next.fText == "es" || next.fText == "compatibility") {
+ this->nextToken();
+ }
+ // version is ignored for now; it will eventually become an error when we stop pretending
+ // to be GLSL
return nullptr;
} else if (start.fText == "#extension") {
Token name;
@@ -227,6 +246,10 @@ std::unique_ptr<ASTDeclaration> Parser::declaration() {
if (lookahead.fKind == Token::STRUCT) {
return this->structVarDeclaration(modifiers);
}
+ if (lookahead.fKind == Token::SEMICOLON) {
+ this->nextToken();
+ return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modifiers));
+ }
std::unique_ptr<ASTType> type(this->type());
if (!type) {
return nullptr;
@@ -477,10 +500,13 @@ ASTLayout Parser::layout() {
int set = -1;
int builtin = -1;
bool originUpperLeft = false;
+ bool overrideCoverage = false;
+ bool blendSupportAllEquations = false;
if (this->peek().fKind == Token::LAYOUT) {
this->nextToken();
if (!this->expect(Token::LPAREN, "'('")) {
- return ASTLayout(location, binding, index, set, builtin, originUpperLeft);
+ return ASTLayout(location, binding, index, set, builtin, originUpperLeft,
+ overrideCoverage, blendSupportAllEquations);
}
for (;;) {
Token t = this->nextToken();
@@ -496,6 +522,10 @@ ASTLayout Parser::layout() {
builtin = this->layoutInt();
} else if (t.fText == "origin_upper_left") {
originUpperLeft = true;
+ } else if (t.fText == "override_coverage") {
+ overrideCoverage = true;
+ } else if (t.fText == "blend_support_all_equations") {
+ blendSupportAllEquations = true;
} else {
this->error(t.fPosition, ("'" + t.fText +
"' is not a valid layout qualifier").c_str());
@@ -509,7 +539,8 @@ ASTLayout Parser::layout() {
}
}
}
- return ASTLayout(location, binding, index, set, builtin, originUpperLeft);
+ return ASTLayout(location, binding, index, set, builtin, originUpperLeft, overrideCoverage,
+ blendSupportAllEquations);
}
/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */
@@ -1211,10 +1242,11 @@ std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() {
/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
std::unique_ptr<ASTExpression> Parser::unaryExpression() {
switch (this->peek().fKind) {
- case Token::PLUS: // fall through
- case Token::MINUS: // fall through
- case Token::NOT: // fall through
- case Token::PLUSPLUS: // fall through
+ case Token::PLUS: // fall through
+ case Token::MINUS: // fall through
+ case Token::LOGICALNOT: // fall through
+ case Token::BITWISENOT: // fall through
+ case Token::PLUSPLUS: // fall through
case Token::MINUSMINUS: {
Token t = this->nextToken();
std::unique_ptr<ASTExpression> expr = this->unaryExpression();
@@ -1254,12 +1286,16 @@ std::unique_ptr<ASTExpression> Parser::postfixExpression() {
}
}
-/* LBRACKET expression RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
+/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
PLUSPLUS | MINUSMINUS */
std::unique_ptr<ASTSuffix> Parser::suffix() {
Token next = this->nextToken();
switch (next.fKind) {
case Token::LBRACKET: {
+ if (this->peek().fKind == Token::RBRACKET) {
+ this->nextToken();
+ return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition));
+ }
std::unique_ptr<ASTExpression> e = this->expression();
if (!e) {
return nullptr;
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index 75f304bc8c..d1ae0d0e9f 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -35,6 +35,7 @@ struct ASTInterfaceBlock;
struct ASTLayout;
struct ASTModifiers;
struct ASTParameter;
+struct ASTPrecision;
struct ASTReturnStatement;
struct ASTStatement;
struct ASTSuffix;
@@ -100,7 +101,7 @@ private:
// don't need to call any of these outside of the parser. The function declarations in the .cpp
// file have comments describing the grammar rules.
- void precision();
+ std::unique_ptr<ASTDeclaration> precision();
std::unique_ptr<ASTDeclaration> directive();
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index d17e3c42a2..5403ba3628 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -15,6 +15,7 @@
#include "ir/SkSLExtension.h"
#include "ir/SkSLIndexExpression.h"
#include "ir/SkSLVariableReference.h"
+#include "SkSLCompiler.h"
namespace SkSL {
@@ -2162,13 +2163,19 @@ SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, std::
lv->store(result, out);
return result;
}
- case Token::NOT: {
+ case Token::LOGICALNOT: {
ASSERT(p.fOperand->fType == *fContext.fBool_Type);
SpvId result = this->nextId();
this->writeInstruction(SpvOpLogicalNot, this->getType(p.fOperand->fType), result,
this->writeExpression(*p.fOperand, out), out);
return result;
}
+ case Token::BITWISENOT: {
+ SpvId result = this->nextId();
+ this->writeInstruction(SpvOpNot, this->getType(p.fOperand->fType), result,
+ this->writeExpression(*p.fOperand, out), out);
+ return result;
+ }
default:
ABORT("unsupported prefix expression: %s", p.description().c_str());
}
@@ -2321,7 +2328,7 @@ void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target) {
this->writeInstruction(SpvOpDecorate, target, SpvDecorationDescriptorSet, layout.fSet,
fDecorationBuffer);
}
- if (layout.fBuiltin >= 0) {
+ if (layout.fBuiltin >= 0 && layout.fBuiltin != SK_FRAGCOLOR_BUILTIN) {
this->writeInstruction(SpvOpDecorate, target, SpvDecorationBuiltIn, layout.fBuiltin,
fDecorationBuffer);
}
@@ -2363,10 +2370,19 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
return result;
}
-void SPIRVCodeGenerator::writeGlobalVars(const VarDeclarations& decl, std::ostream& out) {
+#define BUILTIN_IGNORE 9999
+void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl,
+ std::ostream& out) {
for (size_t i = 0; i < decl.fVars.size(); i++) {
const VarDeclaration& varDecl = decl.fVars[i];
const Variable* var = varDecl.fVar;
+ if (var->fModifiers.fLayout.fBuiltin == BUILTIN_IGNORE) {
+ continue;
+ }
+ if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN &&
+ kind != Program::kFragment_Kind) {
+ continue;
+ }
if (!var->fIsReadFrom && !var->fIsWrittenTo &&
!(var->fModifiers.fFlags & (Modifiers::kIn_Flag |
Modifiers::kOut_Flag |
@@ -2562,7 +2578,8 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, std::ostream&
}
for (size_t i = 0; i < program.fElements.size(); i++) {
if (program.fElements[i]->fKind == ProgramElement::kVar_Kind) {
- this->writeGlobalVars(((VarDeclarations&) *program.fElements[i]), body);
+ this->writeGlobalVars(program.fKind, ((VarDeclarations&) *program.fElements[i]),
+ body);
}
}
for (size_t i = 0; i < program.fElements.size(); i++) {
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h
index e7b2b30232..2800a861b8 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -115,7 +115,7 @@ private:
SpvId writeFunction(const FunctionDefinition& f, std::ostream& out);
- void writeGlobalVars(const VarDeclarations& v, std::ostream& out);
+ void writeGlobalVars(Program::Kind kind, const VarDeclarations& v, std::ostream& out);
void writeVarDeclarations(const VarDeclarations& decl, std::ostream& out);
diff --git a/src/sksl/SkSLToken.h b/src/sksl/SkSLToken.h
index 29fa81e2e0..b8a364c269 100644
--- a/src/sksl/SkSLToken.h
+++ b/src/sksl/SkSLToken.h
@@ -49,10 +49,11 @@ struct Token {
BITWISEOR,
BITWISEXOR,
BITWISEAND,
+ BITWISENOT,
LOGICALOR,
LOGICALXOR,
LOGICALAND,
- NOT,
+ LOGICALNOT,
QUESTION,
COLON,
EQ,
@@ -111,9 +112,11 @@ struct Token {
case Token::PERCENT: return "%";
case Token::SHL: return "<<";
case Token::SHR: return ">>";
+ case Token::LOGICALNOT: return "!";
case Token::LOGICALAND: return "&&";
case Token::LOGICALOR: return "||";
case Token::LOGICALXOR: return "^^";
+ case Token::BITWISENOT: return "~";
case Token::BITWISEAND: return "&";
case Token::BITWISEOR: return "|";
case Token::BITWISEXOR: return "^";
@@ -139,7 +142,6 @@ struct Token {
case Token::BITWISEXOREQ: return "^=";
case Token::PLUSPLUS: return "++";
case Token::MINUSMINUS: return "--";
- case Token::NOT: return "!";
default:
ABORT("unsupported operator: %d\n", kind);
}
diff --git a/src/sksl/SkSLUtil.cpp b/src/sksl/SkSLUtil.cpp
index 327bffe4f1..51ad9fe808 100644
--- a/src/sksl/SkSLUtil.cpp
+++ b/src/sksl/SkSLUtil.cpp
@@ -9,7 +9,48 @@
namespace SkSL {
+std::string to_string(double value) {
+ std::stringstream buffer;
+ buffer << std::setprecision(std::numeric_limits<double>::digits10) << value;
+ std::string result = buffer.str();
+ if (result.find_last_of(".") == std::string::npos &&
+ result.find_last_of("e") == std::string::npos) {
+ result += ".0";
+ }
+ return result;
+}
+
+std::string to_string(int32_t value) {
+ std::stringstream buffer;
+ buffer << value;
+ return buffer.str();
+}
+
+std::string to_string(uint32_t value) {
+ std::stringstream buffer;
+ buffer << value;
+ return buffer.str();
+}
+
+std::string to_string(int64_t value) {
+ std::stringstream buffer;
+ buffer << value;
+ return buffer.str();
+}
+
+std::string to_string(uint64_t value) {
+ std::stringstream buffer;
+ buffer << value;
+ return buffer.str();
+}
+
int stoi(std::string s) {
+ if (s.size() > 2 && s[0] == '0' && s[1] == 'x') {
+ char* p;
+ int result = strtoul(s.substr(2).c_str(), &p, 16);
+ ASSERT(*p == 0);
+ return result;
+ }
return atoi(s.c_str());
}
@@ -18,6 +59,12 @@ double stod(std::string s) {
}
long stol(std::string s) {
+ if (s.size() > 2 && s[0] == '0' && s[1] == 'x') {
+ char* p;
+ long result = strtoul(s.substr(2).c_str(), &p, 16);
+ ASSERT(*p == 0);
+ return result;
+ }
return atol(s.c_str());
}
diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h
index 33611cde02..efffaaec01 100644
--- a/src/sksl/SkSLUtil.h
+++ b/src/sksl/SkSLUtil.h
@@ -19,11 +19,15 @@ namespace SkSL {
// our own definitions of certain std:: functions, because they are not always present on Android
-template <typename T> std::string to_string(T value) {
- std::stringstream buffer;
- buffer << std::setprecision(std::numeric_limits<T>::digits10) << value;
- return buffer.str();
-}
+std::string to_string(double value);
+
+std::string to_string(int32_t value);
+
+std::string to_string(uint32_t value);
+
+std::string to_string(int64_t value);
+
+std::string to_string(uint64_t value);
#if _MSC_VER
#define NORETURN __declspec(noreturn)
diff --git a/src/sksl/ast/SkSLASTDeclaration.h b/src/sksl/ast/SkSLASTDeclaration.h
index 8b55ecf832..70f0ebc72d 100644
--- a/src/sksl/ast/SkSLASTDeclaration.h
+++ b/src/sksl/ast/SkSLASTDeclaration.h
@@ -20,7 +20,9 @@ struct ASTDeclaration : public ASTPositionNode {
kVar_Kind,
kFunction_Kind,
kInterfaceBlock_Kind,
- kExtension_Kind
+ kExtension_Kind,
+ kPrecision_Kind,
+ kModifiers_Kind
};
ASTDeclaration(Position position, Kind kind)
diff --git a/src/sksl/ast/SkSLASTIndexSuffix.h b/src/sksl/ast/SkSLASTIndexSuffix.h
index 44d91fa4c4..755029b0a2 100644
--- a/src/sksl/ast/SkSLASTIndexSuffix.h
+++ b/src/sksl/ast/SkSLASTIndexSuffix.h
@@ -14,17 +14,27 @@
namespace SkSL {
/**
- * A bracketed expression, as in '[0]', indicating an array access.
+ * A bracketed expression, as in '[0]', indicating an array access. Empty brackets (as occur in
+ * 'float[](5, 6)' are represented with a null fExpression.
*/
struct ASTIndexSuffix : public ASTSuffix {
+ ASTIndexSuffix(Position position)
+ : INHERITED(position, ASTSuffix::kIndex_Kind)
+ , fExpression(nullptr) {}
+
ASTIndexSuffix(std::unique_ptr<ASTExpression> expression)
- : INHERITED(expression->fPosition, ASTSuffix::kIndex_Kind)
+ : INHERITED(expression ? expression->fPosition : Position(), ASTSuffix::kIndex_Kind)
, fExpression(std::move(expression)) {}
std::string description() const override {
- return "[" + fExpression->description() + "]";
+ if (fExpression) {
+ return "[" + fExpression->description() + "]";
+ } else {
+ return "[]";
+ }
}
+ // may be null
std::unique_ptr<ASTExpression> fExpression;
typedef ASTSuffix INHERITED;
diff --git a/src/sksl/ast/SkSLASTLayout.h b/src/sksl/ast/SkSLASTLayout.h
index 08d67531c3..515eb2bdbb 100644
--- a/src/sksl/ast/SkSLASTLayout.h
+++ b/src/sksl/ast/SkSLASTLayout.h
@@ -20,13 +20,16 @@ namespace SkSL {
*/
struct ASTLayout : public ASTNode {
// For all parameters, a -1 means no value
- ASTLayout(int location, int binding, int index, int set, int builtin, bool originUpperLeft)
+ ASTLayout(int location, int binding, int index, int set, int builtin, bool originUpperLeft,
+ bool overrideCoverage, bool blendSupportAllEquations)
: fLocation(location)
, fBinding(binding)
, fIndex(index)
, fSet(set)
, fBuiltin(builtin)
- , fOriginUpperLeft(originUpperLeft) {}
+ , fOriginUpperLeft(originUpperLeft)
+ , fOverrideCoverage(overrideCoverage)
+ , fBlendSupportAllEquations(blendSupportAllEquations) {}
std::string description() const {
std::string result;
@@ -55,6 +58,14 @@ struct ASTLayout : public ASTNode {
result += separator + "origin_upper_left";
separator = ", ";
}
+ if (fOverrideCoverage) {
+ result += separator + "override_coverage";
+ separator = ", ";
+ }
+ if (fBlendSupportAllEquations) {
+ result += separator + "blend_support_all_equations";
+ separator = ", ";
+ }
if (result.length() > 0) {
result = "layout (" + result + ")";
}
@@ -67,6 +78,8 @@ struct ASTLayout : public ASTNode {
const int fSet;
const int fBuiltin;
const bool fOriginUpperLeft;
+ const bool fOverrideCoverage;
+ const bool fBlendSupportAllEquations;
};
} // namespace
diff --git a/src/sksl/ast/SkSLASTModifiersDeclaration.h b/src/sksl/ast/SkSLASTModifiersDeclaration.h
new file mode 100644
index 0000000000..f5cc620899
--- /dev/null
+++ b/src/sksl/ast/SkSLASTModifiersDeclaration.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_ASTMODIFIERDECLARATION
+#define SKSL_ASTMODIFIERDECLARATION
+
+#include "SkSLASTDeclaration.h"
+#include "SkSLASTModifiers.h"
+
+namespace SkSL {
+
+/**
+ * A declaration that consists only of modifiers, e.g.:
+ *
+ * layout(blend_support_all_equations) out;
+ */
+struct ASTModifiersDeclaration : public ASTDeclaration {
+ ASTModifiersDeclaration(ASTModifiers modifiers)
+ : INHERITED(Position(), kModifiers_Kind)
+ , fModifiers(modifiers) {}
+
+ std::string description() const {
+ return fModifiers.description() + ";";
+ }
+
+ ASTModifiers fModifiers;
+
+ typedef ASTDeclaration INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/ast/SkSLASTPrecision.h b/src/sksl/ast/SkSLASTPrecision.h
new file mode 100644
index 0000000000..a7df57948e
--- /dev/null
+++ b/src/sksl/ast/SkSLASTPrecision.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_ASTPRECISION
+#define SKSL_ASTPRECISION
+
+#include "SkSLASTDeclaration.h"
+#include "../ir/SkSLModifiers.h"
+
+namespace SkSL {
+
+/**
+ * Represents a precision declaration (e.g. 'precision mediump float;').
+ */
+struct ASTPrecision : public ASTDeclaration {
+ // FIXME handle the type
+ ASTPrecision(Position position, Modifiers::Flag precision)
+ : INHERITED(position, kPrecision_Kind)
+ , fPrecision(precision) {}
+
+ std::string description() const {
+ switch (fPrecision) {
+ case Modifiers::kLowp_Flag: return "precision lowp float;";
+ case Modifiers::kMediump_Flag: return "precision mediump float;";
+ case Modifiers::kHighp_Flag: return "precision highp float;";
+ default:
+ ASSERT(false);
+ return "<error>";
+ }
+ ASSERT(false);
+ return "<error>";
+ }
+
+ const Modifiers::Flag fPrecision;
+
+ typedef ASTDeclaration INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/ir/SkSLIndexExpression.h b/src/sksl/ir/SkSLIndexExpression.h
index f5b0d09c2c..ea9af3d897 100644
--- a/src/sksl/ir/SkSLIndexExpression.h
+++ b/src/sksl/ir/SkSLIndexExpression.h
@@ -19,7 +19,7 @@ namespace SkSL {
static const Type& index_type(const Context& context, const Type& type) {
if (type.kind() == Type::kMatrix_Kind) {
if (type.componentType() == *context.fFloat_Type) {
- switch (type.columns()) {
+ switch (type.rows()) {
case 2: return *context.fVec2_Type;
case 3: return *context.fVec3_Type;
case 4: return *context.fVec4_Type;
@@ -27,7 +27,7 @@ static const Type& index_type(const Context& context, const Type& type) {
}
} else {
ASSERT(type.componentType() == *context.fDouble_Type);
- switch (type.columns()) {
+ switch (type.rows()) {
case 2: return *context.fDVec2_Type;
case 3: return *context.fDVec3_Type;
case 4: return *context.fDVec4_Type;
@@ -47,7 +47,7 @@ struct IndexExpression : public Expression {
: INHERITED(base->fPosition, kIndex_Kind, index_type(context, base->fType))
, fBase(std::move(base))
, fIndex(std::move(index)) {
- ASSERT(fIndex->fType == *context.fInt_Type);
+ ASSERT(fIndex->fType == *context.fInt_Type || fIndex->fType == *context.fUInt_Type);
}
std::string description() const override {
diff --git a/src/sksl/ir/SkSLIntLiteral.h b/src/sksl/ir/SkSLIntLiteral.h
index 2bc565712e..8921c283b5 100644
--- a/src/sksl/ir/SkSLIntLiteral.h
+++ b/src/sksl/ir/SkSLIntLiteral.h
@@ -18,8 +18,8 @@ namespace SkSL {
struct IntLiteral : public Expression {
// FIXME: we will need to revisit this if/when we add full support for both signed and unsigned
// 64-bit integers, but for right now an int64_t will hold every value we care about
- IntLiteral(const Context& context, Position position, int64_t value)
- : INHERITED(position, kIntLiteral_Kind, *context.fInt_Type)
+ IntLiteral(const Context& context, Position position, int64_t value, const Type* type = nullptr)
+ : INHERITED(position, kIntLiteral_Kind, type ? *type : *context.fInt_Type)
, fValue(value) {}
virtual std::string description() const override {
diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h
index d8dc98096f..24087d0612 100644
--- a/src/sksl/ir/SkSLLayout.h
+++ b/src/sksl/ir/SkSLLayout.h
@@ -22,15 +22,20 @@ struct Layout {
, fIndex(layout.fIndex)
, fSet(layout.fSet)
, fBuiltin(layout.fBuiltin)
- , fOriginUpperLeft(layout.fOriginUpperLeft) {}
+ , fOriginUpperLeft(layout.fOriginUpperLeft)
+ , fOverrideCoverage(layout.fOverrideCoverage)
+ , fBlendSupportAllEquations(layout.fBlendSupportAllEquations) {}
- Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft)
+ Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft,
+ bool overrideCoverage, bool blendSupportAllEquations)
: fLocation(location)
, fBinding(binding)
, fIndex(index)
, fSet(set)
, fBuiltin(builtin)
- , fOriginUpperLeft(originUpperLeft) {}
+ , fOriginUpperLeft(originUpperLeft)
+ , fOverrideCoverage(overrideCoverage)
+ , fBlendSupportAllEquations(blendSupportAllEquations) {}
std::string description() const {
std::string result;
@@ -59,6 +64,14 @@ struct Layout {
result += separator + "origin_upper_left";
separator = ", ";
}
+ if (fOverrideCoverage) {
+ result += separator + "override_coverage";
+ separator = ", ";
+ }
+ if (fBlendSupportAllEquations) {
+ result += separator + "blend_support_all_equations";
+ separator = ", ";
+ }
if (result.length() > 0) {
result = "layout (" + result + ")";
}
@@ -66,11 +79,14 @@ struct Layout {
}
bool operator==(const Layout& other) const {
- return fLocation == other.fLocation &&
- fBinding == other.fBinding &&
- fIndex == other.fIndex &&
- fSet == other.fSet &&
- fBuiltin == other.fBuiltin;
+ return fLocation == other.fLocation &&
+ fBinding == other.fBinding &&
+ fIndex == other.fIndex &&
+ fSet == other.fSet &&
+ fBuiltin == other.fBuiltin &&
+ fOriginUpperLeft == other.fOriginUpperLeft &&
+ fOverrideCoverage == other.fOverrideCoverage &&
+ fBlendSupportAllEquations == other.fBlendSupportAllEquations;
}
bool operator!=(const Layout& other) const {
@@ -85,6 +101,8 @@ struct Layout {
int fSet;
int fBuiltin;
bool fOriginUpperLeft;
+ bool fOverrideCoverage;
+ bool fBlendSupportAllEquations;
};
} // namespace
diff --git a/src/sksl/ir/SkSLModifiersDeclaration.h b/src/sksl/ir/SkSLModifiersDeclaration.h
new file mode 100644
index 0000000000..0066fab877
--- /dev/null
+++ b/src/sksl/ir/SkSLModifiersDeclaration.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_MODIFIERDECLARATION
+#define SKSL_MODIFIERDECLARATION
+
+#include "SkSLProgramElement.h"
+#include "SkSLModifiers.h"
+
+namespace SkSL {
+
+/**
+ * A declaration that consists only of modifiers, e.g.:
+ *
+ * layout(blend_support_all_equations) out;
+ */
+struct ModifiersDeclaration : public ProgramElement {
+ ModifiersDeclaration(Modifiers modifiers)
+ : INHERITED(Position(), kModifiers_Kind)
+ , fModifiers(modifiers) {}
+
+ std::string description() const {
+ return fModifiers.description() + ";";
+ }
+
+ Modifiers fModifiers;
+
+ typedef ProgramElement INHERITED;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index 205db6e932..8393341269 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -11,6 +11,7 @@
#include <vector>
#include <memory>
+#include "SkSLModifiers.h"
#include "SkSLProgramElement.h"
#include "SkSLSymbolTable.h"
@@ -25,14 +26,18 @@ struct Program {
kVertex_Kind
};
- Program(Kind kind, std::vector<std::unique_ptr<ProgramElement>> elements,
+ Program(Kind kind,
+ Modifiers::Flag defaultPrecision,
+ std::vector<std::unique_ptr<ProgramElement>> elements,
std::shared_ptr<SymbolTable> symbols)
: fKind(kind)
+ , fDefaultPrecision(defaultPrecision)
, fElements(std::move(elements))
, fSymbols(symbols) {}
Kind fKind;
-
+ // FIXME handle different types; currently it assumes this is for floats
+ Modifiers::Flag fDefaultPrecision;
std::vector<std::unique_ptr<ProgramElement>> fElements;
std::shared_ptr<SymbolTable> fSymbols;
};
diff --git a/src/sksl/ir/SkSLProgramElement.h b/src/sksl/ir/SkSLProgramElement.h
index 44fc340667..2f1ce77199 100644
--- a/src/sksl/ir/SkSLProgramElement.h
+++ b/src/sksl/ir/SkSLProgramElement.h
@@ -20,7 +20,8 @@ struct ProgramElement : public IRNode {
kVar_Kind,
kFunction_Kind,
kInterfaceBlock_Kind,
- kExtension_Kind
+ kExtension_Kind,
+ kModifiers_Kind
};
ProgramElement(Position position, Kind kind)
diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c
index 4993fac3a5..710b67bba5 100644
--- a/src/sksl/lex.sksl.c
+++ b/src/sksl/lex.sksl.c
@@ -4,7 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
+
#line 3 "lex.sksl.c"
#define YY_INT_ALIGNED short int
@@ -14,7 +14,7 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 37
+#define YY_FLEX_SUBMINOR_VERSION 35
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -52,6 +52,7 @@ typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
+typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@@ -59,6 +60,7 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -89,8 +91,6 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
-#endif /* ! C99 */
-
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
@@ -194,7 +194,7 @@ typedef size_t yy_size_t;
*/
#define YY_LESS_LINENO(n) \
do { \
- int yyl;\
+ yy_size_t yyl;\
for ( yyl = n; yyl < yyleng; ++yyl )\
if ( yytext[yyl] == '\n' )\
--yylineno;\
@@ -360,13 +360,13 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*/
#define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \
- yyleng = (size_t) (yy_cp - yy_bp); \
+ yyleng = (yy_size_t) (yy_cp - yy_bp); \
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 82
-#define YY_END_OF_BUFFER 83
+#define YY_NUM_RULES 84
+#define YY_END_OF_BUFFER 85
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -374,30 +374,31 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[201] =
+static yyconst flex_int16_t yy_accept[205] =
{ 0,
- 0, 0, 83, 81, 80, 80, 54, 81, 29, 45,
- 50, 31, 32, 43, 41, 38, 42, 37, 44, 4,
- 56, 77, 61, 57, 60, 55, 35, 36, 49, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 33, 48, 34, 80,
- 59, 30, 29, 68, 53, 73, 66, 39, 64, 40,
- 65, 1, 0, 78, 67, 2, 4, 0, 46, 63,
- 58, 62, 47, 72, 52, 29, 29, 29, 11, 29,
- 29, 29, 29, 29, 7, 16, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 71, 51, 30,
-
- 76, 0, 0, 0, 78, 1, 0, 0, 3, 69,
- 70, 75, 29, 29, 29, 29, 29, 29, 9, 29,
- 29, 29, 29, 29, 29, 17, 29, 29, 29, 29,
- 29, 29, 74, 0, 1, 79, 0, 0, 2, 29,
- 29, 29, 29, 8, 29, 24, 29, 29, 29, 21,
- 29, 29, 29, 29, 29, 5, 29, 29, 0, 1,
- 12, 20, 29, 29, 6, 23, 18, 29, 29, 29,
- 29, 29, 29, 29, 10, 29, 29, 27, 29, 29,
- 29, 15, 26, 29, 29, 14, 22, 29, 29, 19,
- 13, 29, 29, 29, 28, 29, 29, 29, 25, 0
-
+ 0, 0, 85, 83, 82, 82, 56, 83, 30, 46,
+ 51, 32, 33, 44, 42, 39, 43, 38, 45, 4,
+ 4, 58, 79, 63, 59, 62, 57, 36, 37, 50,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 34, 49, 35,
+ 52, 82, 61, 31, 30, 70, 55, 75, 68, 40,
+ 66, 41, 67, 1, 0, 80, 69, 2, 4, 0,
+ 0, 47, 65, 60, 64, 48, 74, 54, 30, 30,
+ 30, 12, 30, 30, 30, 30, 30, 8, 17, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+
+ 73, 53, 31, 78, 0, 0, 0, 80, 1, 0,
+ 0, 3, 5, 71, 72, 77, 30, 30, 30, 30,
+ 30, 30, 10, 30, 30, 30, 30, 30, 30, 18,
+ 30, 30, 30, 30, 30, 30, 76, 0, 1, 81,
+ 0, 0, 2, 30, 30, 30, 30, 9, 30, 25,
+ 30, 30, 30, 22, 30, 30, 30, 30, 30, 6,
+ 30, 30, 0, 1, 13, 21, 30, 30, 7, 24,
+ 19, 30, 30, 30, 30, 30, 30, 30, 11, 30,
+ 30, 28, 30, 30, 30, 16, 27, 30, 30, 15,
+ 23, 30, 30, 20, 14, 30, 30, 30, 29, 30,
+
+ 30, 30, 26, 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -406,16 +407,16 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 4, 1, 5, 6, 7, 8, 1, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 18, 19, 20,
- 21, 22, 23, 1, 6, 6, 6, 6, 24, 6,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 19, 20, 21,
+ 22, 23, 24, 1, 25, 25, 25, 25, 26, 25,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 25, 1, 26, 27, 6, 1, 28, 29, 30, 31,
+ 27, 1, 28, 29, 6, 1, 30, 31, 32, 33,
- 32, 33, 34, 35, 36, 6, 37, 38, 39, 40,
- 41, 42, 6, 43, 44, 45, 46, 47, 48, 6,
- 49, 6, 50, 51, 52, 1, 1, 1, 1, 1,
+ 34, 35, 36, 37, 38, 6, 39, 40, 41, 42,
+ 43, 44, 6, 45, 46, 47, 48, 49, 50, 51,
+ 52, 6, 53, 54, 55, 56, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -432,152 +433,158 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[53] =
+static yyconst flex_int32_t yy_meta[57] =
{ 0,
1, 1, 2, 1, 1, 3, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 4, 1, 1, 1,
- 1, 1, 1, 3, 1, 1, 1, 3, 3, 3,
+ 1, 1, 1, 1, 1, 1, 4, 4, 1, 1,
+ 1, 1, 1, 1, 5, 5, 1, 1, 1, 5,
+ 5, 5, 5, 5, 5, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 1,
- 1, 1
+ 3, 3, 1, 1, 1, 1
} ;
-static yyconst flex_int16_t yy_base[206] =
+static yyconst flex_int16_t yy_base[211] =
{ 0,
- 0, 0, 238, 239, 51, 53, 216, 0, 0, 215,
- 49, 239, 239, 214, 46, 239, 45, 217, 52, 45,
- 239, 239, 44, 212, 50, 239, 239, 239, 53, 189,
- 190, 40, 192, 47, 193, 46, 50, 196, 186, 180,
- 182, 192, 178, 179, 181, 185, 239, 61, 239, 81,
- 239, 0, 0, 239, 198, 239, 239, 239, 239, 239,
- 239, 70, 207, 0, 239, 72, 75, 81, 196, 239,
- 239, 239, 195, 239, 194, 182, 173, 168, 0, 167,
- 172, 181, 165, 173, 0, 165, 156, 156, 172, 160,
- 156, 168, 154, 155, 151, 160, 159, 239, 173, 0,
-
- 239, 89, 182, 176, 0, 91, 97, 174, 173, 239,
- 239, 239, 161, 72, 158, 155, 142, 140, 0, 149,
- 137, 141, 139, 144, 147, 0, 148, 131, 130, 143,
- 141, 135, 239, 155, 154, 239, 107, 153, 152, 131,
- 122, 130, 137, 0, 132, 0, 121, 117, 115, 0,
- 114, 116, 122, 114, 126, 0, 114, 122, 136, 135,
- 0, 0, 111, 107, 0, 0, 0, 104, 109, 103,
- 102, 105, 99, 100, 0, 96, 110, 0, 98, 97,
- 102, 0, 0, 98, 102, 0, 0, 90, 79, 0,
- 0, 88, 73, 65, 0, 69, 53, 65, 0, 239,
-
- 58, 122, 124, 128, 132
+ 0, 0, 273, 274, 55, 57, 250, 0, 0, 249,
+ 53, 274, 274, 248, 50, 274, 49, 47, 57, 52,
+ 59, 274, 274, 59, 247, 60, 274, 274, 274, 62,
+ 223, 224, 49, 226, 58, 227, 54, 64, 230, 220,
+ 214, 216, 226, 212, 213, 215, 219, 274, 68, 274,
+ 274, 97, 274, 0, 0, 274, 233, 274, 274, 274,
+ 274, 274, 274, 87, 243, 0, 274, 91, 97, 112,
+ 0, 231, 274, 274, 274, 230, 274, 229, 216, 207,
+ 202, 0, 201, 206, 215, 199, 207, 0, 199, 189,
+ 190, 206, 194, 190, 202, 188, 189, 185, 194, 193,
+
+ 274, 208, 0, 274, 120, 218, 212, 0, 93, 127,
+ 118, 125, 0, 274, 274, 274, 197, 100, 194, 191,
+ 178, 176, 0, 185, 173, 177, 175, 180, 183, 0,
+ 184, 167, 166, 179, 177, 171, 274, 131, 133, 274,
+ 140, 138, 142, 171, 162, 170, 177, 0, 172, 0,
+ 161, 157, 155, 0, 154, 156, 162, 154, 166, 0,
+ 154, 162, 144, 146, 0, 0, 153, 149, 0, 0,
+ 0, 146, 151, 145, 144, 147, 141, 142, 0, 138,
+ 147, 0, 122, 109, 102, 0, 0, 92, 94, 0,
+ 0, 86, 75, 0, 0, 84, 64, 55, 0, 59,
+
+ 46, 32, 0, 274, 162, 165, 168, 173, 178, 180
} ;
-static yyconst flex_int16_t yy_def[206] =
+static yyconst flex_int16_t yy_def[211] =
{ 0,
- 200, 1, 200, 200, 200, 200, 200, 201, 202, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 200, 200, 200, 200,
- 200, 203, 202, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 204, 205, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 200, 200, 203,
-
- 200, 200, 204, 204, 205, 200, 200, 200, 200, 200,
- 200, 200, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 200, 200, 200, 200, 200, 200, 200, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 200, 200,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 0,
-
- 200, 200, 200, 200, 200
+ 204, 1, 204, 204, 204, 204, 204, 205, 206, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 204, 204, 204,
+ 204, 204, 204, 207, 206, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 208, 209, 204, 204, 204, 204,
+ 210, 204, 204, 204, 204, 204, 204, 204, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+
+ 204, 204, 207, 204, 204, 208, 208, 209, 204, 204,
+ 204, 204, 210, 204, 204, 204, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 204, 204, 204, 204,
+ 204, 204, 204, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 204, 204, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+ 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
+
+ 206, 206, 206, 0, 204, 204, 204, 204, 204, 204
} ;
-static yyconst flex_int16_t yy_nxt[292] =
+static yyconst flex_int16_t yy_nxt[331] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 9, 27, 28, 29, 9, 30, 31,
- 32, 33, 34, 9, 35, 36, 9, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 9, 46, 9, 47,
- 48, 49, 50, 50, 50, 50, 55, 58, 60, 66,
- 52, 67, 63, 69, 70, 61, 59, 64, 68, 56,
- 72, 73, 65, 74, 81, 78, 68, 87, 85, 75,
- 79, 98, 50, 50, 82, 86, 62, 83, 106, 66,
- 88, 67, 108, 102, 108, 107, 199, 109, 68, 198,
-
- 134, 102, 134, 107, 197, 135, 68, 106, 138, 196,
- 138, 99, 195, 139, 137, 141, 142, 194, 159, 193,
- 159, 192, 137, 160, 53, 53, 100, 100, 103, 103,
- 103, 103, 105, 191, 105, 105, 190, 189, 188, 187,
- 186, 185, 184, 183, 182, 181, 180, 179, 178, 177,
- 176, 160, 160, 175, 174, 173, 172, 171, 170, 169,
- 168, 167, 166, 165, 164, 163, 162, 161, 139, 139,
- 135, 135, 158, 157, 156, 155, 154, 153, 152, 151,
- 150, 149, 148, 147, 146, 145, 144, 143, 140, 109,
- 109, 136, 104, 133, 132, 131, 130, 129, 128, 127,
-
+ 24, 25, 26, 27, 9, 9, 28, 29, 30, 9,
+ 31, 32, 33, 34, 35, 9, 36, 37, 9, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 9, 47,
+ 9, 9, 48, 49, 50, 51, 52, 52, 52, 52,
+ 57, 60, 62, 64, 64, 203, 68, 65, 69, 69,
+ 63, 61, 66, 68, 58, 69, 69, 70, 67, 72,
+ 73, 75, 76, 77, 70, 70, 81, 84, 88, 101,
+ 78, 82, 70, 90, 202, 89, 201, 85, 52, 52,
+
+ 86, 200, 71, 64, 64, 199, 91, 109, 109, 109,
+ 109, 68, 105, 69, 69, 198, 110, 197, 141, 196,
+ 105, 102, 70, 111, 110, 111, 141, 195, 112, 112,
+ 70, 138, 194, 138, 112, 112, 139, 139, 142, 193,
+ 142, 112, 112, 143, 143, 145, 146, 139, 139, 139,
+ 139, 163, 192, 163, 143, 143, 164, 164, 143, 143,
+ 164, 164, 164, 164, 54, 191, 54, 55, 55, 55,
+ 103, 103, 103, 106, 106, 106, 106, 106, 108, 190,
+ 108, 108, 108, 113, 113, 189, 188, 187, 186, 185,
+ 184, 183, 182, 181, 180, 179, 178, 177, 176, 175,
+
+ 174, 173, 172, 171, 170, 169, 168, 167, 166, 165,
+ 162, 161, 160, 159, 158, 157, 156, 155, 154, 153,
+ 152, 151, 150, 149, 148, 147, 144, 140, 107, 137,
+ 136, 135, 134, 133, 132, 131, 130, 129, 128, 127,
126, 125, 124, 123, 122, 121, 120, 119, 118, 117,
- 116, 115, 114, 113, 112, 111, 110, 104, 101, 97,
- 96, 95, 94, 93, 92, 91, 90, 89, 84, 80,
- 77, 76, 71, 62, 57, 54, 51, 200, 3, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200
-
+ 116, 115, 114, 107, 104, 100, 99, 98, 97, 96,
+ 95, 94, 93, 92, 87, 83, 80, 79, 74, 59,
+ 56, 53, 204, 3, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204
} ;
-static yyconst flex_int16_t yy_chk[292] =
+static yyconst flex_int16_t yy_chk[331] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 5, 5, 6, 6, 11, 15, 17, 20,
- 201, 20, 19, 23, 23, 17, 15, 19, 20, 11,
- 25, 25, 19, 29, 34, 32, 20, 37, 36, 29,
- 32, 48, 50, 50, 34, 36, 62, 34, 66, 67,
- 37, 67, 68, 62, 68, 66, 198, 68, 67, 197,
-
- 102, 62, 102, 66, 196, 102, 67, 106, 107, 194,
- 107, 48, 193, 107, 106, 114, 114, 192, 137, 189,
- 137, 188, 106, 137, 202, 202, 203, 203, 204, 204,
- 204, 204, 205, 185, 205, 205, 184, 181, 180, 179,
- 177, 176, 174, 173, 172, 171, 170, 169, 168, 164,
- 163, 160, 159, 158, 157, 155, 154, 153, 152, 151,
- 149, 148, 147, 145, 143, 142, 141, 140, 139, 138,
- 135, 134, 132, 131, 130, 129, 128, 127, 125, 124,
- 123, 122, 121, 120, 118, 117, 116, 115, 113, 109,
- 108, 104, 103, 99, 97, 96, 95, 94, 93, 92,
-
- 91, 90, 89, 88, 87, 86, 84, 83, 82, 81,
- 80, 78, 77, 76, 75, 73, 69, 63, 55, 46,
- 45, 44, 43, 42, 41, 40, 39, 38, 35, 33,
- 31, 30, 24, 18, 14, 10, 7, 3, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200
-
+ 1, 1, 1, 1, 1, 1, 5, 5, 6, 6,
+ 11, 15, 17, 18, 18, 202, 20, 19, 20, 20,
+ 17, 15, 19, 21, 11, 21, 21, 20, 19, 24,
+ 24, 26, 26, 30, 21, 20, 33, 35, 37, 49,
+ 30, 33, 21, 38, 201, 37, 200, 35, 52, 52,
+
+ 35, 198, 20, 64, 64, 197, 38, 68, 68, 109,
+ 109, 69, 64, 69, 69, 196, 68, 193, 109, 192,
+ 64, 49, 69, 70, 68, 70, 109, 189, 70, 70,
+ 69, 105, 188, 105, 111, 111, 105, 105, 110, 185,
+ 110, 112, 112, 110, 110, 118, 118, 138, 138, 139,
+ 139, 141, 184, 141, 142, 142, 141, 141, 143, 143,
+ 163, 163, 164, 164, 205, 183, 205, 206, 206, 206,
+ 207, 207, 207, 208, 208, 208, 208, 208, 209, 181,
+ 209, 209, 209, 210, 210, 180, 178, 177, 176, 175,
+ 174, 173, 172, 168, 167, 162, 161, 159, 158, 157,
+
+ 156, 155, 153, 152, 151, 149, 147, 146, 145, 144,
+ 136, 135, 134, 133, 132, 131, 129, 128, 127, 126,
+ 125, 124, 122, 121, 120, 119, 117, 107, 106, 102,
+ 100, 99, 98, 97, 96, 95, 94, 93, 92, 91,
+ 90, 89, 87, 86, 85, 84, 83, 81, 80, 79,
+ 78, 76, 72, 65, 57, 47, 46, 45, 44, 43,
+ 42, 41, 40, 39, 36, 34, 32, 31, 25, 14,
+ 10, 7, 3, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
+ 204, 204, 204, 204, 204, 204, 204, 204, 204, 204
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[83] =
+static yyconst flex_int32_t yy_rule_can_match_eol[85] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 1, 0, 0, };
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, };
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
@@ -600,7 +607,7 @@ static yyconst flex_int32_t yy_rule_can_match_eol[83] =
*/
#define YY_NO_UNISTD_H 1
-#line 598 "lex.sksl.c"
+#line 605 "lex.sksl.c"
#define INITIAL 0
@@ -685,10 +692,6 @@ int skslget_lineno (yyscan_t yyscanner );
void skslset_lineno (int line_number ,yyscan_t yyscanner );
-int skslget_column (yyscan_t yyscanner );
-
-void skslset_column (int column_no ,yyscan_t yyscanner );
-
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
@@ -731,7 +734,7 @@ static int input (yyscan_t yyscanner );
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -742,7 +745,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- size_t n; \
+ yy_size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -828,7 +831,7 @@ YY_DECL
#line 23 "sksl.flex"
-#line 826 "lex.sksl.c"
+#line 829 "lex.sksl.c"
if ( !yyg->yy_init )
{
@@ -881,13 +884,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 201 )
+ if ( yy_current_state >= 205 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_current_state != 200 );
+ while ( yy_current_state != 204 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;
@@ -898,7 +901,7 @@ yy_find_action:
if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
{
- int yyl;
+ yy_size_t yyl;
for ( yyl = 0; yyl < yyleng; ++yyl )
if ( yytext[yyl] == '\n' )
@@ -942,396 +945,406 @@ YY_RULE_SETUP
case 5:
YY_RULE_SETUP
#line 33 "sksl.flex"
-{ return SkSL::Token::TRUE_LITERAL; }
+{ return SkSL::Token::INT_LITERAL; }
YY_BREAK
case 6:
YY_RULE_SETUP
#line 35 "sksl.flex"
-{ return SkSL::Token::FALSE_LITERAL; }
+{ return SkSL::Token::TRUE_LITERAL; }
YY_BREAK
case 7:
YY_RULE_SETUP
#line 37 "sksl.flex"
-{ return SkSL::Token::IF; }
+{ return SkSL::Token::FALSE_LITERAL; }
YY_BREAK
case 8:
YY_RULE_SETUP
#line 39 "sksl.flex"
-{ return SkSL::Token::ELSE; }
+{ return SkSL::Token::IF; }
YY_BREAK
case 9:
YY_RULE_SETUP
#line 41 "sksl.flex"
-{ return SkSL::Token::FOR; }
+{ return SkSL::Token::ELSE; }
YY_BREAK
case 10:
YY_RULE_SETUP
#line 43 "sksl.flex"
-{ return SkSL::Token::WHILE; }
+{ return SkSL::Token::FOR; }
YY_BREAK
case 11:
YY_RULE_SETUP
#line 45 "sksl.flex"
-{ return SkSL::Token::DO; }
+{ return SkSL::Token::WHILE; }
YY_BREAK
case 12:
YY_RULE_SETUP
#line 47 "sksl.flex"
-{ return SkSL::Token::BREAK; }
+{ return SkSL::Token::DO; }
YY_BREAK
case 13:
YY_RULE_SETUP
#line 49 "sksl.flex"
-{ return SkSL::Token::CONTINUE; }
+{ return SkSL::Token::BREAK; }
YY_BREAK
case 14:
YY_RULE_SETUP
#line 51 "sksl.flex"
-{ return SkSL::Token::DISCARD; }
+{ return SkSL::Token::CONTINUE; }
YY_BREAK
case 15:
YY_RULE_SETUP
#line 53 "sksl.flex"
-{ return SkSL::Token::RETURN; }
+{ return SkSL::Token::DISCARD; }
YY_BREAK
case 16:
YY_RULE_SETUP
#line 55 "sksl.flex"
-{ return SkSL::Token::IN; }
+{ return SkSL::Token::RETURN; }
YY_BREAK
case 17:
YY_RULE_SETUP
#line 57 "sksl.flex"
-{ return SkSL::Token::OUT; }
+{ return SkSL::Token::IN; }
YY_BREAK
case 18:
YY_RULE_SETUP
#line 59 "sksl.flex"
-{ return SkSL::Token::INOUT; }
+{ return SkSL::Token::OUT; }
YY_BREAK
case 19:
YY_RULE_SETUP
#line 61 "sksl.flex"
-{ return SkSL::Token::UNIFORM; }
+{ return SkSL::Token::INOUT; }
YY_BREAK
case 20:
YY_RULE_SETUP
#line 63 "sksl.flex"
-{ return SkSL::Token::CONST; }
+{ return SkSL::Token::UNIFORM; }
YY_BREAK
case 21:
YY_RULE_SETUP
#line 65 "sksl.flex"
-{ return SkSL::Token::LOWP; }
+{ return SkSL::Token::CONST; }
YY_BREAK
case 22:
YY_RULE_SETUP
#line 67 "sksl.flex"
-{ return SkSL::Token::MEDIUMP; }
+{ return SkSL::Token::LOWP; }
YY_BREAK
case 23:
YY_RULE_SETUP
#line 69 "sksl.flex"
-{ return SkSL::Token::HIGHP; }
+{ return SkSL::Token::MEDIUMP; }
YY_BREAK
case 24:
YY_RULE_SETUP
#line 71 "sksl.flex"
-{ return SkSL::Token::FLAT; }
+{ return SkSL::Token::HIGHP; }
YY_BREAK
case 25:
YY_RULE_SETUP
#line 73 "sksl.flex"
-{ return SkSL::Token::NOPERSPECTIVE; }
+{ return SkSL::Token::FLAT; }
YY_BREAK
case 26:
YY_RULE_SETUP
#line 75 "sksl.flex"
-{ return SkSL::Token::STRUCT; }
+{ return SkSL::Token::NOPERSPECTIVE; }
YY_BREAK
case 27:
YY_RULE_SETUP
#line 77 "sksl.flex"
-{ return SkSL::Token::LAYOUT; }
+{ return SkSL::Token::STRUCT; }
YY_BREAK
case 28:
YY_RULE_SETUP
#line 79 "sksl.flex"
-{ return SkSL::Token::PRECISION; }
+{ return SkSL::Token::LAYOUT; }
YY_BREAK
case 29:
YY_RULE_SETUP
#line 81 "sksl.flex"
-{ return SkSL::Token::IDENTIFIER; }
+{ return SkSL::Token::PRECISION; }
YY_BREAK
case 30:
YY_RULE_SETUP
#line 83 "sksl.flex"
-{ return SkSL::Token::DIRECTIVE; }
+{ return SkSL::Token::IDENTIFIER; }
YY_BREAK
case 31:
YY_RULE_SETUP
#line 85 "sksl.flex"
-{ return SkSL::Token::LPAREN; }
+{ return SkSL::Token::DIRECTIVE; }
YY_BREAK
case 32:
YY_RULE_SETUP
#line 87 "sksl.flex"
-{ return SkSL::Token::RPAREN; }
+{ return SkSL::Token::LPAREN; }
YY_BREAK
case 33:
YY_RULE_SETUP
#line 89 "sksl.flex"
-{ return SkSL::Token::LBRACE; }
+{ return SkSL::Token::RPAREN; }
YY_BREAK
case 34:
YY_RULE_SETUP
#line 91 "sksl.flex"
-{ return SkSL::Token::RBRACE; }
+{ return SkSL::Token::LBRACE; }
YY_BREAK
case 35:
YY_RULE_SETUP
#line 93 "sksl.flex"
-{ return SkSL::Token::LBRACKET; }
+{ return SkSL::Token::RBRACE; }
YY_BREAK
case 36:
YY_RULE_SETUP
#line 95 "sksl.flex"
-{ return SkSL::Token::RBRACKET; }
+{ return SkSL::Token::LBRACKET; }
YY_BREAK
case 37:
YY_RULE_SETUP
#line 97 "sksl.flex"
-{ return SkSL::Token::DOT; }
+{ return SkSL::Token::RBRACKET; }
YY_BREAK
case 38:
YY_RULE_SETUP
#line 99 "sksl.flex"
-{ return SkSL::Token::COMMA; }
+{ return SkSL::Token::DOT; }
YY_BREAK
case 39:
YY_RULE_SETUP
#line 101 "sksl.flex"
-{ return SkSL::Token::PLUSPLUS; }
+{ return SkSL::Token::COMMA; }
YY_BREAK
case 40:
YY_RULE_SETUP
#line 103 "sksl.flex"
-{ return SkSL::Token::MINUSMINUS; }
+{ return SkSL::Token::PLUSPLUS; }
YY_BREAK
case 41:
YY_RULE_SETUP
#line 105 "sksl.flex"
-{ return SkSL::Token::PLUS; }
+{ return SkSL::Token::MINUSMINUS; }
YY_BREAK
case 42:
YY_RULE_SETUP
#line 107 "sksl.flex"
-{ return SkSL::Token::MINUS; }
+{ return SkSL::Token::PLUS; }
YY_BREAK
case 43:
YY_RULE_SETUP
#line 109 "sksl.flex"
-{ return SkSL::Token::STAR; }
+{ return SkSL::Token::MINUS; }
YY_BREAK
case 44:
YY_RULE_SETUP
#line 111 "sksl.flex"
-{ return SkSL::Token::SLASH; }
+{ return SkSL::Token::STAR; }
YY_BREAK
case 45:
YY_RULE_SETUP
#line 113 "sksl.flex"
-{ return SkSL::Token::PERCENT; }
+{ return SkSL::Token::SLASH; }
YY_BREAK
case 46:
YY_RULE_SETUP
#line 115 "sksl.flex"
-{ return SkSL::Token::SHL; }
+{ return SkSL::Token::PERCENT; }
YY_BREAK
case 47:
YY_RULE_SETUP
#line 117 "sksl.flex"
-{ return SkSL::Token::SHR; }
+{ return SkSL::Token::SHL; }
YY_BREAK
case 48:
YY_RULE_SETUP
#line 119 "sksl.flex"
-{ return SkSL::Token::BITWISEOR; }
+{ return SkSL::Token::SHR; }
YY_BREAK
case 49:
YY_RULE_SETUP
#line 121 "sksl.flex"
-{ return SkSL::Token::BITWISEXOR; }
+{ return SkSL::Token::BITWISEOR; }
YY_BREAK
case 50:
YY_RULE_SETUP
#line 123 "sksl.flex"
-{ return SkSL::Token::BITWISEAND; }
+{ return SkSL::Token::BITWISEXOR; }
YY_BREAK
case 51:
YY_RULE_SETUP
#line 125 "sksl.flex"
-{ return SkSL::Token::LOGICALOR; }
+{ return SkSL::Token::BITWISEAND; }
YY_BREAK
case 52:
YY_RULE_SETUP
#line 127 "sksl.flex"
-{ return SkSL::Token::LOGICALXOR; }
+{ return SkSL::Token::BITWISENOT; }
YY_BREAK
case 53:
YY_RULE_SETUP
#line 129 "sksl.flex"
-{ return SkSL::Token::LOGICALAND; }
+{ return SkSL::Token::LOGICALOR; }
YY_BREAK
case 54:
YY_RULE_SETUP
#line 131 "sksl.flex"
-{ return SkSL::Token::NOT; }
+{ return SkSL::Token::LOGICALXOR; }
YY_BREAK
case 55:
YY_RULE_SETUP
#line 133 "sksl.flex"
-{ return SkSL::Token::QUESTION; }
+{ return SkSL::Token::LOGICALAND; }
YY_BREAK
case 56:
YY_RULE_SETUP
#line 135 "sksl.flex"
-{ return SkSL::Token::COLON; }
+{ return SkSL::Token::LOGICALNOT; }
YY_BREAK
case 57:
YY_RULE_SETUP
#line 137 "sksl.flex"
-{ return SkSL::Token::EQ; }
+{ return SkSL::Token::QUESTION; }
YY_BREAK
case 58:
YY_RULE_SETUP
#line 139 "sksl.flex"
-{ return SkSL::Token::EQEQ; }
+{ return SkSL::Token::COLON; }
YY_BREAK
case 59:
YY_RULE_SETUP
#line 141 "sksl.flex"
-{ return SkSL::Token::NEQ; }
+{ return SkSL::Token::EQ; }
YY_BREAK
case 60:
YY_RULE_SETUP
#line 143 "sksl.flex"
-{ return SkSL::Token::GT; }
+{ return SkSL::Token::EQEQ; }
YY_BREAK
case 61:
YY_RULE_SETUP
#line 145 "sksl.flex"
-{ return SkSL::Token::LT; }
+{ return SkSL::Token::NEQ; }
YY_BREAK
case 62:
YY_RULE_SETUP
#line 147 "sksl.flex"
-{ return SkSL::Token::GTEQ; }
+{ return SkSL::Token::GT; }
YY_BREAK
case 63:
YY_RULE_SETUP
#line 149 "sksl.flex"
-{ return SkSL::Token::LTEQ; }
+{ return SkSL::Token::LT; }
YY_BREAK
case 64:
YY_RULE_SETUP
#line 151 "sksl.flex"
-{ return SkSL::Token::PLUSEQ; }
+{ return SkSL::Token::GTEQ; }
YY_BREAK
case 65:
YY_RULE_SETUP
#line 153 "sksl.flex"
-{ return SkSL::Token::MINUSEQ; }
+{ return SkSL::Token::LTEQ; }
YY_BREAK
case 66:
YY_RULE_SETUP
#line 155 "sksl.flex"
-{ return SkSL::Token::STAREQ; }
+{ return SkSL::Token::PLUSEQ; }
YY_BREAK
case 67:
YY_RULE_SETUP
#line 157 "sksl.flex"
-{ return SkSL::Token::SLASHEQ; }
+{ return SkSL::Token::MINUSEQ; }
YY_BREAK
case 68:
YY_RULE_SETUP
#line 159 "sksl.flex"
-{ return SkSL::Token::PERCENTEQ; }
+{ return SkSL::Token::STAREQ; }
YY_BREAK
case 69:
YY_RULE_SETUP
#line 161 "sksl.flex"
-{ return SkSL::Token::SHLEQ; }
+{ return SkSL::Token::SLASHEQ; }
YY_BREAK
case 70:
YY_RULE_SETUP
#line 163 "sksl.flex"
-{ return SkSL::Token::SHREQ; }
+{ return SkSL::Token::PERCENTEQ; }
YY_BREAK
case 71:
YY_RULE_SETUP
#line 165 "sksl.flex"
-{ return SkSL::Token::BITWISEOREQ; }
+{ return SkSL::Token::SHLEQ; }
YY_BREAK
case 72:
YY_RULE_SETUP
#line 167 "sksl.flex"
-{ return SkSL::Token::BITWISEXOREQ; }
+{ return SkSL::Token::SHREQ; }
YY_BREAK
case 73:
YY_RULE_SETUP
#line 169 "sksl.flex"
-{ return SkSL::Token::BITWISEANDEQ; }
+{ return SkSL::Token::BITWISEOREQ; }
YY_BREAK
case 74:
YY_RULE_SETUP
#line 171 "sksl.flex"
-{ return SkSL::Token::LOGICALOREQ; }
+{ return SkSL::Token::BITWISEXOREQ; }
YY_BREAK
case 75:
YY_RULE_SETUP
#line 173 "sksl.flex"
-{ return SkSL::Token::LOGICALXOREQ; }
+{ return SkSL::Token::BITWISEANDEQ; }
YY_BREAK
case 76:
YY_RULE_SETUP
#line 175 "sksl.flex"
-{ return SkSL::Token::LOGICALANDEQ; }
+{ return SkSL::Token::LOGICALOREQ; }
YY_BREAK
case 77:
YY_RULE_SETUP
#line 177 "sksl.flex"
-{ return SkSL::Token::SEMICOLON; }
+{ return SkSL::Token::LOGICALXOREQ; }
YY_BREAK
case 78:
YY_RULE_SETUP
#line 179 "sksl.flex"
-/* line comment */
+{ return SkSL::Token::LOGICALANDEQ; }
YY_BREAK
case 79:
-/* rule 79 can match eol */
YY_RULE_SETUP
#line 181 "sksl.flex"
-/* block comment */
+{ return SkSL::Token::SEMICOLON; }
YY_BREAK
case 80:
-/* rule 80 can match eol */
YY_RULE_SETUP
#line 183 "sksl.flex"
-/* whitespace */
+/* line comment */
YY_BREAK
case 81:
+/* rule 81 can match eol */
YY_RULE_SETUP
#line 185 "sksl.flex"
-{ return SkSL::Token::INVALID_TOKEN; }
+/* block comment */
YY_BREAK
case 82:
+/* rule 82 can match eol */
YY_RULE_SETUP
#line 187 "sksl.flex"
+/* whitespace */
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 189 "sksl.flex"
+{ return SkSL::Token::INVALID_TOKEN; }
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 191 "sksl.flex"
ECHO;
YY_BREAK
-#line 1329 "lex.sksl.c"
+#line 1342 "lex.sksl.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -1526,7 +1539,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{ /* Not enough room in the buffer - grow it. */
/* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
int yy_c_buf_p_offset =
(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
@@ -1626,7 +1639,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 201 )
+ if ( yy_current_state >= 205 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1655,13 +1668,12 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 201 )
+ if ( yy_current_state >= 205 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 200);
+ yy_is_jam = (yy_current_state == 204);
- (void)yyg;
return yy_is_jam ? 0 : yy_current_state;
}
@@ -1756,7 +1768,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
case EOB_ACT_END_OF_FILE:
{
if ( skslwrap(yyscanner ) )
- return EOF;
+ return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof )
YY_NEW_FILE;
@@ -2112,8 +2124,8 @@ YY_BUFFER_STATE sksl_scan_string (yyconst char * yystr , yyscan_t yyscanner)
/** Setup the input buffer state to scan the given bytes. The next call to sksllex() will
* scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
@@ -2121,8 +2133,7 @@ YY_BUFFER_STATE sksl_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_le
{
YY_BUFFER_STATE b;
char *buf;
- yy_size_t n;
- int i;
+ yy_size_t n, i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
@@ -2268,7 +2279,7 @@ void skslset_lineno (int line_number , yyscan_t yyscanner)
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "skslset_lineno called with no buffer" );
+ yy_fatal_error( "skslset_lineno called with no buffer" , yyscanner);
yylineno = line_number;
}
@@ -2283,7 +2294,7 @@ void skslset_column (int column_no , yyscan_t yyscanner)
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "skslset_column called with no buffer" );
+ yy_fatal_error( "skslset_column called with no buffer" , yyscanner);
yycolumn = column_no;
}
@@ -2495,7 +2506,7 @@ void skslfree (void * ptr , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
-#line 187 "sksl.flex"
+#line 191 "sksl.flex"
diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex
index 67b48e9cb9..4455f50084 100644
--- a/src/sksl/sksl.flex
+++ b/src/sksl/sksl.flex
@@ -30,6 +30,8 @@ LETTER [a-zA-Z_$]
{DIGIT}+ { return SkSL::Token::INT_LITERAL; }
+"0x"[0-9a-fA-F]+ { return SkSL::Token::INT_LITERAL; }
+
true { return SkSL::Token::TRUE_LITERAL; }
false { return SkSL::Token::FALSE_LITERAL; }
@@ -122,13 +124,15 @@ precision { return SkSL::Token::PRECISION; }
"&" { return SkSL::Token::BITWISEAND; }
+"~" { return SkSL::Token::BITWISENOT; }
+
"||" { return SkSL::Token::LOGICALOR; }
"^^" { return SkSL::Token::LOGICALXOR; }
"&&" { return SkSL::Token::LOGICALAND; }
-"!" { return SkSL::Token::NOT; }
+"!" { return SkSL::Token::LOGICALNOT; }
"?" { return SkSL::Token::QUESTION; }
diff --git a/src/sksl/sksl.include b/src/sksl/sksl.include
index 4fd5511ee3..6dc1ff8cf2 100644
--- a/src/sksl/sksl.include
+++ b/src/sksl/sksl.include
@@ -244,6 +244,8 @@ int textureQueryLevels(samplerCubeArrayShadow sampler);
$gvec4 texture($gsampler1D sampler, float P);
$gvec4 texture($gsampler1D sampler, float P, float bias);
$gvec4 texture($gsampler2D sampler, vec2 P);
+vec4 texture(samplerExternalOES sampler, vec2 P, float bias);
+vec4 texture(samplerExternalOES sampler, vec2 P);
$gvec4 texture($gsampler2D sampler, vec2 P, float bias);
$gvec4 texture($gsampler3D sampler, vec3 P);
$gvec4 texture($gsampler3D sampler, vec3 P, float bias);
@@ -464,6 +466,7 @@ vec4 texture1DLod(sampler1D sampler, float coord, float lod);
vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod);
vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod);
vec4 texture2D(sampler2D sampler, vec2 coord);
+vec4 texture2D(samplerExternalOES sampler, vec2 coord);
vec4 texture2D(sampler2D sampler, vec2 coord, float bias);
vec4 texture2DProj(sampler2D sampler, vec3 coord);
vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);
diff --git a/src/sksl/sksl_frag.include b/src/sksl/sksl_frag.include
index 123c3393a2..98dbc90252 100644
--- a/src/sksl/sksl_frag.include
+++ b/src/sksl/sksl_frag.include
@@ -4,5 +4,17 @@ STRINGIFY(
layout(builtin=15) in vec4 gl_FragCoord;
-)
+// 9999 is a temporary value that causes us to ignore these declarations beyond
+// adding them to the symbol table. This works fine in GLSL (where they do not
+// require any further handling) but will fail in SPIR-V. We'll have a better
+// solution for this soon.
+layout(builtin=9999) vec4 gl_LastFragData[1];
+layout(builtin=9999) vec4 gl_LastFragColor;
+layout(builtin=9999) vec4 gl_LastFragColorARM;
+layout(builtin=9999) int gl_SampleMaskIn[];
+layout(builtin=9999) out int gl_SampleMask[];
+layout(builtin=9999) vec4 gl_SecondaryFragColorEXT;
+
+layout(location=0,index=0,builtin=10001) out vec4 sk_FragColor;
+)