Revert "Revert "Switch to the new SkSL lexer.""

This reverts commit 358515491a.

Bug: skia:
Change-Id: I013fac0ed83774d8ae7c6ee6819045cab37f5e97
Reviewed-on: https://skia-review.googlesource.com/45180
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2017-09-11 13:50:14 -07:00 committed by Skia Commit-Bot
parent 9194706e8c
commit 5b5f096a03
126 changed files with 4967 additions and 6492 deletions

View File

@ -45,6 +45,7 @@ declare_args() {
skia_vulkan_sdk = getenv("VULKAN_SDK")
skia_qt_path = getenv("QT_PATH")
skia_compile_processors = false
skia_lex = false
skia_jumper_clang = ""
skia_jumper_objdump = ""
@ -411,7 +412,7 @@ optional("fontmgr_fuchsia") {
]
}
if (skia_compile_processors) {
if (skia_lex) {
executable("sksllex") {
sources = [
"src/sksl/lex/Main.cpp",
@ -422,6 +423,38 @@ if (skia_compile_processors) {
include_dirs = [ "src/sksl/lex" ]
}
action("run_sksllex") {
script = "gn/run_sksllex.py"
sources = [
"src/sksl/lex/layout.lex",
"src/sksl/lex/sksl.lex",
]
# GN insists its outputs should go somewhere underneath target_out_dir, so we trick it with a
# path that starts with target_out_dir and then uses ".." to back up into the src dir.
outputs = [
"$target_out_dir/" +
rebase_path("src/sksl/lex/SkSLLexer.h", target_out_dir),
# the script also modifies the corresponding .cpp file, but if we tell GN that it gets
# confused due to the same file being named by two different paths
]
sksllex_path = "$root_out_dir/"
sksllex_path += "sksllex"
if (host_os == "win") {
sksllex_path += ".exe"
}
args = [
rebase_path(sksllex_path),
rebase_path("bin/clang-format"),
rebase_path("src"),
]
}
} else {
group("run_sksllex") {
}
}
if (skia_compile_processors) {
executable("skslc") {
defines = [ "SKSL_STANDALONE" ]
sources = [
@ -482,6 +515,7 @@ optional("gpu") {
enabled = skia_enable_gpu
deps = [
":compile_processors",
":run_sksllex",
]
public_defines = []

34
gn/run_sksllex.py Normal file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env python
#
# Copyright 2017 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import subprocess
import sys
sksllex = sys.argv[1]
clangFormat = sys.argv[2]
src = sys.argv[3]
try:
subprocess.check_output([sksllex, src + "/sksl/lex/sksl.lex", "Lexer",
"Token", src + "/sksl/SkSLLexer.h", src +
"/sksl/SkSLLexer.cpp"])
subprocess.check_call(clangFormat + " -i \"" + src + "/sksl/SkSLLexer.h\"",
shell=True)
subprocess.check_call(clangFormat + " -i \"" + src +
"/sksl/SkSLLexer.cpp\"", shell=True)
subprocess.check_output([sksllex, src + "/sksl/lex/layout.lex",
"LayoutLexer", "LayoutToken",
src + "/sksl/SkSLLayoutLexer.h",
src + "/sksl/SkSLLayoutLexer.cpp"])
subprocess.check_call(clangFormat + " -i \"" + src +
"/sksl/SkSLLayoutLexer.h\"", shell=True)
subprocess.check_call(clangFormat + " -i \"" + src +
"/sksl/SkSLLayoutLexer.cpp\"", shell=True)
except subprocess.CalledProcessError as err:
print("### Lexer error:")
print(err.output)
exit(1)

View File

@ -9,15 +9,16 @@ _src = get_path_info("../src", "abspath")
skia_sksl_sources = [
"$_src/sksl/SkSLCFGGenerator.cpp",
"$_src/sksl/SkSLCompiler.cpp",
"$_src/sksl/SkSLIRGenerator.cpp",
"$_src/sksl/SkSLParser.cpp",
"$_src/sksl/SkSLCPPCodeGenerator.cpp",
"$_src/sksl/SkSLHCodeGenerator.cpp",
"$_src/sksl/SkSLGLSLCodeGenerator.cpp",
"$_src/sksl/SkSLHCodeGenerator.cpp",
"$_src/sksl/SkSLIRGenerator.cpp",
"$_src/sksl/SkSLLexer.cpp",
"$_src/sksl/SkSLLayoutLexer.cpp",
"$_src/sksl/SkSLParser.cpp",
"$_src/sksl/SkSLSPIRVCodeGenerator.cpp",
"$_src/sksl/SkSLString.cpp",
"$_src/sksl/SkSLUtil.cpp",
"$_src/sksl/lex.layout.cpp",
"$_src/sksl/ir/SkSLSymbolTable.cpp",
"$_src/sksl/ir/SkSLSetting.cpp",
"$_src/sksl/ir/SkSLType.cpp",

View File

@ -130,7 +130,7 @@ std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCrea
GrProcessorTestData* testData) {
sk_sp<GrTextureProxy> bmpProxy = testData->textureProxy(GrProcessorUnitTest::kSkiaPMTextureIdx);
sk_sp<GrTextureProxy> maskProxy = testData->textureProxy(GrProcessorUnitTest::kAlphaTextureIdx);
// Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly.
float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
const int kMaxWidth = 1000;

View File

@ -13,11 +13,13 @@
#include "GrResourceProvider.h"
// Computes an unnormalized half kernel (right side). Returns the summation of all the half
// kernel values.
static float make_unnormalized_half_kernel(float* halfKernel, int halfKernelSize, float sigma) {
const float invSigma = 1.f / sigma;
const float b = -0.5f * invSigma * invSigma;
float tot = 0.0f;
// Compute half kernel values at half pixel steps out from the center.
float t = 0.5f;
for (int i = 0; i < halfKernelSize; ++i) {
float value = expf(t * t * b);
@ -28,8 +30,11 @@ static float make_unnormalized_half_kernel(float* halfKernel, int halfKernelSize
return tot;
}
// Create a Gaussian half-kernel (right side) and a summed area table given a sigma and number
// of discrete steps. The half kernel is normalized to sum to 0.5.
static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHalfKernel,
int halfKernelSize, float sigma) {
// The half kernel should sum to 0.5 not 1.0.
const float tot = 2.f * make_unnormalized_half_kernel(halfKernel, halfKernelSize, sigma);
float sum = 0.f;
for (int i = 0; i < halfKernelSize; ++i) {
@ -39,6 +44,8 @@ static void make_half_kernel_and_summed_table(float* halfKernel, float* summedHa
}
}
// Applies the 1D half kernel vertically at points along the x axis to a circle centered at the
// origin with radius circleR.
void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR,
int halfKernelSize, const float* summedHalfKernelTable) {
float x = firstX;
@ -48,7 +55,8 @@ void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR
continue;
}
float y = sqrtf(circleR * circleR - x * x);
// In the column at x we exit the circle at +y and -y
// The summed table entry j is actually reflects an offset of j + 0.5.
y -= 0.5f;
int yInt = SkScalarFloorToInt(y);
SkASSERT(yInt >= -1);
@ -64,6 +72,10 @@ void apply_kernel_in_y(float* results, int numSteps, float firstX, float circleR
}
}
// Apply a Gaussian at point (evalX, 0) to a circle centered at the origin with radius circleR.
// This relies on having a half kernel computed for the Gaussian and a table of applications of
// the half kernel in y to columns at (evalX - halfKernel, evalX - halfKernel + 1, ..., evalX +
// halfKernel) passed in as yKernelEvaluations.
static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, int halfKernelSize,
const float* yKernelEvaluations) {
float acc = 0;
@ -83,18 +95,28 @@ static uint8_t eval_at(float evalX, float circleR, const float* halfKernel, int
float verticalEval = yKernelEvaluations[i + halfKernelSize];
acc += verticalEval * halfKernel[i];
}
// Since we applied a half kernel in y we multiply acc by 2 (the circle is symmetric about
// the x axis).
return SkUnitScalarClampToByte(2.f * acc);
}
// This function creates a profile of a blurred circle. It does this by computing a kernel for
// half the Gaussian and a matching summed area table. The summed area table is used to compute
// an array of vertical applications of the half kernel to the circle along the x axis. The
// table of y evaluations has 2 * k + n entries where k is the size of the half kernel and n is
// the size of the profile being computed. Then for each of the n profile entries we walk out k
// steps in each horizontal direction multiplying the corresponding y evaluation by the half
// kernel entry and sum these values to compute the profile entry.
static uint8_t* create_circle_profile(float sigma, float circleR, int profileTextureWidth) {
const int numSteps = profileTextureWidth;
uint8_t* weights = new uint8_t[numSteps];
// The full kernel is 6 sigmas wide.
int halfKernelSize = SkScalarCeilToInt(6.0f * sigma);
// round up to next multiple of 2 and then divide by 2
halfKernelSize = ((halfKernelSize + 1) & ~1) >> 1;
// Number of x steps at which to apply kernel in y to cover all the profile samples in x.
int numYSteps = numSteps + 2 * halfKernelSize;
SkAutoTArray<float> bulkAlloc(halfKernelSize + halfKernelSize + numYSteps);
@ -110,34 +132,36 @@ static uint8_t* create_circle_profile(float sigma, float circleR, int profileTex
float evalX = i + 0.5f;
weights[i] = eval_at(evalX, circleR, halfKernel, halfKernelSize, yEvals + i);
}
// Ensure the tail of the Gaussian goes to zero.
weights[numSteps - 1] = 0;
return weights;
}
static uint8_t* create_half_plane_profile(int profileWidth) {
SkASSERT(!(profileWidth & 0x1));
// The full kernel is 6 sigmas wide.
float sigma = profileWidth / 6.f;
int halfKernelSize = profileWidth / 2;
SkAutoTArray<float> halfKernel(halfKernelSize);
uint8_t* profile = new uint8_t[profileWidth];
// The half kernel should sum to 0.5.
const float tot = 2.f * make_unnormalized_half_kernel(halfKernel.get(), halfKernelSize, sigma);
float sum = 0.f;
// Populate the profile from the right edge to the middle.
for (int i = 0; i < halfKernelSize; ++i) {
halfKernel[halfKernelSize - i - 1] /= tot;
sum += halfKernel[halfKernelSize - i - 1];
profile[profileWidth - i - 1] = SkUnitScalarClampToByte(sum);
}
// Populate the profile from the middle to the left edge (by flipping the half kernel and
// continuing the summation).
for (int i = 0; i < halfKernelSize; ++i) {
sum += halfKernel[i];
profile[halfKernelSize - i - 1] = SkUnitScalarClampToByte(sum);
}
// Ensure tail goes to 0.
profile[profileWidth - 1] = 0;
return profile;
}
@ -146,9 +170,13 @@ static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resource
const SkRect& circle, float sigma,
float* solidRadius, float* textureRadius) {
float circleR = circle.width() / 2.0f;
// Profile textures are cached by the ratio of sigma to circle radius and by the size of the
// profile texture (binned by powers of 2).
SkScalar sigmaToCircleRRatio = sigma / circleR;
// When sigma is really small this becomes a equivalent to convolving a Gaussian with a
// half-plane. Similarly, in the extreme high ratio cases circle becomes a point WRT to the
// Guassian and the profile texture is a just a Gaussian evaluation. However, we haven't yet
// implemented this latter optimization.
sigmaToCircleRRatio = SkTMin(sigmaToCircleRRatio, 8.f);
SkFixed sigmaToCircleRRatioFixed;
static const SkScalar kHalfPlaneThreshold = 0.1f;
@ -159,8 +187,10 @@ static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resource
*solidRadius = circleR - 3 * sigma;
*textureRadius = 6 * sigma;
} else {
// Convert to fixed point for the key.
sigmaToCircleRRatioFixed = SkScalarToFixed(sigmaToCircleRRatio);
// We shave off some bits to reduce the number of unique entries. We could probably
// shave off more than we do.
sigmaToCircleRRatioFixed &= ~0xff;
sigmaToCircleRRatio = SkFixedToScalar(sigmaToCircleRRatioFixed);
sigma = circleR * sigmaToCircleRRatio;
@ -188,6 +218,7 @@ static sk_sp<GrTextureProxy> create_profile_texture(GrResourceProvider* resource
if (useHalfPlaneApprox) {
profile.reset(create_half_plane_profile(kProfileTextureWidth));
} else {
// Rescale params to the size of the texture we're creating.
SkScalar scale = kProfileTextureWidth / *textureRadius;
profile.reset(
create_circle_profile(sigma * scale, circleR * scale, kProfileTextureWidth));

View File

@ -72,7 +72,9 @@ private:
if (radii != prevRadii || center != prevCenter) {
float invRXSqd;
float invRYSqd;
// If we're using a scale factor to work around precision issues, choose the larger
// radius as the scale factor. The inv radii need to be pre-adjusted by the scale
// factor.
if (scale.isValid()) {
if (radii.fX > radii.fY) {
invRXSqd = 1.f;

View File

@ -30,6 +30,7 @@ public:
GrSamplerState::Filter::kNearest)));
}
/* clamp mode */
static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
sk_sp<GrColorSpaceXform>
colorSpaceXform,

View File

@ -319,7 +319,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
break;
}
default:
this->addExpression(cfg, &b->fLeft, !Token::IsAssignment(b->fOperator));
this->addExpression(cfg, &b->fLeft, !Compiler::IsAssignment(b->fOperator));
this->addExpression(cfg, &b->fRight, constantPropagate);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({
BasicBlock::Node::kExpression_Kind,

View File

@ -14,7 +14,7 @@ namespace SkSL {
static bool needs_uniform_var(const Variable& var) {
return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
strcmp(var.fType.fName.c_str(), "colorSpaceXform");
var.fType.fName != "colorSpaceXform";
}
CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
@ -58,7 +58,7 @@ void CPPCodeGenerator::writeType(const Type& type) {
if (type.kind() == Type::kStruct_Kind) {
INHERITED::writeType(type);
} else {
this->write(type.name());
this->write(type.fName);
}
}
void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
@ -87,7 +87,7 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) {
this->write("%s");
if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
fErrors.error(i.fIndex->fPosition,
fErrors.error(i.fIndex->fOffset,
"index into sk_TransformedCoords2D must be an integer literal");
return;
}
@ -104,7 +104,7 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
} else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) {
this->write("%s");
if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
fErrors.error(i.fIndex->fPosition,
fErrors.error(i.fIndex->fOffset,
"index into sk_TextureSamplers must be an integer literal");
return;
}
@ -118,16 +118,15 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
}
static const char* default_value(const Type& type) {
const char* name = type.name().c_str();
if (!strcmp(name, "float")) {
if (type.fName == "float") {
return "0.0";
} else if (!strcmp(name, "float2")) {
} else if (type.fName == "float2") {
return "float2(0.0)";
} else if (!strcmp(name, "float3")) {
} else if (type.fName == "float3") {
return "float30.0)";
} else if (!strcmp(name, "float4")) {
} else if (type.fName == "float4") {
return "float4(0.0)";
} else if (!strcmp(name, "floatt4x4") || !strcmp(name, "colorSpaceXform")) {
} else if (type.fName == "floatt4x4" || type.fName == "colorSpaceXform") {
return "float4x4(1.0)";
}
ABORT("unsupported default_value type\n");
@ -155,7 +154,8 @@ void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode
fFormatArgs.push_back(cppCode + ".fX");
fFormatArgs.push_back(cppCode + ".fY");
} else {
printf("%s\n", type.name().c_str());
this->write(type.fName);
this->write("\n");
ABORT("unsupported runtime value type\n");
}
}
@ -227,11 +227,11 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
}
fFormatArgs.push_back(code);
} else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) {
const char* name = ref.fVariable.fName.c_str();
String name(ref.fVariable.fName);
this->writeRuntimeValue(ref.fVariable.fType,
String::printf("_outer.%s()", name).c_str());
String::printf("_outer.%s()", name.c_str()).c_str());
} else {
this->write(ref.fVariable.fName.c_str());
this->write(ref.fVariable.fName);
}
}
}
@ -358,14 +358,16 @@ void CPPCodeGenerator::addUniform(const Variable& var) {
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());
ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(),
String(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();
String name(var.fName);
this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, "
"%s, \"%s\");\n", HCodeGenerator::FieldName(name).c_str(), type, precision, name);
"%s, \"%s\");\n", HCodeGenerator::FieldName(name.c_str()).c_str(), type, precision,
name.c_str());
if (var.fModifiers.fLayout.fWhen.size()) {
this->write(" }\n");
}
@ -380,7 +382,7 @@ void CPPCodeGenerator::writePrivateVars() {
if (is_private(*decl.fVar)) {
this->writef("%s %s;\n",
HCodeGenerator::FieldType(decl.fVar->fType).c_str(),
decl.fVar->fName.c_str());
String(decl.fVar->fName).c_str());
}
}
}
@ -395,7 +397,7 @@ void CPPCodeGenerator::writePrivateVarValues() {
VarDeclaration& decl = (VarDeclaration&) *raw;
if (is_private(*decl.fVar) && decl.fValue) {
this->writef("%s = %s;\n",
decl.fVar->fName.c_str(),
String(decl.fVar->fName).c_str(),
decl.fValue->description().c_str());
}
}
@ -414,12 +416,12 @@ bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
this->addUniform(*u);
if (u->fType == *fContext.fColorSpaceXform_Type) {
if (fNeedColorSpaceHelper) {
fErrors.error(u->fPosition, "only a single ColorSpaceXform is supported");
fErrors.error(u->fOffset, "only a single ColorSpaceXform is supported");
}
fNeedColorSpaceHelper = true;
this->writef(" fColorSpaceHelper.emitCode(args.fUniformHandler, "
"_outer.%s().get());\n",
u->fName.c_str());
String(u->fName).c_str());
}
}
this->writeSection(EMIT_CODE_SECTION);
@ -453,7 +455,8 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
wroteProcessor = true;
this->writef(" {\n");
}
const char* name = u->fName.c_str();
String nameString(u->fName);
const char* name = nameString.c_str();
if (u->fType == *fContext.fFloat4_Type) {
this->writef(" const SkRect %sValue = _outer.%s();\n"
" %s.set4fv(%sVar, 1, (float*) &%sValue);\n",
@ -485,13 +488,13 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
const VarDeclarations* decls = (const VarDeclarations*) p.get();
for (const auto& raw : decls->fVars) {
VarDeclaration& decl = (VarDeclaration&) *raw;
String nameString(decl.fVar->fName);
const char* name = nameString.c_str();
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);
@ -512,14 +515,14 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
void CPPCodeGenerator::writeClone() {
if (!this->writeSection(CLONE_SECTION)) {
if (fSectionAndParameterHelper.getSection(FIELDS_SECTION)) {
fErrors.error(Position(1, 1), "fragment processors with custom @fields must also have "
"a custom @clone");
fErrors.error(0, "fragment processors with custom @fields must also have a custom"
"@clone");
}
this->writef("%s::%s(const %s& src)\n"
": INHERITED(src.optimizationFlags())", fFullName.c_str(), fFullName.c_str(),
fFullName.c_str());
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
String fieldName = HCodeGenerator::FieldName(param->fName.c_str());
String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
this->writef("\n, %s(%s)",
fieldName.c_str(),
("src." + fieldName).c_str());
@ -535,7 +538,7 @@ void CPPCodeGenerator::writeClone() {
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
if (param->fType.kind() == Type::kSampler_Kind) {
this->writef(" this->addTextureSampler(&%s);\n",
HCodeGenerator::FieldName(param->fName.c_str()).c_str());
HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
}
}
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
@ -572,7 +575,8 @@ void CPPCodeGenerator::writeGetKey() {
"GrProcessorKeyBuilder* b) const {\n",
fFullName.c_str());
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
const char* name = param->fName.c_str();
String nameString(param->fName);
const char* name = nameString.c_str();
if (param->fType == *fContext.fColorSpaceXform_Type) {
this->writef(" b->add32(GrColorSpaceXform::XformKey(%s.get()));\n",
HCodeGenerator::FieldName(name).c_str());
@ -580,7 +584,7 @@ void CPPCodeGenerator::writeGetKey() {
}
if (param->fModifiers.fLayout.fKey != Layout::kNo_Key &&
(param->fModifiers.fFlags & Modifiers::kUniform_Flag)) {
fErrors.error(param->fPosition,
fErrors.error(param->fOffset,
"layout(key) may not be specified on uniforms");
}
switch (param->fModifiers.fLayout.fKey) {
@ -608,7 +612,7 @@ void CPPCodeGenerator::writeGetKey() {
break;
case Layout::kIdentity_Key:
if (param->fType.kind() != Type::kMatrix_Kind) {
fErrors.error(param->fPosition,
fErrors.error(param->fOffset,
"layout(key=identity) requires matrix type");
}
this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n",
@ -656,15 +660,15 @@ bool CPPCodeGenerator::generateCode() {
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());
this->writef(" UniformHandle %sVar;\n",
HCodeGenerator::FieldName(String(u->fName).c_str()).c_str());
}
}
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
const char* name = param->fName.c_str();
if (needs_uniform_var(*param)) {
this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
this->writef(" UniformHandle %sVar;\n",
HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
}
}
if (fNeedColorSpaceHelper) {
@ -681,7 +685,8 @@ bool CPPCodeGenerator::generateCode() {
" (void) that;\n",
fullName, fullName, fullName);
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
const char* name = param->fName.c_str();
String nameString(param->fName);
const char* name = nameString.c_str();
this->writef(" if (%s != that.%s) return false;\n",
HCodeGenerator::FieldName(name).c_str(),
HCodeGenerator::FieldName(name).c_str());

View File

@ -51,7 +51,6 @@ static const char* SKSL_FP_INCLUDE =
#include "sksl_fp.include"
;
namespace SkSL {
Compiler::Compiler(Flags flags)
@ -187,20 +186,23 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(GSamplerCubeArrayShadow);
ADD_TYPE(ColorSpaceXform);
String skCapsName("sk_Caps");
Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName,
StringFragment skCapsName("sk_Caps");
Variable* skCaps = new Variable(-1, 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,
StringFragment skArgsName("sk_Args");
Variable* skArgs = new Variable(-1, 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);
fIRGenerator->convertProgram(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored1, &ignored2);
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
if (fErrorCount) {
printf("Unexpected errors: %s\n", fErrorText.c_str());
}
ASSERT(!fErrorCount);
}
@ -260,7 +262,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
BinaryExpression* b = (BinaryExpression*) expr;
if (b->fOperator == Token::EQ) {
this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
} else if (Token::IsAssignment(b->fOperator)) {
} else if (Compiler::IsAssignment(b->fOperator)) {
this->addDefinition(
b->fLeft.get(),
(std::unique_ptr<Expression>*) &fContext.fDefined_Expression,
@ -401,7 +403,7 @@ static bool is_dead(const Expression& lvalue) {
* to a dead target and lack of side effects on the left hand side.
*/
static bool dead_assignment(const BinaryExpression& b) {
if (!Token::IsAssignment(b.fOperator)) {
if (!Compiler::IsAssignment(b.fOperator)) {
return false;
}
return is_dead(*b.fLeft);
@ -540,7 +542,7 @@ void delete_right(BasicBlock* b,
static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) {
std::vector<std::unique_ptr<Expression>> args;
args.push_back(std::move(v));
auto result = std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
auto result = std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
return result;
}
@ -642,7 +644,7 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] &&
(*undefinedVariables).find(&var) == (*undefinedVariables).end()) {
(*undefinedVariables).insert(&var);
this->error(expr->fPosition,
this->error(expr->fOffset,
"'" + var.fName + "' has not been assigned");
}
break;
@ -877,7 +879,7 @@ static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase*
for (const auto& s : statementPtrs) {
statements.push_back(std::move(*s));
}
return std::unique_ptr<Statement>(new Block(Position(), std::move(statements), s->fSymbols));
return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols));
}
void Compiler::simplifyStatement(DefinitionMap& definitions,
@ -964,7 +966,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
break;
} else {
if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fPosition,
this->error(s.fOffset,
"static switch contains non-static conditional break");
s.fIsStatic = false;
}
@ -980,7 +982,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
(*iter)->setStatement(std::move(newBlock));
} else {
if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fPosition,
this->error(s.fOffset,
"static switch contains non-static conditional break");
s.fIsStatic = false;
}
@ -1022,16 +1024,16 @@ void Compiler::scanCFG(FunctionDefinition& f) {
for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
cfg.fBlocks[i].fNodes.size()) {
Position p;
int offset;
switch (cfg.fBlocks[i].fNodes[0].fKind) {
case BasicBlock::Node::kStatement_Kind:
p = (*cfg.fBlocks[i].fNodes[0].statement())->fPosition;
offset = (*cfg.fBlocks[i].fNodes[0].statement())->fOffset;
break;
case BasicBlock::Node::kExpression_Kind:
p = (*cfg.fBlocks[i].fNodes[0].expression())->fPosition;
offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset;
break;
}
this->error(p, String("unreachable"));
this->error(offset, String("unreachable"));
}
}
if (fErrorCount) {
@ -1081,14 +1083,14 @@ void Compiler::scanCFG(FunctionDefinition& f) {
case Statement::kIf_Kind:
if (((const IfStatement&) s).fIsStatic &&
!(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fPosition, "static if has non-static test");
this->error(s.fOffset, "static if has non-static test");
}
++iter;
break;
case Statement::kSwitch_Kind:
if (((const SwitchStatement&) s).fIsStatic &&
!(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fPosition, "static switch has non-static test");
this->error(s.fOffset, "static switch has non-static test");
}
++iter;
break;
@ -1121,7 +1123,7 @@ void Compiler::scanCFG(FunctionDefinition& f) {
// check for missing return
if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) {
if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
this->error(f.fPosition, String("function can exit without returning a value"));
this->error(f.fOffset, String("function can exit without returning a value"));
}
}
}
@ -1135,21 +1137,28 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
Modifiers::Flag ignored;
switch (kind) {
case Program::kVertex_Kind:
fIRGenerator->convertProgram(String(SKSL_VERT_INCLUDE), *fTypes, &ignored, &elements);
fIRGenerator->convertProgram(SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), *fTypes,
&ignored, &elements);
break;
case Program::kFragment_Kind:
fIRGenerator->convertProgram(String(SKSL_FRAG_INCLUDE), *fTypes, &ignored, &elements);
fIRGenerator->convertProgram(SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes,
&ignored, &elements);
break;
case Program::kGeometry_Kind:
fIRGenerator->convertProgram(String(SKSL_GEOM_INCLUDE), *fTypes, &ignored, &elements);
fIRGenerator->convertProgram(SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes,
&ignored, &elements);
break;
case Program::kFragmentProcessor_Kind:
fIRGenerator->convertProgram(String(SKSL_FP_INCLUDE), *fTypes, &ignored, &elements);
fIRGenerator->convertProgram(SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes,
&ignored, &elements);
break;
}
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Modifiers::Flag defaultPrecision;
fIRGenerator->convertProgram(text, *fTypes, &defaultPrecision, &elements);
std::unique_ptr<String> textPtr(new String(std::move(text)));
fSource = textPtr.get();
fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &defaultPrecision,
&elements);
if (!fErrorCount) {
for (auto& element : elements) {
if (element->fKind == ProgramElement::kFunction_Kind) {
@ -1157,11 +1166,13 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
}
}
}
auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
auto result = std::unique_ptr<Program>(new Program(kind, std::move(textPtr), settings,
defaultPrecision, &fContext,
std::move(elements),
fIRGenerator->fSymbolTable,
fIRGenerator->fInputs));
fIRGenerator->finish();
fSource = nullptr;
this->writeErrorCount();
if (fErrorCount) {
return nullptr;
@ -1172,8 +1183,10 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
bool Compiler::toSPIRV(const Program& program, OutputStream& out) {
#ifdef SK_ENABLE_SPIRV_VALIDATION
StringStream buffer;
fSource = program.fSource.get();
SPIRVCodeGenerator cg(&fContext, &program, this, &buffer);
bool result = cg.generateCode();
fSource = nullptr;
if (result) {
spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
const String& data = buffer.str();
@ -1188,8 +1201,10 @@ bool Compiler::toSPIRV(const Program& program, OutputStream& out) {
out.write(data.c_str(), data.size());
}
#else
fSource = program.fSource.get();
SPIRVCodeGenerator cg(&fContext, &program, this, &out);
bool result = cg.generateCode();
fSource = nullptr;
#endif
this->writeErrorCount();
return result;
@ -1205,8 +1220,10 @@ bool Compiler::toSPIRV(const Program& program, String* out) {
}
bool Compiler::toGLSL(const Program& program, OutputStream& out) {
fSource = program.fSource.get();
GLSLCodeGenerator cg(&fContext, &program, this, &out);
bool result = cg.generateCode();
fSource = nullptr;
this->writeErrorCount();
return result;
}
@ -1221,22 +1238,111 @@ bool Compiler::toGLSL(const Program& program, String* out) {
}
bool Compiler::toCPP(const Program& program, String name, OutputStream& out) {
fSource = program.fSource.get();
CPPCodeGenerator cg(&fContext, &program, this, name, &out);
bool result = cg.generateCode();
fSource = nullptr;
this->writeErrorCount();
return result;
}
bool Compiler::toH(const Program& program, String name, OutputStream& out) {
fSource = program.fSource.get();
HCodeGenerator cg(&program, this, name, &out);
bool result = cg.generateCode();
fSource = nullptr;
this->writeErrorCount();
return result;
}
void Compiler::error(Position position, String msg) {
const char* Compiler::OperatorName(Token::Kind kind) {
switch (kind) {
case Token::PLUS: return "+";
case Token::MINUS: return "-";
case Token::STAR: return "*";
case Token::SLASH: return "/";
case Token::PERCENT: return "%";
case Token::SHL: return "<<";
case Token::SHR: return ">>";
case Token::LOGICALNOT: return "!";
case Token::LOGICALAND: return "&&";
case Token::LOGICALOR: return "||";
case Token::LOGICALXOR: return "^^";
case Token::BITWISENOT: return "~";
case Token::BITWISEAND: return "&";
case Token::BITWISEOR: return "|";
case Token::BITWISEXOR: return "^";
case Token::EQ: return "=";
case Token::EQEQ: return "==";
case Token::NEQ: return "!=";
case Token::LT: return "<";
case Token::GT: return ">";
case Token::LTEQ: return "<=";
case Token::GTEQ: return ">=";
case Token::PLUSEQ: return "+=";
case Token::MINUSEQ: return "-=";
case Token::STAREQ: return "*=";
case Token::SLASHEQ: return "/=";
case Token::PERCENTEQ: return "%=";
case Token::SHLEQ: return "<<=";
case Token::SHREQ: return ">>=";
case Token::LOGICALANDEQ: return "&&=";
case Token::LOGICALOREQ: return "||=";
case Token::LOGICALXOREQ: return "^^=";
case Token::BITWISEANDEQ: return "&=";
case Token::BITWISEOREQ: return "|=";
case Token::BITWISEXOREQ: return "^=";
case Token::PLUSPLUS: return "++";
case Token::MINUSMINUS: return "--";
case Token::COMMA: return ",";
default:
ABORT("unsupported operator: %d\n", kind);
}
}
bool Compiler::IsAssignment(Token::Kind op) {
switch (op) {
case Token::EQ: // fall through
case Token::PLUSEQ: // fall through
case Token::MINUSEQ: // fall through
case Token::STAREQ: // fall through
case Token::SLASHEQ: // fall through
case Token::PERCENTEQ: // fall through
case Token::SHLEQ: // fall through
case Token::SHREQ: // fall through
case Token::BITWISEOREQ: // fall through
case Token::BITWISEXOREQ: // fall through
case Token::BITWISEANDEQ: // fall through
case Token::LOGICALOREQ: // fall through
case Token::LOGICALXOREQ: // fall through
case Token::LOGICALANDEQ:
return true;
default:
return false;
}
}
Position Compiler::position(int offset) {
ASSERT(fSource);
int line = 1;
int column = 1;
for (int i = 0; i < offset; i++) {
if ((*fSource)[i] == '\n') {
++line;
column = 1;
}
else {
++column;
}
}
return Position(line, column);
}
void Compiler::error(int offset, String msg) {
fErrorCount++;
fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
Position pos = this->position(offset);
fErrorText += "error: " + to_string(pos.fLine) + ": " + msg.c_str() + "\n";
}
String Compiler::errorText() {

View File

@ -16,7 +16,6 @@
#include "SkSLCFGGenerator.h"
#include "SkSLContext.h"
#include "SkSLErrorReporter.h"
#include "SkSLIRGenerator.h"
#define SK_FRAGCOLOR_BUILTIN 10001
#define SK_IN_BUILTIN 10002
@ -70,7 +69,7 @@ public:
bool toH(const Program& program, String name, OutputStream& out);
void error(Position position, String msg) override;
void error(int offset, String msg) override;
String errorText();
@ -80,6 +79,10 @@ public:
return fErrorCount;
}
static const char* OperatorName(Token::Kind token);
static bool IsAssignment(Token::Kind token);
private:
void addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
DefinitionMap* definitions);
@ -114,11 +117,14 @@ private:
void scanCFG(FunctionDefinition& f);
Position position(int offset);
std::shared_ptr<SymbolTable> fTypes;
IRGenerator* fIRGenerator;
String fSkiaVertText; // FIXME store parsed version instead
int fFlags;
const String* fSource;
Context fContext;
int fErrorCount;
String fErrorText;

View File

@ -19,172 +19,172 @@ namespace SkSL {
class Context {
public:
Context()
: fInvalid_Type(new Type(String("<INVALID>")))
, fVoid_Type(new Type(String("void")))
, fDouble_Type(new Type(String("double"), Type::kFloat_NumberKind))
, fDouble2_Type(new Type(String("double2"), *fDouble_Type, 2))
, fDouble3_Type(new Type(String("double3"), *fDouble_Type, 3))
, fDouble4_Type(new Type(String("double4"), *fDouble_Type, 4))
, fFloat_Type(new Type(String("float"), Type::kFloat_NumberKind))
, fFloat2_Type(new Type(String("float2"), *fFloat_Type, 2))
, fFloat3_Type(new Type(String("float3"), *fFloat_Type, 3))
, fFloat4_Type(new Type(String("float4"), *fFloat_Type, 4))
, fHalf_Type(new Type(String("half"), Type::kFloat_NumberKind))
, fHalf2_Type(new Type(String("half2"), *fHalf_Type, 2))
, fHalf3_Type(new Type(String("half3"), *fHalf_Type, 3))
, fHalf4_Type(new Type(String("half4"), *fHalf_Type, 4))
, fUInt_Type(new Type(String("uint"), Type::kUnsigned_NumberKind))
, fUInt2_Type(new Type(String("uint2"), *fUInt_Type, 2))
, fUInt3_Type(new Type(String("uint3"), *fUInt_Type, 3))
, fUInt4_Type(new Type(String("uint4"), *fUInt_Type, 4))
, fInt_Type(new Type(String("int"), Type::kSigned_NumberKind))
, fInt2_Type(new Type(String("int2"), *fInt_Type, 2))
, fInt3_Type(new Type(String("int3"), *fInt_Type, 3))
, fInt4_Type(new Type(String("int4"), *fInt_Type, 4))
, fUShort_Type(new Type(String("ushort"), Type::kUnsigned_NumberKind))
, fUShort2_Type(new Type(String("ushort2"), *fUShort_Type, 2))
, fUShort3_Type(new Type(String("ushort3"), *fUShort_Type, 3))
, fUShort4_Type(new Type(String("ushort4"), *fUShort_Type, 4))
, fShort_Type(new Type(String("short"), Type::kSigned_NumberKind))
, fShort2_Type(new Type(String("short2"), *fShort_Type, 2))
, fShort3_Type(new Type(String("short3"), *fShort_Type, 3))
, fShort4_Type(new Type(String("short4"), *fShort_Type, 4))
, fBool_Type(new Type(String("bool"), Type::kNonnumeric_NumberKind))
, fBool2_Type(new Type(String("bool2"), *fBool_Type, 2))
, fBool3_Type(new Type(String("bool3"), *fBool_Type, 3))
, fBool4_Type(new Type(String("bool4"), *fBool_Type, 4))
, fFloat2x2_Type(new Type(String("float2x2"), *fFloat_Type, 2, 2))
, fFloat2x3_Type(new Type(String("float2x3"), *fFloat_Type, 2, 3))
, fFloat2x4_Type(new Type(String("float2x4"), *fFloat_Type, 2, 4))
, fFloat3x2_Type(new Type(String("float3x2"), *fFloat_Type, 3, 2))
, fFloat3x3_Type(new Type(String("float3x3"), *fFloat_Type, 3, 3))
, fFloat3x4_Type(new Type(String("float3x4"), *fFloat_Type, 3, 4))
, fFloat4x2_Type(new Type(String("float4x2"), *fFloat_Type, 4, 2))
, fFloat4x3_Type(new Type(String("float4x3"), *fFloat_Type, 4, 3))
, fFloat4x4_Type(new Type(String("float4x4"), *fFloat_Type, 4, 4))
, fHalf2x2_Type(new Type(String("half2x2"), *fHalf_Type, 2, 2))
, fHalf2x3_Type(new Type(String("half2x3"), *fHalf_Type, 2, 3))
, fHalf2x4_Type(new Type(String("half2x4"), *fHalf_Type, 2, 4))
, fHalf3x2_Type(new Type(String("half3x2"), *fHalf_Type, 3, 2))
, fHalf3x3_Type(new Type(String("half3x3"), *fHalf_Type, 3, 3))
, fHalf3x4_Type(new Type(String("half3x4"), *fHalf_Type, 3, 4))
, fHalf4x2_Type(new Type(String("half4x2"), *fHalf_Type, 4, 2))
, fHalf4x3_Type(new Type(String("half4x3"), *fHalf_Type, 4, 3))
, fHalf4x4_Type(new Type(String("half4x4"), *fHalf_Type, 4, 4))
, fDouble2x2_Type(new Type(String("double2x2"), *fDouble_Type, 2, 2))
, fDouble2x3_Type(new Type(String("double2x3"), *fDouble_Type, 2, 3))
, fDouble2x4_Type(new Type(String("double2x4"), *fDouble_Type, 2, 4))
, fDouble3x2_Type(new Type(String("double3x2"), *fDouble_Type, 3, 2))
, fDouble3x3_Type(new Type(String("double3x3"), *fDouble_Type, 3, 3))
, fDouble3x4_Type(new Type(String("double3x4"), *fDouble_Type, 3, 4))
, fDouble4x2_Type(new Type(String("double4x2"), *fDouble_Type, 4, 2))
, fDouble4x3_Type(new Type(String("double4x3"), *fDouble_Type, 4, 3))
, fDouble4x4_Type(new Type(String("double4x4"), *fDouble_Type, 4, 4))
, fSampler1D_Type(new Type(String("sampler1D"), SpvDim1D, false, false, false, true))
, fSampler2D_Type(new Type(String("sampler2D"), SpvDim2D, false, false, false, true))
, fSampler3D_Type(new Type(String("sampler3D"), SpvDim3D, false, false, false, true))
, fSamplerExternalOES_Type(new Type(String("samplerExternalOES"), SpvDim2D, false, false,
: fInvalid_Type(new Type("<INVALID>"))
, fVoid_Type(new Type("void"))
, fDouble_Type(new Type("double", Type::kFloat_NumberKind))
, fDouble2_Type(new Type("double2", *fDouble_Type, 2))
, fDouble3_Type(new Type("double3", *fDouble_Type, 3))
, fDouble4_Type(new Type("double4", *fDouble_Type, 4))
, fFloat_Type(new Type("float", Type::kFloat_NumberKind))
, fFloat2_Type(new Type("float2", *fFloat_Type, 2))
, fFloat3_Type(new Type("float3", *fFloat_Type, 3))
, fFloat4_Type(new Type("float4", *fFloat_Type, 4))
, fHalf_Type(new Type("half", Type::kFloat_NumberKind))
, fHalf2_Type(new Type("half2", *fHalf_Type, 2))
, fHalf3_Type(new Type("half3", *fHalf_Type, 3))
, fHalf4_Type(new Type("half4", *fHalf_Type, 4))
, fUInt_Type(new Type("uint", Type::kUnsigned_NumberKind))
, fUInt2_Type(new Type("uint2", *fUInt_Type, 2))
, fUInt3_Type(new Type("uint3", *fUInt_Type, 3))
, fUInt4_Type(new Type("uint4", *fUInt_Type, 4))
, fInt_Type(new Type("int", Type::kSigned_NumberKind))
, fInt2_Type(new Type("int2", *fInt_Type, 2))
, fInt3_Type(new Type("int3", *fInt_Type, 3))
, fInt4_Type(new Type("int4", *fInt_Type, 4))
, fUShort_Type(new Type("ushort", Type::kUnsigned_NumberKind))
, fUShort2_Type(new Type("ushort2", *fUShort_Type, 2))
, fUShort3_Type(new Type("ushort3", *fUShort_Type, 3))
, fUShort4_Type(new Type("ushort4", *fUShort_Type, 4))
, fShort_Type(new Type("short", Type::kSigned_NumberKind))
, fShort2_Type(new Type("short2", *fShort_Type, 2))
, fShort3_Type(new Type("short3", *fShort_Type, 3))
, fShort4_Type(new Type("short4", *fShort_Type, 4))
, fBool_Type(new Type("bool", Type::kNonnumeric_NumberKind))
, fBool2_Type(new Type("bool2", *fBool_Type, 2))
, fBool3_Type(new Type("bool3", *fBool_Type, 3))
, fBool4_Type(new Type("bool4", *fBool_Type, 4))
, fFloat2x2_Type(new Type("float2x2", *fFloat_Type, 2, 2))
, fFloat2x3_Type(new Type("float2x3", *fFloat_Type, 2, 3))
, fFloat2x4_Type(new Type("float2x4", *fFloat_Type, 2, 4))
, fFloat3x2_Type(new Type("float3x2", *fFloat_Type, 3, 2))
, fFloat3x3_Type(new Type("float3x3", *fFloat_Type, 3, 3))
, fFloat3x4_Type(new Type("float3x4", *fFloat_Type, 3, 4))
, fFloat4x2_Type(new Type("float4x2", *fFloat_Type, 4, 2))
, fFloat4x3_Type(new Type("float4x3", *fFloat_Type, 4, 3))
, fFloat4x4_Type(new Type("float4x4", *fFloat_Type, 4, 4))
, fHalf2x2_Type(new Type("half2x2", *fHalf_Type, 2, 2))
, fHalf2x3_Type(new Type("half2x3", *fHalf_Type, 2, 3))
, fHalf2x4_Type(new Type("half2x4", *fHalf_Type, 2, 4))
, fHalf3x2_Type(new Type("half3x2", *fHalf_Type, 3, 2))
, fHalf3x3_Type(new Type("half3x3", *fHalf_Type, 3, 3))
, fHalf3x4_Type(new Type("half3x4", *fHalf_Type, 3, 4))
, fHalf4x2_Type(new Type("half4x2", *fHalf_Type, 4, 2))
, fHalf4x3_Type(new Type("half4x3", *fHalf_Type, 4, 3))
, fHalf4x4_Type(new Type("half4x4", *fHalf_Type, 4, 4))
, fDouble2x2_Type(new Type("double2x2", *fDouble_Type, 2, 2))
, fDouble2x3_Type(new Type("double2x3", *fDouble_Type, 2, 3))
, fDouble2x4_Type(new Type("double2x4", *fDouble_Type, 2, 4))
, fDouble3x2_Type(new Type("double3x2", *fDouble_Type, 3, 2))
, fDouble3x3_Type(new Type("double3x3", *fDouble_Type, 3, 3))
, fDouble3x4_Type(new Type("double3x4", *fDouble_Type, 3, 4))
, fDouble4x2_Type(new Type("double4x2", *fDouble_Type, 4, 2))
, fDouble4x3_Type(new Type("double4x3", *fDouble_Type, 4, 3))
, fDouble4x4_Type(new Type("double4x4", *fDouble_Type, 4, 4))
, fSampler1D_Type(new Type("sampler1D", SpvDim1D, false, false, false, true))
, fSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true))
, fSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true))
, fSamplerExternalOES_Type(new Type("samplerExternalOES", SpvDim2D, false, false,
false, true))
, fSamplerCube_Type(new Type(String("samplerCube"), SpvDimCube, 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")))
, fSamplerBuffer_Type(new Type(String("samplerBuffer"), SpvDimBuffer, false, false, false,
, fSamplerCube_Type(new Type("samplerCube", SpvDimCube, false, false, false, true))
, fSampler2DRect_Type(new Type("sampler2DRect", SpvDimRect, false, false, false, true))
, fSampler1DArray_Type(new Type("sampler1DArray"))
, fSampler2DArray_Type(new Type("sampler2DArray"))
, fSamplerCubeArray_Type(new Type("samplerCubeArray"))
, fSamplerBuffer_Type(new Type("samplerBuffer", SpvDimBuffer, false, false, false,
true))
, fSampler2DMS_Type(new Type(String("sampler2DMS")))
, fSampler2DMSArray_Type(new Type(String("sampler2DMSArray")))
, fSampler1DShadow_Type(new Type(String("sampler1DShadow")))
, fSampler2DShadow_Type(new Type(String("sampler2DShadow")))
, fSamplerCubeShadow_Type(new Type(String("samplerCubeShadow")))
, fSampler2DRectShadow_Type(new Type(String("sampler2DRectShadow")))
, fSampler1DArrayShadow_Type(new Type(String("sampler1DArrayShadow")))
, fSampler2DArrayShadow_Type(new Type(String("sampler2DArrayShadow")))
, fSamplerCubeArrayShadow_Type(new Type(String("samplerCubeArrayShadow")))
, fSampler2DMS_Type(new Type("sampler2DMS"))
, fSampler2DMSArray_Type(new Type("sampler2DMSArray"))
, fSampler1DShadow_Type(new Type("sampler1DShadow"))
, fSampler2DShadow_Type(new Type("sampler2DShadow"))
, fSamplerCubeShadow_Type(new Type("samplerCubeShadow"))
, fSampler2DRectShadow_Type(new Type("sampler2DRectShadow"))
, fSampler1DArrayShadow_Type(new Type("sampler1DArrayShadow"))
, fSampler2DArrayShadow_Type(new Type("sampler2DArrayShadow"))
, fSamplerCubeArrayShadow_Type(new Type("samplerCubeArrayShadow"))
// Related to below FIXME, gsampler*s don't currently expand to cover integer case.
, fISampler2D_Type(new Type(String("isampler2D"), SpvDim2D, false, false, false, true))
, fISampler2D_Type(new Type("isampler2D", SpvDim2D, false, false, false, true))
// FIXME express these as "gimage2D" that expand to image2D, iimage2D, and uimage2D.
, fImage2D_Type(new Type(String("image2D"), SpvDim2D, false, false, false, true))
, fIImage2D_Type(new Type(String("iimage2D"), SpvDim2D, false, false, false, true))
, fImage2D_Type(new Type("image2D", SpvDim2D, false, false, false, true))
, fIImage2D_Type(new Type("iimage2D", SpvDim2D, false, false, false, true))
// FIXME express these as "gsubpassInput" that expand to subpassInput, isubpassInput,
// and usubpassInput.
, fSubpassInput_Type(new Type(String("subpassInput"), SpvDimSubpassData, false, false,
false, false))
, fSubpassInputMS_Type(new Type(String("subpassInputMS"), SpvDimSubpassData, false, false,
true, false))
, fSubpassInput_Type(new Type("subpassInput", SpvDimSubpassData, false, false,
false, false))
, fSubpassInputMS_Type(new Type("subpassInputMS", SpvDimSubpassData, false, false,
true, false))
// FIXME figure out what we're supposed to do with the gsampler et al. types)
, fGSampler1D_Type(new Type(String("$gsampler1D"), static_type(*fSampler1D_Type)))
, fGSampler2D_Type(new Type(String("$gsampler2D"), static_type(*fSampler2D_Type)))
, fGSampler3D_Type(new Type(String("$gsampler3D"), static_type(*fSampler3D_Type)))
, fGSamplerCube_Type(new Type(String("$gsamplerCube"), static_type(*fSamplerCube_Type)))
, fGSampler2DRect_Type(new Type(String("$gsampler2DRect"), static_type(*fSampler2DRect_Type)))
, fGSampler1DArray_Type(new Type(String("$gsampler1DArray"),
, fGSampler1D_Type(new Type("$gsampler1D", static_type(*fSampler1D_Type)))
, fGSampler2D_Type(new Type("$gsampler2D", static_type(*fSampler2D_Type)))
, fGSampler3D_Type(new Type("$gsampler3D", static_type(*fSampler3D_Type)))
, fGSamplerCube_Type(new Type("$gsamplerCube", static_type(*fSamplerCube_Type)))
, fGSampler2DRect_Type(new Type("$gsampler2DRect", static_type(*fSampler2DRect_Type)))
, fGSampler1DArray_Type(new Type("$gsampler1DArray",
static_type(*fSampler1DArray_Type)))
, fGSampler2DArray_Type(new Type(String("$gsampler2DArray"),
, fGSampler2DArray_Type(new Type("$gsampler2DArray",
static_type(*fSampler2DArray_Type)))
, fGSamplerCubeArray_Type(new Type(String("$gsamplerCubeArray"),
, fGSamplerCubeArray_Type(new Type("$gsamplerCubeArray",
static_type(*fSamplerCubeArray_Type)))
, fGSamplerBuffer_Type(new Type(String("$gsamplerBuffer"), static_type(*fSamplerBuffer_Type)))
, fGSampler2DMS_Type(new Type(String("$gsampler2DMS"), static_type(*fSampler2DMS_Type)))
, fGSampler2DMSArray_Type(new Type(String("$gsampler2DMSArray"),
, fGSamplerBuffer_Type(new Type("$gsamplerBuffer", static_type(*fSamplerBuffer_Type)))
, fGSampler2DMS_Type(new Type("$gsampler2DMS", static_type(*fSampler2DMS_Type)))
, fGSampler2DMSArray_Type(new Type("$gsampler2DMSArray",
static_type(*fSampler2DMSArray_Type)))
, fGSampler2DArrayShadow_Type(new Type(String("$gsampler2DArrayShadow"),
, fGSampler2DArrayShadow_Type(new Type("$gsampler2DArrayShadow",
static_type(*fSampler2DArrayShadow_Type)))
, fGSamplerCubeArrayShadow_Type(new Type(String("$gsamplerCubeArrayShadow"),
, fGSamplerCubeArrayShadow_Type(new Type("$gsamplerCubeArrayShadow",
static_type(*fSamplerCubeArrayShadow_Type)))
, fGenType_Type(new Type(String("$genType"), { fFloat_Type.get(), fFloat2_Type.get(),
fFloat3_Type.get(), fFloat4_Type.get() }))
, fGenHType_Type(new Type(String("$genHType"), { fHalf_Type.get(), fHalf2_Type.get(),
fHalf3_Type.get(), fHalf4_Type.get() }))
, fGenDType_Type(new Type(String("$genDType"), { fDouble_Type.get(), fDouble2_Type.get(),
fDouble3_Type.get(), fDouble4_Type.get() }))
, fGenIType_Type(new Type(String("$genIType"), { fInt_Type.get(), fInt2_Type.get(),
fInt3_Type.get(), fInt4_Type.get() }))
, fGenUType_Type(new Type(String("$genUType"), { fUInt_Type.get(), fUInt2_Type.get(),
fUInt3_Type.get(), fUInt4_Type.get() }))
, fGenBType_Type(new Type(String("$genBType"), { fBool_Type.get(), fBool2_Type.get(),
fBool3_Type.get(), fBool4_Type.get() }))
, fMat_Type(new Type(String("$mat"), { fFloat2x2_Type.get(), fFloat2x3_Type.get(),
fFloat2x4_Type.get(), fFloat3x2_Type.get(),
fFloat3x3_Type.get(), fFloat3x4_Type.get(),
fFloat4x2_Type.get(), fFloat4x3_Type.get(),
fFloat4x4_Type.get(), fHalf2x2_Type.get(),
fHalf2x3_Type.get(), fHalf2x4_Type.get(),
fHalf3x2_Type.get(), fHalf3x3_Type.get(),
fHalf3x4_Type.get(), fHalf4x2_Type.get(),
fHalf4x3_Type.get(), fHalf4x4_Type.get(),
fDouble2x2_Type.get(), fDouble2x3_Type.get(),
fDouble2x4_Type.get(), fDouble3x2_Type.get(),
fDouble3x3_Type.get(), fDouble3x4_Type.get(),
fDouble4x2_Type.get(), fDouble4x3_Type.get(),
fDouble4x4_Type.get() }))
, fVec_Type(new Type(String("$vec"), { fInvalid_Type.get(), fFloat2_Type.get(),
, fGenType_Type(new Type("$genType", { fFloat_Type.get(), fFloat2_Type.get(),
fFloat3_Type.get(), fFloat4_Type.get() }))
, fGVec_Type(new Type(String("$gvec")))
, fGVec2_Type(new Type(String("$gfloat2")))
, fGVec3_Type(new Type(String("$gfloat3")))
, fGVec4_Type(new Type(String("$gfloat4"), static_type(*fFloat4_Type)))
, fHVec_Type(new Type(String("$hvec"), { fInvalid_Type.get(), fHalf2_Type.get(),
, fGenHType_Type(new Type("$genHType", { fHalf_Type.get(), fHalf2_Type.get(),
fHalf3_Type.get(), fHalf4_Type.get() }))
, fDVec_Type(new Type(String("$dvec"), { fInvalid_Type.get(), fDouble2_Type.get(),
, fGenDType_Type(new Type("$genDType", { fDouble_Type.get(), fDouble2_Type.get(),
fDouble3_Type.get(), fDouble4_Type.get() }))
, fIVec_Type(new Type(String("$ivec"), { fInvalid_Type.get(), fInt2_Type.get(),
, fGenIType_Type(new Type("$genIType", { fInt_Type.get(), fInt2_Type.get(),
fInt3_Type.get(), fInt4_Type.get() }))
, fUVec_Type(new Type(String("$uvec"), { fInvalid_Type.get(), fUInt2_Type.get(),
, fGenUType_Type(new Type("$genUType", { fUInt_Type.get(), fUInt2_Type.get(),
fUInt3_Type.get(), fUInt4_Type.get() }))
, fSVec_Type(new Type(String("$svec"), { fInvalid_Type.get(), fShort2_Type.get(),
fShort3_Type.get(), fShort4_Type.get() }))
, fUSVec_Type(new Type(String("$usvec"), { fInvalid_Type.get(), fUShort2_Type.get(),
fUShort3_Type.get(), fUShort4_Type.get() }))
, fBVec_Type(new Type(String("$bvec"), { fInvalid_Type.get(), fBool2_Type.get(),
, fGenBType_Type(new Type("$genBType", { fBool_Type.get(), fBool2_Type.get(),
fBool3_Type.get(), fBool4_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))
, fMat_Type(new Type("$mat", { fFloat2x2_Type.get(), fFloat2x3_Type.get(),
fFloat2x4_Type.get(), fFloat3x2_Type.get(),
fFloat3x3_Type.get(), fFloat3x4_Type.get(),
fFloat4x2_Type.get(), fFloat4x3_Type.get(),
fFloat4x4_Type.get(), fHalf2x2_Type.get(),
fHalf2x3_Type.get(), fHalf2x4_Type.get(),
fHalf3x2_Type.get(), fHalf3x3_Type.get(),
fHalf3x4_Type.get(), fHalf4x2_Type.get(),
fHalf4x3_Type.get(), fHalf4x4_Type.get(),
fDouble2x2_Type.get(), fDouble2x3_Type.get(),
fDouble2x4_Type.get(), fDouble3x2_Type.get(),
fDouble3x3_Type.get(), fDouble3x4_Type.get(),
fDouble4x2_Type.get(), fDouble4x3_Type.get(),
fDouble4x4_Type.get() }))
, fVec_Type(new Type("$vec", { fInvalid_Type.get(), fFloat2_Type.get(),
fFloat3_Type.get(), fFloat4_Type.get() }))
, fGVec_Type(new Type("$gvec"))
, fGVec2_Type(new Type("$gfloat2"))
, fGVec3_Type(new Type("$gfloat3"))
, fGVec4_Type(new Type("$gfloat4", static_type(*fFloat4_Type)))
, fHVec_Type(new Type("$hvec", { fInvalid_Type.get(), fHalf2_Type.get(),
fHalf3_Type.get(), fHalf4_Type.get() }))
, fDVec_Type(new Type("$dvec", { fInvalid_Type.get(), fDouble2_Type.get(),
fDouble3_Type.get(), fDouble4_Type.get() }))
, fIVec_Type(new Type("$ivec", { fInvalid_Type.get(), fInt2_Type.get(),
fInt3_Type.get(), fInt4_Type.get() }))
, fUVec_Type(new Type("$uvec", { fInvalid_Type.get(), fUInt2_Type.get(),
fUInt3_Type.get(), fUInt4_Type.get() }))
, fSVec_Type(new Type("$svec", { fInvalid_Type.get(), fShort2_Type.get(),
fShort3_Type.get(), fShort4_Type.get() }))
, fUSVec_Type(new Type("$usvec", { fInvalid_Type.get(), fUShort2_Type.get(),
fUShort3_Type.get(), fUShort4_Type.get() }))
, fBVec_Type(new Type("$bvec", { fInvalid_Type.get(), fBool2_Type.get(),
fBool3_Type.get(), fBool4_Type.get() }))
, fSkCaps_Type(new Type("$sk_Caps"))
, fSkArgs_Type(new Type("$sk_Args"))
, fColorSpaceXform_Type(new Type("colorSpaceXform", *fFloat_Type, 4, 4))
, fDefined_Expression(new Defined(*fInvalid_Type)) {}
static std::vector<const Type*> static_type(const Type& t) {
@ -343,14 +343,14 @@ private:
class Defined : public Expression {
public:
Defined(const Type& type)
: INHERITED(Position(), kDefined_Kind, type) {}
: INHERITED(-1, kDefined_Kind, type) {}
bool hasSideEffects() const override {
return false;
}
String description() const override {
return String("<defined>");
return "<defined>";
}
typedef Expression INHERITED;

View File

@ -19,11 +19,11 @@ class ErrorReporter {
public:
virtual ~ErrorReporter() {}
void error(Position position, const char* msg) {
this->error(position, String(msg));
void error(int offset, const char* msg) {
this->error(offset, String(msg));
}
virtual void error(Position position, String msg) = 0;
virtual void error(int offset, String msg) = 0;
virtual int errorCount() = 0;
};

View File

@ -42,6 +42,19 @@ void GLSLCodeGenerator::write(const String& s) {
this->write(s.c_str());
}
void GLSLCodeGenerator::write(StringFragment s) {
if (!s.fLength) {
return;
}
if (fAtLineStart) {
for (int i = 0; i < fIndentation; i++) {
fOut->writeText(" ");
}
}
fOut->write(s.fChars, s.fLength);
fAtLineStart = false;
}
void GLSLCodeGenerator::writeLine(const String& s) {
this->writeLine(s.c_str());
}
@ -51,7 +64,9 @@ void GLSLCodeGenerator::writeLine() {
}
void GLSLCodeGenerator::writeExtension(const Extension& ext) {
this->writeLine("#extension " + ext.fName + " : enable");
this->write("#extension ");
this->write(ext.fName);
this->writeLine(" : enable");
}
void GLSLCodeGenerator::writeType(const Type& type) {
@ -59,19 +74,23 @@ void GLSLCodeGenerator::writeType(const Type& type) {
for (const Type* search : fWrittenStructs) {
if (*search == type) {
// already written
this->write(type.name());
this->write(type.fName);
return;
}
}
fWrittenStructs.push_back(&type);
this->writeLine("struct " + type.name() + " {");
this->write("struct ");
this->write(type.fName);
this->writeLine(" {");
fIndentation++;
for (const auto& f : type.fields()) {
this->writeModifiers(f.fModifiers, false);
this->writeTypePrecision(*f.fType);
// sizes (which must be static in structs) are part of the type name here
this->writeType(*f.fType);
this->writeLine(" " + f.fName + ";");
this->write(" ");
this->write(f.fName);
this->writeLine(";");
}
fIndentation--;
this->write("}");
@ -138,12 +157,12 @@ void GLSLCodeGenerator::writeType(const Type& type) {
this->write("uint");
}
else {
this->write(type.name());
this->write(type.fName);
}
break;
}
default:
this->write(type.name());
this->write(type.fName);
}
}
}
@ -210,8 +229,8 @@ void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherEx
ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n";
this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n";
this->fFunctionHeader += String(" ") + absExpr.fType.fName + " " + tmpVar1 + ";\n";
this->fFunctionHeader += String(" ") + otherExpr.fType.fName + " " + tmpVar2 + ";\n";
this->write("((" + tmpVar1 + " = ");
this->writeExpression(absExpr, kTopLevel_Precedence);
this->write(") < (" + tmpVar2 + " = ");
@ -503,7 +522,9 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
this->write("(");
}
this->writeExpression(*b.fLeft, precedence);
this->write(" " + Token::OperatorName(b.fOperator) + " ");
this->write(" ");
this->write(Compiler::OperatorName(b.fOperator));
this->write(" ");
this->writeExpression(*b.fRight, precedence);
if (precedence >= parentPrecedence) {
this->write(")");
@ -530,7 +551,7 @@ void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
if (kPrefix_Precedence >= parentPrecedence) {
this->write("(");
}
this->write(Token::OperatorName(p.fOperator));
this->write(Compiler::OperatorName(p.fOperator));
this->writeExpression(*p.fOperand, kPrefix_Precedence);
if (kPrefix_Precedence >= parentPrecedence) {
this->write(")");
@ -543,7 +564,7 @@ void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
this->write("(");
}
this->writeExpression(*p.fOperand, kPostfix_Precedence);
this->write(Token::OperatorName(p.fOperator));
this->write(Compiler::OperatorName(p.fOperator));
if (kPostfix_Precedence >= parentPrecedence) {
this->write(")");
}

View File

@ -90,6 +90,8 @@ protected:
void write(const String& s);
void write(StringFragment s);
void writeLine(const String& s);
virtual void writeHeader();

View File

@ -23,17 +23,17 @@ HCodeGenerator::HCodeGenerator(const Program* program, ErrorReporter* errors, St
, fSectionAndParameterHelper(*program, *errors) {}
String HCodeGenerator::ParameterType(const Type& type) {
if (type.fName == "float2") {
if (type.name() == "float2") {
return "SkPoint";
} else if (type.fName == "int4") {
} else if (type.name() == "int4") {
return "SkIRect";
} else if (type.fName == "float4") {
} else if (type.name() == "float4") {
return "SkRect";
} else if (type.fName == "float4x4") {
} else if (type.name() == "float4x4") {
return "SkMatrix44";
} else if (type.kind() == Type::kSampler_Kind) {
return "sk_sp<GrTextureProxy>";
} else if (type.fName == "colorSpaceXform") {
} else if (type.name() == "colorSpaceXform") {
return "sk_sp<GrColorSpaceXform>";
}
return type.name();
@ -127,7 +127,7 @@ void HCodeGenerator::writeMake() {
separator = "";
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(),
param->fName.c_str());
String(param->fName).c_str());
separator = ", ";
}
this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
@ -136,7 +136,7 @@ void HCodeGenerator::writeMake() {
fFullName.c_str());
separator = "";
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
this->writef("%s%s", separator, param->fName.c_str());
this->writef("%s%s", separator, String(param->fName).c_str());
separator = ", ";
}
this->writeExtraConstructorParams(separator);
@ -148,7 +148,7 @@ void HCodeGenerator::writeMake() {
void HCodeGenerator::failOnSection(const char* section, const char* msg) {
std::vector<const Section*> s = fSectionAndParameterHelper.getSections(section);
if (s.size()) {
fErrors.error(s[0]->fPosition, String("@") + section + " " + msg);
fErrors.error(s[0]->fOffset, String("@") + section + " " + msg);
}
}
@ -165,7 +165,7 @@ void HCodeGenerator::writeConstructor() {
const char* separator = "";
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
this->writef("%s%s %s", separator, ParameterType(param->fType).c_str(),
param->fName.c_str());
String(param->fName).c_str());
separator = ", ";
}
this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
@ -177,7 +177,8 @@ void HCodeGenerator::writeConstructor() {
this->writef(")");
this->writeSection(INITIALIZERS_SECTION, "\n , ");
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
const char* name = param->fName.c_str();
String nameString(param->fName);
const char* name = nameString.c_str();
if (param->fType.kind() == Type::kSampler_Kind) {
this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name);
for (const Section* s : fSectionAndParameterHelper.getSections(
@ -201,7 +202,7 @@ void HCodeGenerator::writeConstructor() {
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
if (param->fType.kind() == Type::kSampler_Kind) {
this->writef(" this->addTextureSampler(&%s);\n",
FieldName(param->fName.c_str()).c_str());
FieldName(String(param->fName).c_str()).c_str());
}
}
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
@ -216,8 +217,8 @@ void HCodeGenerator::writeConstructor() {
void HCodeGenerator::writeFields() {
this->writeSection(FIELDS_SECTION);
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
const char* name = param->fName.c_str();
this->writef(" %s %s;\n", FieldType(param->fType).c_str(), FieldName(name).c_str());
this->writef(" %s %s;\n", FieldType(param->fType).c_str(),
FieldName(String(param->fName).c_str()).c_str());
}
for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
this->writef(" GrCoordTransform %sCoordTransform;\n",
@ -245,7 +246,8 @@ bool HCodeGenerator::generateCode() {
if (param->fType.kind() == Type::kSampler_Kind) {
continue;
}
const char* name = param->fName.c_str();
String nameString(param->fName);
const char* name = nameString.c_str();
this->writef(" %s %s() const { return %s; }\n",
FieldType(param->fType).c_str(), name, FieldName(name).c_str());
}

File diff suppressed because it is too large Load Diff

View File

@ -61,7 +61,8 @@ public:
IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root,
ErrorReporter& errorReporter);
void convertProgram(String text,
void convertProgram(const char* text,
size_t length,
SymbolTable& types,
Modifiers::Flag* defaultPrecision,
std::vector<std::unique_ptr<ProgramElement>>* result);
@ -103,26 +104,26 @@ private:
const ASTModifiersDeclaration& m);
const Type* convertType(const ASTType& type);
std::unique_ptr<Expression> call(Position position,
std::unique_ptr<Expression> call(int offset,
const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments);
int callCost(const FunctionDeclaration& function,
const std::vector<std::unique_ptr<Expression>>& arguments);
std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function,
std::unique_ptr<Expression> call(int offset, std::unique_ptr<Expression> function,
std::vector<std::unique_ptr<Expression>> arguments);
int coercionCost(const Expression& expr, const Type& type);
std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
std::unique_ptr<Block> convertBlock(const ASTBlock& block);
std::unique_ptr<Statement> convertBreak(const ASTBreakStatement& b);
std::unique_ptr<Expression> convertNumberConstructor(
Position position,
int offset,
const Type& type,
std::vector<std::unique_ptr<Expression>> params);
std::unique_ptr<Expression> convertCompoundConstructor(
Position position,
int offset,
const Type& type,
std::vector<std::unique_ptr<Expression>> params);
std::unique_ptr<Expression> convertConstructor(Position position,
std::unique_ptr<Expression> convertConstructor(int offset,
const Type& type,
std::vector<std::unique_ptr<Expression>> params);
std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c);
@ -142,13 +143,13 @@ private:
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> getCap(int offset, String name);
std::unique_ptr<Expression> getArg(int offset, String name);
std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression);
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
const String& field);
StringFragment field);
std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base,
const String& fields);
StringFragment fields);
std::unique_ptr<Expression> convertTernaryExpression(const ASTTernaryExpression& expression);
std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTVarDeclarationStatement& s);
std::unique_ptr<Statement> convertWhile(const ASTWhileStatement& w);

1343
src/sksl/SkSLLayoutLexer.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*****************************************************************************************
******************** This file was generated by sksllex. Do not edit. *******************
*****************************************************************************************/
#ifndef SKSL_LayoutLexer
#define SKSL_LayoutLexer
#include <cstddef>
#include <cstdint>
namespace SkSL {
struct LayoutToken {
enum Kind {
#undef END_OF_FILE
END_OF_FILE,
#undef LOCATION
LOCATION,
#undef OFFSET
OFFSET,
#undef BINDING
BINDING,
#undef INDEX
INDEX,
#undef SET
SET,
#undef BUILTIN
BUILTIN,
#undef INPUT_ATTACHMENT_INDEX
INPUT_ATTACHMENT_INDEX,
#undef ORIGIN_UPPER_LEFT
ORIGIN_UPPER_LEFT,
#undef OVERRIDE_COVERAGE
OVERRIDE_COVERAGE,
#undef BLEND_SUPPORT_ALL_EQUATIONS
BLEND_SUPPORT_ALL_EQUATIONS,
#undef PUSH_CONSTANT
PUSH_CONSTANT,
#undef POINTS
POINTS,
#undef LINES
LINES,
#undef LINE_STRIP
LINE_STRIP,
#undef LINES_ADJACENCY
LINES_ADJACENCY,
#undef TRIANGLES
TRIANGLES,
#undef TRIANGLE_STRIP
TRIANGLE_STRIP,
#undef TRIANGLES_ADJACENCY
TRIANGLES_ADJACENCY,
#undef MAX_VERTICES
MAX_VERTICES,
#undef INVOCATIONS
INVOCATIONS,
#undef WHEN
WHEN,
#undef KEY
KEY,
#undef INVALID
INVALID,
};
LayoutToken() : fKind(Kind::INVALID), fOffset(-1), fLength(-1) {}
LayoutToken(Kind kind, int offset, int length)
: fKind(kind), fOffset(offset), fLength(length) {}
Kind fKind;
int fOffset;
int fLength;
};
class LayoutLexer {
public:
void start(const char* text, size_t length) {
fText = text;
fLength = length;
fOffset = 0;
}
LayoutToken next();
private:
const char* fText;
int fLength;
int fOffset;
};
} // namespace
#endif

1925
src/sksl/SkSLLexer.cpp Normal file

File diff suppressed because it is too large Load Diff

238
src/sksl/SkSLLexer.h Normal file
View File

@ -0,0 +1,238 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*****************************************************************************************
******************** This file was generated by sksllex. Do not edit. *******************
*****************************************************************************************/
#ifndef SKSL_Lexer
#define SKSL_Lexer
#include <cstddef>
#include <cstdint>
namespace SkSL {
struct Token {
enum Kind {
#undef END_OF_FILE
END_OF_FILE,
#undef FLOAT_LITERAL
FLOAT_LITERAL,
#undef INT_LITERAL
INT_LITERAL,
#undef TRUE_LITERAL
TRUE_LITERAL,
#undef FALSE_LITERAL
FALSE_LITERAL,
#undef IF
IF,
#undef STATIC_IF
STATIC_IF,
#undef ELSE
ELSE,
#undef FOR
FOR,
#undef WHILE
WHILE,
#undef DO
DO,
#undef SWITCH
SWITCH,
#undef STATIC_SWITCH
STATIC_SWITCH,
#undef CASE
CASE,
#undef DEFAULT
DEFAULT,
#undef BREAK
BREAK,
#undef CONTINUE
CONTINUE,
#undef DISCARD
DISCARD,
#undef RETURN
RETURN,
#undef IN
IN,
#undef OUT
OUT,
#undef INOUT
INOUT,
#undef UNIFORM
UNIFORM,
#undef CONST
CONST,
#undef LOWP
LOWP,
#undef MEDIUMP
MEDIUMP,
#undef HIGHP
HIGHP,
#undef FLAT
FLAT,
#undef NOPERSPECTIVE
NOPERSPECTIVE,
#undef READONLY
READONLY,
#undef WRITEONLY
WRITEONLY,
#undef COHERENT
COHERENT,
#undef VOLATILE
VOLATILE,
#undef RESTRICT
RESTRICT,
#undef BUFFER
BUFFER,
#undef HASSIDEEFFECTS
HASSIDEEFFECTS,
#undef STRUCT
STRUCT,
#undef LAYOUT
LAYOUT,
#undef PRECISION
PRECISION,
#undef IDENTIFIER
IDENTIFIER,
#undef DIRECTIVE
DIRECTIVE,
#undef SECTION
SECTION,
#undef LPAREN
LPAREN,
#undef RPAREN
RPAREN,
#undef LBRACE
LBRACE,
#undef RBRACE
RBRACE,
#undef LBRACKET
LBRACKET,
#undef RBRACKET
RBRACKET,
#undef DOT
DOT,
#undef COMMA
COMMA,
#undef PLUSPLUS
PLUSPLUS,
#undef MINUSMINUS
MINUSMINUS,
#undef PLUS
PLUS,
#undef MINUS
MINUS,
#undef STAR
STAR,
#undef SLASH
SLASH,
#undef PERCENT
PERCENT,
#undef SHL
SHL,
#undef SHR
SHR,
#undef BITWISEOR
BITWISEOR,
#undef BITWISEXOR
BITWISEXOR,
#undef BITWISEAND
BITWISEAND,
#undef BITWISENOT
BITWISENOT,
#undef LOGICALOR
LOGICALOR,
#undef LOGICALXOR
LOGICALXOR,
#undef LOGICALAND
LOGICALAND,
#undef LOGICALNOT
LOGICALNOT,
#undef QUESTION
QUESTION,
#undef COLON
COLON,
#undef EQ
EQ,
#undef EQEQ
EQEQ,
#undef NEQ
NEQ,
#undef GT
GT,
#undef LT
LT,
#undef GTEQ
GTEQ,
#undef LTEQ
LTEQ,
#undef PLUSEQ
PLUSEQ,
#undef MINUSEQ
MINUSEQ,
#undef STAREQ
STAREQ,
#undef SLASHEQ
SLASHEQ,
#undef PERCENTEQ
PERCENTEQ,
#undef SHLEQ
SHLEQ,
#undef SHREQ
SHREQ,
#undef BITWISEOREQ
BITWISEOREQ,
#undef BITWISEXOREQ
BITWISEXOREQ,
#undef BITWISEANDEQ
BITWISEANDEQ,
#undef LOGICALOREQ
LOGICALOREQ,
#undef LOGICALXOREQ
LOGICALXOREQ,
#undef LOGICALANDEQ
LOGICALANDEQ,
#undef SEMICOLON
SEMICOLON,
#undef ARROW
ARROW,
#undef COLONCOLON
COLONCOLON,
#undef WHITESPACE
WHITESPACE,
#undef LINE_COMMENT
LINE_COMMENT,
#undef BLOCK_COMMENT
BLOCK_COMMENT,
#undef INVALID
INVALID,
};
Token() : fKind(Kind::INVALID), fOffset(-1), fLength(-1) {}
Token(Kind kind, int offset, int length) : fKind(kind), fOffset(offset), fLength(length) {}
Kind fKind;
int fOffset;
int fLength;
};
class Lexer {
public:
void start(const char* text, size_t length) {
fText = text;
fLength = length;
fOffset = 0;
}
Token next();
private:
const char* fText;
int fLength;
int fOffset;
};
} // namespace
#endif

View File

@ -7,26 +7,6 @@
#include "stdio.h"
#include "SkSLParser.h"
#include "SkSLToken.h"
#define register
#include "disable_flex_warnings.h"
#include "lex.sksl.c"
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");
#undef register
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "lex.layout.h"
#include "ast/SkSLASTBinaryExpression.h"
#include "ast/SkSLASTBlock.h"
#include "ast/SkSLASTBoolLiteral.h"
@ -83,7 +63,7 @@ public:
bool checkValid() {
if (fParser->fDepth > MAX_PARSE_DEPTH) {
fParser->error(fParser->peek().fPosition, String("exceeded max parse depth"));
fParser->error(fParser->peek(), String("exceeded max parse depth"));
return false;
}
return true;
@ -93,20 +73,12 @@ private:
Parser* fParser;
};
Parser::Parser(String text, SymbolTable& types, ErrorReporter& errors)
: fPushback(Position(-1, -1), Token::INVALID_TOKEN, String())
Parser::Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors)
: fText(text)
, fPushback(Token::INVALID, -1, -1)
, fTypes(types)
, fErrors(errors) {
sksllex_init(&fScanner);
layoutlex_init(&fLayoutScanner);
fBuffer = sksl_scan_string(text.c_str(), fScanner);
skslset_lineno(1, fScanner);
}
Parser::~Parser() {
sksl_delete_buffer(fBuffer, fScanner);
sksllex_destroy(fScanner);
layoutlex_destroy(fLayoutScanner);
fLexer.start(text, length);
}
/* (precision | directive | section | declaration)* END_OF_FILE */
@ -148,53 +120,39 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
}
}
Token Parser::nextRawToken(bool needText) {
if (fPushback.fKind != Token::INVALID_TOKEN) {
Token result(std::move(fPushback));
fPushback.fKind = Token::INVALID_TOKEN;
fPushback.fText.clear();
Token Parser::nextRawToken() {
if (fPushback.fKind != Token::INVALID) {
Token result = fPushback;
fPushback.fKind = Token::INVALID;
return result;
}
Token::Kind kind = (Token::Kind) sksllex(fScanner);
if (!needText) {
switch (kind) {
case Token::Kind::DIRECTIVE: // fall through
case Token::Kind::IDENTIFIER: // fall through
case Token::Kind::INT_LITERAL: // fall through
case Token::Kind::FLOAT_LITERAL: // fall through
case Token::Kind::SECTION:
needText = true;
default:
break;
}
}
static String unavailable("<unavailable>");
return Token(Position(skslget_lineno(fScanner), -1), kind,
needText ? String(skslget_text(fScanner)) : unavailable);
Token result = fLexer.next();
return result;
}
Token Parser::nextToken() {
Token token;
do {
token = this->nextRawToken(false);
} while (token.fKind == Token::WHITESPACE);
Token token = this->nextRawToken();
while (token.fKind == Token::WHITESPACE || token.fKind == Token::LINE_COMMENT ||
token.fKind == Token::BLOCK_COMMENT) {
token = this->nextRawToken();
}
return token;
}
void Parser::pushback(Token t) {
ASSERT(fPushback.fKind == Token::INVALID_TOKEN);
ASSERT(fPushback.fKind == Token::INVALID);
fPushback = std::move(t);
}
Token Parser::peek() {
if (fPushback.fKind == Token::INVALID_TOKEN) {
if (fPushback.fKind == Token::INVALID) {
fPushback = this->nextToken();
}
return fPushback;
}
bool Parser::checkNext(Token::Kind kind, Token* result) {
if (fPushback.fKind != Token::INVALID_TOKEN && fPushback.fKind != kind) {
if (fPushback.fKind != Token::INVALID && fPushback.fKind != kind) {
return false;
}
Token next = this->nextToken();
@ -216,25 +174,25 @@ bool Parser::expect(Token::Kind kind, const char* expected, Token* result) {
}
return true;
} else {
if (next.fText.size()) {
this->error(next.fPosition, "expected " + String(expected) + ", but found '" +
next.fText + "'");
} else {
this->error(next.fPosition, "parse error, recompile in debug mode for details");
}
this->error(next, "expected " + String(expected) + ", but found '" +
this->text(next) + "'");
return false;
}
}
void Parser::error(Position p, const char* msg) {
this->error(p, String(msg));
StringFragment Parser::text(Token token) {
return StringFragment(fText + token.fOffset, token.fLength);
}
void Parser::error(Position p, String msg) {
fErrors.error(p, msg);
void Parser::error(Token token, String msg) {
this->error(token.fOffset, msg);
}
bool Parser::isType(const String& name) {
void Parser::error(int offset, String msg) {
fErrors.error(offset, msg);
}
bool Parser::isType(StringFragment name) {
return nullptr != fTypes[name];
}
@ -256,8 +214,8 @@ std::unique_ptr<ASTDeclaration> Parser::precision() {
result = Modifiers::kHighp_Flag;
break;
default:
this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
p.fText + "'");
this->error(p, "expected 'lowp', 'mediump', or 'highp', but found '" +
this->text(p) + "'");
return nullptr;
}
// FIXME handle the type
@ -265,7 +223,7 @@ std::unique_ptr<ASTDeclaration> Parser::precision() {
return nullptr;
}
this->expect(Token::SEMICOLON, "';'");
return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result));
return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fOffset, result));
}
/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
@ -275,16 +233,18 @@ std::unique_ptr<ASTDeclaration> Parser::directive() {
if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
return nullptr;
}
if (start.fText == "#version") {
StringFragment text = this->text(start);
if (text == "#version") {
this->expect(Token::INT_LITERAL, "a version number");
Token next = this->peek();
if (next.fText == "es" || next.fText == "compatibility") {
StringFragment nextText = this->text(next);
if (nextText == "es" || nextText == "compatibility") {
this->nextToken();
}
// version is ignored for now; it will eventually become an error when we stop pretending
// to be GLSL
return nullptr;
} else if (start.fText == "#extension") {
} else if (text == "#extension") {
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
return nullptr;
@ -296,10 +256,10 @@ std::unique_ptr<ASTDeclaration> Parser::directive() {
if (!this->expect(Token::IDENTIFIER, "an identifier")) {
return nullptr;
}
return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
std::move(name.fText)));
return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fOffset,
String(this->text(name))));
} else {
this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
this->error(start, "unsupported directive '" + this->text(start) + "'");
return nullptr;
}
}
@ -318,7 +278,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() {
if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) {
return nullptr;
}
argument = argToken.fText;
argument = this->text(argToken);
if (!this->expect(Token::RPAREN, "')'")) {
return nullptr;
}
@ -329,7 +289,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() {
String text;
int level = 1;
for (;;) {
Token next = this->nextRawToken(true);
Token next = this->nextRawToken();
switch (next.fKind) {
case Token::LBRACE:
++level;
@ -338,7 +298,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() {
--level;
break;
case Token::END_OF_FILE:
this->error(start.fPosition, "reached end of file while parsing section");
this->error(start, "reached end of file while parsing section");
return nullptr;
default:
break;
@ -346,10 +306,13 @@ std::unique_ptr<ASTDeclaration> Parser::section() {
if (!level) {
break;
}
text += next.fText;
text += this->text(next);
}
return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fPosition,
String(start.fText.c_str() + 1),
StringFragment name = this->text(start);
++name.fChars;
--name.fLength;
return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fOffset,
String(name),
argument,
text));
}
@ -359,7 +322,7 @@ std::unique_ptr<ASTDeclaration> Parser::section() {
std::unique_ptr<ASTDeclaration> Parser::declaration() {
Modifiers modifiers = this->modifiers();
Token lookahead = this->peek();
if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) {
if (lookahead.fKind == Token::IDENTIFIER && !this->isType(this->text(lookahead))) {
// we have an identifier that's not a type, could be the start of an interface block
return this->interfaceBlock(modifiers);
}
@ -403,14 +366,14 @@ std::unique_ptr<ASTDeclaration> Parser::declaration() {
return nullptr;
}
}
return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition,
return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fOffset,
modifiers,
std::move(type),
std::move(name.fText),
this->text(name),
std::move(parameters),
std::move(body)));
} else {
return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
}
}
@ -425,7 +388,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
return nullptr;
}
return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText));
return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
}
/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
@ -450,7 +413,7 @@ std::unique_ptr<ASTType> Parser::structDeclaration() {
auto type = (const Type*) fTypes[decl->fType->fName];
for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) {
if (!var.fSizes[i] || var.fSizes[i]->fKind != ASTExpression::kInt_Kind) {
this->error(decl->fPosition, "array size in struct field must be a constant");
this->error(decl->fOffset, "array size in struct field must be a constant");
return nullptr;
}
uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue;
@ -460,15 +423,16 @@ std::unique_ptr<ASTType> Parser::structDeclaration() {
}
fields.push_back(Type::Field(decl->fModifiers, var.fName, type));
if (var.fValue) {
this->error(decl->fPosition, "initializers are not permitted on struct fields");
this->error(decl->fOffset, "initializers are not permitted on struct fields");
}
}
}
if (!this->expect(Token::RBRACE, "'}'")) {
return nullptr;
}
fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fPosition, name.fText, fields)));
return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
fTypes.add(this->text(name), std::unique_ptr<Type>(new Type(name.fOffset, this->text(name),
fields)));
return std::unique_ptr<ASTType>(new ASTType(name.fOffset, this->text(name),
ASTType::kStruct_Kind, std::vector<int>()));
}
@ -482,11 +446,11 @@ std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modif
if (this->checkNext(Token::IDENTIFIER, &name)) {
std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
std::move(type),
std::move(name.fText));
this->text(name));
if (result) {
for (const auto& var : result->fVars) {
if (var.fValue) {
this->error(var.fValue->fPosition,
this->error(var.fValue->fOffset,
"struct variables cannot be initialized");
}
}
@ -501,7 +465,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modif
(LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
std::unique_ptr<ASTType> type,
String name) {
StringFragment name) {
std::vector<ASTVarDeclaration> vars;
std::vector<std::unique_ptr<ASTExpression>> currentVarSizes;
while (this->checkNext(Token::LBRACKET)) {
@ -525,7 +489,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
return nullptr;
}
}
vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value));
vars.emplace_back(name, std::move(currentVarSizes), std::move(value));
while (this->checkNext(Token::COMMA)) {
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
@ -553,7 +517,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
return nullptr;
}
}
vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value));
vars.emplace_back(this->text(name), std::move(currentVarSizes), std::move(value));
}
if (!this->expect(Token::SEMICOLON, "';'")) {
return nullptr;
@ -580,14 +544,13 @@ std::unique_ptr<ASTParameter> Parser::parameter() {
if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) {
return nullptr;
}
sizes.push_back(SkSL::stoi(sizeToken.fText));
sizes.push_back(SkSL::stoi(this->text(sizeToken)));
if (!this->expect(Token::RBRACKET, "']'")) {
return nullptr;
}
}
return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
std::move(type), name.fText,
std::move(sizes)));
return std::unique_ptr<ASTParameter>(new ASTParameter(name.fOffset, modifiers, std::move(type),
this->text(name), std::move(sizes)));
}
/** (EQ INT_LITERAL)? */
@ -597,7 +560,7 @@ int Parser::layoutInt() {
}
Token resultToken;
if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) {
return SkSL::stoi(resultToken.fText);
return SkSL::stoi(this->text(resultToken));
}
return -1;
}
@ -607,13 +570,13 @@ String Parser::layoutCode() {
if (!this->expect(Token::EQ, "'='")) {
return "";
}
Token start = this->nextRawToken(true);
Token start = this->nextRawToken();
this->pushback(start);
String code;
int level = 1;
bool done = false;
while (!done) {
Token next = this->nextRawToken(true);
Token next = this->nextRawToken();
switch (next.fKind) {
case Token::LPAREN:
++level;
@ -627,7 +590,7 @@ String Parser::layoutCode() {
}
break;
case Token::END_OF_FILE:
this->error(start.fPosition, "reached end of file while parsing layout");
this->error(start, "reached end of file while parsing layout");
return nullptr;
default:
break;
@ -639,7 +602,7 @@ String Parser::layoutCode() {
this->pushback(std::move(next));
}
else {
code += next.fText;
code += this->text(next);
}
}
return code;
@ -651,10 +614,10 @@ Layout::Key Parser::layoutKey() {
this->expect(Token::EQ, "'='");
Token key;
if (this->expect(Token::IDENTIFIER, "an identifer", &key)) {
if (key.fText == "identity") {
if (this->text(key) == "identity") {
return Layout::kIdentity_Key;
} else {
this->error(key.fPosition, "unsupported layout key");
this->error(key, "unsupported layout key");
}
}
}
@ -688,84 +651,84 @@ Layout Parser::layout() {
}
for (;;) {
Token t = this->nextToken();
YY_BUFFER_STATE buffer;
buffer = layout_scan_string(t.fText.c_str(), fLayoutScanner);
int token = layoutlex(fLayoutScanner);
layout_delete_buffer(buffer, fLayoutScanner);
if (token != Token::INVALID_TOKEN) {
String text = this->text(t);
fLayoutLexer.start(text.c_str(), text.size());
int token = fLayoutLexer.next().fKind;
if (token != LayoutToken::INVALID) {
switch (token) {
case Token::LOCATION:
case LayoutToken::LOCATION:
location = this->layoutInt();
break;
case Token::OFFSET:
case LayoutToken::OFFSET:
offset = this->layoutInt();
break;
case Token::BINDING:
case LayoutToken::BINDING:
binding = this->layoutInt();
break;
case Token::INDEX:
case LayoutToken::INDEX:
index = this->layoutInt();
break;
case Token::SET:
case LayoutToken::SET:
set = this->layoutInt();
break;
case Token::BUILTIN:
case LayoutToken::BUILTIN:
builtin = this->layoutInt();
break;
case Token::INPUT_ATTACHMENT_INDEX:
case LayoutToken::INPUT_ATTACHMENT_INDEX:
inputAttachmentIndex = this->layoutInt();
break;
case Token::ORIGIN_UPPER_LEFT:
case LayoutToken::ORIGIN_UPPER_LEFT:
originUpperLeft = true;
break;
case Token::OVERRIDE_COVERAGE:
case LayoutToken::OVERRIDE_COVERAGE:
overrideCoverage = true;
break;
case Token::BLEND_SUPPORT_ALL_EQUATIONS:
case LayoutToken::BLEND_SUPPORT_ALL_EQUATIONS:
blendSupportAllEquations = true;
break;
case Token::PUSH_CONSTANT:
case LayoutToken::PUSH_CONSTANT:
pushConstant = true;
break;
case Token::POINTS:
case LayoutToken::POINTS:
primitive = Layout::kPoints_Primitive;
break;
case Token::LINES:
case LayoutToken::LINES:
primitive = Layout::kLines_Primitive;
break;
case Token::LINE_STRIP:
case LayoutToken::LINE_STRIP:
primitive = Layout::kLineStrip_Primitive;
break;
case Token::LINES_ADJACENCY:
case LayoutToken::LINES_ADJACENCY:
primitive = Layout::kLinesAdjacency_Primitive;
break;
case Token::TRIANGLES:
case LayoutToken::TRIANGLES:
primitive = Layout::kTriangles_Primitive;
break;
case Token::TRIANGLE_STRIP:
case LayoutToken::TRIANGLE_STRIP:
primitive = Layout::kTriangleStrip_Primitive;
break;
case Token::TRIANGLES_ADJACENCY:
case LayoutToken::TRIANGLES_ADJACENCY:
primitive = Layout::kTrianglesAdjacency_Primitive;
break;
case Token::MAX_VERTICES:
case LayoutToken::MAX_VERTICES:
maxVertices = this->layoutInt();
break;
case Token::INVOCATIONS:
case LayoutToken::INVOCATIONS:
invocations = this->layoutInt();
break;
case Token::WHEN:
case LayoutToken::WHEN:
when = this->layoutCode();
break;
case Token::KEY:
case LayoutToken::KEY:
key = this->layoutKey();
break;
default:
ASSERT(false);
}
} else if (Layout::ReadFormat(t.fText, &format)) {
} else if (Layout::ReadFormat(this->text(t), &format)) {
// AST::ReadFormat stored the result in 'format'.
} else {
this->error(t.fPosition, ("'" + t.fText +
"' is not a valid layout qualifier").c_str());
this->error(t, ("'" + this->text(t) + "' is not a valid layout qualifier").c_str());
}
if (this->checkNext(Token::RPAREN)) {
break;
@ -899,7 +862,7 @@ std::unique_ptr<ASTStatement> Parser::statement() {
return this->block();
case Token::SEMICOLON:
this->nextToken();
return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
return std::unique_ptr<ASTStatement>(new ASTBlock(start.fOffset,
std::vector<std::unique_ptr<ASTStatement>>()));
case Token::CONST: // fall through
case Token::HIGHP: // fall through
@ -912,7 +875,7 @@ std::unique_ptr<ASTStatement> Parser::statement() {
return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl)));
}
case Token::IDENTIFIER:
if (this->isType(start.fText)) {
if (this->isType(this->text(start))) {
auto decl = this->varDeclarations();
if (!decl) {
return nullptr;
@ -932,8 +895,8 @@ std::unique_ptr<ASTType> Parser::type() {
if (!this->expect(Token::IDENTIFIER, "a type", &type)) {
return nullptr;
}
if (!this->isType(type.fText)) {
this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
if (!this->isType(this->text(type))) {
this->error(type, ("no type named '" + this->text(type) + "'").c_str());
return nullptr;
}
std::vector<int> sizes;
@ -950,7 +913,7 @@ std::unique_ptr<ASTType> Parser::type() {
}
this->expect(Token::RBRACKET, "']'");
}
return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
return std::unique_ptr<ASTType>(new ASTType(type.fOffset, this->text(type),
ASTType::kIdentifier_Kind, sizes));
}
@ -964,7 +927,7 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) {
// we only get into interfaceBlock if we found a top-level identifier which was not a type.
// 99% of the time, the user was not actually intending to create an interface block, so
// it's better to report it as an unknown type
this->error(name.fPosition, "no type named '" + name.fText + "'");
this->error(name, "no type named '" + this->text(name) + "'");
return nullptr;
}
this->nextToken();
@ -978,8 +941,9 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) {
}
this->nextToken();
std::vector<std::unique_ptr<ASTExpression>> sizes;
Token instanceName;
if (this->checkNext(Token::IDENTIFIER, &instanceName)) {
StringFragment instanceName;
Token instanceNameToken;
if (this->checkNext(Token::IDENTIFIER, &instanceNameToken)) {
while (this->checkNext(Token::LBRACKET)) {
if (this->peek().fKind != Token::RBRACKET) {
std::unique_ptr<ASTExpression> size = this->expression();
@ -992,12 +956,13 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) {
}
this->expect(Token::RBRACKET, "']'");
}
instanceName = this->text(instanceNameToken);
}
this->expect(Token::SEMICOLON, "';'");
return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
std::move(name.fText),
return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fOffset, mods,
this->text(name),
std::move(decls),
std::move(instanceName.fText),
instanceName,
std::move(sizes)));
}
@ -1029,7 +994,7 @@ std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
return nullptr;
}
}
return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition,
return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fOffset,
isStatic,
std::move(test),
std::move(ifTrue),
@ -1062,7 +1027,7 @@ std::unique_ptr<ASTDoStatement> Parser::doStatement() {
if (!this->expect(Token::SEMICOLON, "';'")) {
return nullptr;
}
return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fOffset,
std::move(statement),
std::move(test)));
}
@ -1087,7 +1052,7 @@ std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
if (!statement) {
return nullptr;
}
return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fOffset,
std::move(test),
std::move(statement)));
}
@ -1114,7 +1079,7 @@ std::unique_ptr<ASTSwitchCase> Parser::switchCase() {
}
statements.push_back(std::move(s));
}
return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fPosition, std::move(value),
return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fOffset, std::move(value),
std::move(statements)));
}
@ -1162,13 +1127,13 @@ std::unique_ptr<ASTStatement> Parser::switchStatement() {
}
statements.push_back(std::move(s));
}
cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr,
cases.emplace_back(new ASTSwitchCase(defaultStart.fOffset, nullptr,
std::move(statements)));
}
if (!this->expect(Token::RBRACE, "'}'")) {
return nullptr;
}
return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fOffset,
isStatic,
std::move(value),
std::move(cases)));
@ -1200,7 +1165,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() {
break;
}
case Token::IDENTIFIER: {
if (this->isType(nextToken.fText)) {
if (this->isType(this->text(nextToken))) {
std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
if (!vd) {
return nullptr;
@ -1237,7 +1202,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() {
if (!statement) {
return nullptr;
}
return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fOffset,
std::move(initializer),
std::move(test), std::move(next),
std::move(statement)));
@ -1259,7 +1224,7 @@ std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
if (!this->expect(Token::SEMICOLON, "';'")) {
return nullptr;
}
return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fOffset,
std::move(expression)));
}
@ -1272,7 +1237,7 @@ std::unique_ptr<ASTBreakStatement> Parser::breakStatement() {
if (!this->expect(Token::SEMICOLON, "';'")) {
return nullptr;
}
return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition));
return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fOffset));
}
/* CONTINUE SEMICOLON */
@ -1284,7 +1249,7 @@ std::unique_ptr<ASTContinueStatement> Parser::continueStatement() {
if (!this->expect(Token::SEMICOLON, "';'")) {
return nullptr;
}
return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition));
return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fOffset));
}
/* DISCARD SEMICOLON */
@ -1296,7 +1261,7 @@ std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() {
if (!this->expect(Token::SEMICOLON, "';'")) {
return nullptr;
}
return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition));
return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fOffset));
}
/* LBRACE statement* RBRACE */
@ -1314,10 +1279,10 @@ std::unique_ptr<ASTBlock> Parser::block() {
switch (this->peek().fKind) {
case Token::RBRACE:
this->nextToken();
return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
return std::unique_ptr<ASTBlock>(new ASTBlock(start.fOffset,
std::move(statements)));
case Token::END_OF_FILE:
this->error(this->peek().fPosition, "expected '}', but found end of file");
this->error(this->peek(), "expected '}', but found end of file");
return nullptr;
default: {
std::unique_ptr<ASTStatement> statement = this->statement();
@ -1714,7 +1679,7 @@ std::unique_ptr<ASTSuffix> Parser::suffix() {
switch (next.fKind) {
case Token::LBRACKET: {
if (this->checkNext(Token::RBRACKET)) {
return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition));
return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fOffset));
}
std::unique_ptr<ASTExpression> e = this->expression();
if (!e) {
@ -1724,10 +1689,10 @@ std::unique_ptr<ASTSuffix> Parser::suffix() {
return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e)));
}
case Token::DOT: {
Position pos = this->peek().fPosition;
String text;
int offset = this->peek().fOffset;
StringFragment text;
if (this->identifier(&text)) {
return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text)));
return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(offset, std::move(text)));
}
return nullptr;
}
@ -1746,17 +1711,17 @@ std::unique_ptr<ASTSuffix> Parser::suffix() {
}
}
this->expect(Token::RPAREN, "')' to complete function parameters");
return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fOffset,
std::move(parameters)));
}
case Token::PLUSPLUS:
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset,
ASTSuffix::kPostIncrement_Kind));
case Token::MINUSMINUS:
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset,
ASTSuffix::kPostDecrement_Kind));
default: {
this->error(next.fPosition, "expected expression suffix, but found '" + next.fText +
this->error(next, "expected expression suffix, but found '" + this->text(next) +
"'\n");
return nullptr;
}
@ -1769,23 +1734,23 @@ std::unique_ptr<ASTExpression> Parser::term() {
Token t = this->peek();
switch (t.fKind) {
case Token::IDENTIFIER: {
String text;
StringFragment text;
if (this->identifier(&text)) {
result.reset(new ASTIdentifier(t.fPosition, std::move(text)));
result.reset(new ASTIdentifier(t.fOffset, std::move(text)));
}
break;
}
case Token::INT_LITERAL: {
int64_t i;
if (this->intLiteral(&i)) {
result.reset(new ASTIntLiteral(t.fPosition, i));
result.reset(new ASTIntLiteral(t.fOffset, i));
}
break;
}
case Token::FLOAT_LITERAL: {
double f;
if (this->floatLiteral(&f)) {
result.reset(new ASTFloatLiteral(t.fPosition, f));
result.reset(new ASTFloatLiteral(t.fOffset, f));
}
break;
}
@ -1793,7 +1758,7 @@ std::unique_ptr<ASTExpression> Parser::term() {
case Token::FALSE_LITERAL: {
bool b;
if (this->boolLiteral(&b)) {
result.reset(new ASTBoolLiteral(t.fPosition, b));
result.reset(new ASTBoolLiteral(t.fOffset, b));
}
break;
}
@ -1807,7 +1772,7 @@ std::unique_ptr<ASTExpression> Parser::term() {
}
default:
this->nextToken();
this->error(t.fPosition, "expected expression, but found '" + t.fText + "'\n");
this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'\n");
result = nullptr;
}
return result;
@ -1817,7 +1782,7 @@ std::unique_ptr<ASTExpression> Parser::term() {
bool Parser::intLiteral(int64_t* dest) {
Token t;
if (this->expect(Token::INT_LITERAL, "integer literal", &t)) {
*dest = SkSL::stol(t.fText);
*dest = SkSL::stol(this->text(t));
return true;
}
return false;
@ -1827,7 +1792,7 @@ bool Parser::intLiteral(int64_t* dest) {
bool Parser::floatLiteral(double* dest) {
Token t;
if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) {
*dest = SkSL::stod(t.fText);
*dest = SkSL::stod(this->text(t));
return true;
}
return false;
@ -1844,16 +1809,16 @@ bool Parser::boolLiteral(bool* dest) {
*dest = false;
return true;
default:
this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n");
this->error(t, "expected 'true' or 'false', but found '" + this->text(t) + "'\n");
return false;
}
}
/* IDENTIFIER */
bool Parser::identifier(String* dest) {
bool Parser::identifier(StringFragment* dest) {
Token t;
if (this->expect(Token::IDENTIFIER, "identifier", &t)) {
*dest = std::move(t.fText);
*dest = this->text(t);
return true;
}
return false;

View File

@ -14,7 +14,8 @@
#include <unordered_set>
#include "SkSLErrorReporter.h"
#include "ir/SkSLLayout.h"
#include "SkSLToken.h"
#include "SkSLLexer.h"
#include "SkSLLayoutLexer.h"
struct yy_buffer_state;
#define YY_TYPEDEF_YY_BUFFER_STATE
@ -51,9 +52,7 @@ class SymbolTable;
*/
class Parser {
public:
Parser(String text, SymbolTable& types, ErrorReporter& errors);
~Parser();
Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors);
/**
* Consumes a complete .sksl file and produces a list of declarations. Errors are reported via
@ -62,13 +61,15 @@ public:
*/
std::vector<std::unique_ptr<ASTDeclaration>> file();
StringFragment text(Token token);
Position position(Token token);
private:
/**
* Return the next token, including whitespace tokens, from the parse stream. If needText is
* false, the token's text is only filled in if it is a token with variable text (identifiers,
* numbers, etc.).
* Return the next token, including whitespace tokens, from the parse stream.
*/
Token nextRawToken(bool needText);
Token nextRawToken();
/**
* Return the next non-whitespace token from the parse stream.
@ -103,15 +104,15 @@ private:
* Returns true if the read token was as expected, false otherwise.
*/
bool expect(Token::Kind kind, const char* expected, Token* result = nullptr);
bool expect(Token::Kind kind, String expected, Token* result = nullptr);
void error(Position p, const char* msg);
void error(Position p, String msg);
void error(Token token, String msg);
void error(int offset, String msg);
/**
* Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will
* always return true.
*/
bool isType(const String& name);
bool isType(StringFragment name);
// these functions parse individual grammar rules from the current parse position; you probably
// don't need to call any of these outside of the parser. The function declarations in the .cpp
@ -133,7 +134,7 @@ private:
std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(Modifiers modifiers,
std::unique_ptr<ASTType> type,
String name);
StringFragment name);
std::unique_ptr<ASTParameter> parameter();
@ -223,10 +224,11 @@ private:
bool boolLiteral(bool* dest);
bool identifier(String* dest);
bool identifier(StringFragment* dest);
void* fScanner;
void* fLayoutScanner;
const char* fText;
Lexer fLexer;
LayoutLexer fLayoutLexer;
YY_BUFFER_STATE fBuffer;
// current parse depth, used to enforce a recursion limit to try to keep us from overflowing the
// stack on pathological inputs

View File

@ -850,8 +850,7 @@ void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, OutputSt
this->writeWord(word1, out);
}
void SPIRVCodeGenerator::writeString(const char* string, OutputStream& out) {
size_t length = strlen(string);
void SPIRVCodeGenerator::writeString(const char* string, size_t length, OutputStream& out) {
out.write(string, length);
switch (length % 4) {
case 1:
@ -868,28 +867,25 @@ void SPIRVCodeGenerator::writeString(const char* string, OutputStream& out) {
}
}
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, const char* string, OutputStream& out) {
int32_t length = (int32_t) strlen(string);
this->writeOpCode(opCode, 1 + (length + 4) / 4, out);
this->writeString(string, out);
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, StringFragment string, OutputStream& out) {
this->writeOpCode(opCode, 1 + (string.fLength + 4) / 4, out);
this->writeString(string.fChars, string.fLength, out);
}
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const char* string,
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, StringFragment string,
OutputStream& out) {
int32_t length = (int32_t) strlen(string);
this->writeOpCode(opCode, 2 + (length + 4) / 4, out);
this->writeOpCode(opCode, 2 + (string.fLength + 4) / 4, out);
this->writeWord(word1, out);
this->writeString(string, out);
this->writeString(string.fChars, string.fLength, out);
}
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
const char* string, OutputStream& out) {
int32_t length = (int32_t) strlen(string);
this->writeOpCode(opCode, 3 + (length + 4) / 4, out);
StringFragment string, OutputStream& out) {
this->writeOpCode(opCode, 3 + (string.fLength + 4) / 4, out);
this->writeWord(word1, out);
this->writeWord(word2, out);
this->writeString(string, out);
this->writeString(string.fChars, string.fLength, out);
}
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
@ -1003,12 +999,12 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor
const Layout& fieldLayout = type.fields()[i].fModifiers.fLayout;
if (fieldLayout.fOffset >= 0) {
if (fieldLayout.fOffset < (int) offset) {
fErrors.error(type.fPosition,
fErrors.error(type.fOffset,
"offset of field '" + type.fields()[i].fName + "' must be at "
"least " + to_string((int) offset));
}
if (fieldLayout.fOffset % alignment) {
fErrors.error(type.fPosition,
fErrors.error(type.fOffset,
"offset of field '" + type.fields()[i].fName + "' must be a multiple"
" of " + to_string((int) alignment));
}
@ -1019,8 +1015,7 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor
offset += alignment - mod;
}
}
this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName.c_str(),
fNameBuffer);
this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName, fNameBuffer);
this->writeLayout(fieldLayout, resultId, i);
if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) {
this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset,
@ -1081,7 +1076,7 @@ SpvId SPIRVCodeGenerator::getType(const Type& type, const MemoryLayout& layout)
break;
case Type::kArray_Kind: {
if (type.columns() > 0) {
IntLiteral count(fContext, Position(), type.columns());
IntLiteral count(fContext, -1, type.columns());
this->writeInstruction(SpvOpTypeArray, result,
this->getType(type.componentType(), layout),
this->writeIntLiteral(count), fConstantBuffer);
@ -1331,9 +1326,9 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn
case kSubpassLoad_SpecialIntrinsic: {
SpvId img = this->writeExpression(*c.fArguments[0], out);
std::vector<std::unique_ptr<Expression>> args;
args.emplace_back(new FloatLiteral(fContext, Position(), 0.0));
args.emplace_back(new FloatLiteral(fContext, Position(), 0.0));
Constructor ctor(Position(), *fContext.fFloat2_Type, std::move(args));
args.emplace_back(new FloatLiteral(fContext, -1, 0.0));
args.emplace_back(new FloatLiteral(fContext, -1, 0.0));
Constructor ctor(-1, *fContext.fFloat2_Type, std::move(args));
SpvId coords = this->writeConstantVector(ctor);
if (1 == c.fArguments.size()) {
this->writeInstruction(SpvOpImageRead,
@ -1566,7 +1561,7 @@ SpvId SPIRVCodeGenerator::writeUIntConstructor(const Constructor& c, OutputStrea
void SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type,
OutputStream& out) {
FloatLiteral zero(fContext, Position(), 0);
FloatLiteral zero(fContext, -1, 0);
SpvId zeroId = this->writeFloatLiteral(zero);
std::vector<SpvId> columnIds;
for (int column = 0; column < type.columns(); column++) {
@ -1603,10 +1598,10 @@ void SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcTyp
1));
SpvId zeroId;
if (dstType.componentType() == *fContext.fFloat_Type) {
FloatLiteral zero(fContext, Position(), 0.0);
FloatLiteral zero(fContext, -1, 0.0);
zeroId = this->writeFloatLiteral(zero);
} else if (dstType.componentType() == *fContext.fInt_Type) {
IntLiteral zero(fContext, Position(), 0);
IntLiteral zero(fContext, -1, 0);
zeroId = this->writeIntLiteral(zero);
} else {
ABORT("unsupported matrix component type");
@ -1864,7 +1859,7 @@ std::vector<SpvId> SPIRVCodeGenerator::getAccessChain(const Expression& expr, Ou
case Expression::kFieldAccess_Kind: {
FieldAccess& fieldExpr = (FieldAccess&) expr;
chain = this->getAccessChain(*fieldExpr.fBase, out);
IntLiteral index(fContext, Position(), fieldExpr.fFieldIndex);
IntLiteral index(fContext, -1, fieldExpr.fFieldIndex);
chain.push_back(this->writeIntLiteral(index));
break;
}
@ -2010,7 +2005,7 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const
SpvId base = this->getLValue(*swizzle.fBase, out)->getPointer();
ASSERT(base);
if (count == 1) {
IntLiteral index(fContext, Position(), swizzle.fComponents[0]);
IntLiteral index(fContext, -1, swizzle.fComponents[0]);
SpvId member = this->nextId();
this->writeInstruction(SpvOpAccessChain,
this->getPointerType(swizzle.fType,
@ -2064,20 +2059,19 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
std::shared_ptr<SymbolTable> st(new SymbolTable(&fErrors));
ASSERT(fRTHeightFieldIndex == (SpvId) -1);
std::vector<Type::Field> fields;
fields.emplace_back(Modifiers(), String(SKSL_RTHEIGHT_NAME),
fContext.fFloat_Type.get());
String name("sksl_synthetic_uniforms");
Type intfStruct(Position(), name, fields);
fields.emplace_back(Modifiers(), SKSL_RTHEIGHT_NAME, fContext.fFloat_Type.get());
StringFragment name("sksl_synthetic_uniforms");
Type intfStruct(-1, name, fields);
Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false,
Layout::Format::kUnspecified, false, Layout::kUnspecified_Primitive, -1,
-1, "", Layout::kNo_Key);
Variable* intfVar = new Variable(Position(),
Variable* intfVar = new Variable(-1,
Modifiers(layout, Modifiers::kUniform_Flag),
name,
intfStruct,
Variable::kGlobal_Storage);
fSynthetics.takeOwnership(intfVar);
InterfaceBlock intf(Position(), intfVar, name, String(""),
InterfaceBlock intf(-1, intfVar, name, String(""),
std::vector<std::unique_ptr<Expression>>(), st);
fRTHeightStructId = this->writeInterfaceBlock(intf);
fRTHeightFieldIndex = 0;
@ -2087,7 +2081,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
SpvId xId = this->nextId();
this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), xId,
result, 0, out);
IntLiteral fieldIndex(fContext, Position(), fRTHeightFieldIndex);
IntLiteral fieldIndex(fContext, -1, fRTHeightFieldIndex);
SpvId fieldIndexId = this->writeIntLiteral(fieldIndex);
SpvId heightPtr = this->nextId();
this->writeOpCode(SpvOpAccessChain, 5, out);
@ -2104,9 +2098,9 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
SpvId flippedYId = this->nextId();
this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId,
heightRead, rawYId, out);
FloatLiteral zero(fContext, Position(), 0.0);
FloatLiteral zero(fContext, -1, 0.0);
SpvId zeroId = writeFloatLiteral(zero);
FloatLiteral one(fContext, Position(), 1.0);
FloatLiteral one(fContext, -1, 1.0);
SpvId oneId = writeFloatLiteral(one);
SpvId flipped = this->nextId();
this->writeOpCode(SpvOpCompositeConstruct, 7, out);
@ -2509,7 +2503,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStream& out) {
ASSERT(a.fOperator == Token::LOGICALAND);
BoolLiteral falseLiteral(fContext, Position(), false);
BoolLiteral falseLiteral(fContext, -1, false);
SpvId falseConstant = this->writeBoolLiteral(falseLiteral);
SpvId lhs = this->writeExpression(*a.fLeft, out);
SpvId rhsLabel = this->nextId();
@ -2530,7 +2524,7 @@ SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStrea
SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream& out) {
ASSERT(o.fOperator == Token::LOGICALOR);
BoolLiteral trueLiteral(fContext, Position(), true);
BoolLiteral trueLiteral(fContext, -1, true);
SpvId trueConstant = this->writeBoolLiteral(trueLiteral);
SpvId lhs = this->writeExpression(*o.fLeft, out);
SpvId rhsLabel = this->nextId();
@ -2584,10 +2578,10 @@ SpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, Out
std::unique_ptr<Expression> create_literal_1(const Context& context, const Type& type) {
if (type == *context.fInt_Type) {
return std::unique_ptr<Expression>(new IntLiteral(context, Position(), 1));
return std::unique_ptr<Expression>(new IntLiteral(context, -1, 1));
}
else if (type == *context.fFloat_Type) {
return std::unique_ptr<Expression>(new FloatLiteral(context, Position(), 1.0));
return std::unique_ptr<Expression>(new FloatLiteral(context, -1, 1.0));
} else {
ABORT("math is unsupported on type '%s'", type.name().c_str());
}
@ -2747,7 +2741,7 @@ SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, Outpu
SpvId result = fFunctionMap[&f];
this->writeInstruction(SpvOpFunction, this->getType(f.fReturnType), result,
SpvFunctionControlMaskNone, this->getFunctionType(f), out);
this->writeInstruction(SpvOpName, result, f.fName.c_str(), fNameBuffer);
this->writeInstruction(SpvOpName, result, f.fName, fNameBuffer);
for (size_t i = 0; i < f.fParameters.size(); i++) {
SpvId id = this->nextId();
fVariableMap[f.fParameters[i]] = id;
@ -2844,8 +2838,8 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
std::vector<Type::Field> fields = type->fields();
fRTHeightStructId = result;
fRTHeightFieldIndex = fields.size();
fields.emplace_back(Modifiers(), String(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get());
type = new Type(type->fPosition, type->name(), fields);
fields.emplace_back(Modifiers(), StringFragment(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get());
type = new Type(type->fOffset, type->name(), fields);
}
SpvId typeId = this->getType(*type, layout);
if (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag) {
@ -2922,7 +2916,7 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio
fVariableMap[var] = id;
SpvId type = this->getPointerType(var->fType, storageClass);
this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantBuffer);
this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer);
this->writeInstruction(SpvOpName, id, var->fName, fNameBuffer);
this->writePrecisionModifier(var->fModifiers, id);
if (varDecl.fValue) {
ASSERT(!fCurrentBlock);
@ -2958,7 +2952,7 @@ void SPIRVCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, Outpu
fVariableMap[var] = id;
SpvId type = this->getPointerType(var->fType, SpvStorageClassFunction);
this->writeInstruction(SpvOpVariable, type, id, SpvStorageClassFunction, fVariableBuffer);
this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer);
this->writeInstruction(SpvOpName, id, var->fName, fNameBuffer);
if (varDecl.fValue) {
SpvId value = this->writeExpression(*varDecl.fValue, out);
this->writeInstruction(SpvOpStore, id, value, out);
@ -3086,7 +3080,7 @@ void SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, OutputStre
// the time being, we just fail with an error due to the lack of testing. If you encounter this
// message, simply remove the error call below to see whether our while loop support actually
// works.
fErrors.error(w.fPosition, "internal error: while loop support has been disabled in SPIR-V, "
fErrors.error(w.fOffset, "internal error: while loop support has been disabled in SPIR-V, "
"see SkSLSPIRVCodeGenerator.cpp for details");
SpvId header = this->nextId();
@ -3118,7 +3112,7 @@ void SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, OutputStream& ou
// the time being, we just fail with an error due to the lack of testing. If you encounter this
// message, simply remove the error call below to see whether our do loop support actually
// works.
fErrors.error(d.fPosition, "internal error: do loop support has been disabled in SPIR-V, see "
fErrors.error(d.fOffset, "internal error: do loop support has been disabled in SPIR-V, see "
"SkSLSPIRVCodeGenerator.cpp for details");
SpvId header = this->nextId();
@ -3268,7 +3262,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
this->writeCapabilities(out);
this->writeInstruction(SpvOpExtInstImport, fGLSLExtendedInstructions, "GLSL.std.450", out);
this->writeInstruction(SpvOpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450, out);
this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (strlen(main->fName.c_str()) + 4) / 4) +
this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (main->fName.fLength + 4) / 4) +
(int32_t) interfaceVars.size(), out);
switch (program.fKind) {
case Program::kVertex_Kind:
@ -3285,7 +3279,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
}
SpvId entryPoint = fFunctionMap[main];
this->writeWord(entryPoint, out);
this->writeString(main->fName.c_str(), out);
this->writeString(main->fName.fChars, main->fName.fLength, out);
for (int var : interfaceVars) {
this->writeWord(var, out);
}

View File

@ -241,19 +241,19 @@ private:
void writeWord(int32_t word, OutputStream& out);
void writeString(const char* string, OutputStream& out);
void writeString(const char* string, size_t length, OutputStream& out);
void writeLabel(SpvId id, OutputStream& out);
void writeInstruction(SpvOp_ opCode, OutputStream& out);
void writeInstruction(SpvOp_ opCode, const char* string, OutputStream& out);
void writeInstruction(SpvOp_ opCode, StringFragment string, OutputStream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, OutputStream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, OutputStream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, StringFragment string, OutputStream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string,
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, StringFragment string,
OutputStream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, OutputStream& out);

View File

@ -56,21 +56,21 @@ public:
if (IsSupportedSection(s->fName.c_str())) {
if (SectionAcceptsArgument(s->fName.c_str())) {
if (!s->fArgument.size()) {
errors.error(s->fPosition,
errors.error(s->fOffset,
("section '@" + s->fName +
"' requires one parameter").c_str());
}
} else if (s->fArgument.size()) {
errors.error(s->fPosition,
errors.error(s->fOffset,
("section '@" + s->fName + "' has no parameters").c_str());
}
} else {
errors.error(s->fPosition,
errors.error(s->fOffset,
("unsupported section '@" + s->fName + "'").c_str());
}
if (!SectionPermitsDuplicates(s->fName.c_str()) &&
fSections.find(s->fName) != fSections.end()) {
errors.error(s->fPosition,
errors.error(s->fOffset,
("duplicate section '@" + s->fName + "'").c_str());
}
fSections[s->fName].push_back(s);

View File

@ -77,6 +77,32 @@ String String::operator+(const String& s) const {
return result;
}
String String::operator+(StringFragment s) const {
String result(*this);
result.append(s.fChars, s.fLength);
return result;
}
String& String::operator+=(char c) {
INHERITED::operator+=(c);
return *this;
}
String& String::operator+=(const char* s) {
INHERITED::operator+=(s);
return *this;
}
String& String::operator+=(const String& s) {
INHERITED::operator+=(s);
return *this;
}
String& String::operator+=(StringFragment s) {
this->append(s.fChars, s.fLength);
return *this;
}
bool String::operator==(const String& s) const {
return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size());
}
@ -107,6 +133,28 @@ bool operator!=(const char* s1, const String& s2) {
return s2 != s1;
}
bool StringFragment::operator==(StringFragment s) const {
if (fLength != s.fLength) {
return false;
}
return !memcmp(fChars, s.fChars, fLength);
}
bool StringFragment::operator!=(StringFragment s) const {
if (fLength != s.fLength) {
return true;
}
return memcmp(fChars, s.fChars, fLength);
}
bool StringFragment::operator==(const char* s) const {
return !strncmp(fChars, s, fLength);
}
bool StringFragment::operator!=(const char* s) const {
return strncmp(fChars, s, fLength);
}
String to_string(int32_t value) {
return SkSL::String::printf("%d", value);
}

View File

@ -8,6 +8,8 @@
#ifndef SKSL_STRING
#define SKSL_STRING
#include <cstring>
#define SKSL_USE_STD_STRING
#include <stdarg.h>
@ -22,6 +24,33 @@
namespace SkSL {
// Represents a (not necessarily null-terminated) slice of a string.
struct StringFragment {
StringFragment()
: fChars(nullptr)
, fLength(0) {}
StringFragment(const char* chars)
: fChars(chars)
, fLength(strlen(chars)) {}
StringFragment(const char* chars, size_t length)
: fChars(chars)
, fLength(length) {}
char operator[](size_t idx) const {
return fChars[idx];
}
bool operator==(const char* s) const;
bool operator!=(const char* s) const;
bool operator==(StringFragment s) const;
bool operator!=(StringFragment s) const;
const char* fChars;
size_t fLength;
};
class String : public SKSL_STRING_BASE {
public:
String() = default;
@ -41,6 +70,9 @@ public:
String(const char* s, size_t size)
: INHERITED(s, size) {}
String(StringFragment s)
: INHERITED(s.fChars, s.fLength) {}
static String printf(const char* fmt, ...);
#ifdef SKSL_USE_STD_STRING
@ -53,6 +85,11 @@ public:
String operator+(const char* s) const;
String operator+(const String& s) const;
String operator+(StringFragment s) const;
String& operator+=(char c);
String& operator+=(const char* s);
String& operator+=(const String& s);
String& operator+=(StringFragment s);
bool operator==(const char* s) const;
bool operator!=(const char* s) const;
bool operator==(const String& s) const;
@ -86,6 +123,18 @@ long stol(const String& s);
} // namespace
namespace std {
template<> struct hash<SkSL::StringFragment> {
size_t operator()(const SkSL::StringFragment& s) const {
size_t result = 0;
for (size_t i = 0; i < s.fLength; ++i) {
result = result * 101 + s.fChars[i];
}
return result;
}
};
} // namespace
#ifdef SKSL_USE_STD_STRING
namespace std {
template<> struct hash<SkSL::String> {

View File

@ -1,227 +0,0 @@
/*
* 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_TOKEN
#define SKSL_TOKEN
#include "SkSLPosition.h"
#include "SkSLUtil.h"
namespace SkSL {
#undef IN
#undef OUT
#undef CONST
/**
* Represents a lexical analysis token. Token is generally only used during the parse process, but
* Token::Kind is also used to represent operator kinds.
*/
struct Token {
enum Kind {
END_OF_FILE,
WHITESPACE,
IDENTIFIER,
INT_LITERAL,
FLOAT_LITERAL,
TRUE_LITERAL,
FALSE_LITERAL,
LPAREN,
RPAREN,
LBRACE,
RBRACE,
LBRACKET,
RBRACKET,
DOT,
COMMA,
PLUSPLUS,
MINUSMINUS,
PLUS,
MINUS,
STAR,
SLASH,
PERCENT,
SHL,
SHR,
BITWISEOR,
BITWISEXOR,
BITWISEAND,
BITWISENOT,
LOGICALOR,
LOGICALXOR,
LOGICALAND,
LOGICALNOT,
QUESTION,
COLON,
EQ,
EQEQ,
NEQ,
GT,
LT,
GTEQ,
LTEQ,
PLUSEQ,
MINUSEQ,
STAREQ,
SLASHEQ,
PERCENTEQ,
SHLEQ,
SHREQ,
BITWISEOREQ,
BITWISEXOREQ,
BITWISEANDEQ,
LOGICALOREQ,
LOGICALXOREQ,
LOGICALANDEQ,
SEMICOLON,
ARROW,
COLONCOLON,
IF,
STATIC_IF,
ELSE,
FOR,
WHILE,
DO,
SWITCH,
STATIC_SWITCH,
CASE,
DEFAULT,
RETURN,
BREAK,
CONTINUE,
DISCARD,
IN,
OUT,
INOUT,
CONST,
LOWP,
MEDIUMP,
HIGHP,
UNIFORM,
FLAT,
NOPERSPECTIVE,
READONLY,
WRITEONLY,
COHERENT,
VOLATILE,
RESTRICT,
BUFFER,
HASSIDEEFFECTS,
STRUCT,
LAYOUT,
DIRECTIVE,
SECTION,
PRECISION,
LOCATION,
OFFSET,
BINDING,
INDEX,
SET,
BUILTIN,
INPUT_ATTACHMENT_INDEX,
ORIGIN_UPPER_LEFT,
OVERRIDE_COVERAGE,
BLEND_SUPPORT_ALL_EQUATIONS,
PUSH_CONSTANT,
POINTS,
LINES,
LINE_STRIP,
LINES_ADJACENCY,
TRIANGLES,
TRIANGLE_STRIP,
TRIANGLES_ADJACENCY,
MAX_VERTICES,
INVOCATIONS,
WHEN,
KEY,
INVALID_TOKEN
};
static String OperatorName(Kind kind) {
switch (kind) {
case Token::PLUS: return String("+");
case Token::MINUS: return String("-");
case Token::STAR: return String("*");
case Token::SLASH: return String("/");
case Token::PERCENT: return String("%");
case Token::SHL: return String("<<");
case Token::SHR: return String(">>");
case Token::LOGICALNOT: return String("!");
case Token::LOGICALAND: return String("&&");
case Token::LOGICALOR: return String("||");
case Token::LOGICALXOR: return String("^^");
case Token::BITWISENOT: return String("~");
case Token::BITWISEAND: return String("&");
case Token::BITWISEOR: return String("|");
case Token::BITWISEXOR: return String("^");
case Token::EQ: return String("=");
case Token::EQEQ: return String("==");
case Token::NEQ: return String("!=");
case Token::LT: return String("<");
case Token::GT: return String(">");
case Token::LTEQ: return String("<=");
case Token::GTEQ: return String(">=");
case Token::PLUSEQ: return String("+=");
case Token::MINUSEQ: return String("-=");
case Token::STAREQ: return String("*=");
case Token::SLASHEQ: return String("/=");
case Token::PERCENTEQ: return String("%=");
case Token::SHLEQ: return String("<<=");
case Token::SHREQ: return String(">>=");
case Token::LOGICALANDEQ: return String("&&=");
case Token::LOGICALOREQ: return String("||=");
case Token::LOGICALXOREQ: return String("^^=");
case Token::BITWISEANDEQ: return String("&=");
case Token::BITWISEOREQ: return String("|=");
case Token::BITWISEXOREQ: return String("^=");
case Token::PLUSPLUS: return String("++");
case Token::MINUSMINUS: return String("--");
case Token::COMMA: return String(",");
default:
ABORT("unsupported operator: %d\n", kind);
}
}
Token() {
}
Token(Position position, Kind kind, String text)
: fPosition(position)
, fKind(kind)
, fText(std::move(text)) {}
static bool IsAssignment(Token::Kind op) {
switch (op) {
case Token::EQ: // fall through
case Token::PLUSEQ: // fall through
case Token::MINUSEQ: // fall through
case Token::STAREQ: // fall through
case Token::SLASHEQ: // fall through
case Token::PERCENTEQ: // fall through
case Token::SHLEQ: // fall through
case Token::SHREQ: // fall through
case Token::BITWISEOREQ: // fall through
case Token::BITWISEXOREQ: // fall through
case Token::BITWISEANDEQ: // fall through
case Token::LOGICALOREQ: // fall through
case Token::LOGICALXOREQ: // fall through
case Token::LOGICALANDEQ:
return true;
default:
return false;
}
}
Position fPosition;
Kind fKind;
// will be the empty string unless the token has variable text content (identifiers, numeric
// literals, and directives)
String fText;
};
} // namespace
#endif

View File

@ -9,7 +9,8 @@
#define SKSL_ASTBINARYEXPRESSION
#include "SkSLASTExpression.h"
#include "../SkSLToken.h"
#include "../SkSLCompiler.h"
#include "../SkSLLexer.h"
namespace SkSL {
@ -19,13 +20,13 @@ namespace SkSL {
struct ASTBinaryExpression : public ASTExpression {
ASTBinaryExpression(std::unique_ptr<ASTExpression> left, Token op,
std::unique_ptr<ASTExpression> right)
: INHERITED(op.fPosition, kBinary_Kind)
: INHERITED(op.fOffset, kBinary_Kind)
, fLeft(std::move(left))
, fOperator(op.fKind)
, fRight(std::move(right)) {}
String description() const override {
return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " +
return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " +
fRight->description() + ")";
}

View File

@ -16,8 +16,8 @@ namespace SkSL {
* Represents a curly-braced block of statements.
*/
struct ASTBlock : public ASTStatement {
ASTBlock(Position position, std::vector<std::unique_ptr<ASTStatement>> statements)
: INHERITED(position, kBlock_Kind)
ASTBlock(int offset, std::vector<std::unique_ptr<ASTStatement>> statements)
: INHERITED(offset, kBlock_Kind)
, fStatements(std::move(statements)) {}
String description() const override {

View File

@ -16,8 +16,8 @@ namespace SkSL {
* Represents "true" or "false".
*/
struct ASTBoolLiteral : public ASTExpression {
ASTBoolLiteral(Position position, bool value)
: INHERITED(position, kBool_Kind)
ASTBoolLiteral(int offset, bool value)
: INHERITED(offset, kBool_Kind)
, fValue(value) {}
String description() const override {

View File

@ -16,8 +16,8 @@ namespace SkSL {
* A 'break' statement.
*/
struct ASTBreakStatement : public ASTStatement {
ASTBreakStatement(Position position)
: INHERITED(position, kBreak_Kind) {}
ASTBreakStatement(int offset)
: INHERITED(offset, kBreak_Kind) {}
String description() const override {
return String("break;");

View File

@ -17,8 +17,8 @@ namespace SkSL {
* A parenthesized list of arguments following an expression, indicating a function call.
*/
struct ASTCallSuffix : public ASTSuffix {
ASTCallSuffix(Position position, std::vector<std::unique_ptr<ASTExpression>> arguments)
: INHERITED(position, ASTSuffix::kCall_Kind)
ASTCallSuffix(int offset, std::vector<std::unique_ptr<ASTExpression>> arguments)
: INHERITED(offset, ASTSuffix::kCall_Kind)
, fArguments(std::move(arguments)) {}
String description() const override {

View File

@ -16,8 +16,8 @@ namespace SkSL {
* A 'continue' statement.
*/
struct ASTContinueStatement : public ASTStatement {
ASTContinueStatement(Position position)
: INHERITED(position, kContinue_Kind) {}
ASTContinueStatement(int offset)
: INHERITED(offset, kContinue_Kind) {}
String description() const override {
return String("continue;");

View File

@ -26,8 +26,8 @@ struct ASTDeclaration : public ASTPositionNode {
kSection_Kind
};
ASTDeclaration(Position position, Kind kind)
: INHERITED(position)
ASTDeclaration(int offset, Kind kind)
: INHERITED(offset)
, fKind(kind) {}
Kind fKind;

View File

@ -16,8 +16,8 @@ namespace SkSL {
* A 'discard' statement.
*/
struct ASTDiscardStatement : public ASTStatement {
ASTDiscardStatement(Position position)
: INHERITED(position, kDiscard_Kind) {}
ASTDiscardStatement(int offset)
: INHERITED(offset, kDiscard_Kind) {}
String description() const override {
return String("discard;");

View File

@ -16,9 +16,9 @@ namespace SkSL {
* A 'do' loop.
*/
struct ASTDoStatement : public ASTStatement {
ASTDoStatement(Position position, std::unique_ptr<ASTStatement> statement,
ASTDoStatement(int offset, std::unique_ptr<ASTStatement> statement,
std::unique_ptr<ASTExpression> test)
: INHERITED(position, kDo_Kind)
: INHERITED(offset, kDo_Kind)
, fStatement(std::move(statement))
, fTest(std::move(test)) {}

View File

@ -27,8 +27,8 @@ struct ASTExpression : public ASTPositionNode {
kTernary_Kind
};
ASTExpression(Position position, Kind kind)
: INHERITED(position)
ASTExpression(int offset, Kind kind)
: INHERITED(offset)
, fKind(kind) {}
const Kind fKind;

View File

@ -17,7 +17,7 @@ namespace SkSL {
*/
struct ASTExpressionStatement : public ASTStatement {
ASTExpressionStatement(std::unique_ptr<ASTExpression> expression)
: INHERITED(expression->fPosition, kExpression_Kind)
: INHERITED(expression->fOffset, kExpression_Kind)
, fExpression(std::move(expression)) {}
String description() const override {

View File

@ -16,8 +16,8 @@ namespace SkSL {
* An extension declaration.
*/
struct ASTExtension : public ASTDeclaration {
ASTExtension(Position position, String name)
: INHERITED(position, kExtension_Kind)
ASTExtension(int offset, String name)
: INHERITED(offset, kExtension_Kind)
, fName(std::move(name)) {}
String description() const override {

View File

@ -17,15 +17,15 @@ namespace SkSL {
* actually vector swizzle (which looks the same to the parser).
*/
struct ASTFieldSuffix : public ASTSuffix {
ASTFieldSuffix(Position position, String field)
: INHERITED(position, ASTSuffix::kField_Kind)
, fField(std::move(field)) {}
ASTFieldSuffix(int offset, StringFragment field)
: INHERITED(offset, ASTSuffix::kField_Kind)
, fField(field) {}
String description() const override {
return "." + fField;
}
String fField;
StringFragment fField;
typedef ASTSuffix INHERITED;
};

View File

@ -16,8 +16,8 @@ namespace SkSL {
* A literal floating point number.
*/
struct ASTFloatLiteral : public ASTExpression {
ASTFloatLiteral(Position position, double value)
: INHERITED(position, kFloat_Kind)
ASTFloatLiteral(int offset, double value)
: INHERITED(offset, kFloat_Kind)
, fValue(value) {}
String description() const override {

View File

@ -16,10 +16,10 @@ namespace SkSL {
* A 'for' loop.
*/
struct ASTForStatement : public ASTStatement {
ASTForStatement(Position position, std::unique_ptr<ASTStatement> initializer,
ASTForStatement(int offset, std::unique_ptr<ASTStatement> initializer,
std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTExpression> next,
std::unique_ptr<ASTStatement> statement)
: INHERITED(position, kFor_Kind)
: INHERITED(offset, kFor_Kind)
, fInitializer(std::move(initializer))
, fTest(std::move(test))
, fNext(std::move(next))

View File

@ -19,13 +19,13 @@ namespace SkSL {
* A function declaration or definition. The fBody field will be null for declarations.
*/
struct ASTFunction : public ASTDeclaration {
ASTFunction(Position position, Modifiers modifiers, std::unique_ptr<ASTType> returnType,
String name, std::vector<std::unique_ptr<ASTParameter>> parameters,
ASTFunction(int offset, Modifiers modifiers, std::unique_ptr<ASTType> returnType,
StringFragment name, std::vector<std::unique_ptr<ASTParameter>> parameters,
std::unique_ptr<ASTBlock> body)
: INHERITED(position, kFunction_Kind)
: INHERITED(offset, kFunction_Kind)
, fModifiers(modifiers)
, fReturnType(std::move(returnType))
, fName(std::move(name))
, fName(name)
, fParameters(std::move(parameters))
, fBody(std::move(body)) {}
@ -47,7 +47,7 @@ struct ASTFunction : public ASTDeclaration {
const Modifiers fModifiers;
const std::unique_ptr<ASTType> fReturnType;
const String fName;
const StringFragment fName;
const std::vector<std::unique_ptr<ASTParameter>> fParameters;
const std::unique_ptr<ASTBlock> fBody;

View File

@ -16,15 +16,15 @@ namespace SkSL {
* An identifier in an expression context.
*/
struct ASTIdentifier : public ASTExpression {
ASTIdentifier(Position position, String text)
: INHERITED(position, kIdentifier_Kind)
, fText(std::move(text)) {}
ASTIdentifier(int offset, StringFragment text)
: INHERITED(offset, kIdentifier_Kind)
, fText(text) {}
String description() const override {
return fText;
return String(fText);
}
const String fText;
const StringFragment fText;
typedef ASTExpression INHERITED;
};

View File

@ -16,9 +16,9 @@ namespace SkSL {
* An 'if' statement.
*/
struct ASTIfStatement : public ASTStatement {
ASTIfStatement(Position position, bool isStatic, std::unique_ptr<ASTExpression> test,
ASTIfStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> test,
std::unique_ptr<ASTStatement> ifTrue, std::unique_ptr<ASTStatement> ifFalse)
: INHERITED(position, kIf_Kind)
: INHERITED(offset, kIf_Kind)
, fIsStatic(isStatic)
, fTest(std::move(test))
, fIfTrue(std::move(ifTrue))

View File

@ -18,12 +18,12 @@ namespace SkSL {
* 'float[](5, 6)' are represented with a null fExpression.
*/
struct ASTIndexSuffix : public ASTSuffix {
ASTIndexSuffix(Position position)
: INHERITED(position, ASTSuffix::kIndex_Kind)
ASTIndexSuffix(int offset)
: INHERITED(offset, ASTSuffix::kIndex_Kind)
, fExpression(nullptr) {}
ASTIndexSuffix(std::unique_ptr<ASTExpression> expression)
: INHERITED(expression ? expression->fPosition : Position(), ASTSuffix::kIndex_Kind)
: INHERITED(expression ? expression->fOffset : -1, ASTSuffix::kIndex_Kind)
, fExpression(std::move(expression)) {}
String description() const override {

View File

@ -17,8 +17,8 @@ namespace SkSL {
* appear as a unary minus being applied to an integer literal.
*/
struct ASTIntLiteral : public ASTExpression {
ASTIntLiteral(Position position, uint64_t value)
: INHERITED(position, kInt_Kind)
ASTIntLiteral(int offset, uint64_t value)
: INHERITED(offset, kInt_Kind)
, fValue(value) {}
String description() const override {

View File

@ -23,17 +23,17 @@ namespace SkSL {
*/
struct ASTInterfaceBlock : public ASTDeclaration {
// valueName is empty when it was not present in the source
ASTInterfaceBlock(Position position,
ASTInterfaceBlock(int offset,
Modifiers modifiers,
String typeName,
StringFragment typeName,
std::vector<std::unique_ptr<ASTVarDeclarations>> declarations,
String instanceName,
StringFragment instanceName,
std::vector<std::unique_ptr<ASTExpression>> sizes)
: INHERITED(position, kInterfaceBlock_Kind)
: INHERITED(offset, kInterfaceBlock_Kind)
, fModifiers(modifiers)
, fTypeName(std::move(typeName))
, fTypeName(typeName)
, fDeclarations(std::move(declarations))
, fInstanceName(std::move(instanceName))
, fInstanceName(instanceName)
, fSizes(std::move(sizes)) {}
String description() const override {
@ -42,7 +42,7 @@ struct ASTInterfaceBlock : public ASTDeclaration {
result += fDeclarations[i]->description() + "\n";
}
result += "}";
if (fInstanceName.size()) {
if (fInstanceName.fLength) {
result += " " + fInstanceName;
for (const auto& size : fSizes) {
result += "[";
@ -56,9 +56,9 @@ struct ASTInterfaceBlock : public ASTDeclaration {
}
const Modifiers fModifiers;
const String fTypeName;
const StringFragment fTypeName;
const std::vector<std::unique_ptr<ASTVarDeclarations>> fDeclarations;
const String fInstanceName;
const StringFragment fInstanceName;
const std::vector<std::unique_ptr<ASTExpression>> fSizes;
typedef ASTDeclaration INHERITED;

View File

@ -20,7 +20,7 @@ namespace SkSL {
*/
struct ASTModifiersDeclaration : public ASTDeclaration {
ASTModifiersDeclaration(Modifiers modifiers)
: INHERITED(Position(), kModifiers_Kind)
: INHERITED(-1, kModifiers_Kind)
, fModifiers(modifiers) {}
String description() const {

View File

@ -20,12 +20,12 @@ namespace SkSL {
struct ASTParameter : public ASTPositionNode {
// 'sizes' is a list of the array sizes appearing on a parameter, in source order.
// e.g. int x[3][1] would have sizes [3, 1].
ASTParameter(Position position, Modifiers modifiers, std::unique_ptr<ASTType> type,
String name, std::vector<int> sizes)
: INHERITED(position)
ASTParameter(int offset, Modifiers modifiers, std::unique_ptr<ASTType> type,
StringFragment name, std::vector<int> sizes)
: INHERITED(offset)
, fModifiers(modifiers)
, fType(std::move(type))
, fName(std::move(name))
, fName(name)
, fSizes(std::move(sizes)) {}
String description() const override {
@ -38,7 +38,7 @@ struct ASTParameter : public ASTPositionNode {
const Modifiers fModifiers;
const std::unique_ptr<ASTType> fType;
const String fName;
const StringFragment fName;
const std::vector<int> fSizes;
typedef ASTPositionNode INHERITED;

View File

@ -17,10 +17,12 @@ namespace SkSL {
* An AST node with an associated position in the source.
*/
struct ASTPositionNode : public ASTNode {
ASTPositionNode(Position position)
: fPosition(position) {}
ASTPositionNode(int offset)
: fOffset(offset) {}
const Position fPosition;
// character offset of this element within the program being compiled, for error reporting
// purposes
const int fOffset;
};
} // namespace

View File

@ -18,8 +18,8 @@ namespace SkSL {
*/
struct ASTPrecision : public ASTDeclaration {
// FIXME handle the type
ASTPrecision(Position position, Modifiers::Flag precision)
: INHERITED(position, kPrecision_Kind)
ASTPrecision(int offset, Modifiers::Flag precision)
: INHERITED(offset, kPrecision_Kind)
, fPrecision(precision) {}
String description() const {

View File

@ -9,7 +9,8 @@
#define SKSL_ASTPREFIXEXPRESSION
#include "SkSLASTExpression.h"
#include "../SkSLToken.h"
#include "../SkSLCompiler.h"
#include "../SkSLLexer.h"
namespace SkSL {
@ -18,12 +19,12 @@ namespace SkSL {
*/
struct ASTPrefixExpression : public ASTExpression {
ASTPrefixExpression(Token op, std::unique_ptr<ASTExpression> operand)
: INHERITED(op.fPosition, kPrefix_Kind)
: INHERITED(op.fOffset, kPrefix_Kind)
, fOperator(op.fKind)
, fOperand(std::move(operand)) {}
String description() const override {
return Token::OperatorName(fOperator) + fOperand->description();
return Compiler::OperatorName(fOperator) + fOperand->description();
}
const Token::Kind fOperator;

View File

@ -17,8 +17,8 @@ namespace SkSL {
*/
struct ASTReturnStatement : public ASTStatement {
// expression may be null
ASTReturnStatement(Position position, std::unique_ptr<ASTExpression> expression)
: INHERITED(position, kReturn_Kind)
ASTReturnStatement(int offset, std::unique_ptr<ASTExpression> expression)
: INHERITED(offset, kReturn_Kind)
, fExpression(std::move(expression)) {}
String description() const override {

View File

@ -16,8 +16,8 @@ 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)
ASTSection(int offset, String name, String arg, String text)
: INHERITED(offset, kSection_Kind)
, fName(std::move(name))
, fArgument(std::move(arg))
, fText(std::move(text)) {}

View File

@ -33,8 +33,8 @@ struct ASTStatement : public ASTPositionNode {
kDiscard_Kind
};
ASTStatement(Position position, Kind kind)
: INHERITED(position)
ASTStatement(int offset, Kind kind)
: INHERITED(offset)
, fKind(kind) {}
Kind fKind;

View File

@ -26,8 +26,8 @@ struct ASTSuffix : public ASTPositionNode {
kPostDecrement_Kind
};
ASTSuffix(Position position, Kind kind)
: INHERITED(position)
ASTSuffix(int offset, Kind kind)
: INHERITED(offset)
, fKind(kind) {}
String description() const override {

View File

@ -18,7 +18,7 @@ namespace SkSL {
*/
struct ASTSuffixExpression : public ASTExpression {
ASTSuffixExpression(std::unique_ptr<ASTExpression> base, std::unique_ptr<ASTSuffix> suffix)
: INHERITED(base->fPosition, kSuffix_Kind)
: INHERITED(base->fOffset, kSuffix_Kind)
, fBase(std::move(base))
, fSuffix(std::move(suffix)) {}

View File

@ -17,9 +17,9 @@ namespace SkSL {
*/
struct ASTSwitchCase : public ASTStatement {
// a null value means "default:"
ASTSwitchCase(Position position, std::unique_ptr<ASTExpression> value,
ASTSwitchCase(int offset, std::unique_ptr<ASTExpression> value,
std::vector<std::unique_ptr<ASTStatement>> statements)
: INHERITED(position, kSwitch_Kind)
: INHERITED(offset, kSwitch_Kind)
, fValue(std::move(value))
, fStatements(std::move(statements)) {}

View File

@ -17,9 +17,9 @@ namespace SkSL {
* A 'switch' statement.
*/
struct ASTSwitchStatement : public ASTStatement {
ASTSwitchStatement(Position position, bool isStatic, std::unique_ptr<ASTExpression> value,
ASTSwitchStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> value,
std::vector<std::unique_ptr<ASTSwitchCase>> cases)
: INHERITED(position, kSwitch_Kind)
: INHERITED(offset, kSwitch_Kind)
, fIsStatic(isStatic)
, fValue(std::move(value))
, fCases(std::move(cases)) {}

View File

@ -19,7 +19,7 @@ struct ASTTernaryExpression : public ASTExpression {
ASTTernaryExpression(std::unique_ptr<ASTExpression> test,
std::unique_ptr<ASTExpression> ifTrue,
std::unique_ptr<ASTExpression> ifFalse)
: INHERITED(test->fPosition, kTernary_Kind)
: INHERITED(test->fOffset, kTernary_Kind)
, fTest(std::move(test))
, fIfTrue(std::move(ifTrue))
, fIfFalse(std::move(ifFalse)) {}

View File

@ -21,9 +21,9 @@ struct ASTType : public ASTPositionNode {
kStruct_Kind
};
ASTType(Position position, String name, Kind kind, std::vector<int> sizes)
: INHERITED(position)
, fName(std::move(name))
ASTType(int offset, StringFragment name, Kind kind, std::vector<int> sizes)
: INHERITED(offset)
, fName(name)
, fKind(kind)
, fSizes(std::move(sizes)) {}
@ -31,7 +31,7 @@ struct ASTType : public ASTPositionNode {
return fName;
}
const String fName;
const StringFragment fName;
const Kind fKind;

View File

@ -22,7 +22,7 @@ namespace SkSL {
* instances.
*/
struct ASTVarDeclaration {
ASTVarDeclaration(const String name,
ASTVarDeclaration(StringFragment name,
std::vector<std::unique_ptr<ASTExpression>> sizes,
std::unique_ptr<ASTExpression> value)
: fName(name)
@ -30,7 +30,7 @@ struct ASTVarDeclaration {
, fValue(std::move(value)) {}
String description() const {
String result = fName;
String result(fName);
for (const auto& size : fSizes) {
if (size) {
result += "[" + size->description() + "]";
@ -44,7 +44,7 @@ struct ASTVarDeclaration {
return result;
}
String fName;
StringFragment fName;
// array sizes, if any. e.g. 'foo[3][]' has sizes [3, null]
std::vector<std::unique_ptr<ASTExpression>> fSizes;
@ -60,7 +60,7 @@ struct ASTVarDeclarations : public ASTDeclaration {
ASTVarDeclarations(Modifiers modifiers,
std::unique_ptr<ASTType> type,
std::vector<ASTVarDeclaration> vars)
: INHERITED(type->fPosition, kVar_Kind)
: INHERITED(type->fOffset, kVar_Kind)
, fModifiers(modifiers)
, fType(std::move(type))
, fVars(std::move(vars)) {}

View File

@ -18,7 +18,7 @@ namespace SkSL {
*/
struct ASTVarDeclarationStatement : public ASTStatement {
ASTVarDeclarationStatement(std::unique_ptr<ASTVarDeclarations> decl)
: INHERITED(decl->fPosition, kVarDeclaration_Kind)
: INHERITED(decl->fOffset, kVarDeclaration_Kind)
, fDeclarations(std::move(decl)) {}
String description() const override {

View File

@ -16,9 +16,9 @@ namespace SkSL {
* A 'while' statement.
*/
struct ASTWhileStatement : public ASTStatement {
ASTWhileStatement(Position position, std::unique_ptr<ASTExpression> test,
ASTWhileStatement(int offset, std::unique_ptr<ASTExpression> test,
std::unique_ptr<ASTStatement> statement)
: INHERITED(position, kWhile_Kind)
: INHERITED(offset, kWhile_Kind)
, fTest(std::move(test))
, fStatement(std::move(statement)) {}

View File

@ -1,28 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// useless include to avoid "#if before #include" complaint from Skia presubmit
#include "SkSLUtil.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
#pragma clang diagnostic ignored "-Wnull-conversion"
#pragma clang diagnostic ignored "-Wsign-compare"
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wdeprecated-register"
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4018)
#endif
#define YY_NO_UNPUT

View File

@ -11,7 +11,7 @@
#include "SkSLExpression.h"
#include "SkSLExpression.h"
#include "../SkSLIRGenerator.h"
#include "../SkSLToken.h"
#include "../SkSLLexer.h"
namespace SkSL {
@ -19,9 +19,9 @@ namespace SkSL {
* A binary operation.
*/
struct BinaryExpression : public Expression {
BinaryExpression(Position position, std::unique_ptr<Expression> left, Token::Kind op,
BinaryExpression(int offset, std::unique_ptr<Expression> left, Token::Kind op,
std::unique_ptr<Expression> right, const Type& type)
: INHERITED(position, kBinary_Kind, type)
: INHERITED(offset, kBinary_Kind, type)
, fLeft(std::move(left))
, fOperator(op)
, fRight(std::move(right)) {}
@ -34,12 +34,12 @@ struct BinaryExpression : public Expression {
}
bool hasSideEffects() const override {
return Token::IsAssignment(fOperator) || fLeft->hasSideEffects() ||
return Compiler::IsAssignment(fOperator) || fLeft->hasSideEffects() ||
fRight->hasSideEffects();
}
String description() const override {
return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " +
return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " +
fRight->description() + ")";
}

View File

@ -17,9 +17,9 @@ namespace SkSL {
* A block of multiple statements functioning as a single statement.
*/
struct Block : public Statement {
Block(Position position, std::vector<std::unique_ptr<Statement>> statements,
Block(int offset, std::vector<std::unique_ptr<Statement>> statements,
const std::shared_ptr<SymbolTable> symbols = nullptr)
: INHERITED(position, kBlock_Kind)
: INHERITED(offset, kBlock_Kind)
, fSymbols(std::move(symbols))
, fStatements(std::move(statements)) {}

View File

@ -17,8 +17,8 @@ namespace SkSL {
* Represents 'true' or 'false'.
*/
struct BoolLiteral : public Expression {
BoolLiteral(const Context& context, Position position, bool value)
: INHERITED(position, kBoolLiteral_Kind, *context.fBool_Type)
BoolLiteral(const Context& context, int offset, bool value)
: INHERITED(offset, kBoolLiteral_Kind, *context.fBool_Type)
, fValue(value) {}
String description() const override {

View File

@ -17,8 +17,8 @@ namespace SkSL {
* A 'break' statement.
*/
struct BreakStatement : public Statement {
BreakStatement(Position position)
: INHERITED(position, kBreak_Kind) {}
BreakStatement(int offset)
: INHERITED(offset, kBreak_Kind) {}
String description() const override {
return String("break;");

View File

@ -16,7 +16,7 @@
namespace SkSL {
/**
* Represents the construction of a compound type, such as "float2x, y)".
* Represents the construction of a compound type, such as "float2(x, y)".
*
* Vector constructors will always consist of either exactly 1 scalar, or a collection of vectors
* and scalars totalling exactly the right number of scalar components.
@ -25,9 +25,8 @@ namespace SkSL {
* collection of vectors and scalars totalling exactly the right number of scalar components.
*/
struct Constructor : public Expression {
Constructor(Position position, const Type& type,
std::vector<std::unique_ptr<Expression>> arguments)
: INHERITED(position, kConstructor_Kind, type)
Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments)
: INHERITED(offset, kConstructor_Kind, type)
, fArguments(std::move(arguments)) {}
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
@ -37,13 +36,13 @@ struct Constructor : public Expression {
// promote float(1) to 1.0
int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
return std::unique_ptr<Expression>(new FloatLiteral(irGenerator.fContext,
fPosition,
fOffset,
intValue));
} else if (fType == *irGenerator.fContext.fUInt_Type) {
// promote uint(1) to 1u
int64_t intValue = ((IntLiteral&) *fArguments[0]).fValue;
return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
fPosition,
fOffset,
intValue,
&fType));
}
@ -96,8 +95,8 @@ struct Constructor : public Expression {
// a constant scalar constructor should have been collapsed down to the appropriate
// literal
ASSERT(fType.kind() == Type::kMatrix_Kind);
const FloatLiteral fzero(context, Position(), 0);
const IntLiteral izero(context, Position(), 0);
const FloatLiteral fzero(context, -1, 0);
const IntLiteral izero(context, -1, 0);
const Expression* zero;
if (fType.componentType() == *context.fFloat_Type) {
zero = &fzero;

View File

@ -17,8 +17,8 @@ namespace SkSL {
* A 'continue' statement.
*/
struct ContinueStatement : public Statement {
ContinueStatement(Position position)
: INHERITED(position, kContinue_Kind) {}
ContinueStatement(int offset)
: INHERITED(offset, kContinue_Kind) {}
String description() const override {
return String("continue;");

View File

@ -17,8 +17,8 @@ namespace SkSL {
* A 'discard' statement.
*/
struct DiscardStatement : public Statement {
DiscardStatement(Position position)
: INHERITED(position, kDiscard_Kind) {}
DiscardStatement(int offset)
: INHERITED(offset, kDiscard_Kind) {}
String description() const override {
return String("discard;");

View File

@ -17,9 +17,9 @@ namespace SkSL {
* A 'do' statement.
*/
struct DoStatement : public Statement {
DoStatement(Position position, std::unique_ptr<Statement> statement,
DoStatement(int offset, std::unique_ptr<Statement> statement,
std::unique_ptr<Expression> test)
: INHERITED(position, kDo_Kind)
: INHERITED(offset, kDo_Kind)
, fStatement(std::move(statement))
, fTest(std::move(test)) {}

View File

@ -44,8 +44,8 @@ struct Expression : public IRNode {
kDefined_Kind
};
Expression(Position position, Kind kind, const Type& type)
: INHERITED(position)
Expression(int offset, Kind kind, const Type& type)
: INHERITED(offset)
, fKind(kind)
, fType(std::move(type)) {}

View File

@ -18,7 +18,7 @@ namespace SkSL {
*/
struct ExpressionStatement : public Statement {
ExpressionStatement(std::unique_ptr<Expression> expression)
: INHERITED(expression->fPosition, kExpression_Kind)
: INHERITED(expression->fOffset, kExpression_Kind)
, fExpression(std::move(expression)) {}
String description() const override {

View File

@ -16,8 +16,8 @@ namespace SkSL {
* An extension declaration.
*/
struct Extension : public ProgramElement {
Extension(Position position, String name)
: INHERITED(position, kExtension_Kind)
Extension(int offset, String name)
: INHERITED(offset, kExtension_Kind)
, fName(std::move(name)) {}
String description() const override {

View File

@ -22,8 +22,8 @@ namespace SkSL {
* result of declaring anonymous interface blocks.
*/
struct Field : public Symbol {
Field(Position position, const Variable& owner, int fieldIndex)
: INHERITED(position, kField_Kind, owner.fType.fields()[fieldIndex].fName)
Field(int offset, const Variable& owner, int fieldIndex)
: INHERITED(offset, kField_Kind, owner.fType.fields()[fieldIndex].fName)
, fOwner(owner)
, fFieldIndex(fieldIndex) {}

View File

@ -26,7 +26,7 @@ struct FieldAccess : public Expression {
FieldAccess(std::unique_ptr<Expression> base, int fieldIndex,
OwnerKind ownerKind = kDefault_OwnerKind)
: INHERITED(base->fPosition, kFieldAccess_Kind, *base->fType.fields()[fieldIndex].fType)
: INHERITED(base->fOffset, kFieldAccess_Kind, *base->fType.fields()[fieldIndex].fType)
, fBase(std::move(base))
, fFieldIndex(fieldIndex)
, fOwnerKind(ownerKind) {}

View File

@ -17,9 +17,9 @@ namespace SkSL {
* A literal floating point number.
*/
struct FloatLiteral : public Expression {
FloatLiteral(const Context& context, Position position, double value,
FloatLiteral(const Context& context, int offset, double value,
const Type* type = nullptr)
: INHERITED(position, kFloatLiteral_Kind, type ? *type : *context.fFloat_Type)
: INHERITED(offset, kFloatLiteral_Kind, type ? *type : *context.fFloat_Type)
, fValue(value) {}
String description() const override {

View File

@ -18,10 +18,10 @@ namespace SkSL {
* A 'for' statement.
*/
struct ForStatement : public Statement {
ForStatement(Position position, std::unique_ptr<Statement> initializer,
ForStatement(int offset, std::unique_ptr<Statement> initializer,
std::unique_ptr<Expression> test, std::unique_ptr<Expression> next,
std::unique_ptr<Statement> statement, std::shared_ptr<SymbolTable> symbols)
: INHERITED(position, kFor_Kind)
: INHERITED(offset, kFor_Kind)
, fSymbols(symbols)
, fInitializer(std::move(initializer))
, fTest(std::move(test))

View File

@ -17,9 +17,9 @@ namespace SkSL {
* A function invocation.
*/
struct FunctionCall : public Expression {
FunctionCall(Position position, const Type& type, const FunctionDeclaration& function,
FunctionCall(int offset, const Type& type, const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments)
: INHERITED(position, kFunctionCall_Kind, type)
: INHERITED(offset, kFunctionCall_Kind, type)
, fFunction(std::move(function))
, fArguments(std::move(arguments)) {}
@ -33,7 +33,7 @@ struct FunctionCall : public Expression {
}
String description() const override {
String result = fFunction.fName + "(";
String result = String(fFunction.fName) + "(";
String separator;
for (size_t i = 0; i < fArguments.size(); i++) {
result += separator;

View File

@ -21,9 +21,9 @@ namespace SkSL {
* A function declaration (not a definition -- does not contain a body).
*/
struct FunctionDeclaration : public Symbol {
FunctionDeclaration(Position position, Modifiers modifiers, String name,
FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
std::vector<const Variable*> parameters, const Type& returnType)
: INHERITED(position, kFunctionDeclaration_Kind, std::move(name))
: INHERITED(offset, kFunctionDeclaration_Kind, std::move(name))
, fDefined(false)
, fBuiltin(false)
, fModifiers(modifiers)

View File

@ -18,9 +18,9 @@ namespace SkSL {
* A function definition (a declaration plus an associated block of code).
*/
struct FunctionDefinition : public ProgramElement {
FunctionDefinition(Position position, const FunctionDeclaration& declaration,
FunctionDefinition(int offset, const FunctionDeclaration& declaration,
std::unique_ptr<Statement> body)
: INHERITED(position, kFunction_Kind)
: INHERITED(offset, kFunction_Kind)
, fDeclaration(declaration)
, fBody(std::move(body)) {}

View File

@ -19,9 +19,9 @@ namespace SkSL {
* always eventually replaced by FunctionCalls in valid programs.
*/
struct FunctionReference : public Expression {
FunctionReference(const Context& context, Position position,
FunctionReference(const Context& context, int offset,
std::vector<const FunctionDeclaration*> function)
: INHERITED(position, kFunctionReference_Kind, *context.fInvalid_Type)
: INHERITED(offset, kFunctionReference_Kind, *context.fInvalid_Type)
, fFunctions(function) {}
bool hasSideEffects() const override {

View File

@ -8,7 +8,7 @@
#ifndef SKSL_IRNODE
#define SKSL_IRNODE
#include "../SkSLPosition.h"
#include "../SkSLLexer.h"
namespace SkSL {
@ -17,14 +17,16 @@ namespace SkSL {
* version of the program (all types determined, everything validated), ready for code generation.
*/
struct IRNode {
IRNode(Position position)
: fPosition(position) {}
IRNode(int offset)
: fOffset(offset) {}
virtual ~IRNode() {}
virtual String description() const = 0;
const Position fPosition;
// character offset of this element within the program being compiled, for error reporting
// purposes
const int fOffset;
};
} // namespace

View File

@ -17,9 +17,9 @@ namespace SkSL {
* An 'if' statement.
*/
struct IfStatement : public Statement {
IfStatement(Position position, bool isStatic, std::unique_ptr<Expression> test,
IfStatement(int offset, bool isStatic, std::unique_ptr<Expression> test,
std::unique_ptr<Statement> ifTrue, std::unique_ptr<Statement> ifFalse)
: INHERITED(position, kIf_Kind)
: INHERITED(offset, kIf_Kind)
, fIsStatic(isStatic)
, fTest(std::move(test))
, fIfTrue(std::move(ifTrue))

View File

@ -45,7 +45,7 @@ static const Type& index_type(const Context& context, const Type& type) {
struct IndexExpression : public Expression {
IndexExpression(const Context& context, std::unique_ptr<Expression> base,
std::unique_ptr<Expression> index)
: INHERITED(base->fPosition, kIndex_Kind, index_type(context, base->fType))
: INHERITED(base->fOffset, kIndex_Kind, index_type(context, base->fType))
, fBase(std::move(base))
, fIndex(std::move(index)) {
ASSERT(fIndex->fType == *context.fInt_Type || fIndex->fType == *context.fUInt_Type);

View File

@ -19,8 +19,8 @@ namespace SkSL {
struct IntLiteral : public Expression {
// FIXME: we will need to revisit this if/when we add full support for both signed and unsigned
// 64-bit integers, but for right now an int64_t will hold every value we care about
IntLiteral(const Context& context, Position position, int64_t value, const Type* type = nullptr)
: INHERITED(position, kIntLiteral_Kind, type ? *type : *context.fInt_Type)
IntLiteral(const Context& context, int offset, int64_t value, const Type* type = nullptr)
: INHERITED(offset, kIntLiteral_Kind, type ? *type : *context.fInt_Type)
, fValue(value) {}
String description() const override {

View File

@ -25,10 +25,10 @@ namespace SkSL {
* At the IR level, this is represented by a single variable of struct type.
*/
struct InterfaceBlock : public ProgramElement {
InterfaceBlock(Position position, const Variable* var, String typeName, String instanceName,
InterfaceBlock(int offset, const Variable* var, String typeName, String instanceName,
std::vector<std::unique_ptr<Expression>> sizes,
std::shared_ptr<SymbolTable> typeOwner)
: INHERITED(position, kInterfaceBlock_Kind)
: INHERITED(offset, kInterfaceBlock_Kind)
, fVariable(*var)
, fTypeName(std::move(typeName))
, fInstanceName(std::move(instanceName))

View File

@ -20,7 +20,7 @@ namespace SkSL {
*/
struct ModifiersDeclaration : public ProgramElement {
ModifiersDeclaration(Modifiers modifiers)
: INHERITED(Position(), kModifiers_Kind)
: INHERITED(-1, kModifiers_Kind)
, fModifiers(modifiers) {}
String description() const {

View File

@ -18,7 +18,7 @@ namespace SkSL {
*/
struct Nop : public Statement {
Nop()
: INHERITED(Position(), kNop_Kind) {}
: INHERITED(-1, kNop_Kind) {}
virtual bool isEmpty() const override {
return true;

View File

@ -9,7 +9,7 @@
#define SKSL_POSTFIXEXPRESSION
#include "SkSLExpression.h"
#include "SkSLToken.h"
#include "SkSLLexer.h"
namespace SkSL {
@ -18,7 +18,7 @@ namespace SkSL {
*/
struct PostfixExpression : public Expression {
PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op)
: INHERITED(operand->fPosition, kPostfix_Kind, operand->fType)
: INHERITED(operand->fOffset, kPostfix_Kind, operand->fType)
, fOperand(std::move(operand))
, fOperator(op) {}
@ -27,7 +27,7 @@ struct PostfixExpression : public Expression {
}
String description() const override {
return fOperand->description() + Token::OperatorName(fOperator);
return fOperand->description() + Compiler::OperatorName(fOperator);
}
std::unique_ptr<Expression> fOperand;

View File

@ -11,7 +11,7 @@
#include "SkSLExpression.h"
#include "SkSLFloatLiteral.h"
#include "SkSLIRGenerator.h"
#include "SkSLToken.h"
#include "SkSLLexer.h"
namespace SkSL {
@ -20,7 +20,7 @@ namespace SkSL {
*/
struct PrefixExpression : public Expression {
PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand)
: INHERITED(operand->fPosition, kPrefix_Kind, operand->fType)
: INHERITED(operand->fOffset, kPrefix_Kind, operand->fType)
, fOperand(std::move(operand))
, fOperator(op) {}
@ -38,7 +38,7 @@ struct PrefixExpression : public Expression {
if (fOperand->fKind == Expression::kFloatLiteral_Kind) {
return std::unique_ptr<Expression>(new FloatLiteral(
irGenerator.fContext,
Position(),
fOffset,
-((FloatLiteral&) *fOperand).fValue));
}
@ -46,7 +46,7 @@ struct PrefixExpression : public Expression {
}
String description() const override {
return Token::OperatorName(fOperator) + fOperand->description();
return Compiler::OperatorName(fOperator) + fOperand->description();
}
std::unique_ptr<Expression> fOperand;

View File

@ -39,15 +39,15 @@ struct Program {
: fKind(kInt_Kind)
, fValue(i) {}
std::unique_ptr<Expression> literal(const Context& context, Position position) const {
std::unique_ptr<Expression> literal(const Context& context, int offset) const {
switch (fKind) {
case Program::Settings::Value::kBool_Kind:
return std::unique_ptr<Expression>(new BoolLiteral(context,
position,
offset,
fValue));
case Program::Settings::Value::kInt_Kind:
return std::unique_ptr<Expression>(new IntLiteral(context,
position,
offset,
fValue));
default:
ASSERT(false);
@ -103,6 +103,7 @@ struct Program {
};
Program(Kind kind,
std::unique_ptr<String> source,
Settings settings,
Modifiers::Flag defaultPrecision,
Context* context,
@ -110,6 +111,7 @@ struct Program {
std::shared_ptr<SymbolTable> symbols,
Inputs inputs)
: fKind(kind)
, fSource(std::move(source))
, fSettings(settings)
, fDefaultPrecision(defaultPrecision)
, fContext(context)
@ -118,6 +120,7 @@ struct Program {
, fInputs(inputs) {}
Kind fKind;
std::unique_ptr<String> fSource;
Settings fSettings;
// FIXME handle different types; currently it assumes this is for floats
Modifiers::Flag fDefaultPrecision;

View File

@ -25,8 +25,8 @@ struct ProgramElement : public IRNode {
kSection_Kind
};
ProgramElement(Position position, Kind kind)
: INHERITED(position)
ProgramElement(int offset, Kind kind)
: INHERITED(offset)
, fKind(kind) {}
Kind fKind;

View File

@ -17,11 +17,11 @@ namespace SkSL {
* A 'return' statement.
*/
struct ReturnStatement : public Statement {
ReturnStatement(Position position)
: INHERITED(position, kReturn_Kind) {}
ReturnStatement(int offset)
: INHERITED(offset, kReturn_Kind) {}
ReturnStatement(std::unique_ptr<Expression> expression)
: INHERITED(expression->fPosition, kReturn_Kind)
: INHERITED(expression->fOffset, kReturn_Kind)
, fExpression(std::move(expression)) {}
String description() const override {

Some files were not shown because too many files have changed in this diff Show More