diff options
author | Ethan Nicholas <ethannicholas@google.com> | 2017-06-27 09:56:09 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-06-27 14:20:05 +0000 |
commit | ccf59917d3fe7aaf59de714acfbd0596503f324f (patch) | |
tree | cc97719c47276c9dcbf0ec09effd580c4e7450dd /src/sksl | |
parent | c3aef18419c1bb16951370e11758c7ef131fa10b (diff) |
sksl fragment processor support
Bug: skia:
Change-Id: Ia3b0305c2b0c78074303831f628fb01852b90d34
Reviewed-on: https://skia-review.googlesource.com/17843
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
Diffstat (limited to 'src/sksl')
46 files changed, 2534 insertions, 743 deletions
diff --git a/src/sksl/README b/src/sksl/README index a16dd80858..0c1712dc08 100644 --- a/src/sksl/README +++ b/src/sksl/README @@ -9,6 +9,7 @@ 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 ===================== @@ -56,3 +57,58 @@ following differences between SkSL and GLSL: SkSL is still under development, and is expected to diverge further from GLSL over time. + + +SkSL Fragment Processors +======================== + +An extension of SkSL allows for the creation of fragment processors in pure +SkSL. The program defines its inputs similarly to a normal SkSL program (with +'in' and 'uniform' variables), but the 'main()' function represents only this +fragment processor's portion of the overall fragment shader. + +Within an '.fp' fragment processor file: + +* C++ code can be embedded in sections of the form: + + @section_name { <arbitrary C++ code> } + + Supported section are: + @header (in the .h file, outside the class declaration) + @class (in the .h file, inside the class declaration) + @cpp (in the .cpp file) + @constructorParams (extra parameters to the constructor, comma-separated) + @constructor (replaces the default constructor) + @initializers (constructor initializer list, comma-separated) + @emitCode (extra code for the emitCode function) + @fields (extra private fields, each terminated with a semicolon) + @make (replaces the default Make function) + @setData(<pdman>) (extra code for the setData function, where <pdman> is + the name of the GrGLSLProgramDataManager) + @test(<testData>) (the body of the TestCreate function, where <testData> is + the name of the GrProcessorTestData* parameter) +* global 'in' variables represent data passed to the fragment processor at + construction time. These variables become constructor parameters and are + stored in fragment processor fields. vec2s map to SkPoints, and vec4s map to + SkRects (in x, y, width, height) order. +* 'uniform' variables become, as one would expect, top-level uniforms. By + default they do not have any data provided to them; you will need to provide + them with data via the @setData section. +* 'in uniform' variables are uniforms that are automatically wired up to + fragment processor constructor parameters +* the 'sk_TransformedCoords2D' array provides access to 2D transformed + coordinates. sk_TransformedCoords2D[0] is equivalent to calling + fragBuilder->ensureCoords2D(args.fTransformedCoords[0]) (and the result is + cached, so you need not worry about using the value repeatedly). +* 'colorSpaceXform' is a supported type. It is reflected within SkSL as a mat4, + and on the C++ side as sk_sp<GrColorSpaceXform>. +* the texture() function can be passed a colorSpaceXform as an additional + parameter +* Uniform variables support an additional 'when' layout key. + 'layout(when=foo) uniform int x;' means that this uniform will only be + emitted when the 'foo' expression is true. +* 'in' variables support an additional 'key' layout key. + 'layout(key) uniform int x;' means that this uniform should be included in + the program's key. Matrix variables additionally support 'key=identity', + which causes the key to consider only whether or not the matrix is an + identity matrix. diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp index df10c62b7a..e8964db0bc 100644 --- a/src/sksl/SkSLCFGGenerator.cpp +++ b/src/sksl/SkSLCFGGenerator.cpp @@ -231,6 +231,7 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it case Expression::kBoolLiteral_Kind: // fall through case Expression::kFloatLiteral_Kind: // fall through case Expression::kIntLiteral_Kind: // fall through + case Expression::kSetting_Kind: // fall through case Expression::kVariableReference_Kind: *iter = fNodes.erase(*iter); return true; @@ -380,6 +381,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool case Expression::kBoolLiteral_Kind: // fall through case Expression::kFloatLiteral_Kind: // fall through case Expression::kIntLiteral_Kind: // fall through + case Expression::kSetting_Kind: // fall through case Expression::kVariableReference_Kind: cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind, constantPropagate, e, nullptr }); diff --git a/src/sksl/SkSLCPP.h b/src/sksl/SkSLCPP.h new file mode 100644 index 0000000000..47f8a4080b --- /dev/null +++ b/src/sksl/SkSLCPP.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKSL_CPP +#define SKSL_CPP + +// functions used by CPP programs created by skslc + +#include "SkPoint.h" + +// macros to make sk_Caps.<cap name> work from C++ code +#define sk_Caps (*args.fShaderCaps) + +#define floatPrecisionVaries floatPrecisionVaries() + +// functions to make GLSL constructors work from C++ code +inline SkPoint vec2(float xy) { return SkPoint::Make(xy, xy); } + +inline SkPoint vec2(float x, float y) { return SkPoint::Make(x, y); } + +#endif diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp new file mode 100644 index 0000000000..c317b4ec66 --- /dev/null +++ b/src/sksl/SkSLCPPCodeGenerator.cpp @@ -0,0 +1,597 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSLCPPCodeGenerator.h" + +#include "SkSLCompiler.h" +#include "SkSLHCodeGenerator.h" + +namespace SkSL { + +static bool needs_uniform_var(const Variable& var) { + return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) && + strcmp(var.fType.fName.c_str(), "colorSpaceXform"); +} + +CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program, + ErrorReporter* errors, String name, OutputStream* out) +: INHERITED(context, program, errors, out) +, fName(std::move(name)) +, fFullName(String::printf("Gr%s", fName.c_str())) +, fSectionAndParameterHelper(*program, *errors) { + fLineEnding = "\\n"; +} + +void CPPCodeGenerator::writef(const char* s, va_list va) { + static constexpr int BUFFER_SIZE = 1024; + char buffer[BUFFER_SIZE]; + int length = vsnprintf(buffer, BUFFER_SIZE, s, va); + if (length < BUFFER_SIZE) { + fOut->write(buffer, length); + } else { + std::unique_ptr<char[]> heap(new char[length + 1]); + vsprintf(heap.get(), s, va); + fOut->write(heap.get(), length); + } +} + +void CPPCodeGenerator::writef(const char* s, ...) { + va_list va; + va_start(va, s); + this->writef(s, va); + va_end(va); +} + +void CPPCodeGenerator::writeHeader() { +} + +void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b, + Precedence parentPrecedence) { + if (b.fOperator == Token::PERCENT) { + // need to use "%%" instead of "%" b/c the code will be inside of a printf + Precedence precedence = GetBinaryPrecedence(b.fOperator); + if (precedence >= parentPrecedence) { + this->write("("); + } + this->writeExpression(*b.fLeft, precedence); + this->write(" %% "); + this->writeExpression(*b.fRight, precedence); + if (precedence >= parentPrecedence) { + this->write(")"); + } + } else { + INHERITED::writeBinaryExpression(b, parentPrecedence); + } +} + +void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) { + const Expression& base = *i.fBase; + if (base.fKind == Expression::kVariableReference_Kind) { + int builtin = ((VariableReference&) base).fVariable.fModifiers.fLayout.fBuiltin; + if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) { + this->write("%s"); + if (i.fIndex->fKind != Expression::kIntLiteral_Kind) { + fErrors.error(i.fIndex->fPosition, + "index into sk_TransformedCoords2D must be an integer literal"); + return; + } + int64_t index = ((IntLiteral&) *i.fIndex).fValue; + String name = "sk_TransformedCoords2D_" + to_string(index); + fFormatArgs.push_back(name + ".c_str()"); + if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) { + fExtraEmitCodeCode += " SkSL::String " + name + + " = fragBuilder->ensureCoords2D(args.fTransformedCoords[" + + to_string(index) + "]);\n"; + fWrittenTransformedCoords.insert(index); + } + return; + } else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) { + this->write("%s"); + if (i.fIndex->fKind != Expression::kIntLiteral_Kind) { + fErrors.error(i.fIndex->fPosition, + "index into sk_TextureSamplers must be an integer literal"); + return; + } + int64_t index = ((IntLiteral&) *i.fIndex).fValue; + fFormatArgs.push_back(" fragBuilder->getProgramBuilder()->samplerVariable(" + "args.fTexSamplers[" + to_string(index) + "]).c_str()"); + return; + } + } + INHERITED::writeIndexExpression(i); +} + +static const char* default_value(const Type& type) { + const char* name = type.name().c_str(); + if (!strcmp(name, "float")) { + return "0.0"; + } else if (!strcmp(name, "vec2")) { + return "vec2(0.0)"; + } else if (!strcmp(name, "vec3")) { + return "vec3(0.0)"; + } else if (!strcmp(name, "vec4")) { + return "vec4(0.0)"; + } else if (!strcmp(name, "mat4") || !strcmp(name, "colorSpaceXform")) { + return "mat4(1.0)"; + } + ABORT("unsupported default_value type\n"); +} + +static bool is_private(const Variable& var) { + return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) && + !(var.fModifiers.fFlags & Modifiers::kIn_Flag) && + var.fStorage == Variable::kGlobal_Storage && + var.fModifiers.fLayout.fBuiltin == -1; +} + +void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) { + if (type == *fContext.fFloat_Type) { + this->write("%f"); + fFormatArgs.push_back(cppCode); + } else if (type == *fContext.fInt_Type) { + this->write("%d"); + fFormatArgs.push_back(cppCode); + } else if (type == *fContext.fBool_Type) { + this->write("%s"); + fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")"); + } else if (type == *fContext.fVec2_Type) { + this->write("vec2(%f, %f)"); + fFormatArgs.push_back(cppCode + ".fX"); + fFormatArgs.push_back(cppCode + ".fY"); + } else { + printf("%s\n", type.name().c_str()); + ABORT("unsupported runtime value type\n"); + } +} + +void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) { + if (is_private(var)) { + this->writeRuntimeValue(var.fType, var.fName); + } else { + this->writeExpression(value, kTopLevel_Precedence); + } +} + +void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) { + switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { + case SK_INCOLOR_BUILTIN: + this->write("%s"); + fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"vec4(1)\"")); + break; + case SK_OUTCOLOR_BUILTIN: + this->write("%s"); + fFormatArgs.push_back(String("args.fOutputColor")); + break; + default: + if (ref.fVariable.fType.kind() == Type::kSampler_Kind) { + int samplerCount = 0; + for (const auto param : fSectionAndParameterHelper.fParameters) { + if (&ref.fVariable == param) { + this->write("%s"); + fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerVariable(" + "args.fTexSamplers[" + to_string(samplerCount) + + "]).c_str()"); + return; + } + if (param->fType.kind() == Type::kSampler_Kind) { + ++samplerCount; + } + } + ABORT("should have found sampler in parameters\n"); + } + if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) { + this->write("%s"); + String name = ref.fVariable.fName; + String var; + if (ref.fVariable.fType == *fContext.fColorSpaceXform_Type) { + ASSERT(fNeedColorSpaceHelper); + var = String::printf("fColorSpaceHelper.isValid() ? " + "args.fUniformHandler->getUniformCStr(" + "fColorSpaceHelper.gamutXformUniform()) : \"%s\"", + default_value(ref.fVariable.fType)); + } else { + var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)", + HCodeGenerator::FieldName(name.c_str()).c_str()); + } + String code; + if (ref.fVariable.fModifiers.fLayout.fWhen.size()) { + code = String::printf("%sVar.isValid() ? %s : \"%s\"", + HCodeGenerator::FieldName(name.c_str()).c_str(), + var.c_str(), + default_value(ref.fVariable.fType)); + } else { + code = var; + } + fFormatArgs.push_back(code); + } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) { + const char* name = ref.fVariable.fName.c_str(); + this->writeRuntimeValue(ref.fVariable.fType, + String::printf("_outer.%s()", name).c_str()); + } else { + this->write(ref.fVariable.fName.c_str()); + } + } +} + +void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) { + if (f.fDeclaration.fName == "main") { + fFunctionHeader = ""; + OutputStream* oldOut = fOut; + StringStream buffer; + fOut = &buffer; + for (const auto& s : ((Block&) *f.fBody).fStatements) { + this->writeStatement(*s); + this->writeLine(); + } + + fOut = oldOut; + this->write(fFunctionHeader); + this->write(buffer.str()); + } else { + INHERITED::writeFunction(f); + } +} + +void CPPCodeGenerator::writeSetting(const Setting& s) { + static constexpr const char* kPrefix = "sk_Args."; + if (!strncmp(s.fName.c_str(), kPrefix, strlen(kPrefix))) { + const char* name = s.fName.c_str() + strlen(kPrefix); + this->writeRuntimeValue(s.fType, HCodeGenerator::FieldName(name).c_str()); + } else { + this->write(s.fName.c_str()); + } +} + +void CPPCodeGenerator::writeSection(const char* name, const char* prefix) { + const auto found = fSectionAndParameterHelper.fSections.find(String(name)); + if (found != fSectionAndParameterHelper.fSections.end()) { + this->writef("%s%s", prefix, found->second->fText.c_str()); + } +} + +void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) { + if (p.fKind == ProgramElement::kSection_Kind) { + return; + } + if (p.fKind == ProgramElement::kVar_Kind) { + const VarDeclarations& decls = (const VarDeclarations&) p; + if (!decls.fVars.size()) { + return; + } + const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar; + if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) || + -1 != var.fModifiers.fLayout.fBuiltin) { + return; + } + } + INHERITED::writeProgramElement(p); +} + +void CPPCodeGenerator::addUniform(const Variable& var) { + if (!needs_uniform_var(var)) { + return; + } + const char* precision; + if (var.fModifiers.fFlags & Modifiers::kHighp_Flag) { + precision = "kHigh_GrSLPrecision"; + } else if (var.fModifiers.fFlags & Modifiers::kMediump_Flag) { + precision = "kMedium_GrSLPrecision"; + } else if (var.fModifiers.fFlags & Modifiers::kLowp_Flag) { + precision = "kLow_GrSLPrecision"; + } else { + precision = "kDefault_GrSLPrecision"; + } + const char* type; + if (var.fType == *fContext.fFloat_Type) { + type = "kFloat_GrSLType"; + } else if (var.fType == *fContext.fVec2_Type) { + type = "kVec2f_GrSLType"; + } else if (var.fType == *fContext.fVec4_Type) { + type = "kVec4f_GrSLType"; + } else if (var.fType == *fContext.fMat4x4_Type || + var.fType == *fContext.fColorSpaceXform_Type) { + type = "kMat44f_GrSLType"; + } else { + ABORT("unsupported uniform type: %s %s;\n", var.fType.name().c_str(), var.fName.c_str()); + } + if (var.fModifiers.fLayout.fWhen.size()) { + this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str()); + } + const char* name = var.fName.c_str(); + this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, " + "%s, \"%s\");\n", HCodeGenerator::FieldName(name).c_str(), type, precision, name); + if (var.fModifiers.fLayout.fWhen.size()) { + this->write(" }\n"); + } +} + +void CPPCodeGenerator::writePrivateVars() { + for (const auto& p : fProgram.fElements) { + if (ProgramElement::kVar_Kind == p->fKind) { + const VarDeclarations* decls = (const VarDeclarations*) p.get(); + for (const auto& raw : decls->fVars) { + VarDeclaration& decl = (VarDeclaration&) *raw; + if (is_private(*decl.fVar)) { + this->writef("%s %s;\n", + HCodeGenerator::FieldType(decl.fVar->fType).c_str(), + decl.fVar->fName.c_str()); + } + } + } + } +} + +void CPPCodeGenerator::writePrivateVarValues() { + for (const auto& p : fProgram.fElements) { + if (ProgramElement::kVar_Kind == p->fKind) { + const VarDeclarations* decls = (const VarDeclarations*) p.get(); + for (const auto& raw : decls->fVars) { + VarDeclaration& decl = (VarDeclaration&) *raw; + if (is_private(*decl.fVar) && decl.fValue) { + this->writef("%s = %s;\n", + decl.fVar->fName.c_str(), + decl.fValue->description().c_str()); + } + } + } + } +} + +bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) { + this->write(" void emitCode(EmitArgs& args) override {\n" + " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"); + this->writef(" const %s& _outer = args.fFp.cast<%s>();\n" + " (void) _outer;\n", + fFullName.c_str(), fFullName.c_str()); + this->writePrivateVarValues(); + for (const auto u : uniforms) { + this->addUniform(*u); + if (u->fType == *fContext.fColorSpaceXform_Type) { + if (fNeedColorSpaceHelper) { + fErrors.error(u->fPosition, "only a single ColorSpaceXform is supported"); + } + fNeedColorSpaceHelper = true; + this->writef(" fColorSpaceHelper.emitCode(args.fUniformHandler, " + "_outer.%s().get());\n", + u->fName.c_str()); + } + } + this->writeSection(EMIT_CODE_SECTION); + OutputStream* old = fOut; + StringStream mainBuffer; + fOut = &mainBuffer; + bool result = INHERITED::generateCode(); + fOut = old; + this->writef("%s fragBuilder->codeAppendf(\"%s\"", fExtraEmitCodeCode.c_str(), + mainBuffer.str().c_str()); + for (const auto& s : fFormatArgs) { + this->writef(", %s", s.c_str()); + } + this->write(");\n" + " }\n"); + return result; +} + +void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) { + const char* fullName = fFullName.c_str(); + auto section = fSectionAndParameterHelper.fSections.find(String(SET_DATA_SECTION)); + const char* pdman = section != fSectionAndParameterHelper.fSections.end() ? + section->second->fArgument.c_str() : + "pdman"; + this->writef(" void onSetData(const GrGLSLProgramDataManager& %s, " + "const GrFragmentProcessor& _proc) override {\n", + pdman); + bool wroteProcessor = false; + for (const auto u : uniforms) { + if (u->fModifiers.fFlags & Modifiers::kIn_Flag) { + if (!wroteProcessor) { + this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, fullName); + wroteProcessor = true; + this->writef(" {\n"); + } + const char* name = u->fName.c_str(); + if (u->fType == *fContext.fVec4_Type) { + this->writef(" const SkRect %sValue = _outer.%s();\n" + " %s.set4fv(%sVar, 4, (float*) &%sValue);\n", + name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name); + } else if (u->fType == *fContext.fMat4x4_Type) { + this->writef(" float %sValue[16];\n" + " _outer.%s().asColMajorf(%sValue);\n" + " %s.setMatrix4f(%sVar, %sValue);\n", + name, name, name, pdman, HCodeGenerator::FieldName(name).c_str(), + name); + } else if (u->fType == *fContext.fColorSpaceXform_Type) { + ASSERT(fNeedColorSpaceHelper); + this->writef(" if (fColorSpaceHelper.isValid()) {\n" + " fColorSpaceHelper.setData(%s, _outer.%s().get());\n" + " }\n", + pdman, name); + } else { + this->writef(" %s.set1f(%sVar, _outer.%s());\n", + pdman, HCodeGenerator::FieldName(name).c_str(), name); + } + } + } + if (wroteProcessor) { + this->writef(" }\n"); + } + if (section != fSectionAndParameterHelper.fSections.end()) { + for (const auto& p : fProgram.fElements) { + if (ProgramElement::kVar_Kind == p->fKind) { + const VarDeclarations* decls = (const VarDeclarations*) p.get(); + for (const auto& raw : decls->fVars) { + VarDeclaration& decl = (VarDeclaration&) *raw; + if (needs_uniform_var(*decl.fVar)) { + const char* name = decl.fVar->fName.c_str(); + this->writef(" UniformHandle& %s = %sVar;\n" + " (void) %s;\n", + name, HCodeGenerator::FieldName(name).c_str(), name); + } else if (SectionAndParameterHelper::IsParameter(*decl.fVar)) { + const char* name = decl.fVar->fName.c_str(); + if (!wroteProcessor) { + this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, + fullName); + wroteProcessor = true; + } + this->writef(" auto %s = _outer.%s();\n" + " (void) %s;\n", + name, name, name); + } + } + } + } + this->writeSection(SET_DATA_SECTION); + } + this->write(" }\n"); +} + +void CPPCodeGenerator::writeTest() { + const auto found = fSectionAndParameterHelper.fSections.find(TEST_CODE_SECTION); + if (found == fSectionAndParameterHelper.fSections.end()) { + return; + } + const Section* test = found->second; + this->writef("GR_DEFINE_FRAGMENT_PROCESSOR_TEST(%s);\n" + "#if GR_TEST_UTILS\n" + "sk_sp<GrFragmentProcessor> %s::TestCreate(GrProcessorTestData* %s) {\n", + fFullName.c_str(), + fFullName.c_str(), + test->fArgument.c_str()); + this->writeSection(TEST_CODE_SECTION); + this->write("}\n" + "#endif\n"); +} + +void CPPCodeGenerator::writeGetKey() { + this->writef("void %s::onGetGLSLProcessorKey(const GrShaderCaps& caps, " + "GrProcessorKeyBuilder* b) const {\n", + fFullName.c_str()); + for (const auto& param : fSectionAndParameterHelper.fParameters) { + const char* name = param->fName.c_str(); + if (param->fType == *fContext.fColorSpaceXform_Type) { + this->writef(" b->add32(GrColorSpaceXform::XformKey(%s.get()));\n", + HCodeGenerator::FieldName(name).c_str()); + continue; + } + if (param->fModifiers.fLayout.fKey != Layout::kNo_Key && + (param->fModifiers.fFlags & Modifiers::kUniform_Flag)) { + fErrors.error(param->fPosition, + "layout(key) may not be specified on uniforms"); + } + switch (param->fModifiers.fLayout.fKey) { + case Layout::kKey_Key: + if (param->fType == *fContext.fMat4x4_Type) { + ABORT("no automatic key handling for mat4\n"); + } else if (param->fType == *fContext.fVec2_Type) { + this->writef(" b->add32(%s.fX);\n", + HCodeGenerator::FieldName(name).c_str()); + this->writef(" b->add32(%s.fY);\n", + HCodeGenerator::FieldName(name).c_str()); + } else if (param->fType == *fContext.fVec4_Type) { + this->writef(" b->add32(%s.x());\n", + HCodeGenerator::FieldName(name).c_str()); + this->writef(" b->add32(%s.y());\n", + HCodeGenerator::FieldName(name).c_str()); + this->writef(" b->add32(%s.width());\n", + HCodeGenerator::FieldName(name).c_str()); + this->writef(" b->add32(%s.height());\n", + HCodeGenerator::FieldName(name).c_str()); + } else { + this->writef(" b->add32(%s);\n", + HCodeGenerator::FieldName(name).c_str()); + } + break; + case Layout::kIdentity_Key: + if (param->fType.kind() != Type::kMatrix_Kind) { + fErrors.error(param->fPosition, + "layout(key=identity) requires matrix type"); + } + this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n", + HCodeGenerator::FieldName(name).c_str()); + break; + case Layout::kNo_Key: + break; + } + } + this->write("}\n"); +} + +bool CPPCodeGenerator::generateCode() { + std::vector<const Variable*> uniforms; + for (const auto& p : fProgram.fElements) { + if (ProgramElement::kVar_Kind == p->fKind) { + const VarDeclarations* decls = (const VarDeclarations*) p.get(); + for (const auto& raw : decls->fVars) { + VarDeclaration& decl = (VarDeclaration&) *raw; + if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) && + decl.fVar->fType.kind() != Type::kSampler_Kind) { + uniforms.push_back(decl.fVar); + } + } + } + } + const char* baseName = fName.c_str(); + const char* fullName = fFullName.c_str(); + this->writef("/*\n" + " * This file was autogenerated from %s.fp.\n" + " */\n" + "#include \"%s.h\"\n" + "#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n" + "#include \"glsl/GrGLSLFragmentProcessor.h\"\n" + "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n" + "#include \"glsl/GrGLSLProgramBuilder.h\"\n" + "#include \"GrResourceProvider.h\"\n" + "#include \"SkSLCPP.h\"\n" + "#include \"SkSLUtil.h\"\n" + "class GrGLSL%s : public GrGLSLFragmentProcessor {\n" + "public:\n" + " GrGLSL%s() {}\n", + fullName, fullName, baseName, baseName); + bool result = this->writeEmitCode(uniforms); + this->write("private:\n"); + this->writeSetData(uniforms); + this->writePrivateVars(); + for (const auto& u : uniforms) { + const char* name = u->fName.c_str(); + if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) { + this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str()); + } + } + for (const auto& param : fSectionAndParameterHelper.fParameters) { + const char* name = param->fName.c_str(); + if (needs_uniform_var(*param)) { + this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str()); + } + } + if (fNeedColorSpaceHelper) { + this->write(" GrGLSLColorSpaceXformHelper fColorSpaceHelper;\n"); + } + this->writef("};\n" + "GrGLSLFragmentProcessor* %s::onCreateGLSLInstance() const {\n" + " return new GrGLSL%s();\n" + "}\n", + fullName, baseName); + this->writeGetKey(); + this->writef("bool %s::onIsEqual(const GrFragmentProcessor& other) const {\n" + " const %s& that = other.cast<%s>();\n" + " (void) that;\n", + fullName, fullName, fullName); + for (const auto& param : fSectionAndParameterHelper.fParameters) { + const char* name = param->fName.c_str(); + this->writef(" if (%s != that.%s) return false;\n", + HCodeGenerator::FieldName(name).c_str(), + HCodeGenerator::FieldName(name).c_str()); + } + this->write(" return true;\n" + "}\n"); + this->writeSection(CPP_SECTION); + this->writeTest(); + result &= 0 == fErrors.errorCount(); + return result; +} + +} // namespace diff --git a/src/sksl/SkSLCPPCodeGenerator.h b/src/sksl/SkSLCPPCodeGenerator.h new file mode 100644 index 0000000000..74ee8f6289 --- /dev/null +++ b/src/sksl/SkSLCPPCodeGenerator.h @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKSL_CPPCODEGENERATOR +#define SKSL_CPPCODEGENERATOR + +#include "SkSLGLSLCodeGenerator.h" +#include "SkSLSectionAndParameterHelper.h" + +#include <set> + +namespace SkSL { + +class CPPCodeGenerator : public GLSLCodeGenerator { +public: + CPPCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors, + String name, OutputStream* out); + + bool generateCode() override; + +private: + void writef(const char* s, va_list va) SKSL_PRINTF_LIKE(2, 0); + + void writef(const char* s, ...) SKSL_PRINTF_LIKE(2, 3); + + void writeSection(const char* name, const char* prefix = ""); + + void writeHeader() override; + + void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence) override; + + void writeIndexExpression(const IndexExpression& i) override; + + void writeVariableReference(const VariableReference& ref) override; + + void writeFunction(const FunctionDefinition& f) override; + + void writeSetting(const Setting& s) override; + + void writeProgramElement(const ProgramElement& p) override; + + void addUniform(const Variable& var); + + // writes a printf escape that will be filled in at runtime by the given C++ expression string + void writeRuntimeValue(const Type& type, const String& cppCode); + + void writeVarInitializer(const Variable& var, const Expression& value) override; + + void writePrivateVars(); + + void writePrivateVarValues(); + + bool writeEmitCode(std::vector<const Variable*>& uniforms); + + void writeSetData(std::vector<const Variable*>& uniforms); + + void writeGetKey(); + + void writeTest(); + + String fName; + String fFullName; + SectionAndParameterHelper fSectionAndParameterHelper; + String fExtraEmitCodeCode; + std::vector<String> fFormatArgs; + std::set<int> fWrittenTransformedCoords; + bool fNeedColorSpaceHelper = false; + + typedef GLSLCodeGenerator INHERITED; +}; + +} + +#endif diff --git a/src/sksl/SkSLCodeGenerator.h b/src/sksl/SkSLCodeGenerator.h index f6f990503c..1f577b58b1 100644 --- a/src/sksl/SkSLCodeGenerator.h +++ b/src/sksl/SkSLCodeGenerator.h @@ -9,6 +9,7 @@ #define SKSL_CODEGENERATOR #include "ir/SkSLProgram.h" +#include "SkSLOutputStream.h" namespace SkSL { diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index 39ac31532e..593397bd2a 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -8,7 +8,9 @@ #include "SkSLCompiler.h" #include "SkSLCFGGenerator.h" +#include "SkSLCPPCodeGenerator.h" #include "SkSLGLSLCodeGenerator.h" +#include "SkSLHCodeGenerator.h" #include "SkSLIRGenerator.h" #include "SkSLSPIRVCodeGenerator.h" #include "ir/SkSLExpression.h" @@ -45,6 +47,11 @@ static const char* SKSL_GEOM_INCLUDE = #include "sksl_geom.include" ; +static const char* SKSL_FP_INCLUDE = +#include "sksl_fp.include" +; + + namespace SkSL { Compiler::Compiler() @@ -146,12 +153,18 @@ Compiler::Compiler() ADD_TYPE(SamplerCubeArrayShadow); ADD_TYPE(GSampler2DArrayShadow); ADD_TYPE(GSamplerCubeArrayShadow); + ADD_TYPE(ColorSpaceXform); String skCapsName("sk_Caps"); Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName, *fContext.fSkCaps_Type, Variable::kGlobal_Storage); fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps)); + String skArgsName("sk_Args"); + Variable* skArgs = new Variable(Position(), Modifiers(), skArgsName, + *fContext.fSkArgs_Type, Variable::kGlobal_Storage); + fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs)); + Modifiers::Flag ignored1; std::vector<std::unique_ptr<ProgramElement>> ignored2; fIRGenerator->convertProgram(String(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2); @@ -778,7 +791,6 @@ void Compiler::simplifyExpression(DefinitionMap& definitions, } } - // returns true if this statement could potentially execute a break at the current level (we ignore // nested loops and switches, since any breaks inside of them will merely break the loop / switch) static bool contains_break(Statement& s) { @@ -1097,6 +1109,9 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex case Program::kGeometry_Kind: fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements); break; + case Program::kFragmentProcessor_Kind: + fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements); + break; } fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); Modifiers::Flag defaultPrecision; @@ -1127,15 +1142,16 @@ bool Compiler::toSPIRV(const Program& program, OutputStream& out) { bool result = cg.generateCode(); if (result) { spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0); - ASSERT(0 == buffer.size() % 4); + const String& data = buffer.str(); + ASSERT(0 == data.size() % 4); auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) { SkDebugf("SPIR-V validation error: %s\n", m); }; tools.SetMessageConsumer(dumpmsg); // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior // to the failure to see the validation errors. - ASSERT_RESULT(tools.Validate((const uint32_t*) buffer.data(), buffer.size() / 4)); - out.write(buffer.data(), buffer.size()); + ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4)); + out.write(data.c_str(), data.size()); } #else SPIRVCodeGenerator cg(&fContext, &program, this, &out); @@ -1149,7 +1165,7 @@ bool Compiler::toSPIRV(const Program& program, String* out) { StringStream buffer; bool result = this->toSPIRV(program, buffer); if (result) { - *out = String(buffer.data(), buffer.size()); + *out = buffer.str(); } return result; } @@ -1165,11 +1181,24 @@ bool Compiler::toGLSL(const Program& program, String* out) { StringStream buffer; bool result = this->toGLSL(program, buffer); if (result) { - *out = String(buffer.data(), buffer.size()); + *out = buffer.str(); } return result; } +bool Compiler::toCPP(const Program& program, String name, OutputStream& out) { + CPPCodeGenerator cg(&fContext, &program, this, name, &out); + bool result = cg.generateCode(); + this->writeErrorCount(); + return result; +} + +bool Compiler::toH(const Program& program, String name, OutputStream& out) { + HCodeGenerator cg(&program, this, name, &out); + bool result = cg.generateCode(); + this->writeErrorCount(); + return result; +} void Compiler::error(Position position, String msg) { fErrorCount++; diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index bc9a1964ac..2acb55958f 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -18,12 +18,16 @@ #include "SkSLErrorReporter.h" #include "SkSLIRGenerator.h" -#define SK_FRAGCOLOR_BUILTIN 10001 -#define SK_IN_BUILTIN 10002 -#define SK_FRAGCOORD_BUILTIN 15 -#define SK_VERTEXID_BUILTIN 5 -#define SK_CLIPDISTANCE_BUILTIN 3 -#define SK_INVOCATIONID_BUILTIN 8 +#define SK_FRAGCOLOR_BUILTIN 10001 +#define SK_IN_BUILTIN 10002 +#define SK_INCOLOR_BUILTIN 10003 +#define SK_OUTCOLOR_BUILTIN 10004 +#define SK_TRANSFORMEDCOORDS2D_BUILTIN 10005 +#define SK_TEXTURESAMPLERS_BUILTIN 10006 +#define SK_FRAGCOORD_BUILTIN 15 +#define SK_VERTEXID_BUILTIN 5 +#define SK_CLIPDISTANCE_BUILTIN 3 +#define SK_INVOCATIONID_BUILTIN 8 namespace SkSL { @@ -54,6 +58,10 @@ public: bool toGLSL(const Program& program, String* out); + bool toCPP(const Program& program, String name, OutputStream& out); + + bool toH(const Program& program, String name, OutputStream& out); + void error(Position position, String msg) override; String errorText(); diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h index 53e5ea0954..1155af4817 100644 --- a/src/sksl/SkSLContext.h +++ b/src/sksl/SkSLContext.h @@ -66,8 +66,7 @@ public: , fSamplerExternalOES_Type(new Type(String("samplerExternalOES"), SpvDim2D, false, false, false, true)) , fSamplerCube_Type(new Type(String("samplerCube"), SpvDimCube, false, false, false, true)) - , fSampler2DRect_Type(new Type(String("sampler2DRect"), SpvDimRect, false, false, false, - true)) + , fSampler2DRect_Type(new Type(String("sampler2DRect"), SpvDimRect, false, false, false, true)) , fSampler1DArray_Type(new Type(String("sampler1DArray"))) , fSampler2DArray_Type(new Type(String("sampler2DArray"))) , fSamplerCubeArray_Type(new Type(String("samplerCubeArray"))) @@ -151,6 +150,8 @@ public: , fBVec_Type(new Type(String("$bvec"), { fInvalid_Type.get(), fBVec2_Type.get(), fBVec3_Type.get(), fBVec4_Type.get() })) , fSkCaps_Type(new Type(String("$sk_Caps"))) + , fSkArgs_Type(new Type(String("$sk_Args"))) + , fColorSpaceXform_Type(new Type(String("colorSpaceXform"), *fFloat_Type, 4, 4)) , fDefined_Expression(new Defined(*fInvalid_Type)) {} static std::vector<const Type*> static_type(const Type& t) { @@ -225,7 +226,6 @@ public: const std::unique_ptr<Type> fSampler2DArrayShadow_Type; const std::unique_ptr<Type> fSamplerCubeArrayShadow_Type; - const std::unique_ptr<Type> fISampler2D_Type; const std::unique_ptr<Type> fImage2D_Type; @@ -269,6 +269,8 @@ public: const std::unique_ptr<Type> fBVec_Type; const std::unique_ptr<Type> fSkCaps_Type; + const std::unique_ptr<Type> fSkArgs_Type; + const std::unique_ptr<Type> fColorSpaceXform_Type; // dummy expression used to mark that a variable has a value during dataflow analysis (when it // could have several different values, or the analyzer is otherwise unable to assign it a @@ -281,14 +283,14 @@ private: Defined(const Type& type) : INHERITED(Position(), kDefined_Kind, type) {} - virtual String description() const override { - return String("<defined>"); - } - bool hasSideEffects() const override { return false; } + String description() const override { + return String("<defined>"); + } + typedef Expression INHERITED; }; }; diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index 4326f4c794..36a43cf927 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -34,7 +34,7 @@ void GLSLCodeGenerator::write(const char* s) { void GLSLCodeGenerator::writeLine(const char* s) { this->write(s); - fOut->write8('\n'); + fOut->writeText(fLineEnding); fAtLineStart = true; } @@ -108,6 +108,9 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren case Expression::kPostfix_Kind: this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence); break; + case Expression::kSetting_Kind: + this->writeSetting((Setting&) expr); + break; case Expression::kSwizzle_Kind: this->writeSwizzle((Swizzle&) expr); break; @@ -371,7 +374,7 @@ void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { } } -static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) { +GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) { switch (op) { case Token::STAR: // fall through case Token::SLASH: // fall through @@ -413,7 +416,7 @@ static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) { void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence) { - Precedence precedence = get_binary_precedence(b.fOperator); + Precedence precedence = GetBinaryPrecedence(b.fOperator); if (precedence >= parentPrecedence) { this->write("("); } @@ -480,6 +483,10 @@ void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { this->write(to_string(f.fValue)); } +void GLSLCodeGenerator::writeSetting(const Setting& s) { + ABORT("internal error; setting was not folded to a constant during compilation\n"); +} + void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { this->writeType(f.fDeclaration.fReturnType); this->write(" " + f.fDeclaration.fName + "("); @@ -517,7 +524,7 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { fOut = oldOut; this->write(fFunctionHeader); - this->write(String(buffer.data(), buffer.size())); + this->write(buffer.str()); } void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, @@ -617,6 +624,10 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { this->writeLine(";"); } +void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) { + this->writeExpression(value, kTopLevel_Precedence); +} + void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { ASSERT(decl.fVars.size() > 0); bool wroteType = false; @@ -640,7 +651,7 @@ void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool g } if (var.fValue) { this->write(" = "); - this->writeExpression(*var.fValue, kTopLevel_Precedence); + this->writeVarInitializer(*var.fVar, *var.fValue); } if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) { if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) { @@ -797,10 +808,7 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { this->write(";"); } -bool GLSLCodeGenerator::generateCode() { - OutputStream* rawOut = fOut; - fOut = &fHeader; - fProgramKind = fProgram.fKind; +void GLSLCodeGenerator::writeHeader() { this->write(fProgram.fSettings.fCaps->versionDeclString()); this->writeLine(); for (const auto& e : fProgram.fElements) { @@ -808,8 +816,6 @@ bool GLSLCodeGenerator::generateCode() { this->writeExtension((Extension&) *e); } } - StringStream body; - fOut = &body; if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { this->write("precision "); switch (fProgram.fDefaultPrecision) { @@ -828,47 +834,58 @@ bool GLSLCodeGenerator::generateCode() { } this->writeLine(" float;"); } - for (const auto& e : fProgram.fElements) { - switch (e->fKind) { - case ProgramElement::kExtension_Kind: - break; - case ProgramElement::kVar_Kind: { - VarDeclarations& decl = (VarDeclarations&) *e; - if (decl.fVars.size() > 0) { - ASSERT(decl.fVars[0]->fKind == Statement::kVarDeclaration_Kind); - int builtin = - ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin; - if (builtin == -1) { - // normal var - this->writeVarDeclarations(decl, true); - this->writeLine(); - } else if (builtin == SK_FRAGCOLOR_BUILTIN && - fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { - this->write("out "); - if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { - this->write("mediump "); - } - this->writeLine("vec4 sk_FragColor;"); +} + +void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { + switch (e.fKind) { + case ProgramElement::kExtension_Kind: + break; + case ProgramElement::kVar_Kind: { + VarDeclarations& decl = (VarDeclarations&) e; + if (decl.fVars.size() > 0) { + int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin; + if (builtin == -1) { + // normal var + this->writeVarDeclarations(decl, true); + this->writeLine(); + } else if (builtin == SK_FRAGCOLOR_BUILTIN && + fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { + this->write("out "); + if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { + this->write("mediump "); } + this->writeLine("vec4 sk_FragColor;"); } - break; } - case ProgramElement::kInterfaceBlock_Kind: - this->writeInterfaceBlock((InterfaceBlock&) *e); - break; - 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"); + break; } + case ProgramElement::kInterfaceBlock_Kind: + this->writeInterfaceBlock((InterfaceBlock&) e); + break; + 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"); + } +} + +bool GLSLCodeGenerator::generateCode() { + OutputStream* rawOut = fOut; + fOut = &fHeader; + fProgramKind = fProgram.fKind; + this->writeHeader(); + StringStream body; + fOut = &body; + for (const auto& e : fProgram.fElements) { + this->writeProgramElement(*e); } - fOut = nullptr; + fOut = rawOut; write_stringstream(fHeader, *rawOut); write_stringstream(body, *rawOut); diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h index 032b70eea1..c0a638797b 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.h +++ b/src/sksl/SkSLGLSLCodeGenerator.h @@ -13,6 +13,7 @@ #include <unordered_map> #include "SkSLCodeGenerator.h" +#include "SkSLStringStream.h" #include "ir/SkSLBinaryExpression.h" #include "ir/SkSLBoolLiteral.h" #include "ir/SkSLConstructor.h" @@ -32,6 +33,7 @@ #include "ir/SkSLPostfixExpression.h" #include "ir/SkSLProgramElement.h" #include "ir/SkSLReturnStatement.h" +#include "ir/SkSLSetting.h" #include "ir/SkSLStatement.h" #include "ir/SkSLSwitchStatement.h" #include "ir/SkSLSwizzle.h" @@ -74,11 +76,12 @@ public: GLSLCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors, OutputStream* out) : INHERITED(program, errors, out) + , fLineEnding("\n") , fContext(*context) {} - virtual bool generateCode() override; + bool generateCode() override; -private: +protected: void write(const char* s); void writeLine(); @@ -89,6 +92,8 @@ private: void writeLine(const String& s); + virtual void writeHeader(); + void writeType(const Type& type); void writeExtension(const Extension& ext); @@ -99,7 +104,7 @@ private: void writeFunctionDeclaration(const FunctionDeclaration& f); - void writeFunction(const FunctionDefinition& f); + virtual void writeFunction(const FunctionDefinition& f); void writeLayout(const Layout& layout); @@ -107,11 +112,13 @@ private: void writeGlobalVars(const VarDeclaration& vs); + virtual void writeVarInitializer(const Variable& var, const Expression& value); + void writeVarDeclarations(const VarDeclarations& decl, bool global); void writeFragCoord(); - void writeVariableReference(const VariableReference& ref); + virtual void writeVariableReference(const VariableReference& ref); void writeExpression(const Expression& expr, Precedence parentPrecedence); @@ -127,11 +134,13 @@ private: void writeSwizzle(const Swizzle& swizzle); - void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence); + static Precedence GetBinaryPrecedence(Token::Kind op); + + virtual void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence); void writeTernaryExpression(const TernaryExpression& t, Precedence parentPrecedence); - void writeIndexExpression(const IndexExpression& expr); + virtual void writeIndexExpression(const IndexExpression& expr); void writePrefixExpression(const PrefixExpression& p, Precedence parentPrecedence); @@ -143,6 +152,8 @@ private: void writeFloatLiteral(const FloatLiteral& f); + virtual void writeSetting(const Setting& s); + void writeStatement(const Statement& s); void writeStatements(const std::vector<std::unique_ptr<Statement>>& statements); @@ -161,6 +172,9 @@ private: void writeReturnStatement(const ReturnStatement& r); + virtual void writeProgramElement(const ProgramElement& e); + + const char* fLineEnding; const Context& fContext; StringStream fHeader; String fFunctionHeader; diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp new file mode 100644 index 0000000000..0eb43df046 --- /dev/null +++ b/src/sksl/SkSLHCodeGenerator.cpp @@ -0,0 +1,236 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSLHCodeGenerator.h" + +#include "SkSLUtil.h" +#include "ir/SkSLFunctionDeclaration.h" +#include "ir/SkSLFunctionDefinition.h" +#include "ir/SkSLSection.h" +#include "ir/SkSLVarDeclarations.h" + +namespace SkSL { + +HCodeGenerator::HCodeGenerator(const Program* program, ErrorReporter* errors, String name, + OutputStream* out) +: INHERITED(program, errors, out) +, fName(std::move(name)) +, fFullName(String::printf("Gr%s", fName.c_str())) +, fSectionAndParameterHelper(*program, *errors) {} + +String HCodeGenerator::ParameterType(const Type& type) { + if (type.fName == "vec2") { + return "SkPoint"; + } else if (type.fName == "ivec4") { + return "SkIRect"; + } else if (type.fName == "vec4") { + return "SkRect"; + } else if (type.fName == "mat4") { + return "SkMatrix44"; + } else if (type.kind() == Type::kSampler_Kind) { + return "sk_sp<GrTextureProxy>"; + } else if (type.fName == "colorSpaceXform") { + return "sk_sp<GrColorSpaceXform>"; + } + return type.name(); +} + +String HCodeGenerator::FieldType(const Type& type) { + if (type.kind() == Type::kSampler_Kind) { + return "TextureSampler"; + } + return ParameterType(type); +} + +void HCodeGenerator::writef(const char* s, va_list va) { + static constexpr int BUFFER_SIZE = 1024; + char buffer[BUFFER_SIZE]; + int length = vsnprintf(buffer, BUFFER_SIZE, s, va); + if (length < BUFFER_SIZE) { + fOut->write(buffer, length); + } else { + std::unique_ptr<char[]> heap(new char[length + 1]); + vsprintf(heap.get(), s, va); + fOut->write(heap.get(), length); + } +} + +void HCodeGenerator::writef(const char* s, ...) { + va_list va; + va_start(va, s); + this->writef(s, va); + va_end(va); +} + +bool HCodeGenerator::writeSection(const char* name, const char* prefix) { + const auto found = fSectionAndParameterHelper.fSections.find(String(name)); + if (found != fSectionAndParameterHelper.fSections.end()) { + this->writef("%s%s", prefix, found->second->fText.c_str()); + return true; + } + return false; +} + +void HCodeGenerator::writeExtraConstructorParams(const char* separator) { + // super-simple parse, just assume the last token before a comma is the name of a parameter + // (which is true as long as there are no multi-parameter template types involved). Will replace + // this with something more robust if the need arises. + const auto found = fSectionAndParameterHelper.fSections.find( + String(CONSTRUCTOR_PARAMS_SECTION)); + if (found != fSectionAndParameterHelper.fSections.end()) { + const char* s = found->second->fText.c_str(); + #define BUFFER_SIZE 64 + char lastIdentifier[BUFFER_SIZE]; + int lastIdentifierLength = 0; + bool foundBreak = false; + while (*s) { + char c = *s; + ++s; + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || + c == '_') { + if (foundBreak) { + lastIdentifierLength = 0; + foundBreak = false; + } + ASSERT(lastIdentifierLength < BUFFER_SIZE); + lastIdentifier[lastIdentifierLength] = c; + ++lastIdentifierLength; + } else { + foundBreak = true; + if (c == ',') { + ASSERT(lastIdentifierLength < BUFFER_SIZE); + lastIdentifier[lastIdentifierLength] = 0; + this->writef("%s%s", separator, lastIdentifier); + separator = ", "; + } else if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { + lastIdentifierLength = 0; + } + } + } + if (lastIdentifierLength) { + ASSERT(lastIdentifierLength < BUFFER_SIZE); + lastIdentifier[lastIdentifierLength] = 0; + this->writef("%s%s", separator, lastIdentifier); + } + } +} + +void HCodeGenerator::writeMake() { + const char* separator; + if (!this->writeSection(MAKE_SECTION)) { + this->writef(" static sk_sp<GrFragmentProcessor> Make("); + separator = ""; + for (const auto& param : fSectionAndParameterHelper.fParameters) { + this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(), + param->fName.c_str()); + separator = ", "; + } + this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator); + this->writef(") {\n" + " return sk_sp<GrFragmentProcessor>(new %s(", + fFullName.c_str()); + separator = ""; + for (const auto& param : fSectionAndParameterHelper.fParameters) { + this->writef("%s%s", separator, param->fName.c_str()); + separator = ", "; + } + this->writeExtraConstructorParams(separator); + this->writef("));\n" + " }\n"); + } +} + +void HCodeGenerator::writeConstructor() { + if (this->writeSection(CONSTRUCTOR_SECTION)) { + return; + } + this->writef(" %s(", fFullName.c_str()); + const char* separator = ""; + for (const auto& param : fSectionAndParameterHelper.fParameters) { + this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(), + param->fName.c_str()); + separator = ", "; + } + this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator); + this->writef(")\n" + " : INHERITED("); + if (!this->writeSection(OPTIMIZATION_FLAGS_SECTION, "(OptimizationFlags) ")) { + this->writef("kNone_OptimizationFlags"); + } + this->writef(")"); + this->writeSection(INITIALIZERS_SECTION, "\n , "); + for (const auto& param : fSectionAndParameterHelper.fParameters) { + const char* name = param->fName.c_str(); + if (param->fType.kind() == Type::kSampler_Kind) { + this->writef("\n , %s(resourceProvider, std::move(%s))", FieldName(name).c_str(), + name); + } else { + this->writef("\n , %s(%s)", FieldName(name).c_str(), name); + } + } + this->writef(" {\n"); + this->writeSection(CONSTRUCTOR_CODE_SECTION); + for (const auto& param : fSectionAndParameterHelper.fParameters) { + if (param->fType.kind() == Type::kSampler_Kind) { + this->writef(" this->addTextureSampler(&%s);\n", + FieldName(param->fName.c_str()).c_str()); + } + } + this->writef(" this->initClassID<%s>();\n" + " }\n", + fFullName.c_str()); +} + +void HCodeGenerator::writeFields() { + this->writeSection(FIELDS_SECTION); + for (const auto& param : fSectionAndParameterHelper.fParameters) { + const char* name = param->fName.c_str(); + this->writef(" %s %s;\n", FieldType(param->fType).c_str(), FieldName(name).c_str()); + } +} + +bool HCodeGenerator::generateCode() { + this->writef("/*\n" + " * This file was autogenerated from %s.fp.\n" + " */\n" + "#ifndef %s_DEFINED\n" + "#define %s_DEFINED\n" + "#include \"GrFragmentProcessor.h\"\n" + "#include \"GrCoordTransform.h\"\n" + "#include \"effects/GrProxyMove.h\"\n", + fFullName.c_str(), fFullName.c_str(), fFullName.c_str()); + this->writeSection(HEADER_SECTION); + this->writef("class %s : public GrFragmentProcessor {\n" + "public:\n", + fFullName.c_str()); + this->writeSection(CLASS_SECTION); + for (const auto& param : fSectionAndParameterHelper.fParameters) { + if (param->fType.kind() == Type::kSampler_Kind) { + continue; + } + const char* name = param->fName.c_str(); + this->writef("%s %s() const { return %s; }\n", + FieldType(param->fType).c_str(), name, FieldName(name).c_str()); + } + this->writeMake(); + this->writef(" const char* name() const override { return \"%s\"; }\n" + "private:\n", + fName.c_str()); + this->writeConstructor(); + this->writef(" GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n" + " void onGetGLSLProcessorKey(const GrShaderCaps&," + "GrProcessorKeyBuilder*) const override;\n" + " bool onIsEqual(const GrFragmentProcessor&) const override;\n" + " GR_DECLARE_FRAGMENT_PROCESSOR_TEST;\n"); + this->writeFields(); + this->writef(" typedef GrFragmentProcessor INHERITED;\n" + "};\n" + "#endif\n"); + return 0 == fErrors.errorCount(); +} + +} // namespace diff --git a/src/sksl/SkSLHCodeGenerator.h b/src/sksl/SkSLHCodeGenerator.h new file mode 100644 index 0000000000..1025d7f43c --- /dev/null +++ b/src/sksl/SkSLHCodeGenerator.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKSL_HCODEGENERATOR +#define SKSL_HCODEGENERATOR + +#include "SkSLCodeGenerator.h" +#include "SkSLSectionAndParameterHelper.h" +#include "ir/SkSLType.h" +#include "ir/SkSLVariable.h" + +#include <cctype> + +namespace SkSL { + +class HCodeGenerator : public CodeGenerator { +public: + HCodeGenerator(const Program* program, ErrorReporter* errors, String name, OutputStream* out); + + bool generateCode() override; + + static String ParameterType(const Type& type); + + static String FieldType(const Type& type); + + static String FieldName(const char* varName) { + return String::printf("f%c%s", toupper(varName[0]), varName + 1); + } + +private: + void writef(const char* s, va_list va) SKSL_PRINTF_LIKE(2, 0); + + void writef(const char* s, ...) SKSL_PRINTF_LIKE(2, 3); + + bool writeSection(const char* name, const char* prefix = ""); + + // given a @constructorParams section of e.g. 'int x, float y', writes out "<separator>x, y". + // Writes nothing (not even the separator) if there is no @constructorParams section. + void writeExtraConstructorParams(const char* separator); + + void writeMake(); + + void writeConstructor(); + + void writeFields(); + + String fName; + String fFullName; + SectionAndParameterHelper fSectionAndParameterHelper; + + typedef CodeGenerator INHERITED; +}; + +} // namespace SkSL + +#endif diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index 159ede46e2..78672cb52e 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -42,6 +42,7 @@ #include "ir/SkSLPostfixExpression.h" #include "ir/SkSLPrefixExpression.h" #include "ir/SkSLReturnStatement.h" +#include "ir/SkSLSetting.h" #include "ir/SkSLSwitchCase.h" #include "ir/SkSLSwitchStatement.h" #include "ir/SkSLSwizzle.h" @@ -104,9 +105,11 @@ IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> sy ErrorReporter& errorReporter) : fContext(*context) , fCurrentFunction(nullptr) -, fSymbolTable(std::move(symbolTable)) +, fRootSymbolTable(symbolTable) +, fSymbolTable(symbolTable) , fLoopLevel(0) , fSwitchLevel(0) +, fTmpCount(0) , fErrors(errorReporter) {} void IRGenerator::pushSymbolTable() { @@ -117,8 +120,10 @@ void IRGenerator::popSymbolTable() { fSymbolTable = fSymbolTable->fParent; } -static void fill_caps(const SKSL_CAPS_CLASS& caps, std::unordered_map<String, CapValue>* capsMap) { -#define CAP(name) capsMap->insert(std::make_pair(String(#name), CapValue(caps.name()))); +static void fill_caps(const SKSL_CAPS_CLASS& caps, + std::unordered_map<String, Program::Settings::Value>* capsMap) { +#define CAP(name) capsMap->insert(std::make_pair(String(#name), \ + Program::Settings::Value(caps.name()))); CAP(fbFetchSupport); CAP(fbFetchNeedsCustomOutput); CAP(bindlessTextureSupport); @@ -135,6 +140,7 @@ static void fill_caps(const SKSL_CAPS_CLASS& caps, std::unordered_map<String, Ca CAP(mustEnableSpecificAdvBlendEqs); CAP(mustDeclareFragmentShaderOutput); CAP(canUseAnyFunctionInShader); + CAP(floatPrecisionVaries); #undef CAP } @@ -673,7 +679,12 @@ void IRGenerator::convertFunction(const ASTFunction& f, bool needInvocationIDWorkaround = fSettings->fCaps && fSettings->fCaps->mustImplementGSInvocationsWithLoop() && fInvocations != -1 && f.fName == "main"; + ASSERT(!fExtraVars.size()); std::unique_ptr<Block> body = this->convertBlock(*f.fBody); + for (auto& v : fExtraVars) { + body->fStatements.insert(body->fStatements.begin(), std::move(v)); + } + fExtraVars.clear(); fCurrentFunction = nullptr; if (!body) { return; @@ -845,6 +856,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& } case Symbol::kVariable_Kind: { const Variable* var = (const Variable*) result; +#ifndef SKSL_STANDALONE if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) { fInputs.fFlipY = true; if (fSettings->fFlipY && @@ -853,6 +865,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& fInputs.fRTHeight = true; } } +#endif // default to kRead_RefKind; this will be corrected later if the variable is written to return std::unique_ptr<VariableReference>(new VariableReference( identifier.fPosition, @@ -876,9 +889,13 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& default: ABORT("unsupported symbol type %d\n", result->fKind); } +} +std::unique_ptr<Section> IRGenerator::convertSection(const ASTSection& s) { + return std::unique_ptr<Section>(new Section(s.fPosition, s.fName, s.fArgument, s.fText)); } + std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr, const Type& type) { if (!expr) { @@ -904,6 +921,9 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr ASSERT(ctor); return this->call(Position(), std::move(ctor), std::move(args)); } + if (type == *fContext.fColorSpaceXform_Type && expr->fType == *fContext.fMat4x4_Type) { + return expr; + } 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))); @@ -1332,7 +1352,7 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, return nullptr; } if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) { - this->markWrittenTo(*arguments[i], + this->markWrittenTo(*arguments[i], function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag); } } @@ -1373,6 +1393,87 @@ bool IRGenerator::determineCallCost(const FunctionDeclaration& function, return true; } +std::unique_ptr<Expression> IRGenerator::applyColorSpace(std::unique_ptr<Expression> texture, + const Variable* xform) { + // Before: + // vec4 color = texture(img, coords, xform); + // After: + // vec4 tmp; + // vec4 color = (tmp = texture(img, coords) , + // xform != mat4(1) ? + // vec4(clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a), tmp.a) : + // tmp); + + // a few macros to keep line lengths manageable + #define EXPR std::unique_ptr<Expression> + #define REF(v) EXPR(new VariableReference(p, *v)) + #define FLOAT(x) EXPR(new FloatLiteral(fContext, p, x)) + using std::move; + Position p = Position(); + // vec4 tmp; + Variable* tmp = new Variable(p, Modifiers(), "_tmp" + to_string(fTmpCount++), texture->fType, + Variable::kLocal_Storage); + fRootSymbolTable->takeOwnership(tmp); + std::vector<std::unique_ptr<VarDeclaration>> decls; + decls.emplace_back(new VarDeclaration(tmp, std::vector<std::unique_ptr<Expression>>(), + nullptr)); + const Type& type = texture->fType; + fExtraVars.emplace_back(new VarDeclarationsStatement(std::unique_ptr<VarDeclarations>( + new VarDeclarations(p, &type, move(decls))))); + // tmp = texture + EXPR assignment = EXPR(new BinaryExpression(p, + EXPR(new VariableReference(p, *tmp, + VariableReference::kWrite_RefKind)), + Token::EQ, + move(texture), type)); + // 1.0 + std::vector<EXPR> matArgs; + matArgs.push_back(FLOAT(1.0)); + // mat4(1.0) + EXPR mat = EXPR(new Constructor(p, *fContext.fMat4x4_Type, move(matArgs))); + // <xform> != mat4(1.0) + EXPR matNeq = EXPR(new BinaryExpression(p, REF(xform), Token::NEQ, move(mat), + *fContext.fBool_Type)); + // tmp.rgb + std::vector<int> rgb { 0, 1, 2 }; + EXPR tmpRgb = EXPR(new Swizzle(fContext, REF(tmp), rgb)); + // vec4(tmp.rgb, 1.0) + std::vector<EXPR> tmpVecArgs; + tmpVecArgs.push_back(move(tmpRgb)); + tmpVecArgs.push_back(FLOAT(1.0)); + EXPR tmpVec = EXPR(new Constructor(p, *fContext.fVec4_Type, move(tmpVecArgs))); + // xform * vec4(tmp.rgb, 1.0) + EXPR mul = EXPR(new BinaryExpression(p, REF(xform), Token::STAR, move(tmpVec), + *fContext.fVec4_Type)); + // (xform * vec4(tmp.rgb, 1.0)).rgb + EXPR mulRGB = EXPR(new Swizzle(fContext, std::move(mul), rgb)); + // tmp.a + std::vector<int> a { 3 }; + EXPR tmpA = EXPR(new Swizzle(fContext, REF(tmp), a)); + // clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a) + EXPR clamp = this->convertIdentifier(ASTIdentifier(p, "clamp")); + std::vector<EXPR> clampArgs; + clampArgs.push_back(move(mulRGB)); + clampArgs.push_back(FLOAT(0)); + clampArgs.push_back(move(tmpA)); + EXPR clampCall = this->call(p, move(clamp), move(clampArgs)); + // tmp.a + tmpA = EXPR(new Swizzle(fContext, REF(tmp), a)); + // vec4(clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a), tmp.a) + std::vector<EXPR> finalVecArgs; + finalVecArgs.push_back(move(clampCall)); + finalVecArgs.push_back(move(tmpA)); + EXPR finalVec = EXPR(new Constructor(p, *fContext.fVec4_Type, move(finalVecArgs))); + // xform != mat4(1) ? vec4(clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a), tmp.a) : tmp) + EXPR ternary = EXPR(new TernaryExpression(p, move(matNeq), move(finalVec), REF(tmp))); + // (tmp = texture , + // xform != mat4(1) ? vec4(clamp((xform * vec4(tmp.rgb, 1.0)).rgb, 0.0, tmp.a), tmp.a) : tmp)) + return EXPR(new BinaryExpression(p, move(assignment), Token::COMMA, move(ternary), type)); + #undef EXPR + #undef REF + #undef FLOAT +} + std::unique_ptr<Expression> IRGenerator::call(Position position, std::unique_ptr<Expression> functionValue, std::vector<std::unique_ptr<Expression>> arguments) { @@ -1386,6 +1487,17 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, return nullptr; } FunctionReference* ref = (FunctionReference*) functionValue.get(); + if (ref->fFunctions[0]->fName == "texture" && + arguments.back()->fType == *fContext.fColorSpaceXform_Type) { + std::unique_ptr<Expression> colorspace = std::move(arguments.back()); + ASSERT(colorspace->fKind == Expression::kVariableReference_Kind); + arguments.pop_back(); + return this->applyColorSpace(this->call(position, + std::move(functionValue), + std::move(arguments)), + &((VariableReference&) *colorspace).fVariable); + } + int bestCost = INT_MAX; const FunctionDeclaration* best = nullptr; if (ref->fFunctions.size() > 1) { @@ -1451,7 +1563,7 @@ std::unique_ptr<Expression> IRGenerator::convertNumberConstructor( args[0]->fType.description() + "')"); return nullptr; } - return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args))); + return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); } int component_count(const Type& type) { @@ -1473,8 +1585,7 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor( if (type.kind() == Type::kMatrix_Kind && args.size() == 1 && args[0]->fType.kind() == Type::kMatrix_Kind) { // matrix from matrix is always legal - return std::unique_ptr<Expression>(new Constructor(position, std::move(type), - std::move(args))); + return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); } int actual = 0; int expected = type.rows() * type.columns(); @@ -1511,7 +1622,7 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor( return nullptr; } } - return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args))); + return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); } std::unique_ptr<Expression> IRGenerator::convertConstructor( @@ -1534,8 +1645,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor( return nullptr; } } - return std::unique_ptr<Expression>(new Constructor(position, std::move(type), - std::move(args))); + return std::unique_ptr<Expression>(new Constructor(position, type, std::move(args))); } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) { return this->convertCompoundConstructor(position, type, std::move(args)); } else { @@ -1727,16 +1837,21 @@ std::unique_ptr<Expression> IRGenerator::getCap(Position position, String name) fErrors.error(position, "unknown capability flag '" + name + "'"); return nullptr; } - switch (found->second.fKind) { - case CapValue::kBool_Kind: - return std::unique_ptr<Expression>(new BoolLiteral(fContext, position, - (bool) found->second.fValue)); - case CapValue::kInt_Kind: - return std::unique_ptr<Expression>(new IntLiteral(fContext, position, - found->second.fValue)); + String fullName = "sk_Caps." + name; + return std::unique_ptr<Expression>(new Setting(position, fullName, + found->second.literal(fContext, position))); +} + +std::unique_ptr<Expression> IRGenerator::getArg(Position position, String name) { + auto found = fSettings->fArgs.find(name); + if (found == fSettings->fArgs.end()) { + fErrors.error(position, "unknown argument '" + name + "'"); + return nullptr; } - ASSERT(false); - return nullptr; + String fullName = "sk_Args." + name; + return std::unique_ptr<Expression>(new Setting(position, + fullName, + found->second.literal(fContext, position))); } std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( @@ -1780,6 +1895,10 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( return this->getCap(expression.fPosition, ((ASTFieldSuffix&) *expression.fSuffix).fField); } + if (base->fType == *fContext.fSkArgs_Type) { + return this->getArg(expression.fPosition, + ((ASTFieldSuffix&) *expression.fSuffix).fField); + } switch (base->fType.kind()) { case Type::kVector_Kind: return this->convertSwizzle(std::move(base), @@ -1924,6 +2043,13 @@ void IRGenerator::convertProgram(String text, } break; } + case ASTDeclaration::kSection_Kind: { + std::unique_ptr<Section> s = this->convertSection((ASTSection&) decl); + if (s) { + out->push_back(std::move(s)); + } + break; + } case ASTDeclaration::kPrecision_Kind: { *defaultPrecision = ((ASTPrecision&) decl).fPrecision; break; diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 29513d8d34..3078a9e8df 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -27,6 +27,7 @@ #include "ast/SkSLASTModifiersDeclaration.h" #include "ast/SkSLASTPrefixExpression.h" #include "ast/SkSLASTReturnStatement.h" +#include "ast/SkSLASTSection.h" #include "ast/SkSLASTStatement.h" #include "ast/SkSLASTSuffixExpression.h" #include "ast/SkSLASTSwitchStatement.h" @@ -42,6 +43,7 @@ #include "ir/SkSLModifiers.h" #include "ir/SkSLModifiersDeclaration.h" #include "ir/SkSLProgram.h" +#include "ir/SkSLSection.h" #include "ir/SkSLSymbolTable.h" #include "ir/SkSLStatement.h" #include "ir/SkSLType.h" @@ -50,28 +52,6 @@ namespace SkSL { -struct CapValue { - CapValue() - : fKind(kInt_Kind) - , fValue(-1) { - ASSERT(false); - } - - CapValue(bool b) - : fKind(kBool_Kind) - , fValue(b) {} - - CapValue(int i) - : fKind(kInt_Kind) - , fValue(i) {} - - enum { - kBool_Kind, - kInt_Kind, - } fKind; - int fValue; -}; - /** * Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding * (unoptimized) intermediate representation (IR). @@ -95,6 +75,7 @@ public: Token::Kind op, const Expression& right) const; Program::Inputs fInputs; + const Program::Settings* fSettings; const Context& fContext; private: @@ -160,7 +141,9 @@ private: Modifiers convertModifiers(const Modifiers& m); std::unique_ptr<Expression> convertPrefixExpression(const ASTPrefixExpression& expression); std::unique_ptr<Statement> convertReturn(const ASTReturnStatement& r); + std::unique_ptr<Section> convertSection(const ASTSection& e); std::unique_ptr<Expression> getCap(Position position, String name); + std::unique_ptr<Expression> getArg(Position position, String name); std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression); std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base, const String& field); @@ -173,16 +156,26 @@ private: std::unique_ptr<Block> main, std::vector<std::unique_ptr<ProgramElement>>* out); + /** + * Wraps an expression in code that applies a colorspace transformation to it. This is used + * to implement texture(sampler, coord, colorSpaceXForm). + */ + std::unique_ptr<Expression> applyColorSpace(std::unique_ptr<Expression> texture, + const Variable* xform); void fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments); void checkValid(const Expression& expr); void markWrittenTo(const Expression& expr, bool readWrite); const FunctionDeclaration* fCurrentFunction; - const Program::Settings* fSettings; - std::unordered_map<String, CapValue> fCapsMap; + std::unordered_map<String, Program::Settings::Value> fCapsMap; + std::shared_ptr<SymbolTable> fRootSymbolTable; std::shared_ptr<SymbolTable> fSymbolTable; + // holds extra temp variable declarations needed for the current function + std::vector<std::unique_ptr<Statement>> fExtraVars; int fLoopLevel; int fSwitchLevel; + // count of temporary variables we have created + int fTmpCount; ErrorReporter& fErrors; int fInvocations; diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp index 1461bf9aae..ee868fb35e 100644 --- a/src/sksl/SkSLMain.cpp +++ b/src/sksl/SkSLMain.cpp @@ -5,11 +5,28 @@ * found in the LICENSE file. */ -#include "stdio.h" #include <fstream> #include "SkSLCompiler.h" #include "SkSLFileOutputStream.h" +// Given the path to a file (e.g. src/gpu/effects/GrFooFragmentProcessor.fp) and the expected +// filename prefix and suffix (e.g. "Gr" and ".fp"), returns the "base name" of the +// file (in this case, 'FooFragmentProcessor'). If no match, returns the empty string. +static SkSL::String base_name(const char* fpPath, const char* prefix, const char* suffix) { + SkSL::String result; + const char* end = fpPath + strlen(fpPath); + const char* fileName = end; + // back up until we find a slash + while (fileName != fpPath && '/' != *(fileName - 1) && '\\' != *(fileName - 1)) { + --fileName; + } + if (!strncmp(fileName, prefix, strlen(prefix)) && + !strncmp(end - strlen(suffix), suffix, strlen(suffix))) { + result.append(fileName + strlen(prefix), end - fileName - strlen(prefix) - strlen(suffix)); + } + return result; +} + /** * Very simple standalone executable to facilitate testing. */ @@ -19,15 +36,17 @@ int main(int argc, const char** argv) { exit(1); } SkSL::Program::Kind kind; - size_t len = strlen(argv[1]); - if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".vert")) { + String input(argv[1]); + if (input.endsWith(".vert")) { kind = SkSL::Program::kVertex_Kind; - } else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".frag")) { + } else if (input.endsWith(".frag")) { kind = SkSL::Program::kFragment_Kind; - } else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".geom")) { + } else if (input.endsWith(".geom")) { kind = SkSL::Program::kGeometry_Kind; + } else if (input.endsWith(".fp")) { + kind = SkSL::Program::kFragmentProcessor_Kind; } else { - printf("input filename must end in '.vert', '.frag', or '.geom'\n"); + printf("input filename must end in '.vert', '.frag', '.geom', or '.fp'\n"); exit(1); } @@ -40,6 +59,7 @@ int main(int argc, const char** argv) { exit(2); } SkSL::Program::Settings settings; + settings.fArgs.insert(std::make_pair("gpImplementsDistanceVector", 1)); SkSL::String name(argv[2]); if (name.endsWith(".spirv")) { SkSL::FileOutputStream out(argv[2]); @@ -73,7 +93,41 @@ int main(int argc, const char** argv) { printf("error writing '%s'\n", argv[2]); exit(4); } + } else if (name.endsWith(".h")) { + SkSL::FileOutputStream out(argv[2]); + SkSL::Compiler compiler; + if (!out.isValid()) { + printf("error writing '%s'\n", argv[2]); + exit(4); + } + settings.fReplaceSettings = false; + std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); + if (!program || !compiler.toH(*program, base_name(argv[1], "Gr", ".fp"), out)) { + printf("%s", compiler.errorText().c_str()); + exit(3); + } + if (!out.close()) { + printf("error writing '%s'\n", argv[2]); + exit(4); + } + } else if (name.endsWith(".cpp")) { + SkSL::FileOutputStream out(argv[2]); + SkSL::Compiler compiler; + if (!out.isValid()) { + printf("error writing '%s'\n", argv[2]); + exit(4); + } + settings.fReplaceSettings = false; + std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); + if (!program || !compiler.toCPP(*program, base_name(argv[1], "Gr", ".fp"), out)) { + printf("%s", compiler.errorText().c_str()); + exit(3); + } + if (!out.close()) { + printf("error writing '%s'\n", argv[2]); + exit(4); + } } else { - printf("expected output filename to end with '.spirv' or '.glsl'"); + printf("expected output filename to end with '.spirv', '.glsl', '.cpp', or '.h'"); } } diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index 5e8ec6398b..18ca311ee7 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -52,6 +52,7 @@ static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 + #include "ast/SkSLASTPrecision.h" #include "ast/SkSLASTPrefixExpression.h" #include "ast/SkSLASTReturnStatement.h" +#include "ast/SkSLASTSection.h" #include "ast/SkSLASTStatement.h" #include "ast/SkSLASTSuffixExpression.h" #include "ast/SkSLASTSwitchCase.h" @@ -113,7 +114,7 @@ Parser::~Parser() { layoutlex_destroy(fLayoutScanner); } -/* (precision | directive | declaration)* END_OF_FILE */ +/* (precision | directive | section | declaration)* END_OF_FILE */ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { std::vector<std::unique_ptr<ASTDeclaration>> result; for (;;) { @@ -134,6 +135,13 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { } break; } + case Token::SECTION: { + std::unique_ptr<ASTDeclaration> section = this->section(); + if (section) { + result.push_back(std::move(section)); + } + break; + } default: { std::unique_ptr<ASTDeclaration> decl = this->declaration(); if (!decl) { @@ -145,7 +153,7 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { } } -Token Parser::nextToken() { +Token Parser::nextRawToken() { if (fPushback.fKind != Token::INVALID_TOKEN) { Token result = fPushback; fPushback.fKind = Token::INVALID_TOKEN; @@ -153,25 +161,16 @@ Token Parser::nextToken() { return result; } int token = sksllex(fScanner); - String text; - switch ((Token::Kind) token) { - case Token::IDENTIFIER: // fall through - case Token::INT_LITERAL: // fall through - case Token::FLOAT_LITERAL: // fall through - case Token::DIRECTIVE: - text = String(skslget_text(fScanner)); - break; - default: -#ifdef SK_DEBUG - text = String(skslget_text(fScanner)); -#endif - break; - } - Position p = Position(skslget_lineno(fScanner), -1); - if (token == Token::INVALID_TOKEN) { - this->error(p, "invalid token: '" + text + "'"); - } - return Token(p, (Token::Kind) token, text); + return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token, + String(skslget_text(fScanner))); +} + +Token Parser::nextToken() { + Token token; + do { + token = this->nextRawToken(); + } while (token.fKind == Token::WHITESPACE); + return token; } void Parser::pushback(Token t) { @@ -296,6 +295,56 @@ std::unique_ptr<ASTDeclaration> Parser::directive() { } } +/* SECTION LBRACE (LPAREN IDENTIFIER RPAREN)? <any sequence of tokens with balanced braces> + RBRACE */ +std::unique_ptr<ASTDeclaration> Parser::section() { + Token start; + if (!this->expect(Token::SECTION, "a section token", &start)) { + return nullptr; + } + String argument; + if (this->peek().fKind == Token::LPAREN) { + this->nextToken(); + Token argToken; + if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) { + return nullptr; + } + argument = argToken.fText; + if (!this->expect(Token::RPAREN, "')'")) { + return nullptr; + } + } + if (!this->expect(Token::LBRACE, "'{'")) { + return nullptr; + } + String text; + int level = 1; + for (;;) { + Token next = this->nextRawToken(); + switch (next.fKind) { + case Token::LBRACE: + ++level; + break; + case Token::RBRACE: + --level; + break; + case Token::END_OF_FILE: + this->error(start.fPosition, "reached end of file while parsing section"); + return nullptr; + default: + break; + } + if (!level) { + break; + } + text += next.fText; + } + return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fPosition, + String(start.fText.c_str() + 1), + argument, + text)); +} + /* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */ std::unique_ptr<ASTDeclaration> Parser::declaration() { @@ -544,6 +593,61 @@ int Parser::layoutInt() { return -1; } +/** EQ <any sequence of tokens with balanced parentheses and no top-level comma> */ +String Parser::layoutCode() { + if (!this->expect(Token::EQ, "'='")) { + return ""; + } + Token start = this->peek(); + String code; + int level = 1; + bool done = false; + while (!done) { + Token next = this->peek(); + switch (next.fKind) { + case Token::LPAREN: + ++level; + break; + case Token::RPAREN: + --level; + break; + case Token::COMMA: + if (level == 1) { + done = true; + } + break; + case Token::END_OF_FILE: + this->error(start.fPosition, "reached end of file while parsing layout"); + return nullptr; + default: + break; + } + if (!level) { + done = true; + } + if (!done) { + code += this->nextRawToken().fText; + } + } + return code; +} + +/** (EQ IDENTIFIER('identity'))? */ +Layout::Key Parser::layoutKey() { + if (this->peek().fKind == Token::EQ) { + this->expect(Token::EQ, "'='"); + Token key; + if (this->expect(Token::IDENTIFIER, "an identifer", &key)) { + if (key.fText == "identity") { + return Layout::kIdentity_Key; + } else { + this->error(key.fPosition, "unsupported layout key"); + } + } + } + return Layout::kKey_Key; +} + /* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */ Layout Parser::layout() { int location = -1; @@ -561,11 +665,13 @@ Layout Parser::layout() { Layout::Primitive primitive = Layout::kUnspecified_Primitive; int maxVertices = -1; int invocations = -1; + String when; + Layout::Key key = Layout::kNo_Key; if (this->checkNext(Token::LAYOUT)) { if (!this->expect(Token::LPAREN, "'('")) { return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft, overrideCoverage, blendSupportAllEquations, format, - pushConstant, primitive, maxVertices, invocations); + pushConstant, primitive, maxVertices, invocations, when, key); } for (;;) { Token t = this->nextToken(); @@ -635,6 +741,12 @@ Layout Parser::layout() { case Token::INVOCATIONS: invocations = this->layoutInt(); break; + case Token::WHEN: + when = this->layoutCode(); + break; + case Token::KEY: + key = this->layoutKey(); + break; } } else if (Layout::ReadFormat(t.fText, &format)) { // AST::ReadFormat stored the result in 'format'. @@ -652,7 +764,7 @@ Layout Parser::layout() { } return Layout(location, offset, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft, overrideCoverage, blendSupportAllEquations, format, - pushConstant, primitive, maxVertices, invocations); + pushConstant, primitive, maxVertices, invocations, when, key); } /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE | diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h index 2f55b34986..e820484591 100644 --- a/src/sksl/SkSLParser.h +++ b/src/sksl/SkSLParser.h @@ -13,6 +13,7 @@ #include <unordered_map> #include <unordered_set> #include "SkSLErrorReporter.h" +#include "ir/SkSLLayout.h" #include "SkSLToken.h" struct yy_buffer_state; @@ -42,7 +43,6 @@ struct ASTSwitchStatement; struct ASTType; struct ASTWhileStatement; struct ASTVarDeclarations; -struct Layout; struct Modifiers; class SymbolTable; @@ -64,7 +64,12 @@ public: private: /** - * Return the next token from the parse stream. + * Return the next token, including whitespace tokens, from the parse stream. + */ + Token nextRawToken(); + + /** + * Return the next non-whitespace token from the parse stream. */ Token nextToken(); @@ -76,7 +81,7 @@ private: void pushback(Token t); /** - * Returns the next token without consuming it from the stream. + * Returns the next non-whitespace token without consuming it from the stream. */ Token peek(); @@ -87,8 +92,8 @@ private: bool checkNext(Token::Kind kind, Token* result = nullptr); /** - * Reads the next token and generates an error if it is not the expected type. The 'expected' - * string is part of the error message, which reads: + * Reads the next non-whitespace token and generates an error if it is not the expected type. + * The 'expected' string is part of the error message, which reads: * * "expected <expected>, but found '<actual text>'" * @@ -115,6 +120,8 @@ private: std::unique_ptr<ASTDeclaration> directive(); + std::unique_ptr<ASTDeclaration> section(); + std::unique_ptr<ASTDeclaration> declaration(); std::unique_ptr<ASTVarDeclarations> varDeclarations(); @@ -131,6 +138,10 @@ private: int layoutInt(); + String layoutCode(); + + Layout::Key layoutKey(); + Layout layout(); Modifiers modifiers(); diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index fda98204c0..94e8a58e51 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -1906,7 +1906,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O Type intfStruct(Position(), name, fields); Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false, Layout::Format::kUnspecified, false, Layout::kUnspecified_Primitive, -1, - -1); + -1, "", Layout::kNo_Key); Variable* intfVar = new Variable(Position(), Modifiers(layout, Modifiers::kUniform_Flag), name, @@ -2948,6 +2948,8 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& case Program::kGeometry_Kind: this->writeWord(SpvExecutionModelGeometry, out); break; + default: + ABORT("cannot write this kind of program to SPIR-V\n"); } this->writeWord(fFunctionMap[main], out); this->writeString(main->fName.c_str(), out); diff --git a/src/sksl/SkSLSectionAndParameterHelper.h b/src/sksl/SkSLSectionAndParameterHelper.h new file mode 100644 index 0000000000..81e5f3b192 --- /dev/null +++ b/src/sksl/SkSLSectionAndParameterHelper.h @@ -0,0 +1,111 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKSL_SECTIONANDPARAMETERHELPER +#define SKSL_SECTIONANDPARAMETERHELPER + +#include "SkSLErrorReporter.h" +#include "ir/SkSLProgram.h" +#include "ir/SkSLSection.h" +#include "ir/SkSLVarDeclarations.h" +#include <unordered_map> +#include <vector> + +namespace SkSL { + +#define CLASS_SECTION "class" +#define CPP_SECTION "cpp" +#define HEADER_SECTION "header" +#define CONSTRUCTOR_PARAMS_SECTION "constructorParams" +#define CONSTRUCTOR_SECTION "constructor" +#define CONSTRUCTOR_CODE_SECTION "constructorCode" +#define INITIALIZERS_SECTION "initializers" +#define EMIT_CODE_SECTION "emitCode" +#define FIELDS_SECTION "fields" +#define MAKE_SECTION "make" +#define OPTIMIZATION_FLAGS_SECTION "optimizationFlags" +#define SET_DATA_SECTION "setData" +#define TEST_CODE_SECTION "test" + +class SectionAndParameterHelper { +public: + SectionAndParameterHelper(const Program& program, ErrorReporter& errors) { + for (const auto& p : program.fElements) { + switch (p->fKind) { + case ProgramElement::kVar_Kind: { + const VarDeclarations* decls = (const VarDeclarations*) p.get(); + for (const auto& raw : decls->fVars) { + const VarDeclaration& decl = (VarDeclaration&) *raw; + if (IsParameter(*decl.fVar)) { + fParameters.push_back(decl.fVar); + } + } + break; + } + case ProgramElement::kSection_Kind: { + const Section* s = (const Section*) p.get(); + if (IsSupportedSection(s->fName.c_str())) { + if (SectionAcceptsArgument(s->fName.c_str())) { + if (!s->fArgument.size()) { + errors.error(s->fPosition, + ("section '@" + s->fName + + "' requires one parameter").c_str()); + } + } else if (s->fArgument.size()) { + errors.error(s->fPosition, + ("section '@" + s->fName + "' has no parameters").c_str()); + } + } else { + errors.error(s->fPosition, + ("unsupported section '@" + s->fName + "'").c_str()); + } + if (fSections.find(s->fName) != fSections.end()) { + errors.error(s->fPosition, + ("duplicate section '@" + s->fName + "'").c_str()); + } + fSections[s->fName] = s; + break; + } + default: + break; + } + } + } + + static bool IsParameter(const Variable& var) { + return (var.fModifiers.fFlags & Modifiers::kIn_Flag) && + -1 == var.fModifiers.fLayout.fBuiltin; + } + + static bool IsSupportedSection(const char* name) { + return !strcmp(name, CLASS_SECTION) || + !strcmp(name, CPP_SECTION) || + !strcmp(name, HEADER_SECTION) || + !strcmp(name, CONSTRUCTOR_SECTION) || + !strcmp(name, CONSTRUCTOR_CODE_SECTION) || + !strcmp(name, CONSTRUCTOR_PARAMS_SECTION) || + !strcmp(name, EMIT_CODE_SECTION) || + !strcmp(name, FIELDS_SECTION) || + !strcmp(name, INITIALIZERS_SECTION) || + !strcmp(name, MAKE_SECTION) || + !strcmp(name, OPTIMIZATION_FLAGS_SECTION) || + !strcmp(name, SET_DATA_SECTION) || + !strcmp(name, TEST_CODE_SECTION); + } + + static bool SectionAcceptsArgument(const char* name) { + return !strcmp(name, SET_DATA_SECTION) || + !strcmp(name, TEST_CODE_SECTION); + } + + std::vector<const Variable*> fParameters; + std::unordered_map<String, const Section*> fSections; +}; + +} // namespace SkSL + +#endif diff --git a/src/sksl/SkSLString.cpp b/src/sksl/SkSLString.cpp index 9b2c1780f8..fb8fd56de8 100644 --- a/src/sksl/SkSLString.cpp +++ b/src/sksl/SkSLString.cpp @@ -40,15 +40,16 @@ void String::vappendf(const char* fmt, va_list args) { #endif #define BUFFER_SIZE 256 char buffer[BUFFER_SIZE]; + va_list reuse; + va_copy(reuse, args); size_t size = VSNPRINTF(buffer, BUFFER_SIZE, fmt, args); if (BUFFER_SIZE >= size) { this->append(buffer, size); } else { - auto newBuffer = std::unique_ptr<char[]>(new char[size]); - VSNPRINTF(newBuffer.get(), size, fmt, args); + auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]); + VSNPRINTF(newBuffer.get(), size + 1, fmt, reuse); this->append(newBuffer.get(), size); } - va_end(args); } diff --git a/src/sksl/SkSLStringStream.h b/src/sksl/SkSLStringStream.h index 9061432018..a8690668d2 100644 --- a/src/sksl/SkSLStringStream.h +++ b/src/sksl/SkSLStringStream.h @@ -28,12 +28,8 @@ public: fBuffer.append((const char*) s, size); } - const char* data() const { - return fBuffer.c_str(); - } - - size_t size() const { - return fBuffer.size(); + const String& str() const { + return fBuffer; } void reset() { @@ -54,42 +50,33 @@ namespace SkSL { class StringStream : public OutputStream { public: void write8(uint8_t b) override { - SkASSERT(!fData); fStream.write8(b); } void writeText(const char* s) override { - SkASSERT(!fData); fStream.writeText(s); } void write(const void* s, size_t size) override { - SkASSERT(!fData); fStream.write(s, size); } - const char* data() const { - if (!fData) { - fData = fStream.detachAsData(); - } - return (const char*) fData->data(); - } - - size_t size() const { - if (!fData) { - fData = fStream.detachAsData(); + const String& str() const { + if (!fString.size()) { + sk_sp<SkData> data = fStream.detachAsData(); + fString = String((const char*) data->data(), data->size()); } - return fData->size(); + return fString; } void reset() { fStream.reset(); - fData = nullptr; + fString = ""; } private: mutable SkDynamicMemoryWStream fStream; - mutable sk_sp<SkData> fData; + mutable String fString; }; #endif // SKSL_STANDALONE diff --git a/src/sksl/SkSLToken.h b/src/sksl/SkSLToken.h index 92193b9674..2857a82547 100644 --- a/src/sksl/SkSLToken.h +++ b/src/sksl/SkSLToken.h @@ -24,6 +24,7 @@ namespace SkSL { struct Token { enum Kind { END_OF_FILE, + WHITESPACE, IDENTIFIER, INT_LITERAL, FLOAT_LITERAL, @@ -77,6 +78,8 @@ struct Token { LOGICALXOREQ, LOGICALANDEQ, SEMICOLON, + ARROW, + COLONCOLON, IF, STATIC_IF, ELSE, @@ -111,6 +114,7 @@ struct Token { STRUCT, LAYOUT, DIRECTIVE, + SECTION, PRECISION, LOCATION, OFFSET, @@ -132,6 +136,8 @@ struct Token { TRIANGLES_ADJACENCY, MAX_VERTICES, INVOCATIONS, + WHEN, + KEY, INVALID_TOKEN }; diff --git a/src/sksl/SkSLUtil.cpp b/src/sksl/SkSLUtil.cpp index c715cf1d09..49d37e3056 100644 --- a/src/sksl/SkSLUtil.cpp +++ b/src/sksl/SkSLUtil.cpp @@ -27,7 +27,7 @@ void sksl_abort() { } void write_stringstream(const StringStream& s, OutputStream& out) { - out.write(s.data(), s.size()); + out.write(s.str().c_str(), s.str().size()); } } // namespace diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index b56ae16d2c..606d3e375f 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -135,6 +135,10 @@ public: return false; } + bool floatPrecisionVaries() const { + return false; + } + const char* shaderDerivativeExtensionString() const { return nullptr; } diff --git a/src/sksl/ast/SkSLASTDeclaration.h b/src/sksl/ast/SkSLASTDeclaration.h index 0395ef91b4..873c6b2208 100644 --- a/src/sksl/ast/SkSLASTDeclaration.h +++ b/src/sksl/ast/SkSLASTDeclaration.h @@ -22,7 +22,8 @@ struct ASTDeclaration : public ASTPositionNode { kInterfaceBlock_Kind, kExtension_Kind, kPrecision_Kind, - kModifiers_Kind + kModifiers_Kind, + kSection_Kind }; ASTDeclaration(Position position, Kind kind) diff --git a/src/sksl/ast/SkSLASTFunction.h b/src/sksl/ast/SkSLASTFunction.h index 0dff3aeaa1..36d8a3af9f 100644 --- a/src/sksl/ast/SkSLASTFunction.h +++ b/src/sksl/ast/SkSLASTFunction.h @@ -20,7 +20,7 @@ namespace SkSL { */ struct ASTFunction : public ASTDeclaration { ASTFunction(Position position, Modifiers modifiers, std::unique_ptr<ASTType> returnType, - String name, std::vector<std::unique_ptr<ASTParameter>> parameters, + String name, std::vector<std::unique_ptr<ASTParameter>> parameters, std::unique_ptr<ASTBlock> body) : INHERITED(position, kFunction_Kind) , fModifiers(modifiers) diff --git a/src/sksl/ast/SkSLASTSection.h b/src/sksl/ast/SkSLASTSection.h new file mode 100644 index 0000000000..d0887e20fe --- /dev/null +++ b/src/sksl/ast/SkSLASTSection.h @@ -0,0 +1,43 @@ +/* + * 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_ASTSECTION +#define SKSL_ASTSECTION + +#include "SkSLASTDeclaration.h" + +namespace SkSL { + +/** + * A section declaration (e.g. @body { body code here }).. + */ +struct ASTSection : public ASTDeclaration { + ASTSection(Position position, String name, String arg, String text) + : INHERITED(position, kSection_Kind) + , fName(std::move(name)) + , fArgument(std::move(arg)) + , fText(std::move(text)) {} + + String description() const override { + String result = "@" + fName; + if (fArgument.size()) { + result += "(" + fArgument + ")"; + } + result += " { " + fText + " }"; + return result; + } + + const String fName; + const String fArgument; + const String fText; + + typedef ASTDeclaration INHERITED; +}; + +} // namespace + +#endif diff --git a/src/sksl/ir/SkSLExpression.h b/src/sksl/ir/SkSLExpression.h index 07dad1d7df..89a1a1e84a 100644 --- a/src/sksl/ir/SkSLExpression.h +++ b/src/sksl/ir/SkSLExpression.h @@ -36,6 +36,7 @@ struct Expression : public IRNode { kIndex_Kind, kPrefix_Kind, kPostfix_Kind, + kSetting_Kind, kSwizzle_Kind, kVariableReference_Kind, kTernary_Kind, diff --git a/src/sksl/ir/SkSLFunctionDeclaration.h b/src/sksl/ir/SkSLFunctionDeclaration.h index 8704c9a5b0..64236d3980 100644 --- a/src/sksl/ir/SkSLFunctionDeclaration.h +++ b/src/sksl/ir/SkSLFunctionDeclaration.h @@ -71,7 +71,7 @@ struct FunctionDeclaration : public Symbol { bool determineFinalTypes(const std::vector<std::unique_ptr<Expression>>& arguments, std::vector<const Type*>* outParameterTypes, const Type** outReturnType) const { - assert(arguments.size() == fParameters.size()); + ASSERT(arguments.size() == fParameters.size()); int genericIndex = -1; for (size_t i = 0; i < arguments.size(); i++) { if (fParameters[i]->fType.kind() == Type::kGeneric_Kind) { @@ -93,7 +93,7 @@ struct FunctionDeclaration : public Symbol { } } if (fReturnType.kind() == Type::kGeneric_Kind) { - assert(genericIndex != -1); + ASSERT(genericIndex != -1); *outReturnType = fReturnType.coercibleTypes()[genericIndex]; } else { *outReturnType = &fReturnType; diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h index 3a8416ac4e..8bf0472a95 100644 --- a/src/sksl/ir/SkSLLayout.h +++ b/src/sksl/ir/SkSLLayout.h @@ -8,6 +8,7 @@ #ifndef SKSL_LAYOUT #define SKSL_LAYOUT +#include "SkSLString.h" #include "SkSLUtil.h" namespace SkSL { @@ -42,6 +43,16 @@ struct Layout { kR8I, }; + // used by SkSL processors + enum Key { + // field is not a key + kNo_Key, + // field is a key + kKey_Key, + // key is 0 or 1 depending on whether the matrix is an identity matrix + kIdentity_Key, + }; + static const char* FormatToStr(Format format) { switch (format) { case Format::kUnspecified: return ""; @@ -55,7 +66,6 @@ struct Layout { case Format::kR8I: return "r8i"; } ABORT("Unexpected format"); - return ""; } static bool ReadFormat(String str, Format* format) { @@ -90,7 +100,7 @@ struct Layout { Layout(int location, int offset, int binding, int index, int set, int builtin, int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations, Format format, bool pushconstant, Primitive primitive, - int maxVertices, int invocations) + int maxVertices, int invocations, String when, Key key) : fLocation(location) , fOffset(offset) , fBinding(binding) @@ -105,7 +115,9 @@ struct Layout { , fPushConstant(pushconstant) , fPrimitive(primitive) , fMaxVertices(maxVertices) - , fInvocations(invocations) {} + , fInvocations(invocations) + , fWhen(when) + , fKey(key) {} Layout() : fLocation(-1) @@ -122,7 +134,8 @@ struct Layout { , fPushConstant(false) , fPrimitive(kUnspecified_Primitive) , fMaxVertices(-1) - , fInvocations(-1) {} + , fInvocations(-1) + , fKey(kNo_Key) {} String description() const { String result; @@ -215,6 +228,22 @@ struct Layout { result += separator + "invocations = " + to_string(fInvocations); separator = ", "; } + if (fWhen.size()) { + result += separator + "when = " + fWhen; + separator = ", "; + } + switch (fKey) { + case kNo_Key: + break; + case kKey_Key: + result += separator + "key"; + separator = ", "; + break; + case kIdentity_Key: + result += separator + "key=identity"; + separator = ", "; + break; + } if (result.size() > 0) { result = "layout (" + result + ")"; } @@ -261,6 +290,8 @@ struct Layout { Primitive fPrimitive; int fMaxVertices; int fInvocations; + String fWhen; + Key fKey; }; } // namespace diff --git a/src/sksl/ir/SkSLPrefixExpression.h b/src/sksl/ir/SkSLPrefixExpression.h index acab37ed88..5ac84c66b1 100644 --- a/src/sksl/ir/SkSLPrefixExpression.h +++ b/src/sksl/ir/SkSLPrefixExpression.h @@ -33,9 +33,8 @@ struct PrefixExpression : public Expression { fOperand->hasSideEffects(); } - virtual std::unique_ptr<Expression> constantPropagate( - const IRGenerator& irGenerator, - const DefinitionMap& definitions) override { + std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, + const DefinitionMap& definitions) override { if (fOperand->fKind == Expression::kFloatLiteral_Kind) { return std::unique_ptr<Expression>(new FloatLiteral( irGenerator.fContext, diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index 96bd5c4fbd..a3eeaa3612 100644 --- a/src/sksl/ir/SkSLProgram.h +++ b/src/sksl/ir/SkSLProgram.h @@ -11,7 +11,9 @@ #include <vector> #include <memory> -#include "SkSLContext.h" +#include "SkSLBoolLiteral.h" +#include "SkSLExpression.h" +#include "SkSLIntLiteral.h" #include "SkSLModifiers.h" #include "SkSLProgramElement.h" #include "SkSLSymbolTable.h" @@ -21,11 +23,46 @@ namespace SkSL { +class Context; + /** * Represents a fully-digested program, ready for code generation. */ struct Program { struct Settings { + struct Value { + Value(bool b) + : fKind(kBool_Kind) + , fValue(b) {} + + Value(int i) + : fKind(kInt_Kind) + , fValue(i) {} + + std::unique_ptr<Expression> literal(const Context& context, Position position) const { + switch (fKind) { + case Program::Settings::Value::kBool_Kind: + return std::unique_ptr<Expression>(new BoolLiteral(context, + position, + fValue)); + case Program::Settings::Value::kInt_Kind: + return std::unique_ptr<Expression>(new IntLiteral(context, + position, + fValue)); + default: + ASSERT(false); + return nullptr; + } + } + + enum { + kBool_Kind, + kInt_Kind, + } fKind; + + int fValue; + }; + #ifdef SKSL_STANDALONE const StandaloneShaderCaps* fCaps = &standaloneCaps; #else @@ -34,6 +71,10 @@ struct Program { // if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate // must be flipped. bool fFlipY = false; + // if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their + // constant equivalents during compilation + bool fReplaceSettings = true; + std::unordered_map<String, Value> fArgs; }; struct Inputs { @@ -57,7 +98,8 @@ struct Program { enum Kind { kFragment_Kind, kVertex_Kind, - kGeometry_Kind + kGeometry_Kind, + kFragmentProcessor_Kind }; Program(Kind kind, diff --git a/src/sksl/ir/SkSLProgramElement.h b/src/sksl/ir/SkSLProgramElement.h index ebb4e9a84d..1e2bb48641 100644 --- a/src/sksl/ir/SkSLProgramElement.h +++ b/src/sksl/ir/SkSLProgramElement.h @@ -21,7 +21,8 @@ struct ProgramElement : public IRNode { kFunction_Kind, kInterfaceBlock_Kind, kExtension_Kind, - kModifiers_Kind + kModifiers_Kind, + kSection_Kind }; ProgramElement(Position position, Kind kind) diff --git a/src/sksl/ir/SkSLSection.h b/src/sksl/ir/SkSLSection.h new file mode 100644 index 0000000000..f9815b1caa --- /dev/null +++ b/src/sksl/ir/SkSLSection.h @@ -0,0 +1,43 @@ +/* + * 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_SECTION +#define SKSL_SECTION + +#include "SkSLProgramElement.h" + +namespace SkSL { + +/** + * A section declaration (e.g. @body { body code here }).. + */ +struct Section : public ProgramElement { + Section(Position position, String name, String arg, String text) + : INHERITED(position, kSection_Kind) + , fName(std::move(name)) + , fArgument(std::move(arg)) + , fText(std::move(text)) {} + + String description() const override { + String result = "@" + fName; + if (fArgument.size()) { + result += "(" + fArgument + ")"; + } + result += " { " + fText + " }"; + return result; + } + + const String fName; + const String fArgument; + const String fText; + + typedef ProgramElement INHERITED; +}; + +} // namespace + +#endif diff --git a/src/sksl/ir/SkSLSetting.cpp b/src/sksl/ir/SkSLSetting.cpp new file mode 100644 index 0000000000..2d4a8ba151 --- /dev/null +++ b/src/sksl/ir/SkSLSetting.cpp @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSLSetting.h" +#include "SkSLIRGenerator.h" +#include "SkSLVariableReference.h" + +namespace SkSL { + +std::unique_ptr<Expression> Setting::constantPropagate(const IRGenerator& irGenerator, + const DefinitionMap& definitions) { + if (irGenerator.fSettings->fReplaceSettings) { + return VariableReference::copy_constant(irGenerator, fValue.get()); + } + return nullptr; + } +} // namespace + diff --git a/src/sksl/ir/SkSLSetting.h b/src/sksl/ir/SkSLSetting.h new file mode 100644 index 0000000000..995fcf55bf --- /dev/null +++ b/src/sksl/ir/SkSLSetting.h @@ -0,0 +1,51 @@ +/* + * 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_SETTING +#define SKSL_SETTING + +#include "SkSLContext.h" +#include "SkSLExpression.h" + +namespace SkSL { + +/** + * Represents a compile-time constant setting, such as sk_Caps.fbFetchSupport. These are generally + * collapsed down to their constant representations during the compilation process. + */ +struct Setting : public Expression { + Setting(Position position, String name, std::unique_ptr<Expression> value) + : INHERITED(position, kSetting_Kind, value->fType) + , fName(std::move(name)) + , fValue(std::move(value)) { + ASSERT(fValue->isConstant()); + } + + std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, + const DefinitionMap& definitions) override; + + String description() const override { + return fName; + } + + bool hasSideEffects() const override { + return false; + } + + bool isConstant() const override { + return true; + } + + const String fName; + std::unique_ptr<Expression> fValue; + + typedef Expression INHERITED; +}; + +} // namespace + +#endif diff --git a/src/sksl/ir/SkSLSwizzle.h b/src/sksl/ir/SkSLSwizzle.h index 1e36c41e41..442e92f348 100644 --- a/src/sksl/ir/SkSLSwizzle.h +++ b/src/sksl/ir/SkSLSwizzle.h @@ -71,10 +71,8 @@ struct Swizzle : public Expression { ASSERT(fComponents.size() >= 1 && fComponents.size() <= 4); } - virtual std::unique_ptr<Expression> constantPropagate( - const IRGenerator& irGenerator, - const DefinitionMap& definitions) override { - + std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, + const DefinitionMap& definitions) override { if (fBase->fKind == Expression::kConstructor_Kind && fBase->isConstant()) { // we're swizzling a constant vector, e.g. vec4(1).x. Simplify it. ASSERT(fBase->fKind == Expression::kConstructor_Kind); diff --git a/src/sksl/ir/SkSLVarDeclarations.h b/src/sksl/ir/SkSLVarDeclarations.h index c07fee87db..1eda87e979 100644 --- a/src/sksl/ir/SkSLVarDeclarations.h +++ b/src/sksl/ir/SkSLVarDeclarations.h @@ -55,7 +55,7 @@ struct VarDeclaration : public Statement { * A variable declaration statement, which may consist of one or more individual variables. */ struct VarDeclarations : public ProgramElement { - VarDeclarations(Position position, const Type* baseType, + VarDeclarations(Position position, const Type* baseType, std::vector<std::unique_ptr<VarDeclaration>> vars) : INHERITED(position, kVar_Kind) , fBaseType(*baseType) { diff --git a/src/sksl/ir/SkSLVariableReference.h b/src/sksl/ir/SkSLVariableReference.h index 92aef94290..ba17437e24 100644 --- a/src/sksl/ir/SkSLVariableReference.h +++ b/src/sksl/ir/SkSLVariableReference.h @@ -14,6 +14,7 @@ #include "SkSLFloatLiteral.h" #include "SkSLIRGenerator.h" #include "SkSLIntLiteral.h" +#include "SkSLSetting.h" namespace SkSL { @@ -104,6 +105,12 @@ struct VariableReference : public Expression { return std::unique_ptr<Expression>(new Constructor(Position(), c->fType, std::move(args))); } + case Expression::kSetting_Kind: { + const Setting* s = (const Setting*) expr; + return std::unique_ptr<Expression>(new Setting(Position(), s->fName, + copy_constant(irGenerator, + s->fValue.get()))); + } default: ABORT("unsupported constant\n"); } diff --git a/src/sksl/layout.flex b/src/sksl/layout.flex index 412bd4707b..4e6695cfdc 100644 --- a/src/sksl/layout.flex +++ b/src/sksl/layout.flex @@ -51,6 +51,8 @@ "triangles_adjacency" { return SkSL::Token::TRIANGLES_ADJACENCY; } "max_vertices" { return SkSL::Token::MAX_VERTICES; } "invocations" { return SkSL::Token::INVOCATIONS; } +"when" { return SkSL::Token::WHEN; } +"key" { return SkSL::Token::KEY; } . { return SkSL::Token::INVALID_TOKEN; } diff --git a/src/sksl/lex.layout.c b/src/sksl/lex.layout.c index 42db0fe5ef..63369fe93b 100644 --- a/src/sksl/lex.layout.c +++ b/src/sksl/lex.layout.c @@ -5,7 +5,7 @@ * found in the LICENSE file. */ -#line 2 "lex.layout.c" +#line 3 "lex.layout.c" #define YY_INT_ALIGNED short int @@ -14,81 +14,11 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 3 +#define YY_FLEX_SUBMINOR_VERSION 1 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif - #define yy_create_buffer layout_create_buffer - - #define yy_delete_buffer layout_delete_buffer - - #define yy_scan_buffer layout_scan_buffer - - #define yy_scan_string layout_scan_string - - #define yy_scan_bytes layout_scan_bytes - - #define yy_init_buffer layout_init_buffer - - #define yy_flush_buffer layout_flush_buffer - - #define yy_load_buffer_state layout_load_buffer_state - - #define yy_switch_to_buffer layout_switch_to_buffer - - #define yypush_buffer_state layoutpush_buffer_state - - #define yypop_buffer_state layoutpop_buffer_state - - #define yyensure_buffer_stack layoutensure_buffer_stack - - #define yylex layoutlex - - #define yyrestart layoutrestart - - #define yylex_init layoutlex_init - - #define yylex_init_extra layoutlex_init_extra - - #define yylex_destroy layoutlex_destroy - - #define yyget_debug layoutget_debug - - #define yyset_debug layoutset_debug - - #define yyget_extra layoutget_extra - - #define yyset_extra layoutset_extra - - #define yyget_in layoutget_in - - #define yyset_in layoutset_in - - #define yyget_out layoutget_out - - #define yyset_out layoutset_out - - #define yyget_leng layoutget_leng - - #define yyget_text layoutget_text - - #define yyget_lineno layoutget_lineno - - #define yyset_lineno layoutset_lineno - - #define yyget_column layoutget_column - - #define yyset_column layoutset_column - - #define yywrap layoutwrap - - #define yyalloc layoutalloc - - #define yyrealloc layoutrealloc - - #define yyfree layoutfree - /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ @@ -175,10 +105,12 @@ typedef unsigned int flex_uint32_t; /* Returned upon end-of-file. */ #define YY_NULL 0 -/* Promotes a possibly negative, possibly signed char to an - * integer in range [0..255] for use as an array index. +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. */ -#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* An opaque pointer. */ #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -202,16 +134,20 @@ typedef void* yyscan_t; * definition of BEGIN. */ #define BEGIN yyg->yy_start = 1 + 2 * + /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yyg->yy_start - 1) / 2) #define YYSTATE YY_START + /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE layoutrestart(yyin ,yyscanner ) + #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ @@ -244,10 +180,10 @@ typedef size_t yy_size_t; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 - + /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE layoutlex. + * existing scanners that call yyless() from OUTSIDE layoutlex. * One obvious solution it to make yy_act a global. I tried that, and saw * a 5% performance hit in a non-yylineno scanner, because yy_act is * normally declared as a register variable-- so it is not worth it. @@ -280,6 +216,7 @@ typedef size_t yy_size_t; YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) + #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) #ifndef YY_STRUCT_YY_BUFFER_STATE @@ -322,7 +259,7 @@ struct yy_buffer_state int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ - + /* Whether to try to fill the input buffer when we reach the * end of it. */ @@ -356,33 +293,36 @@ struct yy_buffer_state #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ : NULL) + /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] -void layoutrestart ( FILE *input_file , yyscan_t yyscanner ); -void layout_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); -YY_BUFFER_STATE layout_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); -void layout_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); -void layout_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); -void layoutpush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); -void layoutpop_buffer_state ( yyscan_t yyscanner ); - -static void layoutensure_buffer_stack ( yyscan_t yyscanner ); -static void layout_load_buffer_state ( yyscan_t yyscanner ); -static void layout_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); +void layoutrestart (FILE *input_file ,yyscan_t yyscanner ); +void layout_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE layout_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void layout_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void layout_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void layoutpush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void layoutpop_buffer_state (yyscan_t yyscanner ); + +static void layoutensure_buffer_stack (yyscan_t yyscanner ); +static void layout_load_buffer_state (yyscan_t yyscanner ); +static void layout_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + #define YY_FLUSH_BUFFER layout_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) -YY_BUFFER_STATE layout_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); -YY_BUFFER_STATE layout_scan_string ( const char *yy_str , yyscan_t yyscanner ); -YY_BUFFER_STATE layout_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); +YY_BUFFER_STATE layout_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE layout_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE layout_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); -void *layoutalloc ( yy_size_t , yyscan_t yyscanner ); -void *layoutrealloc ( void *, yy_size_t , yyscan_t yyscanner ); -void layoutfree ( void * , yyscan_t yyscanner ); +void *layoutalloc (yy_size_t ,yyscan_t yyscanner ); +void *layoutrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void layoutfree (void * ,yyscan_t yyscanner ); #define yy_new_buffer layout_create_buffer + #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ @@ -392,6 +332,7 @@ void layoutfree ( void * , yyscan_t yyscanner ); } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } + #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ @@ -401,19 +342,21 @@ void layoutfree ( void * , yyscan_t yyscanner ); } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } + #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ -typedef flex_uint8_t YY_CHAR; + +typedef unsigned char YY_CHAR; typedef int yy_state_type; #define yytext_ptr yytext_r -static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); -static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); -static int yy_get_next_buffer ( yyscan_t yyscanner ); -static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. @@ -424,8 +367,9 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 22 -#define YY_END_OF_BUFFER 23 + +#define YY_NUM_RULES 24 +#define YY_END_OF_BUFFER 25 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -433,34 +377,34 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[204] = +static yyconst flex_int16_t yy_accept[211] = { 0, - 0, 0, 23, 21, 22, 21, 21, 21, 21, 21, - 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 25, 23, 24, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, 0, 0, 4, 0, + 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2, 0, 0, 12, 0, 0, 3, - 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 12, 0, 0, 3, 0, 6, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 16, 0, 0, 0, 14, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, - 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, - 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, - 18, 0, 0, 0, 0, 0, 7, 0, 0, 0, - - 0, 10, 0 + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, 15, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 9, 0, 0, 0, 0, 0, 0, 18, 0, 0, + + 0, 0, 0, 7, 0, 0, 0, 0, 10, 0 } ; -static const YY_CHAR yy_ec[256] = +static yyconst YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -473,9 +417,9 @@ static const YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 1, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 1, 25, - 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 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, @@ -492,134 +436,138 @@ static const YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1 } ; -static const YY_CHAR yy_meta[27] = +static yyconst YY_CHAR yy_meta[29] = { 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 } ; -static const flex_int16_t yy_base[205] = +static yyconst flex_uint16_t yy_base[212] = { 0, - 0, 21, 218, 219, 219, 17, 201, 7, 212, 21, - 11, 207, 194, 197, 204, 199, 30, 194, 203, 183, - 198, 194, 197, 192, 182, 180, 189, 193, 183, 184, - 189, 173, 178, 186, 189, 189, 170, 180, 169, 172, - 176, 219, 182, 173, 177, 161, 157, 159, 174, 4, - 157, 154, 169, 164, 155, 152, 170, 156, 155, 167, - 157, 219, 165, 163, 145, 162, 152, 155, 140, 145, - 148, 138, 152, 147, 146, 134, 138, 149, 130, 129, - 146, 132, 128, 219, 144, 139, 219, 128, 130, 219, - 120, 219, 120, 129, 120, 132, 122, 115, 113, 127, - - 118, 125, 114, 109, 113, 117, 115, 219, 115, 108, - 122, 103, 6, 105, 118, 105, 102, 115, 112, 99, - 110, 93, 93, 110, 95, 105, 89, 219, 103, 100, - 99, 89, 101, 82, 99, 82, 90, 219, 92, 78, - 78, 73, 80, 75, 87, 71, 77, 75, 219, 87, - 81, 66, 75, 73, 82, 76, 77, 68, 61, 219, - 62, 75, 74, 61, 50, 67, 70, 219, 67, 58, - 49, 219, 61, 59, 60, 53, 63, 43, 56, 47, - 59, 49, 219, 219, 54, 51, 42, 31, 37, 48, - 219, 30, 44, 47, 25, 27, 219, 35, 29, 28, - - 11, 219, 219, 0 + 0, 25, 227, 228, 228, 5, 209, 217, 13, 220, + 24, 10, 215, 201, 210, 203, 211, 206, 17, 189, + 199, 209, 187, 204, 200, 203, 198, 187, 185, 195, + 198, 198, 187, 188, 194, 177, 182, 228, 191, 194, + 194, 174, 185, 173, 176, 181, 228, 187, 173, 177, + 181, 164, 159, 162, 178, 10, 160, 157, 173, 168, + 158, 155, 174, 159, 228, 158, 171, 161, 228, 169, + 167, 148, 166, 156, 159, 143, 148, 152, 141, 156, + 151, 150, 137, 141, 153, 133, 132, 150, 135, 131, + 228, 148, 143, 228, 131, 133, 228, 123, 228, 123, + + 133, 123, 136, 125, 118, 116, 131, 121, 129, 117, + 112, 116, 121, 119, 228, 119, 111, 126, 106, 32, + 108, 122, 108, 105, 119, 116, 102, 114, 96, 96, + 114, 98, 109, 92, 228, 107, 104, 103, 92, 105, + 85, 103, 85, 94, 228, 96, 81, 81, 76, 83, + 78, 91, 74, 80, 78, 228, 91, 85, 69, 79, + 77, 86, 80, 81, 71, 64, 228, 65, 79, 78, + 64, 52, 71, 74, 228, 71, 61, 52, 228, 65, + 63, 64, 56, 67, 46, 60, 50, 63, 53, 228, + 228, 58, 55, 45, 33, 40, 52, 228, 34, 49, + + 52, 28, 30, 228, 40, 32, 29, 16, 228, 228, + 0 } ; -static const flex_int16_t yy_def[205] = +static yyconst flex_int16_t yy_def[212] = { 0, - 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - - 203, 203, 0, 203 + 211, 211, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + + 210, 210, 210, 210, 210, 210, 210, 210, 210, 0, + 210 } ; -static const flex_int16_t yy_nxt[246] = +static yyconst flex_uint16_t yy_nxt[257] = { 0, - 4, 5, 203, 203, 6, 203, 65, 203, 123, 203, - 203, 7, 203, 8, 9, 203, 10, 11, 18, 203, - 12, 13, 5, 19, 66, 6, 124, 24, 14, 21, - 15, 202, 7, 25, 8, 9, 31, 10, 11, 16, - 22, 12, 13, 201, 23, 200, 199, 32, 198, 197, - 196, 195, 194, 33, 193, 192, 191, 190, 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, 164, 163, 162, 161, 160, 159, 158, - 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, - - 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, - 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, - 127, 126, 125, 122, 121, 120, 119, 118, 117, 116, - 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, - 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, - 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, - 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, - 75, 74, 73, 72, 71, 70, 69, 68, 67, 64, - 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, - 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, - - 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, - 30, 29, 28, 27, 26, 20, 17, 203, 3, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203 + 4, 5, 210, 210, 6, 210, 210, 210, 210, 210, + 210, 7, 72, 8, 9, 10, 16, 11, 12, 17, + 210, 13, 14, 35, 21, 15, 5, 27, 18, 6, + 22, 73, 24, 28, 130, 36, 7, 209, 8, 9, + 10, 37, 11, 12, 25, 208, 13, 14, 26, 207, + 15, 206, 205, 131, 204, 203, 202, 201, 200, 199, + 198, 197, 196, 195, 194, 193, 192, 191, 190, 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, 164, 163, 162, 161, 160, 159, + + 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, + 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, + 138, 137, 136, 135, 134, 133, 132, 129, 128, 127, + 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, + 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, + 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, + 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, + 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, + 76, 75, 74, 71, 70, 69, 68, 67, 66, 65, + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, + + 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, + 44, 43, 42, 41, 40, 39, 38, 34, 33, 32, + 31, 30, 29, 23, 20, 19, 210, 3, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210 } ; -static const flex_int16_t yy_chk[246] = +static yyconst flex_int16_t yy_chk[257] = { 0, - 204, 1, 0, 0, 1, 0, 50, 0, 113, 0, - 0, 1, 0, 1, 1, 0, 1, 1, 8, 0, - 1, 1, 2, 8, 50, 2, 113, 11, 6, 10, - 6, 201, 2, 11, 2, 2, 17, 2, 2, 6, - 10, 2, 2, 200, 10, 199, 198, 17, 196, 195, - 194, 193, 192, 17, 190, 189, 188, 187, 186, 185, - 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, - 171, 170, 169, 167, 166, 165, 164, 163, 162, 161, - 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, - 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, - - 137, 136, 135, 134, 133, 132, 131, 130, 129, 127, - 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, - 116, 115, 114, 112, 111, 110, 109, 107, 106, 105, - 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, - 94, 93, 91, 89, 88, 86, 85, 83, 82, 81, - 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, - 70, 69, 68, 67, 66, 65, 64, 63, 61, 60, - 59, 58, 57, 56, 55, 54, 53, 52, 51, 49, - 48, 47, 46, 45, 44, 43, 41, 40, 39, 38, - 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, - - 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, - 16, 15, 14, 13, 12, 9, 7, 3, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203 + 211, 1, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 56, 1, 1, 1, 6, 1, 1, 6, + 0, 1, 1, 19, 9, 1, 2, 12, 6, 2, + 9, 56, 11, 12, 120, 19, 2, 208, 2, 2, + 2, 19, 2, 2, 11, 207, 2, 2, 11, 206, + 2, 205, 203, 120, 202, 201, 200, 199, 197, 196, + 195, 194, 193, 192, 189, 188, 187, 186, 185, 184, + 183, 182, 181, 180, 178, 177, 176, 174, 173, 172, + 171, 170, 169, 168, 166, 165, 164, 163, 162, 161, + 160, 159, 158, 157, 155, 154, 153, 152, 151, 150, + + 149, 148, 147, 146, 144, 143, 142, 141, 140, 139, + 138, 137, 136, 134, 133, 132, 131, 130, 129, 128, + 127, 126, 125, 124, 123, 122, 121, 119, 118, 117, + 116, 114, 113, 112, 111, 110, 109, 108, 107, 106, + 105, 104, 103, 102, 101, 100, 98, 96, 95, 93, + 92, 90, 89, 88, 87, 86, 85, 84, 83, 82, + 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, + 71, 70, 68, 67, 66, 64, 63, 62, 61, 60, + 59, 58, 57, 55, 54, 53, 52, 51, 50, 49, + 48, 46, 45, 44, 43, 42, 41, 40, 39, 37, + + 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, + 26, 25, 24, 23, 22, 21, 20, 18, 17, 16, + 15, 14, 13, 10, 8, 7, 3, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210 } ; /* Table of booleans, true if rule could match eol. */ -static const flex_int32_t yy_rule_can_match_eol[23] = +static yyconst flex_int32_t yy_rule_can_match_eol[25] = { 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, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -651,8 +599,7 @@ static const flex_int32_t yy_rule_can_match_eol[23] = #define YY_NO_UNISTD_H 1 #line 29 "layout.flex" #include "SkSLToken.h" -#line 648 "lex.layout.c" -#line 649 "lex.layout.c" +#line 597 "lex.layout.c" #define INITIAL 0 @@ -702,44 +649,44 @@ struct yyguts_t }; /* end struct yyguts_t */ -static int yy_init_globals ( yyscan_t yyscanner ); +static int yy_init_globals (yyscan_t yyscanner ); int layoutlex_init (yyscan_t* scanner); -int layoutlex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); +int layoutlex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ -int layoutlex_destroy ( yyscan_t yyscanner ); +int layoutlex_destroy (yyscan_t yyscanner ); -int layoutget_debug ( yyscan_t yyscanner ); +int layoutget_debug (yyscan_t yyscanner ); -void layoutset_debug ( int debug_flag , yyscan_t yyscanner ); +void layoutset_debug (int debug_flag ,yyscan_t yyscanner ); -YY_EXTRA_TYPE layoutget_extra ( yyscan_t yyscanner ); +YY_EXTRA_TYPE layoutget_extra (yyscan_t yyscanner ); -void layoutset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); +void layoutset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); -FILE *layoutget_in ( yyscan_t yyscanner ); +FILE *layoutget_in (yyscan_t yyscanner ); -void layoutset_in ( FILE * _in_str , yyscan_t yyscanner ); +void layoutset_in (FILE * _in_str ,yyscan_t yyscanner ); -FILE *layoutget_out ( yyscan_t yyscanner ); +FILE *layoutget_out (yyscan_t yyscanner ); -void layoutset_out ( FILE * _out_str , yyscan_t yyscanner ); +void layoutset_out (FILE * _out_str ,yyscan_t yyscanner ); - int layoutget_leng ( yyscan_t yyscanner ); + int layoutget_leng (yyscan_t yyscanner ); -char *layoutget_text ( yyscan_t yyscanner ); +char *layoutget_text (yyscan_t yyscanner ); -int layoutget_lineno ( yyscan_t yyscanner ); +int layoutget_lineno (yyscan_t yyscanner ); -void layoutset_lineno ( int _line_number , yyscan_t yyscanner ); +void layoutset_lineno (int _line_number ,yyscan_t yyscanner ); -int layoutget_column ( yyscan_t yyscanner ); +int layoutget_column (yyscan_t yyscanner ); -void layoutset_column ( int _column_no , yyscan_t yyscanner ); +void layoutset_column (int _column_no ,yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. @@ -747,31 +694,32 @@ void layoutset_column ( int _column_no , yyscan_t yyscanner ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int layoutwrap ( yyscan_t yyscanner ); +extern "C" int layoutwrap (yyscan_t yyscanner ); #else -extern int layoutwrap ( yyscan_t yyscanner ); +extern int layoutwrap (yyscan_t yyscanner ); #endif #endif #ifndef YY_NO_UNPUT - static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner); + static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner); #endif #ifndef yytext_ptr -static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); #endif #ifndef YY_NO_INPUT + #ifdef __cplusplus -static int yyinput ( yyscan_t yyscanner ); +static int yyinput (yyscan_t yyscanner ); #else -static int input ( yyscan_t yyscanner ); +static int input (yyscan_t yyscanner ); #endif #endif @@ -802,7 +750,7 @@ static int input ( yyscan_t yyscanner ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - int n; \ + size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -815,7 +763,7 @@ static int input ( yyscan_t yyscanner ); else \ { \ errno=0; \ - while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ @@ -915,7 +863,7 @@ YY_DECL #line 32 "layout.flex" -#line 912 "lex.layout.c" +#line 861 "lex.layout.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -942,13 +890,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 >= 204 ) - yy_c = yy_meta[yy_c]; + if ( yy_current_state >= 211 ) + yy_c = yy_meta[(unsigned int) yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; ++yy_cp; } - while ( yy_current_state != 203 ); + while ( yy_current_state != 210 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -959,10 +907,10 @@ 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' ) - + do{ yylineno++; yycolumn=0; }while(0) @@ -1082,15 +1030,25 @@ YY_RULE_SETUP YY_BREAK case 21: YY_RULE_SETUP -#line 55 "layout.flex" -{ return SkSL::Token::INVALID_TOKEN; } +#line 54 "layout.flex" +{ return SkSL::Token::WHEN; } YY_BREAK case 22: YY_RULE_SETUP +#line 55 "layout.flex" +{ return SkSL::Token::KEY; } + YY_BREAK +case 23: +YY_RULE_SETUP #line 57 "layout.flex" +{ return SkSL::Token::INVALID_TOKEN; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 59 "layout.flex" ECHO; YY_BREAK -#line 1087 "lex.layout.c" +#line 1046 "lex.layout.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1237,7 +1195,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = yyg->yytext_ptr; - int number_to_move, i; + yy_size_t number_to_move, i; int ret_val; if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) @@ -1266,7 +1224,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); + number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); @@ -1302,7 +1260,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - layoutrealloc((void *) b->yy_ch_buf,(yy_size_t) (b->yy_buf_size + 2) ,yyscanner ); + layoutrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); } else /* Can't grow it, we don't own it. */ @@ -1348,10 +1306,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else ret_val = EOB_ACT_CONTINUE_SCAN; - if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) layoutrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,(yy_size_t) new_size ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) layoutrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } @@ -1386,10 +1344,10 @@ 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 >= 204 ) - yy_c = yy_meta[yy_c]; + if ( yy_current_state >= 211 ) + yy_c = yy_meta[(unsigned int) yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; } return yy_current_state; @@ -1415,11 +1373,11 @@ 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 >= 204 ) - yy_c = yy_meta[yy_c]; + if ( yy_current_state >= 211 ) + yy_c = yy_meta[(unsigned int) yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 203); + yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; + yy_is_jam = (yy_current_state == 210); (void)yyg; return yy_is_jam ? 0 : yy_current_state; @@ -1496,7 +1454,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else { /* need more input */ - int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; ++yyg->yy_c_buf_p; switch ( yy_get_next_buffer( yyscanner ) ) @@ -1543,7 +1501,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) yyg->yy_hold_char = *++yyg->yy_c_buf_p; if ( c == '\n' ) - + do{ yylineno++; yycolumn=0; }while(0) @@ -1631,12 +1589,12 @@ static void layout_load_buffer_state (yyscan_t yyscanner) if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in layout_create_buffer()" ); - b->yy_buf_size = size; + b->yy_buf_size = (yy_size_t)size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) layoutalloc((yy_size_t) (b->yy_buf_size + 2) ,yyscanner ); + b->yy_ch_buf = (char *) layoutalloc(b->yy_buf_size + 2 ,yyscanner ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in layout_create_buffer()" ); @@ -1783,7 +1741,7 @@ void layoutpop_buffer_state (yyscan_t yyscanner) */ static void layoutensure_buffer_stack (yyscan_t yyscanner) { - yy_size_t num_to_alloc; + int num_to_alloc; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!yyg->yy_buffer_stack) { @@ -1798,9 +1756,9 @@ static void layoutensure_buffer_stack (yyscan_t yyscanner) , yyscanner); if ( ! yyg->yy_buffer_stack ) YY_FATAL_ERROR( "out of dynamic memory in layoutensure_buffer_stack()" ); - + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - + yyg->yy_buffer_stack_max = num_to_alloc; yyg->yy_buffer_stack_top = 0; return; @@ -1829,7 +1787,7 @@ static void layoutensure_buffer_stack (yyscan_t yyscanner) * @param base the character buffer * @param size the size in bytes of the character buffer * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. + * @return the newly allocated buffer state object. */ YY_BUFFER_STATE layout_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { @@ -1845,7 +1803,7 @@ YY_BUFFER_STATE layout_scan_buffer (char * base, yy_size_t size , yyscan_t yys if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in layout_scan_buffer()" ); - b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = NULL; @@ -1868,7 +1826,7 @@ YY_BUFFER_STATE layout_scan_buffer (char * base, yy_size_t size , yyscan_t yys * @note If you want to scan bytes that may contain NUL values, then use * layout_scan_bytes() instead. */ -YY_BUFFER_STATE layout_scan_string (const char * yystr , yyscan_t yyscanner) +YY_BUFFER_STATE layout_scan_string (yyconst char * yystr , yyscan_t yyscanner) { return layout_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner); @@ -1881,15 +1839,15 @@ YY_BUFFER_STATE layout_scan_string (const char * yystr , yyscan_t yyscanner) * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE layout_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner) +YY_BUFFER_STATE layout_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; yy_size_t n; - int i; + yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ - n = (yy_size_t) (_yybytes_len + 2); + n = (yy_size_t) _yybytes_len + 2; buf = (char *) layoutalloc(n ,yyscanner ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in layout_scan_bytes()" ); @@ -1915,7 +1873,7 @@ YY_BUFFER_STATE layout_scan_bytes (const char * yybytes, int _yybytes_len , yy #define YY_EXIT_FAILURE 2 #endif -static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) +static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; @@ -1957,7 +1915,7 @@ YY_EXTRA_TYPE layoutget_extra (yyscan_t yyscanner) int layoutget_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - + if (! YY_CURRENT_BUFFER) return 0; @@ -1970,7 +1928,7 @@ int layoutget_lineno (yyscan_t yyscanner) int layoutget_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - + if (! YY_CURRENT_BUFFER) return 0; @@ -2092,7 +2050,9 @@ void layoutset_debug (int _bdebug , yyscan_t yyscanner) * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ + int layoutlex_init(yyscan_t* ptr_yy_globals) + { if (ptr_yy_globals == NULL){ errno = EINVAL; @@ -2119,7 +2079,9 @@ int layoutlex_init(yyscan_t* ptr_yy_globals) * The user defined value in the first argument will be available to layoutalloc in * the yyextra field. */ + int layoutlex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + { struct yyguts_t dummy_yyguts; @@ -2129,20 +2091,20 @@ int layoutlex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals errno = EINVAL; return 1; } - + *ptr_yy_globals = (yyscan_t) layoutalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); - + if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } - + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - + layoutset_extra (yy_user_defined, *ptr_yy_globals); - + return yy_init_globals ( *ptr_yy_globals ); } @@ -2214,7 +2176,7 @@ int layoutlex_destroy (yyscan_t yyscanner) */ #ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; (void)yyg; @@ -2226,7 +2188,7 @@ static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscann #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (const char * s , yyscan_t yyscanner) +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) { int n; for ( n = 0; s[n]; ++n ) @@ -2267,7 +2229,8 @@ void layoutfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 57 "layout.flex" +#line 59 "layout.flex" + int layoutwrap(yyscan_t scanner) { diff --git a/src/sksl/lex.layout.cpp b/src/sksl/lex.layout.cpp index 4289b110d9..937c93190e 100644 --- a/src/sksl/lex.layout.cpp +++ b/src/sksl/lex.layout.cpp @@ -7,6 +7,6 @@ #include "disable_flex_warnings.h" #include "lex.layout.c" -static_assert(YY_FLEX_MAJOR_VERSION * 100 + YY_FLEX_MINOR_VERSION * 10 + - YY_FLEX_SUBMINOR_VERSION >= 261, +static_assert(YY_FLEX_MAJOR_VERSION * 10000 + YY_FLEX_MINOR_VERSION * 100 + + YY_FLEX_SUBMINOR_VERSION >= 20601, "we require Flex 2.6.1 or better for security reasons"); diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c index ebf94edaf7..6e44f5aea7 100644 --- a/src/sksl/lex.sksl.c +++ b/src/sksl/lex.sksl.c @@ -1,3 +1,9 @@ +/* + * Copyright 2017 Google Inc. + * + * 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" @@ -362,8 +368,8 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 96 -#define YY_END_OF_BUFFER 97 +#define YY_NUM_RULES 99 +#define YY_END_OF_BUFFER 100 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -371,39 +377,39 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[285] = +static yyconst flex_int16_t yy_accept[289] = { 0, - 0, 0, 97, 95, 94, 94, 68, 95, 42, 58, - 63, 44, 45, 56, 54, 51, 55, 50, 57, 4, - 4, 70, 91, 75, 71, 74, 69, 95, 48, 49, - 62, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 46, - 61, 47, 64, 94, 73, 43, 42, 82, 67, 87, - 80, 52, 78, 53, 79, 1, 0, 92, 81, 2, - 4, 0, 0, 59, 77, 72, 76, 60, 0, 0, - 86, 66, 42, 42, 42, 42, 42, 42, 13, 42, - 42, 42, 42, 42, 8, 22, 42, 42, 42, 42, + 0, 0, 100, 98, 95, 95, 69, 98, 42, 59, + 64, 45, 46, 57, 55, 52, 56, 51, 58, 4, + 4, 71, 92, 76, 72, 75, 70, 98, 49, 50, + 63, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, + 62, 48, 65, 95, 74, 43, 42, 83, 68, 88, + 81, 53, 79, 54, 80, 93, 1, 0, 96, 82, + 2, 4, 0, 0, 94, 60, 78, 73, 77, 61, + 44, 44, 44, 87, 67, 42, 42, 42, 42, 42, + 42, 13, 42, 42, 42, 42, 42, 8, 22, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 85, 65, 43, 90, 0, 0, 0, 92, 1, - 0, 0, 3, 5, 83, 84, 9, 0, 89, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 11, - 42, 42, 42, 42, 42, 42, 23, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 88, - 0, 1, 93, 0, 0, 2, 0, 42, 42, 16, - 42, 42, 42, 42, 42, 10, 42, 30, 42, 42, - 42, 27, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 6, 42, 42, 42, 42, 0, 1, 0, 18, - - 42, 42, 26, 42, 42, 42, 7, 29, 24, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 12, 42, 0, 37, 42, 42, 42, 42, 40, - 42, 42, 42, 42, 42, 21, 42, 39, 14, 42, - 42, 42, 15, 42, 42, 17, 20, 28, 42, 42, - 42, 42, 42, 25, 42, 42, 34, 19, 42, 42, - 32, 36, 42, 35, 42, 42, 41, 42, 33, 42, - 42, 42, 42, 42, 42, 31, 42, 42, 42, 42, - 42, 42, 38, 0 + 42, 42, 42, 42, 86, 66, 43, 91, 0, 0, + 0, 96, 1, 0, 0, 3, 5, 84, 85, 44, + 9, 44, 90, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 11, 42, 42, 42, 42, 42, 42, + 23, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 89, 0, 1, 97, 0, 0, 2, + 44, 42, 42, 16, 42, 42, 42, 42, 42, 10, + 42, 30, 42, 42, 42, 27, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 6, 42, 42, 42, 42, + + 0, 1, 44, 18, 42, 42, 26, 42, 42, 42, + 7, 29, 24, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 12, 42, 44, 37, 42, + 42, 42, 42, 40, 42, 42, 42, 42, 42, 21, + 42, 39, 14, 42, 42, 42, 15, 42, 42, 17, + 20, 28, 42, 42, 42, 42, 42, 25, 42, 42, + 34, 19, 42, 42, 32, 36, 42, 35, 42, 42, + 41, 42, 33, 42, 42, 42, 42, 42, 42, 31, + 42, 42, 42, 42, 42, 42, 38, 0 } ; static yyconst YY_CHAR yy_ec[256] = @@ -448,77 +454,81 @@ static yyconst YY_CHAR yy_meta[59] = 3, 3, 3, 3, 1, 1, 1, 1 } ; -static yyconst flex_uint16_t yy_base[291] = +static yyconst flex_uint16_t yy_base[297] = { 0, - 0, 0, 353, 354, 57, 59, 330, 0, 0, 329, - 55, 354, 354, 328, 52, 354, 51, 49, 59, 61, - 65, 354, 354, 47, 327, 49, 354, 45, 354, 354, - 64, 37, 57, 55, 306, 64, 307, 61, 58, 310, - 300, 294, 296, 306, 58, 294, 296, 294, 65, 354, - 86, 354, 354, 113, 354, 0, 0, 354, 316, 354, - 354, 354, 354, 354, 354, 100, 326, 0, 354, 102, - 107, 114, 0, 314, 354, 354, 354, 313, 297, 281, - 354, 310, 295, 293, 281, 91, 291, 279, 0, 278, - 283, 292, 276, 284, 0, 276, 266, 267, 283, 271, - - 267, 279, 91, 283, 266, 272, 261, 270, 267, 268, - 267, 354, 284, 0, 354, 132, 294, 288, 0, 130, - 141, 134, 143, 0, 354, 354, 354, 263, 354, 270, - 264, 264, 263, 114, 266, 263, 260, 247, 245, 0, - 254, 242, 246, 244, 249, 252, 0, 253, 251, 236, - 234, 244, 232, 232, 244, 242, 246, 235, 227, 354, - 147, 150, 354, 157, 155, 159, 226, 233, 237, 0, - 225, 222, 230, 219, 236, 0, 231, 0, 220, 216, - 214, 0, 213, 215, 221, 215, 212, 211, 225, 222, - 221, 0, 209, 204, 216, 215, 161, 163, 216, 0, - - 202, 212, 0, 203, 204, 198, 0, 0, 0, 195, - 200, 194, 193, 196, 199, 194, 189, 187, 196, 187, - 193, 0, 187, 192, 0, 186, 179, 179, 192, 0, - 180, 179, 184, 181, 188, 0, 190, 0, 0, 177, - 177, 174, 354, 168, 180, 0, 0, 0, 179, 169, - 159, 163, 163, 0, 174, 167, 0, 0, 174, 163, - 0, 0, 166, 0, 151, 155, 0, 168, 0, 157, - 147, 119, 125, 118, 109, 0, 104, 100, 97, 87, - 64, 63, 0, 354, 179, 182, 185, 190, 195, 197 + 0, 0, 360, 361, 57, 59, 337, 0, 0, 336, + 55, 361, 361, 335, 52, 361, 53, 48, 57, 54, + 65, 337, 361, 63, 333, 64, 361, 30, 361, 361, + 66, 44, 57, 59, 312, 61, 313, 61, 65, 316, + 306, 300, 302, 312, 59, 300, 302, 300, 70, 361, + 90, 361, 361, 111, 361, 0, 0, 361, 322, 361, + 361, 361, 361, 361, 361, 361, 98, 332, 0, 361, + 101, 105, 112, 0, 361, 320, 361, 361, 361, 319, + 0, 303, 287, 361, 316, 301, 299, 287, 92, 297, + 285, 0, 284, 289, 298, 282, 290, 0, 282, 272, + + 273, 289, 277, 273, 285, 95, 289, 272, 278, 267, + 276, 273, 274, 273, 361, 290, 0, 361, 121, 300, + 294, 0, 130, 137, 135, 141, 0, 361, 361, 0, + 0, 269, 361, 276, 270, 270, 269, 112, 272, 269, + 266, 253, 251, 0, 260, 248, 252, 250, 255, 258, + 0, 259, 257, 242, 240, 250, 238, 238, 250, 248, + 252, 241, 233, 361, 145, 147, 361, 155, 153, 157, + 232, 239, 243, 0, 231, 228, 236, 225, 242, 0, + 237, 0, 226, 222, 220, 0, 219, 221, 227, 221, + 218, 217, 231, 228, 227, 0, 215, 210, 222, 221, + + 159, 161, 222, 0, 208, 218, 0, 209, 210, 204, + 0, 0, 0, 201, 206, 200, 199, 202, 205, 200, + 195, 193, 202, 193, 199, 0, 193, 198, 0, 192, + 185, 185, 198, 0, 186, 185, 190, 187, 194, 0, + 196, 0, 0, 183, 183, 180, 0, 174, 186, 0, + 0, 0, 185, 175, 165, 169, 169, 0, 180, 173, + 0, 0, 180, 169, 0, 0, 172, 0, 157, 161, + 0, 174, 0, 168, 171, 147, 156, 145, 132, 0, + 119, 113, 109, 108, 91, 73, 0, 361, 177, 180, + 183, 186, 191, 196, 198, 201 + } ; -static yyconst flex_int16_t yy_def[291] = +static yyconst flex_int16_t yy_def[297] = { 0, - 284, 1, 284, 284, 284, 284, 284, 285, 286, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 284, - 284, 284, 284, 284, 284, 287, 286, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 288, 289, 284, 284, - 284, 284, 290, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 284, 284, 287, 284, 284, 288, 288, 289, 284, - 284, 284, 284, 290, 284, 284, 284, 284, 284, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 284, - 284, 284, 284, 284, 284, 284, 284, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 284, 284, 284, 286, - - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 284, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 284, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, - 286, 286, 286, 0, 284, 284, 284, 284, 284, 284 + 288, 1, 288, 288, 288, 288, 288, 289, 290, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 291, 288, 288, + 288, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 288, + 288, 288, 288, 288, 288, 292, 290, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 293, 294, 288, + 288, 288, 288, 295, 288, 288, 288, 288, 288, 288, + 296, 296, 296, 288, 288, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 288, 288, 292, 288, 288, 293, + 293, 294, 288, 288, 288, 288, 295, 288, 288, 296, + 296, 296, 288, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 288, 288, 288, 288, 288, 288, 288, + 296, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + + 288, 288, 296, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 296, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 296, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 0, 288, 288, + 288, 288, 288, 288, 288, 288 + } ; -static yyconst flex_uint16_t yy_nxt[413] = +static yyconst flex_uint16_t yy_nxt[420] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, @@ -526,49 +536,49 @@ static yyconst flex_uint16_t yy_nxt[413] = 9, 9, 32, 33, 34, 35, 36, 9, 37, 38, 9, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 9, 9, 50, 51, 52, 53, 54, 54, - 54, 54, 59, 62, 64, 66, 66, 74, 75, 67, - 77, 78, 65, 63, 68, 70, 60, 71, 71, 70, - 69, 71, 71, 83, 79, 81, 84, 72, 85, 97, - 87, 72, 80, 82, 88, 91, 72, 95, 104, 89, - - 72, 86, 98, 110, 96, 92, 105, 112, 93, 106, - 283, 111, 282, 73, 54, 54, 66, 66, 120, 120, - 281, 70, 149, 71, 71, 122, 116, 122, 121, 133, - 123, 123, 280, 72, 134, 116, 279, 121, 150, 151, - 278, 113, 72, 161, 277, 161, 120, 120, 162, 162, - 123, 123, 165, 276, 165, 275, 164, 166, 166, 123, - 123, 172, 173, 162, 162, 164, 162, 162, 197, 274, - 197, 166, 166, 198, 198, 166, 166, 198, 198, 198, - 198, 56, 273, 56, 57, 57, 57, 114, 114, 114, - 117, 117, 117, 117, 117, 119, 272, 119, 119, 119, - - 124, 124, 271, 270, 269, 268, 267, 266, 265, 264, + 54, 54, 59, 62, 67, 67, 64, 68, 71, 82, + 72, 72, 69, 63, 65, 66, 60, 83, 70, 71, + 73, 72, 72, 76, 77, 79, 80, 84, 88, 73, + 86, 73, 94, 87, 90, 85, 100, 98, 91, 107, + + 73, 89, 95, 92, 99, 96, 74, 108, 113, 101, + 109, 115, 54, 54, 67, 67, 114, 123, 123, 71, + 287, 72, 72, 125, 119, 125, 153, 124, 126, 126, + 137, 73, 165, 119, 165, 138, 124, 166, 166, 286, + 73, 285, 154, 155, 284, 116, 123, 123, 169, 283, + 169, 126, 126, 170, 170, 282, 168, 126, 126, 176, + 177, 166, 166, 166, 166, 168, 201, 281, 201, 170, + 170, 202, 202, 170, 170, 202, 202, 202, 202, 56, + 280, 56, 57, 57, 57, 81, 279, 81, 117, 117, + 117, 120, 120, 120, 120, 120, 122, 278, 122, 122, + + 122, 127, 127, 130, 130, 130, 277, 276, 275, 274, + 273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, - 203, 202, 201, 200, 199, 196, 195, 194, 193, 192, + 203, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, - 181, 180, 179, 178, 177, 176, 175, 174, 171, 170, - - 169, 168, 167, 163, 118, 160, 159, 158, 157, 156, - 155, 154, 153, 152, 148, 147, 146, 145, 144, 143, - 142, 141, 140, 139, 138, 137, 136, 135, 132, 131, - 130, 129, 128, 127, 126, 125, 118, 115, 109, 108, - 107, 103, 102, 101, 100, 99, 94, 90, 76, 61, - 58, 55, 284, 3, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284 + + 181, 180, 179, 178, 175, 174, 173, 172, 171, 167, + 121, 164, 163, 162, 161, 160, 159, 158, 157, 156, + 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, + 142, 141, 140, 139, 136, 135, 134, 133, 132, 131, + 129, 128, 121, 118, 112, 111, 110, 106, 105, 104, + 103, 102, 97, 93, 78, 75, 61, 58, 55, 288, + 3, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288 } ; -static yyconst flex_int16_t yy_chk[413] = +static yyconst flex_int16_t yy_chk[420] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -576,56 +586,57 @@ static yyconst flex_int16_t yy_chk[413] = 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, 18, 18, 24, 24, 19, - 26, 26, 17, 15, 19, 20, 11, 20, 20, 21, - 19, 21, 21, 32, 28, 31, 32, 20, 33, 39, - 34, 21, 28, 31, 34, 36, 20, 38, 45, 34, - - 21, 33, 39, 49, 38, 36, 45, 51, 36, 45, - 282, 49, 281, 20, 54, 54, 66, 66, 70, 70, - 280, 71, 103, 71, 71, 72, 66, 72, 70, 86, - 72, 72, 279, 71, 86, 66, 278, 70, 103, 103, - 277, 51, 71, 116, 275, 116, 120, 120, 116, 116, - 122, 122, 121, 274, 121, 273, 120, 121, 121, 123, - 123, 134, 134, 161, 161, 120, 162, 162, 164, 272, - 164, 165, 165, 164, 164, 166, 166, 197, 197, 198, - 198, 285, 271, 285, 286, 286, 286, 287, 287, 287, - 288, 288, 288, 288, 288, 289, 270, 289, 289, 289, - - 290, 290, 268, 266, 265, 263, 260, 259, 256, 255, - 253, 252, 251, 250, 249, 245, 244, 242, 241, 240, - 237, 235, 234, 233, 232, 231, 229, 228, 227, 226, - 224, 223, 221, 220, 219, 218, 217, 216, 215, 214, - 213, 212, 211, 210, 206, 205, 204, 202, 201, 199, - 196, 195, 194, 193, 191, 190, 189, 188, 187, 186, - 185, 184, 183, 181, 180, 179, 177, 175, 174, 173, - 172, 171, 169, 168, 167, 159, 158, 157, 156, 155, - 154, 153, 152, 151, 150, 149, 148, 146, 145, 144, - 143, 142, 141, 139, 138, 137, 136, 135, 133, 132, - - 131, 130, 128, 118, 117, 113, 111, 110, 109, 108, - 107, 106, 105, 104, 102, 101, 100, 99, 98, 97, - 96, 94, 93, 92, 91, 90, 88, 87, 85, 84, - 83, 82, 80, 79, 78, 74, 67, 59, 48, 47, - 46, 44, 43, 42, 41, 40, 37, 35, 25, 14, - 10, 7, 3, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - - 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, - 284, 284 + 6, 6, 11, 15, 18, 18, 17, 19, 20, 28, + 20, 20, 19, 15, 17, 17, 11, 28, 19, 21, + 20, 21, 21, 24, 24, 26, 26, 31, 33, 20, + 32, 21, 36, 32, 34, 31, 39, 38, 34, 45, + + 21, 33, 36, 34, 38, 36, 20, 45, 49, 39, + 45, 51, 54, 54, 67, 67, 49, 71, 71, 72, + 286, 72, 72, 73, 67, 73, 106, 71, 73, 73, + 89, 72, 119, 67, 119, 89, 71, 119, 119, 285, + 72, 284, 106, 106, 283, 51, 123, 123, 124, 282, + 124, 125, 125, 124, 124, 281, 123, 126, 126, 138, + 138, 165, 165, 166, 166, 123, 168, 279, 168, 169, + 169, 168, 168, 170, 170, 201, 201, 202, 202, 289, + 278, 289, 290, 290, 290, 291, 277, 291, 292, 292, + 292, 293, 293, 293, 293, 293, 294, 276, 294, 294, + + 294, 295, 295, 296, 296, 296, 275, 274, 272, 270, + 269, 267, 264, 263, 260, 259, 257, 256, 255, 254, + 253, 249, 248, 246, 245, 244, 241, 239, 238, 237, + 236, 235, 233, 232, 231, 230, 228, 227, 225, 224, + 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, + 210, 209, 208, 206, 205, 203, 200, 199, 198, 197, + 195, 194, 193, 192, 191, 190, 189, 188, 187, 185, + 184, 183, 181, 179, 178, 177, 176, 175, 173, 172, + 171, 163, 162, 161, 160, 159, 158, 157, 156, 155, + 154, 153, 152, 150, 149, 148, 147, 146, 145, 143, + + 142, 141, 140, 139, 137, 136, 135, 134, 132, 121, + 120, 116, 114, 113, 112, 111, 110, 109, 108, 107, + 105, 104, 103, 102, 101, 100, 99, 97, 96, 95, + 94, 93, 91, 90, 88, 87, 86, 85, 83, 82, + 80, 76, 68, 59, 48, 47, 46, 44, 43, 42, + 41, 40, 37, 35, 25, 22, 14, 10, 7, 3, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + + 288, 288, 288, 288, 288, 288, 288, 288, 288, 288, + 288, 288, 288, 288, 288, 288, 288, 288, 288 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[97] = +static yyconst flex_int32_t yy_rule_can_match_eol[100] = { 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, 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, 1, 0, 1, 0, 0, + }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -654,7 +665,7 @@ static yyconst flex_int32_t yy_rule_can_match_eol[97] = */ #define YY_NO_UNISTD_H 1 -#line 658 "lex.sksl.c" +#line 663 "lex.sksl.c" #define INITIAL 0 @@ -918,7 +929,7 @@ YY_DECL #line 30 "sksl.flex" -#line 922 "lex.sksl.c" +#line 927 "lex.sksl.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -945,13 +956,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 >= 285 ) + if ( yy_current_state >= 289 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; ++yy_cp; } - while ( yy_current_state != 284 ); + while ( yy_current_state != 288 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -1201,271 +1212,286 @@ YY_RULE_SETUP case 44: YY_RULE_SETUP #line 118 "sksl.flex" -{ return SkSL::Token::LPAREN; } +{ return SkSL::Token::SECTION; } YY_BREAK case 45: YY_RULE_SETUP #line 120 "sksl.flex" -{ return SkSL::Token::RPAREN; } +{ return SkSL::Token::LPAREN; } YY_BREAK case 46: YY_RULE_SETUP #line 122 "sksl.flex" -{ return SkSL::Token::LBRACE; } +{ return SkSL::Token::RPAREN; } YY_BREAK case 47: YY_RULE_SETUP #line 124 "sksl.flex" -{ return SkSL::Token::RBRACE; } +{ return SkSL::Token::LBRACE; } YY_BREAK case 48: YY_RULE_SETUP #line 126 "sksl.flex" -{ return SkSL::Token::LBRACKET; } +{ return SkSL::Token::RBRACE; } YY_BREAK case 49: YY_RULE_SETUP #line 128 "sksl.flex" -{ return SkSL::Token::RBRACKET; } +{ return SkSL::Token::LBRACKET; } YY_BREAK case 50: YY_RULE_SETUP #line 130 "sksl.flex" -{ return SkSL::Token::DOT; } +{ return SkSL::Token::RBRACKET; } YY_BREAK case 51: YY_RULE_SETUP #line 132 "sksl.flex" -{ return SkSL::Token::COMMA; } +{ return SkSL::Token::DOT; } YY_BREAK case 52: YY_RULE_SETUP #line 134 "sksl.flex" -{ return SkSL::Token::PLUSPLUS; } +{ return SkSL::Token::COMMA; } YY_BREAK case 53: YY_RULE_SETUP #line 136 "sksl.flex" -{ return SkSL::Token::MINUSMINUS; } +{ return SkSL::Token::PLUSPLUS; } YY_BREAK case 54: YY_RULE_SETUP #line 138 "sksl.flex" -{ return SkSL::Token::PLUS; } +{ return SkSL::Token::MINUSMINUS; } YY_BREAK case 55: YY_RULE_SETUP #line 140 "sksl.flex" -{ return SkSL::Token::MINUS; } +{ return SkSL::Token::PLUS; } YY_BREAK case 56: YY_RULE_SETUP #line 142 "sksl.flex" -{ return SkSL::Token::STAR; } +{ return SkSL::Token::MINUS; } YY_BREAK case 57: YY_RULE_SETUP #line 144 "sksl.flex" -{ return SkSL::Token::SLASH; } +{ return SkSL::Token::STAR; } YY_BREAK case 58: YY_RULE_SETUP #line 146 "sksl.flex" -{ return SkSL::Token::PERCENT; } +{ return SkSL::Token::SLASH; } YY_BREAK case 59: YY_RULE_SETUP #line 148 "sksl.flex" -{ return SkSL::Token::SHL; } +{ return SkSL::Token::PERCENT; } YY_BREAK case 60: YY_RULE_SETUP #line 150 "sksl.flex" -{ return SkSL::Token::SHR; } +{ return SkSL::Token::SHL; } YY_BREAK case 61: YY_RULE_SETUP #line 152 "sksl.flex" -{ return SkSL::Token::BITWISEOR; } +{ return SkSL::Token::SHR; } YY_BREAK case 62: YY_RULE_SETUP #line 154 "sksl.flex" -{ return SkSL::Token::BITWISEXOR; } +{ return SkSL::Token::BITWISEOR; } YY_BREAK case 63: YY_RULE_SETUP #line 156 "sksl.flex" -{ return SkSL::Token::BITWISEAND; } +{ return SkSL::Token::BITWISEXOR; } YY_BREAK case 64: YY_RULE_SETUP #line 158 "sksl.flex" -{ return SkSL::Token::BITWISENOT; } +{ return SkSL::Token::BITWISEAND; } YY_BREAK case 65: YY_RULE_SETUP #line 160 "sksl.flex" -{ return SkSL::Token::LOGICALOR; } +{ return SkSL::Token::BITWISENOT; } YY_BREAK case 66: YY_RULE_SETUP #line 162 "sksl.flex" -{ return SkSL::Token::LOGICALXOR; } +{ return SkSL::Token::LOGICALOR; } YY_BREAK case 67: YY_RULE_SETUP #line 164 "sksl.flex" -{ return SkSL::Token::LOGICALAND; } +{ return SkSL::Token::LOGICALXOR; } YY_BREAK case 68: YY_RULE_SETUP #line 166 "sksl.flex" -{ return SkSL::Token::LOGICALNOT; } +{ return SkSL::Token::LOGICALAND; } YY_BREAK case 69: YY_RULE_SETUP #line 168 "sksl.flex" -{ return SkSL::Token::QUESTION; } +{ return SkSL::Token::LOGICALNOT; } YY_BREAK case 70: YY_RULE_SETUP #line 170 "sksl.flex" -{ return SkSL::Token::COLON; } +{ return SkSL::Token::QUESTION; } YY_BREAK case 71: YY_RULE_SETUP #line 172 "sksl.flex" -{ return SkSL::Token::EQ; } +{ return SkSL::Token::COLON; } YY_BREAK case 72: YY_RULE_SETUP #line 174 "sksl.flex" -{ return SkSL::Token::EQEQ; } +{ return SkSL::Token::EQ; } YY_BREAK case 73: YY_RULE_SETUP #line 176 "sksl.flex" -{ return SkSL::Token::NEQ; } +{ return SkSL::Token::EQEQ; } YY_BREAK case 74: YY_RULE_SETUP #line 178 "sksl.flex" -{ return SkSL::Token::GT; } +{ return SkSL::Token::NEQ; } YY_BREAK case 75: YY_RULE_SETUP #line 180 "sksl.flex" -{ return SkSL::Token::LT; } +{ return SkSL::Token::GT; } YY_BREAK case 76: YY_RULE_SETUP #line 182 "sksl.flex" -{ return SkSL::Token::GTEQ; } +{ return SkSL::Token::LT; } YY_BREAK case 77: YY_RULE_SETUP #line 184 "sksl.flex" -{ return SkSL::Token::LTEQ; } +{ return SkSL::Token::GTEQ; } YY_BREAK case 78: YY_RULE_SETUP #line 186 "sksl.flex" -{ return SkSL::Token::PLUSEQ; } +{ return SkSL::Token::LTEQ; } YY_BREAK case 79: YY_RULE_SETUP #line 188 "sksl.flex" -{ return SkSL::Token::MINUSEQ; } +{ return SkSL::Token::PLUSEQ; } YY_BREAK case 80: YY_RULE_SETUP #line 190 "sksl.flex" -{ return SkSL::Token::STAREQ; } +{ return SkSL::Token::MINUSEQ; } YY_BREAK case 81: YY_RULE_SETUP #line 192 "sksl.flex" -{ return SkSL::Token::SLASHEQ; } +{ return SkSL::Token::STAREQ; } YY_BREAK case 82: YY_RULE_SETUP #line 194 "sksl.flex" -{ return SkSL::Token::PERCENTEQ; } +{ return SkSL::Token::SLASHEQ; } YY_BREAK case 83: YY_RULE_SETUP #line 196 "sksl.flex" -{ return SkSL::Token::SHLEQ; } +{ return SkSL::Token::PERCENTEQ; } YY_BREAK case 84: YY_RULE_SETUP #line 198 "sksl.flex" -{ return SkSL::Token::SHREQ; } +{ return SkSL::Token::SHLEQ; } YY_BREAK case 85: YY_RULE_SETUP #line 200 "sksl.flex" -{ return SkSL::Token::BITWISEOREQ; } +{ return SkSL::Token::SHREQ; } YY_BREAK case 86: YY_RULE_SETUP #line 202 "sksl.flex" -{ return SkSL::Token::BITWISEXOREQ; } +{ return SkSL::Token::BITWISEOREQ; } YY_BREAK case 87: YY_RULE_SETUP #line 204 "sksl.flex" -{ return SkSL::Token::BITWISEANDEQ; } +{ return SkSL::Token::BITWISEXOREQ; } YY_BREAK case 88: YY_RULE_SETUP #line 206 "sksl.flex" -{ return SkSL::Token::LOGICALOREQ; } +{ return SkSL::Token::BITWISEANDEQ; } YY_BREAK case 89: YY_RULE_SETUP #line 208 "sksl.flex" -{ return SkSL::Token::LOGICALXOREQ; } +{ return SkSL::Token::LOGICALOREQ; } YY_BREAK case 90: YY_RULE_SETUP #line 210 "sksl.flex" -{ return SkSL::Token::LOGICALANDEQ; } +{ return SkSL::Token::LOGICALXOREQ; } YY_BREAK case 91: YY_RULE_SETUP #line 212 "sksl.flex" -{ return SkSL::Token::SEMICOLON; } +{ return SkSL::Token::LOGICALANDEQ; } YY_BREAK case 92: YY_RULE_SETUP #line 214 "sksl.flex" -/* line comment */ +{ return SkSL::Token::SEMICOLON; } YY_BREAK case 93: -/* rule 93 can match eol */ YY_RULE_SETUP #line 216 "sksl.flex" -/* block comment */ +{ return SkSL::Token::ARROW; } YY_BREAK case 94: -/* rule 94 can match eol */ YY_RULE_SETUP #line 218 "sksl.flex" -/* whitespace */ +{ return SkSL::Token::COLONCOLON; } YY_BREAK case 95: +/* rule 95 can match eol */ YY_RULE_SETUP #line 220 "sksl.flex" -{ return SkSL::Token::INVALID_TOKEN; } +{ return SkSL::Token::WHITESPACE; } YY_BREAK case 96: YY_RULE_SETUP #line 222 "sksl.flex" +/* line comment */ + YY_BREAK +case 97: +/* rule 97 can match eol */ +YY_RULE_SETUP +#line 224 "sksl.flex" +/* block comment */ + YY_BREAK +case 98: +YY_RULE_SETUP +#line 226 "sksl.flex" +{ return SkSL::Token::INVALID_TOKEN; } + YY_BREAK +case 99: +YY_RULE_SETUP +#line 228 "sksl.flex" ECHO; YY_BREAK -#line 1469 "lex.sksl.c" +#line 1489 "lex.sksl.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1761,7 +1787,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 >= 285 ) + if ( yy_current_state >= 289 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; @@ -1790,11 +1816,11 @@ 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 >= 285 ) + if ( yy_current_state >= 289 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c]; - yy_is_jam = (yy_current_state == 284); + yy_is_jam = (yy_current_state == 288); (void)yyg; return yy_is_jam ? 0 : yy_current_state; @@ -2646,7 +2672,7 @@ void skslfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 222 "sksl.flex" +#line 228 "sksl.flex" diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex index c5d5ec34d0..275a4e6633 100644 --- a/src/sksl/sksl.flex +++ b/src/sksl/sksl.flex @@ -115,6 +115,8 @@ precision { return SkSL::Token::PRECISION; } "#"{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::DIRECTIVE; } +"@"{LETTER}({DIGIT}|{LETTER})* { return SkSL::Token::SECTION; } + "(" { return SkSL::Token::LPAREN; } ")" { return SkSL::Token::RPAREN; } @@ -211,12 +213,16 @@ precision { return SkSL::Token::PRECISION; } ";" { return SkSL::Token::SEMICOLON; } +"->" { return SkSL::Token::ARROW; } + +"::" { return SkSL::Token::COLONCOLON; } + +[ \t\r\n]+ { return SkSL::Token::WHITESPACE; } + "//".* /* line comment */ "/*"([^*]|"*"[^/])*"*/" /* block comment */ -[ \t\r\n]+ /* whitespace */ - . { return SkSL::Token::INVALID_TOKEN; } %% diff --git a/src/sksl/sksl_fp.include b/src/sksl/sksl_fp.include new file mode 100644 index 0000000000..566e441e30 --- /dev/null +++ b/src/sksl/sksl_fp.include @@ -0,0 +1,23 @@ +STRINGIFY( + +// defines built-in interfaces supported by SkiaSL fragment shaders + +layout(builtin=15) in vec4 sk_FragCoord; +layout(builtin=3) float sk_ClipDistance[1]; + +// 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[1]; +layout(builtin=9999) out int gl_SampleMask[1]; +layout(builtin=9999) vec4 gl_SecondaryFragColorEXT; + +layout(builtin=10003) vec4 sk_InColor; +layout(builtin=10004) out vec4 sk_OutColor; +layout(builtin=10005) vec2[] sk_TransformedCoords2D; +layout(builtin=10006) sampler2D[] sk_TextureSamplers; +) |