Revamped handling of SkSL node kinds

Moved the actual field into the base class, changed all of the enums
into non-overlapping enum classes, and finally renamed Type::Kind to
fix the ambiguity there.

Change-Id: I4e6c24d2dbbc7b1d12b7b7bf12e77c651eea7ed9
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/315318
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
Ethan Nicholas 2020-09-08 10:22:09 -04:00 committed by Skia Commit-Bot
parent a9b45b6a7c
commit e659214bc6
75 changed files with 1256 additions and 1183 deletions

View File

@ -155,7 +155,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
// Go through program elements, pulling out information that we need // Go through program elements, pulling out information that we need
for (const auto& elem : *program) { for (const auto& elem : *program) {
// Variables (uniform, varying, etc.) // Variables (uniform, varying, etc.)
if (elem.fKind == SkSL::ProgramElement::kVar_Kind) { if (elem.kind() == SkSL::ProgramElement::Kind::kVar) {
const auto& varDecls = static_cast<const SkSL::VarDeclarations&>(elem); const auto& varDecls = static_cast<const SkSL::VarDeclarations&>(elem);
for (const auto& varDecl : varDecls.fVars) { for (const auto& varDecl : varDecls.fVars) {
const SkSL::Variable& var = const SkSL::Variable& var =
@ -163,9 +163,10 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
// Varyings (only used in conjunction with drawVertices) // Varyings (only used in conjunction with drawVertices)
if (var.fModifiers.fFlags & SkSL::Modifiers::kVarying_Flag) { if (var.fModifiers.fFlags & SkSL::Modifiers::kVarying_Flag) {
varyings.push_back({var.fName, var.fType.kind() == SkSL::Type::kVector_Kind varyings.push_back({var.fName,
? var.fType.columns() var.fType.typeKind() == SkSL::Type::TypeKind::kVector
: 1}); ? var.fType.columns()
: 1});
} }
// Fragment Processors (aka 'shader'): These are child effects // Fragment Processors (aka 'shader'): These are child effects
else if (&var.fType == ctx.fFragmentProcessor_Type.get()) { else if (&var.fType == ctx.fFragmentProcessor_Type.get()) {
@ -180,7 +181,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
uni.fCount = 1; uni.fCount = 1;
const SkSL::Type* type = &var.fType; const SkSL::Type* type = &var.fType;
if (type->kind() == SkSL::Type::kArray_Kind) { if (type->typeKind() == SkSL::Type::TypeKind::kArray) {
uni.fFlags |= Uniform::kArray_Flag; uni.fFlags |= Uniform::kArray_Flag;
uni.fCount = type->columns(); uni.fCount = type->columns();
type = &type->componentType(); type = &type->componentType();
@ -213,7 +214,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
} }
} }
// Functions // Functions
else if (elem.fKind == SkSL::ProgramElement::kFunction_Kind) { else if (elem.kind() == SkSL::ProgramElement::Kind::kFunction) {
const auto& func = static_cast<const SkSL::FunctionDefinition&>(elem); const auto& func = static_cast<const SkSL::FunctionDefinition&>(elem);
const SkSL::FunctionDeclaration& decl = func.fDeclaration; const SkSL::FunctionDeclaration& decl = func.fDeclaration;
if (decl.fName == "main") { if (decl.fName == "main") {

View File

@ -65,7 +65,7 @@ namespace {
static bool is_sample_call_to_fp(const FunctionCall& fc, const Variable& fp) { static bool is_sample_call_to_fp(const FunctionCall& fc, const Variable& fp) {
const FunctionDeclaration& f = fc.fFunction; const FunctionDeclaration& f = fc.fFunction;
return f.fBuiltin && f.fName == "sample" && fc.fArguments.size() >= 1 && return f.fBuiltin && f.fName == "sample" && fc.fArguments.size() >= 1 &&
fc.fArguments[0]->fKind == Expression::kVariableReference_Kind && fc.fArguments[0]->kind() == Expression::Kind::kVariableReference &&
&((VariableReference&) *fc.fArguments[0]).fVariable == &fp; &((VariableReference&) *fc.fArguments[0]).fVariable == &fp;
} }
@ -88,7 +88,7 @@ protected:
bool visitExpression(const Expression& e) override { bool visitExpression(const Expression& e) override {
// Looking for sample(fp, inColor?, ...) // Looking for sample(fp, inColor?, ...)
if (e.fKind == Expression::kFunctionCall_Kind) { if (e.kind() == Expression::Kind::kFunctionCall) {
const FunctionCall& fc = e.as<FunctionCall>(); const FunctionCall& fc = e.as<FunctionCall>();
if (is_sample_call_to_fp(fc, fFP)) { if (is_sample_call_to_fp(fc, fFP)) {
// Determine the type of call at this site, and merge it with the accumulated state // Determine the type of call at this site, and merge it with the accumulated state
@ -99,8 +99,8 @@ protected:
} else if (lastArg->fType == *fContext.fFloat3x3_Type) { } else if (lastArg->fType == *fContext.fFloat3x3_Type) {
// Determine the type of matrix for this call site // Determine the type of matrix for this call site
if (lastArg->isConstantOrUniform()) { if (lastArg->isConstantOrUniform()) {
if (lastArg->fKind == Expression::Kind::kVariableReference_Kind || if (lastArg->kind() == Expression::Kind::kVariableReference ||
lastArg->fKind == Expression::Kind::kConstructor_Kind) { lastArg->kind() == Expression::Kind::kConstructor) {
// FIXME if this is a constant, we should parse the float3x3 constructor // FIXME if this is a constant, we should parse the float3x3 constructor
// and determine if the resulting matrix introduces perspective. // and determine if the resulting matrix introduces perspective.
fUsage.merge(SampleUsage::UniformMatrix(lastArg->description())); fUsage.merge(SampleUsage::UniformMatrix(lastArg->description()));
@ -136,7 +136,7 @@ public:
BuiltinVariableVisitor(int builtin) : fBuiltin(builtin) {} BuiltinVariableVisitor(int builtin) : fBuiltin(builtin) {}
bool visitExpression(const Expression& e) override { bool visitExpression(const Expression& e) override {
if (e.fKind == Expression::kVariableReference_Kind) { if (e.kind() == Expression::Kind::kVariableReference) {
const VariableReference& var = e.as<VariableReference>(); const VariableReference& var = e.as<VariableReference>();
return var.fVariable.fModifiers.fLayout.fBuiltin == fBuiltin; return var.fVariable.fModifiers.fLayout.fBuiltin == fBuiltin;
} }
@ -188,7 +188,7 @@ public:
} }
bool visitExpression(const Expression& e) override { bool visitExpression(const Expression& e) override {
if (e.fKind == Expression::kVariableReference_Kind) { if (e.kind() == Expression::Kind::kVariableReference) {
const VariableReference& ref = e.as<VariableReference>(); const VariableReference& ref = e.as<VariableReference>();
if (&ref.fVariable == fVar && (ref.fRefKind == VariableReference::kWrite_RefKind || if (&ref.fVariable == fVar && (ref.fRefKind == VariableReference::kWrite_RefKind ||
ref.fRefKind == VariableReference::kReadWrite_RefKind || ref.fRefKind == VariableReference::kReadWrite_RefKind ||
@ -249,51 +249,51 @@ bool ProgramVisitor::visit(const Program& program) {
} }
bool ProgramVisitor::visitExpression(const Expression& e) { bool ProgramVisitor::visitExpression(const Expression& e) {
switch(e.fKind) { switch(e.kind()) {
case Expression::kBoolLiteral_Kind: case Expression::Kind::kBoolLiteral:
case Expression::kDefined_Kind: case Expression::Kind::kDefined:
case Expression::kExternalValue_Kind: case Expression::Kind::kExternalValue:
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
case Expression::kFunctionReference_Kind: case Expression::Kind::kFunctionReference:
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
case Expression::kNullLiteral_Kind: case Expression::Kind::kNullLiteral:
case Expression::kSetting_Kind: case Expression::Kind::kSetting:
case Expression::kTypeReference_Kind: case Expression::Kind::kTypeReference:
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
// Leaf expressions return false // Leaf expressions return false
return false; return false;
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
const BinaryExpression& b = e.as<BinaryExpression>(); const BinaryExpression& b = e.as<BinaryExpression>();
return this->visitExpression(*b.fLeft) || this->visitExpression(*b.fRight); } return this->visitExpression(*b.fLeft) || this->visitExpression(*b.fRight); }
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
const Constructor& c = e.as<Constructor>(); const Constructor& c = e.as<Constructor>();
for (const auto& arg : c.fArguments) { for (const auto& arg : c.fArguments) {
if (this->visitExpression(*arg)) { return true; } if (this->visitExpression(*arg)) { return true; }
} }
return false; } return false; }
case Expression::kExternalFunctionCall_Kind: { case Expression::Kind::kExternalFunctionCall: {
const ExternalFunctionCall& c = e.as<ExternalFunctionCall>(); const ExternalFunctionCall& c = e.as<ExternalFunctionCall>();
for (const auto& arg : c.fArguments) { for (const auto& arg : c.fArguments) {
if (this->visitExpression(*arg)) { return true; } if (this->visitExpression(*arg)) { return true; }
} }
return false; } return false; }
case Expression::kFunctionCall_Kind: { case Expression::Kind::kFunctionCall: {
const FunctionCall& c = e.as<FunctionCall>(); const FunctionCall& c = e.as<FunctionCall>();
for (const auto& arg : c.fArguments) { for (const auto& arg : c.fArguments) {
if (this->visitExpression(*arg)) { return true; } if (this->visitExpression(*arg)) { return true; }
} }
return false; } return false; }
case Expression::kIndex_Kind:{ case Expression::Kind::kIndex: {
const IndexExpression& i = e.as<IndexExpression>(); const IndexExpression& i = e.as<IndexExpression>();
return this->visitExpression(*i.fBase) || this->visitExpression(*i.fIndex); } return this->visitExpression(*i.fBase) || this->visitExpression(*i.fIndex); }
case Expression::kPostfix_Kind: case Expression::Kind::kPostfix:
return this->visitExpression(*e.as<PostfixExpression>().fOperand); return this->visitExpression(*e.as<PostfixExpression>().fOperand);
case Expression::kPrefix_Kind: case Expression::Kind::kPrefix:
return this->visitExpression(*e.as<PrefixExpression>().fOperand); return this->visitExpression(*e.as<PrefixExpression>().fOperand);
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
return this->visitExpression(*e.as<Swizzle>().fBase); return this->visitExpression(*e.as<Swizzle>().fBase);
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
const TernaryExpression& t = e.as<TernaryExpression>(); const TernaryExpression& t = e.as<TernaryExpression>();
return this->visitExpression(*t.fTest) || return this->visitExpression(*t.fTest) ||
this->visitExpression(*t.fIfTrue) || this->visitExpression(*t.fIfTrue) ||
@ -304,38 +304,38 @@ bool ProgramVisitor::visitExpression(const Expression& e) {
} }
bool ProgramVisitor::visitStatement(const Statement& s) { bool ProgramVisitor::visitStatement(const Statement& s) {
switch(s.fKind) { switch(s.kind()) {
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
case Statement::kContinue_Kind: case Statement::Kind::kContinue:
case Statement::kDiscard_Kind: case Statement::Kind::kDiscard:
case Statement::kNop_Kind: case Statement::Kind::kNop:
// Leaf statements just return false // Leaf statements just return false
return false; return false;
case Statement::kBlock_Kind: case Statement::Kind::kBlock:
for (const std::unique_ptr<Statement>& blockStmt : s.as<Block>().fStatements) { for (const std::unique_ptr<Statement>& blockStmt : s.as<Block>().fStatements) {
if (this->visitStatement(*blockStmt)) { return true; } if (this->visitStatement(*blockStmt)) { return true; }
} }
return false; return false;
case Statement::kDo_Kind: { case Statement::Kind::kDo: {
const DoStatement& d = s.as<DoStatement>(); const DoStatement& d = s.as<DoStatement>();
return this->visitExpression(*d.fTest) || this->visitStatement(*d.fStatement); } return this->visitExpression(*d.fTest) || this->visitStatement(*d.fStatement); }
case Statement::kExpression_Kind: case Statement::Kind::kExpression:
return this->visitExpression(*s.as<ExpressionStatement>().fExpression); return this->visitExpression(*s.as<ExpressionStatement>().fExpression);
case Statement::kFor_Kind: { case Statement::Kind::kFor: {
const ForStatement& f = s.as<ForStatement>(); const ForStatement& f = s.as<ForStatement>();
return (f.fInitializer && this->visitStatement(*f.fInitializer)) || return (f.fInitializer && this->visitStatement(*f.fInitializer)) ||
(f.fTest && this->visitExpression(*f.fTest)) || (f.fTest && this->visitExpression(*f.fTest)) ||
(f.fNext && this->visitExpression(*f.fNext)) || (f.fNext && this->visitExpression(*f.fNext)) ||
this->visitStatement(*f.fStatement); } this->visitStatement(*f.fStatement); }
case Statement::kIf_Kind: { case Statement::Kind::kIf: {
const IfStatement& i = s.as<IfStatement>(); const IfStatement& i = s.as<IfStatement>();
return this->visitExpression(*i.fTest) || return this->visitExpression(*i.fTest) ||
this->visitStatement(*i.fIfTrue) || this->visitStatement(*i.fIfTrue) ||
(i.fIfFalse && this->visitStatement(*i.fIfFalse)); } (i.fIfFalse && this->visitStatement(*i.fIfFalse)); }
case Statement::kReturn_Kind: { case Statement::Kind::kReturn: {
const ReturnStatement& r = s.as<ReturnStatement>(); const ReturnStatement& r = s.as<ReturnStatement>();
return r.fExpression && this->visitExpression(*r.fExpression); } return r.fExpression && this->visitExpression(*r.fExpression); }
case Statement::kSwitch_Kind: { case Statement::Kind::kSwitch: {
const SwitchStatement& sw = s.as<SwitchStatement>(); const SwitchStatement& sw = s.as<SwitchStatement>();
if (this->visitExpression(*sw.fValue)) { return true; } if (this->visitExpression(*sw.fValue)) { return true; }
for (const auto& c : sw.fCases) { for (const auto& c : sw.fCases) {
@ -345,15 +345,15 @@ bool ProgramVisitor::visitStatement(const Statement& s) {
} }
} }
return false; } return false; }
case Statement::kVarDeclaration_Kind: { case Statement::Kind::kVarDeclaration: {
const VarDeclaration& v = s.as<VarDeclaration>(); const VarDeclaration& v = s.as<VarDeclaration>();
for (const std::unique_ptr<Expression>& sizeExpr : v.fSizes) { for (const std::unique_ptr<Expression>& sizeExpr : v.fSizes) {
if (sizeExpr && this->visitExpression(*sizeExpr)) { return true; } if (sizeExpr && this->visitExpression(*sizeExpr)) { return true; }
} }
return v.fValue && this->visitExpression(*v.fValue); } return v.fValue && this->visitExpression(*v.fValue); }
case Statement::kVarDeclarations_Kind: case Statement::Kind::kVarDeclarations:
return this->visitProgramElement(*s.as<VarDeclarationsStatement>().fDeclaration); return this->visitProgramElement(*s.as<VarDeclarationsStatement>().fDeclaration);
case Statement::kWhile_Kind: { case Statement::Kind::kWhile: {
const WhileStatement& w = s.as<WhileStatement>(); const WhileStatement& w = s.as<WhileStatement>();
return this->visitExpression(*w.fTest) || this->visitStatement(*w.fStatement); } return this->visitExpression(*w.fTest) || this->visitStatement(*w.fStatement); }
default: default:
@ -362,21 +362,21 @@ bool ProgramVisitor::visitStatement(const Statement& s) {
} }
bool ProgramVisitor::visitProgramElement(const ProgramElement& pe) { bool ProgramVisitor::visitProgramElement(const ProgramElement& pe) {
switch(pe.fKind) { switch(pe.kind()) {
case ProgramElement::kEnum_Kind: case ProgramElement::Kind::kEnum:
case ProgramElement::kExtension_Kind: case ProgramElement::Kind::kExtension:
case ProgramElement::kModifiers_Kind: case ProgramElement::Kind::kModifiers:
case ProgramElement::kSection_Kind: case ProgramElement::Kind::kSection:
// Leaf program elements just return false by default // Leaf program elements just return false by default
return false; return false;
case ProgramElement::kFunction_Kind: case ProgramElement::Kind::kFunction:
return this->visitStatement(*pe.as<FunctionDefinition>().fBody); return this->visitStatement(*pe.as<FunctionDefinition>().fBody);
case ProgramElement::kInterfaceBlock_Kind: case ProgramElement::Kind::kInterfaceBlock:
for (const auto& e : pe.as<InterfaceBlock>().fSizes) { for (const auto& e : pe.as<InterfaceBlock>().fSizes) {
if (this->visitExpression(*e)) { return true; } if (this->visitExpression(*e)) { return true; }
} }
return false; return false;
case ProgramElement::kVar_Kind: case ProgramElement::Kind::kVar:
for (const auto& v : pe.as<VarDeclarations>().fVars) { for (const auto& v : pe.as<VarDeclarations>().fVars) {
if (this->visitStatement(*v)) { return true; } if (this->visitStatement(*v)) { return true; }
} }

View File

@ -12,9 +12,9 @@
namespace SkSL { namespace SkSL {
static TypeCategory type_category(const Type& type) { static TypeCategory type_category(const Type& type) {
switch (type.kind()) { switch (type.typeKind()) {
case Type::Kind::kVector_Kind: case Type::TypeKind::kVector:
case Type::Kind::kMatrix_Kind: case Type::TypeKind::kMatrix:
return type_category(type.componentType()); return type_category(type.componentType());
default: default:
if (type.fName == "bool") { if (type.fName == "bool") {
@ -92,23 +92,26 @@ ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* prog
int ByteCodeGenerator::SlotCount(const Type& type) { int ByteCodeGenerator::SlotCount(const Type& type) {
if (type.kind() == Type::kOther_Kind) { switch (type.typeKind()) {
return 0; case Type::TypeKind::kOther:
} else if (type.kind() == Type::kStruct_Kind) { return 0;
int slots = 0; case Type::TypeKind::kStruct: {
for (const auto& f : type.fields()) { int slots = 0;
slots += SlotCount(*f.fType); for (const auto& f : type.fields()) {
slots += SlotCount(*f.fType);
}
SkASSERT(slots <= 255);
return slots;
} }
SkASSERT(slots <= 255); case Type::TypeKind::kArray: {
return slots; int columns = type.columns();
} else if (type.kind() == Type::kArray_Kind) { SkASSERT(columns >= 0);
int columns = type.columns(); int slots = columns * SlotCount(type.componentType());
SkASSERT(columns >= 0); SkASSERT(slots <= 255);
int slots = columns * SlotCount(type.componentType()); return slots;
SkASSERT(slots <= 255); }
return slots; default:
} else { return type.columns() * type.rows();
return type.columns() * type.rows();
} }
} }
@ -121,27 +124,31 @@ static inline bool is_in(const SkSL::Variable& var) {
} }
void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) { void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
if (type.kind() == Type::kOther_Kind) { switch (type.typeKind()) {
return; case Type::TypeKind::kOther:
} else if (type.kind() == Type::kStruct_Kind) { break;
for (const auto& f : type.fields()) { case Type::TypeKind::kStruct:
this->gatherUniforms(*f.fType, name + "." + f.fName); for (const auto& f : type.fields()) {
} this->gatherUniforms(*f.fType, name + "." + f.fName);
} else if (type.kind() == Type::kArray_Kind) { }
for (int i = 0; i < type.columns(); ++i) { break;
this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(), i)); case Type::TypeKind::kArray:
} for (int i = 0; i < type.columns(); ++i) {
} else { this->gatherUniforms(type.componentType(), String::printf("%s[%d]", name.c_str(),
fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(), i));
fOutput->fUniformSlotCount }); }
fOutput->fUniformSlotCount += type.columns() * type.rows(); break;
default:
fOutput->fUniforms.push_back({ name, type_category(type), type.rows(), type.columns(),
fOutput->fUniformSlotCount });
fOutput->fUniformSlotCount += type.columns() * type.rows();
} }
} }
bool ByteCodeGenerator::generateCode() { bool ByteCodeGenerator::generateCode() {
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
switch (e.fKind) { switch (e.kind()) {
case ProgramElement::kFunction_Kind: { case ProgramElement::Kind::kFunction: {
std::unique_ptr<ByteCodeFunction> f = std::unique_ptr<ByteCodeFunction> f =
this->writeFunction(e.as<FunctionDefinition>()); this->writeFunction(e.as<FunctionDefinition>());
if (!f) { if (!f) {
@ -151,7 +158,7 @@ bool ByteCodeGenerator::generateCode() {
fFunctions.push_back(&e.as<FunctionDefinition>()); fFunctions.push_back(&e.as<FunctionDefinition>());
break; break;
} }
case ProgramElement::kVar_Kind: { case ProgramElement::Kind::kVar: {
const VarDeclarations& decl = e.as<VarDeclarations>(); const VarDeclarations& decl = e.as<VarDeclarations>();
for (const auto& v : decl.fVars) { for (const auto& v : decl.fVars) {
const Variable* declVar = v->as<VarDeclaration>().fVar; const Variable* declVar = v->as<VarDeclaration>().fVar;
@ -210,7 +217,7 @@ std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const Functio
// If the expression is a reference to a builtin global variable, return the builtin ID. // If the expression is a reference to a builtin global variable, return the builtin ID.
// Otherwise, return -1. // Otherwise, return -1.
static int expression_as_builtin(const Expression& e) { static int expression_as_builtin(const Expression& e) {
if (e.fKind == Expression::kVariableReference_Kind) { if (e.kind() == Expression::Kind::kVariableReference) {
const Variable& var(e.as<VariableReference>().fVariable); const Variable& var(e.as<VariableReference>().fVariable);
if (var.fStorage == Variable::kGlobal_Storage) { if (var.fStorage == Variable::kGlobal_Storage) {
return var.fModifiers.fLayout.fBuiltin; return var.fModifiers.fLayout.fBuiltin;
@ -228,10 +235,10 @@ static bool swizzle_is_simple(const Swizzle& s) {
return false; return false;
} }
switch (s.fBase->fKind) { switch (s.fBase->kind()) {
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
break; break;
default: default:
return false; return false;
@ -449,7 +456,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
if (var.fType == *fContext.fFragmentProcessor_Type) { if (var.fType == *fContext.fFragmentProcessor_Type) {
int offset = 0; int offset = 0;
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (e.fKind == ProgramElement::kVar_Kind) { if (e.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decl = e.as<VarDeclarations>(); const VarDeclarations& decl = e.as<VarDeclarations>();
for (const auto& v : decl.fVars) { for (const auto& v : decl.fVars) {
const Variable* declVar = v->as<VarDeclaration>().fVar; const Variable* declVar = v->as<VarDeclaration>().fVar;
@ -479,7 +486,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
int offset = 0; int offset = 0;
bool isUniform = is_uniform(var); bool isUniform = is_uniform(var);
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (e.fKind == ProgramElement::kVar_Kind) { if (e.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decl = e.as<VarDeclarations>(); const VarDeclarations& decl = e.as<VarDeclarations>();
for (const auto& v : decl.fVars) { for (const auto& v : decl.fVars) {
const Variable* declVar = v->as<VarDeclaration>().fVar; const Variable* declVar = v->as<VarDeclaration>().fVar;
@ -507,8 +514,8 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
} }
ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) { ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& expr) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kFieldAccess_Kind: { case Expression::Kind::kFieldAccess: {
const FieldAccess& f = expr.as<FieldAccess>(); const FieldAccess& f = expr.as<FieldAccess>();
Location baseLoc = this->getLocation(*f.fBase); Location baseLoc = this->getLocation(*f.fBase);
int offset = 0; int offset = 0;
@ -526,7 +533,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& exp
return baseLoc + offset; return baseLoc + offset;
} }
} }
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
const IndexExpression& i = expr.as<IndexExpression>(); const IndexExpression& i = expr.as<IndexExpression>();
int stride = SlotCount(i.fType); int stride = SlotCount(i.fType);
int length = i.fBase->fType.columns(); int length = i.fBase->fType.columns();
@ -582,7 +589,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& exp
this->write(ByteCodeInstruction::kAddI, 1); this->write(ByteCodeInstruction::kAddI, 1);
return baseLoc.makeOnStack(); return baseLoc.makeOnStack();
} }
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
const Swizzle& s = expr.as<Swizzle>(); const Swizzle& s = expr.as<Swizzle>();
SkASSERT(swizzle_is_simple(s)); SkASSERT(swizzle_is_simple(s));
Location baseLoc = this->getLocation(*s.fBase); Location baseLoc = this->getLocation(*s.fBase);
@ -598,7 +605,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Expression& exp
return baseLoc + offset; return baseLoc + offset;
} }
} }
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const Variable& var = expr.as<VariableReference>().fVariable; const Variable& var = expr.as<VariableReference>().fVariable;
return this->getLocation(var); return this->getLocation(var);
} }
@ -683,8 +690,10 @@ bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool di
} }
const Type& lType = b.fLeft->fType; const Type& lType = b.fLeft->fType;
const Type& rType = b.fRight->fType; const Type& rType = b.fRight->fType;
bool lVecOrMtx = (lType.kind() == Type::kVector_Kind || lType.kind() == Type::kMatrix_Kind); bool lVecOrMtx = (lType.typeKind() == Type::TypeKind::kVector ||
bool rVecOrMtx = (rType.kind() == Type::kVector_Kind || rType.kind() == Type::kMatrix_Kind); lType.typeKind() == Type::TypeKind::kMatrix);
bool rVecOrMtx = (rType.typeKind() == Type::TypeKind::kVector ||
rType.typeKind() == Type::TypeKind::kMatrix);
Token::Kind op; Token::Kind op;
std::unique_ptr<LValue> lvalue; std::unique_ptr<LValue> lvalue;
if (is_assignment(b.fOperator)) { if (is_assignment(b.fOperator)) {
@ -764,7 +773,8 @@ bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool di
} }
// Special case for M*V, V*M, M*M (but not V*V!) // Special case for M*V, V*M, M*M (but not V*V!)
if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx && if (op == Token::Kind::TK_STAR && lVecOrMtx && rVecOrMtx &&
!(lType.kind() == Type::kVector_Kind && rType.kind() == Type::kVector_Kind)) { !(lType.typeKind() == Type::TypeKind::kVector &&
rType.typeKind() == Type::TypeKind::kVector)) {
this->write(ByteCodeInstruction::kMatrixMultiply, this->write(ByteCodeInstruction::kMatrixMultiply,
SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType))); SlotCount(b.fType) - (SlotCount(lType) + SlotCount(rType)));
int rCols = rType.columns(), int rCols = rType.columns(),
@ -772,7 +782,7 @@ bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool di
lCols = lType.columns(), lCols = lType.columns(),
lRows = lType.rows(); lRows = lType.rows();
// M*V treats the vector as a column // M*V treats the vector as a column
if (rType.kind() == Type::kVector_Kind) { if (rType.typeKind() == Type::TypeKind::kVector) {
std::swap(rCols, rRows); std::swap(rCols, rRows);
} }
SkASSERT(lCols == rRows); SkASSERT(lCols == rRows);
@ -921,7 +931,8 @@ void ByteCodeGenerator::writeConstructor(const Constructor& c) {
SkASSERT(false); SkASSERT(false);
} }
} }
if (inType.kind() == Type::kMatrix_Kind && outType.kind() == Type::kMatrix_Kind) { if (inType.typeKind() == Type::TypeKind::kMatrix &&
outType.typeKind() == Type::TypeKind::kMatrix) {
this->write(ByteCodeInstruction::kMatrixToMatrix, this->write(ByteCodeInstruction::kMatrixToMatrix,
SlotCount(outType) - SlotCount(inType)); SlotCount(outType) - SlotCount(inType));
this->write8(inType.columns()); this->write8(inType.columns());
@ -930,12 +941,12 @@ void ByteCodeGenerator::writeConstructor(const Constructor& c) {
this->write8(outType.rows()); this->write8(outType.rows());
} else if (inCount != outCount) { } else if (inCount != outCount) {
SkASSERT(inCount == 1); SkASSERT(inCount == 1);
if (outType.kind() == Type::kMatrix_Kind) { if (outType.typeKind() == Type::TypeKind::kMatrix) {
this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1); this->write(ByteCodeInstruction::kScalarToMatrix, SlotCount(outType) - 1);
this->write8(outType.columns()); this->write8(outType.columns());
this->write8(outType.rows()); this->write8(outType.rows());
} else { } else {
SkASSERT(outType.kind() == Type::kVector_Kind); SkASSERT(outType.typeKind() == Type::TypeKind::kVector);
for (; inCount != outCount; ++inCount) { for (; inCount != outCount; ++inCount) {
this->write(ByteCodeInstruction::kDup, 1); this->write(ByteCodeInstruction::kDup, 1);
} }
@ -1430,49 +1441,49 @@ void ByteCodeGenerator::writeTernaryExpression(const TernaryExpression& t) {
} }
void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) { void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
switch (e.fKind) { switch (e.kind()) {
case Expression::kBinary_Kind: case Expression::Kind::kBinary:
discard = this->writeBinaryExpression(e.as<BinaryExpression>(), discard); discard = this->writeBinaryExpression(e.as<BinaryExpression>(), discard);
break; break;
case Expression::kBoolLiteral_Kind: case Expression::Kind::kBoolLiteral:
this->writeBoolLiteral(e.as<BoolLiteral>()); this->writeBoolLiteral(e.as<BoolLiteral>());
break; break;
case Expression::kConstructor_Kind: case Expression::Kind::kConstructor:
this->writeConstructor(e.as<Constructor>()); this->writeConstructor(e.as<Constructor>());
break; break;
case Expression::kExternalFunctionCall_Kind: case Expression::Kind::kExternalFunctionCall:
this->writeExternalFunctionCall(e.as<ExternalFunctionCall>()); this->writeExternalFunctionCall(e.as<ExternalFunctionCall>());
break; break;
case Expression::kExternalValue_Kind: case Expression::Kind::kExternalValue:
this->writeExternalValue(e.as<ExternalValueReference>()); this->writeExternalValue(e.as<ExternalValueReference>());
break; break;
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
this->writeVariableExpression(e); this->writeVariableExpression(e);
break; break;
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
this->writeFloatLiteral(e.as<FloatLiteral>()); this->writeFloatLiteral(e.as<FloatLiteral>());
break; break;
case Expression::kFunctionCall_Kind: case Expression::Kind::kFunctionCall:
this->writeFunctionCall(e.as<FunctionCall>()); this->writeFunctionCall(e.as<FunctionCall>());
break; break;
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
this->writeIntLiteral(e.as<IntLiteral>()); this->writeIntLiteral(e.as<IntLiteral>());
break; break;
case Expression::kNullLiteral_Kind: case Expression::Kind::kNullLiteral:
this->writeNullLiteral(e.as<NullLiteral>()); this->writeNullLiteral(e.as<NullLiteral>());
break; break;
case Expression::kPrefix_Kind: case Expression::Kind::kPrefix:
discard = this->writePrefixExpression(e.as<PrefixExpression>(), discard); discard = this->writePrefixExpression(e.as<PrefixExpression>(), discard);
break; break;
case Expression::kPostfix_Kind: case Expression::Kind::kPostfix:
discard = this->writePostfixExpression(e.as<PostfixExpression>(), discard); discard = this->writePostfixExpression(e.as<PostfixExpression>(), discard);
break; break;
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
this->writeSwizzle(e.as<Swizzle>()); this->writeSwizzle(e.as<Swizzle>());
break; break;
case Expression::kTernary_Kind: case Expression::Kind::kTernary:
this->writeTernaryExpression(e.as<TernaryExpression>()); this->writeTernaryExpression(e.as<TernaryExpression>());
break; break;
default: default:
@ -1601,25 +1612,25 @@ private:
}; };
std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) { std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
switch (e.fKind) { switch (e.kind()) {
case Expression::kExternalValue_Kind: { case Expression::Kind::kExternalValue: {
const ExternalValue* value = e.as<ExternalValueReference>().fValue; const ExternalValue* value = e.as<ExternalValueReference>().fValue;
int index = fOutput->fExternalValues.size(); int index = fOutput->fExternalValues.size();
fOutput->fExternalValues.push_back(value); fOutput->fExternalValues.push_back(value);
SkASSERT(index <= 255); SkASSERT(index <= 255);
return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index)); return std::unique_ptr<LValue>(new ByteCodeExternalValueLValue(this, *value, index));
} }
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e)); return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
const Swizzle& s = e.as<Swizzle>(); const Swizzle& s = e.as<Swizzle>();
return swizzle_is_simple(s) return swizzle_is_simple(s)
? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e)) ? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
: std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s)); : std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));
} }
case Expression::kTernary_Kind: case Expression::Kind::kTernary:
default: default:
#ifdef SK_DEBUG #ifdef SK_DEBUG
ABORT("unsupported lvalue %s\n", e.description().c_str()); ABORT("unsupported lvalue %s\n", e.description().c_str());
@ -1769,43 +1780,43 @@ void ByteCodeGenerator::writeWhileStatement(const WhileStatement& w) {
} }
void ByteCodeGenerator::writeStatement(const Statement& s) { void ByteCodeGenerator::writeStatement(const Statement& s) {
switch (s.fKind) { switch (s.kind()) {
case Statement::kBlock_Kind: case Statement::Kind::kBlock:
this->writeBlock(s.as<Block>()); this->writeBlock(s.as<Block>());
break; break;
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
this->writeBreakStatement(s.as<BreakStatement>()); this->writeBreakStatement(s.as<BreakStatement>());
break; break;
case Statement::kContinue_Kind: case Statement::Kind::kContinue:
this->writeContinueStatement(s.as<ContinueStatement>()); this->writeContinueStatement(s.as<ContinueStatement>());
break; break;
case Statement::kDiscard_Kind: case Statement::Kind::kDiscard:
// not yet implemented // not yet implemented
abort(); abort();
case Statement::kDo_Kind: case Statement::Kind::kDo:
this->writeDoStatement(s.as<DoStatement>()); this->writeDoStatement(s.as<DoStatement>());
break; break;
case Statement::kExpression_Kind: case Statement::Kind::kExpression:
this->writeExpression(*s.as<ExpressionStatement>().fExpression, true); this->writeExpression(*s.as<ExpressionStatement>().fExpression, true);
break; break;
case Statement::kFor_Kind: case Statement::Kind::kFor:
this->writeForStatement(s.as<ForStatement>()); this->writeForStatement(s.as<ForStatement>());
break; break;
case Statement::kIf_Kind: case Statement::Kind::kIf:
this->writeIfStatement(s.as<IfStatement>()); this->writeIfStatement(s.as<IfStatement>());
break; break;
case Statement::kNop_Kind: case Statement::Kind::kNop:
break; break;
case Statement::kReturn_Kind: case Statement::Kind::kReturn:
this->writeReturnStatement(s.as<ReturnStatement>()); this->writeReturnStatement(s.as<ReturnStatement>());
break; break;
case Statement::kSwitch_Kind: case Statement::Kind::kSwitch:
this->writeSwitchStatement(s.as<SwitchStatement>()); this->writeSwitchStatement(s.as<SwitchStatement>());
break; break;
case Statement::kVarDeclarations_Kind: case Statement::Kind::kVarDeclarations:
this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration); this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration);
break; break;
case Statement::kWhile_Kind: case Statement::Kind::kWhile:
this->writeWhileStatement(s.as<WhileStatement>()); this->writeWhileStatement(s.as<WhileStatement>());
break; break;
default: default:

View File

@ -87,7 +87,7 @@ void CFG::dump() {
bool BasicBlock::tryRemoveExpressionBefore(std::vector<BasicBlock::Node>::iterator* iter, bool BasicBlock::tryRemoveExpressionBefore(std::vector<BasicBlock::Node>::iterator* iter,
Expression* e) { Expression* e) {
if (e->fKind == Expression::kTernary_Kind) { if (e->kind() == Expression::Kind::kTernary) {
return false; return false;
} }
bool result; bool result;
@ -128,22 +128,22 @@ bool BasicBlock::tryRemoveExpressionBefore(std::vector<BasicBlock::Node>::iterat
bool BasicBlock::tryRemoveLValueBefore(std::vector<BasicBlock::Node>::iterator* iter, bool BasicBlock::tryRemoveLValueBefore(std::vector<BasicBlock::Node>::iterator* iter,
Expression* lvalue) { Expression* lvalue) {
switch (lvalue->fKind) { switch (lvalue->kind()) {
case Expression::kExternalValue_Kind: // fall through case Expression::Kind::kExternalValue: // fall through
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
return true; return true;
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
return this->tryRemoveLValueBefore(iter, lvalue->as<Swizzle>().fBase.get()); return this->tryRemoveLValueBefore(iter, lvalue->as<Swizzle>().fBase.get());
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
return this->tryRemoveLValueBefore(iter, lvalue->as<FieldAccess>().fBase.get()); return this->tryRemoveLValueBefore(iter, lvalue->as<FieldAccess>().fBase.get());
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
IndexExpression& indexExpr = lvalue->as<IndexExpression>(); IndexExpression& indexExpr = lvalue->as<IndexExpression>();
if (!this->tryRemoveLValueBefore(iter, indexExpr.fBase.get())) { if (!this->tryRemoveLValueBefore(iter, indexExpr.fBase.get())) {
return false; return false;
} }
return this->tryRemoveExpressionBefore(iter, indexExpr.fIndex.get()); return this->tryRemoveExpressionBefore(iter, indexExpr.fIndex.get());
} }
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
TernaryExpression& ternary = lvalue->as<TernaryExpression>(); TernaryExpression& ternary = lvalue->as<TernaryExpression>();
if (!this->tryRemoveExpressionBefore(iter, ternary.fTest.get())) { if (!this->tryRemoveExpressionBefore(iter, ternary.fTest.get())) {
return false; return false;
@ -163,8 +163,8 @@ bool BasicBlock::tryRemoveLValueBefore(std::vector<BasicBlock::Node>::iterator*
bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* iter) { bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* iter) {
Expression* expr = (*iter)->expression()->get(); Expression* expr = (*iter)->expression()->get();
switch (expr->fKind) { switch (expr->kind()) {
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
BinaryExpression& b = expr->as<BinaryExpression>(); BinaryExpression& b = expr->as<BinaryExpression>();
if (b.fOperator == Token::Kind::TK_EQ) { if (b.fOperator == Token::Kind::TK_EQ) {
if (!this->tryRemoveLValueBefore(iter, b.fLeft.get())) { if (!this->tryRemoveLValueBefore(iter, b.fLeft.get())) {
@ -180,11 +180,11 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
} }
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
// ternaries cross basic block boundaries, must regenerate the CFG to remove it // ternaries cross basic block boundaries, must regenerate the CFG to remove it
return false; return false;
} }
case Expression::kFieldAccess_Kind: { case Expression::Kind::kFieldAccess: {
FieldAccess& f = expr->as<FieldAccess>(); FieldAccess& f = expr->as<FieldAccess>();
if (!this->tryRemoveExpressionBefore(iter, f.fBase.get())) { if (!this->tryRemoveExpressionBefore(iter, f.fBase.get())) {
return false; return false;
@ -192,7 +192,7 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
} }
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
Swizzle& s = expr->as<Swizzle>(); Swizzle& s = expr->as<Swizzle>();
if (s.fBase && !this->tryRemoveExpressionBefore(iter, s.fBase.get())) { if (s.fBase && !this->tryRemoveExpressionBefore(iter, s.fBase.get())) {
return false; return false;
@ -200,7 +200,7 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
} }
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
IndexExpression& idx = expr->as<IndexExpression>(); IndexExpression& idx = expr->as<IndexExpression>();
if (!this->tryRemoveExpressionBefore(iter, idx.fBase.get())) { if (!this->tryRemoveExpressionBefore(iter, idx.fBase.get())) {
return false; return false;
@ -211,7 +211,7 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
} }
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
Constructor& c = expr->as<Constructor>(); Constructor& c = expr->as<Constructor>();
for (auto& arg : c.fArguments) { for (auto& arg : c.fArguments) {
if (!this->tryRemoveExpressionBefore(iter, arg.get())) { if (!this->tryRemoveExpressionBefore(iter, arg.get())) {
@ -222,7 +222,7 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
} }
case Expression::kFunctionCall_Kind: { case Expression::Kind::kFunctionCall: {
FunctionCall& f = expr->as<FunctionCall>(); FunctionCall& f = expr->as<FunctionCall>();
for (auto& arg : f.fArguments) { for (auto& arg : f.fArguments) {
if (!this->tryRemoveExpressionBefore(iter, arg.get())) { if (!this->tryRemoveExpressionBefore(iter, arg.get())) {
@ -233,25 +233,25 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
} }
case Expression::kPrefix_Kind: case Expression::Kind::kPrefix:
if (!this->tryRemoveExpressionBefore(iter, if (!this->tryRemoveExpressionBefore(iter,
expr->as<PrefixExpression>().fOperand.get())) { expr->as<PrefixExpression>().fOperand.get())) {
return false; return false;
} }
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
case Expression::kPostfix_Kind: case Expression::Kind::kPostfix:
if (!this->tryRemoveExpressionBefore(iter, if (!this->tryRemoveExpressionBefore(iter,
expr->as<PrefixExpression>().fOperand.get())) { expr->as<PrefixExpression>().fOperand.get())) {
return false; return false;
} }
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
case Expression::kBoolLiteral_Kind: // fall through case Expression::Kind::kBoolLiteral: // fall through
case Expression::kFloatLiteral_Kind: // fall through case Expression::Kind::kFloatLiteral: // fall through
case Expression::kIntLiteral_Kind: // fall through case Expression::Kind::kIntLiteral: // fall through
case Expression::kSetting_Kind: // fall through case Expression::Kind::kSetting: // fall through
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
*iter = fNodes.erase(*iter); *iter = fNodes.erase(*iter);
return true; return true;
default: default:
@ -264,8 +264,8 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
bool BasicBlock::tryInsertExpression(std::vector<BasicBlock::Node>::iterator* iter, bool BasicBlock::tryInsertExpression(std::vector<BasicBlock::Node>::iterator* iter,
std::unique_ptr<Expression>* expr) { std::unique_ptr<Expression>* expr) {
switch ((*expr)->fKind) { switch ((*expr)->kind()) {
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
BinaryExpression& b = expr->get()->as<BinaryExpression>(); BinaryExpression& b = expr->get()->as<BinaryExpression>();
if (!this->tryInsertExpression(iter, &b.fRight)) { if (!this->tryInsertExpression(iter, &b.fRight)) {
return false; return false;
@ -279,15 +279,15 @@ bool BasicBlock::tryInsertExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.insert(*iter, node); *iter = fNodes.insert(*iter, node);
return true; return true;
} }
case Expression::kBoolLiteral_Kind: // fall through case Expression::Kind::kBoolLiteral: // fall through
case Expression::kFloatLiteral_Kind: // fall through case Expression::Kind::kFloatLiteral: // fall through
case Expression::kIntLiteral_Kind: // fall through case Expression::Kind::kIntLiteral: // fall through
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
BasicBlock::Node node = { BasicBlock::Node::kExpression_Kind, true, expr, nullptr }; BasicBlock::Node node = { BasicBlock::Node::kExpression_Kind, true, expr, nullptr };
*iter = fNodes.insert(*iter, node); *iter = fNodes.insert(*iter, node);
return true; return true;
} }
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
Constructor& c = expr->get()->as<Constructor>(); Constructor& c = expr->get()->as<Constructor>();
for (auto& arg : c.fArguments) { for (auto& arg : c.fArguments) {
if (!this->tryInsertExpression(iter, &arg)) { if (!this->tryInsertExpression(iter, &arg)) {
@ -299,7 +299,7 @@ bool BasicBlock::tryInsertExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.insert(*iter, node); *iter = fNodes.insert(*iter, node);
return true; return true;
} }
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
Swizzle& s = expr->get()->as<Swizzle>(); Swizzle& s = expr->get()->as<Swizzle>();
if (!this->tryInsertExpression(iter, &s.fBase)) { if (!this->tryInsertExpression(iter, &s.fBase)) {
return false; return false;
@ -316,8 +316,8 @@ bool BasicBlock::tryInsertExpression(std::vector<BasicBlock::Node>::iterator* it
void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool constantPropagate) { void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool constantPropagate) {
SkASSERT(e); SkASSERT(e);
switch ((*e)->fKind) { switch ((*e)->kind()) {
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
BinaryExpression& b = e->get()->as<BinaryExpression>(); BinaryExpression& b = e->get()->as<BinaryExpression>();
switch (b.fOperator) { switch (b.fOperator) {
case Token::Kind::TK_LOGICALAND: // fall through case Token::Kind::TK_LOGICALAND: // fall through
@ -362,7 +362,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
} }
break; break;
} }
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
Constructor& c = e->get()->as<Constructor>(); Constructor& c = e->get()->as<Constructor>();
for (auto& arg : c.fArguments) { for (auto& arg : c.fArguments) {
this->addExpression(cfg, &arg, constantPropagate); this->addExpression(cfg, &arg, constantPropagate);
@ -371,7 +371,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
} }
case Expression::kExternalFunctionCall_Kind: { case Expression::Kind::kExternalFunctionCall: {
ExternalFunctionCall& c = e->get()->as<ExternalFunctionCall>(); ExternalFunctionCall& c = e->get()->as<ExternalFunctionCall>();
for (auto& arg : c.fArguments) { for (auto& arg : c.fArguments) {
this->addExpression(cfg, &arg, constantPropagate); this->addExpression(cfg, &arg, constantPropagate);
@ -380,7 +380,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
} }
case Expression::kFunctionCall_Kind: { case Expression::Kind::kFunctionCall: {
FunctionCall& c = e->get()->as<FunctionCall>(); FunctionCall& c = e->get()->as<FunctionCall>();
for (auto& arg : c.fArguments) { for (auto& arg : c.fArguments) {
this->addExpression(cfg, &arg, constantPropagate); this->addExpression(cfg, &arg, constantPropagate);
@ -389,12 +389,13 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
} }
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess: {
this->addExpression(cfg, &e->get()->as<FieldAccess>().fBase, constantPropagate); this->addExpression(cfg, &e->get()->as<FieldAccess>().fBase, constantPropagate);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
case Expression::kIndex_Kind: { }
case Expression::Kind::kIndex: {
IndexExpression& indexExpr = e->get()->as<IndexExpression>(); IndexExpression& indexExpr = e->get()->as<IndexExpression>();
this->addExpression(cfg, &indexExpr.fBase, constantPropagate); this->addExpression(cfg, &indexExpr.fBase, constantPropagate);
@ -403,7 +404,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
} }
case Expression::kPrefix_Kind: { case Expression::Kind::kPrefix: {
PrefixExpression& p = e->get()->as<PrefixExpression>(); PrefixExpression& p = e->get()->as<PrefixExpression>();
this->addExpression(cfg, &p.fOperand, constantPropagate && this->addExpression(cfg, &p.fOperand, constantPropagate &&
p.fOperator != Token::Kind::TK_PLUSPLUS && p.fOperator != Token::Kind::TK_PLUSPLUS &&
@ -412,27 +413,27 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
} }
case Expression::kPostfix_Kind: case Expression::Kind::kPostfix:
this->addExpression(cfg, &e->get()->as<PostfixExpression>().fOperand, false); this->addExpression(cfg, &e->get()->as<PostfixExpression>().fOperand, false);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
this->addExpression(cfg, &e->get()->as<Swizzle>().fBase, constantPropagate); this->addExpression(cfg, &e->get()->as<Swizzle>().fBase, constantPropagate);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
case Expression::kBoolLiteral_Kind: // fall through case Expression::Kind::kBoolLiteral: // fall through
case Expression::kExternalValue_Kind: // fall through case Expression::Kind::kExternalValue: // fall through
case Expression::kFloatLiteral_Kind: // fall through case Expression::Kind::kFloatLiteral: // fall through
case Expression::kIntLiteral_Kind: // fall through case Expression::Kind::kIntLiteral: // fall through
case Expression::kNullLiteral_Kind: // fall through case Expression::Kind::kNullLiteral: // fall through
case Expression::kSetting_Kind: // fall through case Expression::Kind::kSetting: // fall through
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
constantPropagate, e, nullptr }); constantPropagate, e, nullptr });
break; break;
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
TernaryExpression& t = e->get()->as<TernaryExpression>(); TernaryExpression& t = e->get()->as<TernaryExpression>();
this->addExpression(cfg, &t.fTest, constantPropagate); this->addExpression(cfg, &t.fTest, constantPropagate);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
@ -448,9 +449,9 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
cfg.fCurrent = next; cfg.fCurrent = next;
break; break;
} }
case Expression::kFunctionReference_Kind: // fall through case Expression::Kind::kFunctionReference: // fall through
case Expression::kTypeReference_Kind: // fall through case Expression::Kind::kTypeReference: // fall through
case Expression::kDefined_Kind: case Expression::Kind::kDefined:
SkASSERT(false); SkASSERT(false);
break; break;
} }
@ -458,23 +459,23 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
// adds expressions that are evaluated as part of resolving an lvalue // adds expressions that are evaluated as part of resolving an lvalue
void CFGGenerator::addLValue(CFG& cfg, std::unique_ptr<Expression>* e) { void CFGGenerator::addLValue(CFG& cfg, std::unique_ptr<Expression>* e) {
switch ((*e)->fKind) { switch ((*e)->kind()) {
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
this->addLValue(cfg, &e->get()->as<FieldAccess>().fBase); this->addLValue(cfg, &e->get()->as<FieldAccess>().fBase);
break; break;
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
IndexExpression& indexExpr = e->get()->as<IndexExpression>(); IndexExpression& indexExpr = e->get()->as<IndexExpression>();
this->addLValue(cfg, &indexExpr.fBase); this->addLValue(cfg, &indexExpr.fBase);
this->addExpression(cfg, &indexExpr.fIndex, /*constantPropagate=*/true); this->addExpression(cfg, &indexExpr.fIndex, /*constantPropagate=*/true);
break; break;
} }
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
this->addLValue(cfg, &e->get()->as<Swizzle>().fBase); this->addLValue(cfg, &e->get()->as<Swizzle>().fBase);
break; break;
case Expression::kExternalValue_Kind: // fall through case Expression::Kind::kExternalValue: // fall through
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
break; break;
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
TernaryExpression& ternary = e->get()->as<TernaryExpression>(); TernaryExpression& ternary = e->get()->as<TernaryExpression>();
this->addExpression(cfg, &ternary.fTest, /*constantPropagate=*/true); this->addExpression(cfg, &ternary.fTest, /*constantPropagate=*/true);
// Technically we will of course only evaluate one or the other, but if the test turns // Technically we will of course only evaluate one or the other, but if the test turns
@ -492,17 +493,17 @@ void CFGGenerator::addLValue(CFG& cfg, std::unique_ptr<Expression>* e) {
} }
static bool is_true(Expression& expr) { static bool is_true(Expression& expr) {
return expr.fKind == Expression::kBoolLiteral_Kind && expr.as<BoolLiteral>().fValue; return expr.kind() == Expression::Kind::kBoolLiteral && expr.as<BoolLiteral>().fValue;
} }
void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) { void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
switch ((*s)->fKind) { switch ((*s)->kind()) {
case Statement::kBlock_Kind: case Statement::Kind::kBlock:
for (auto& child : (*s)->as<Block>().fStatements) { for (auto& child : (*s)->as<Block>().fStatements) {
addStatement(cfg, &child); addStatement(cfg, &child);
} }
break; break;
case Statement::kIf_Kind: { case Statement::Kind::kIf: {
IfStatement& ifs = (*s)->as<IfStatement>(); IfStatement& ifs = (*s)->as<IfStatement>();
this->addExpression(cfg, &ifs.fTest, /*constantPropagate=*/true); this->addExpression(cfg, &ifs.fTest, /*constantPropagate=*/true);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
@ -522,17 +523,17 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
} }
break; break;
} }
case Statement::kExpression_Kind: { case Statement::Kind::kExpression: {
this->addExpression(cfg, &(*s)->as<ExpressionStatement>().fExpression, this->addExpression(cfg, &(*s)->as<ExpressionStatement>().fExpression,
/*constantPropagate=*/true); /*constantPropagate=*/true);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
nullptr, s }); nullptr, s });
break; break;
} }
case Statement::kVarDeclarations_Kind: { case Statement::Kind::kVarDeclarations: {
VarDeclarationsStatement& decls = (*s)->as<VarDeclarationsStatement>(); VarDeclarationsStatement& decls = (*s)->as<VarDeclarationsStatement>();
for (auto& stmt : decls.fDeclaration->fVars) { for (auto& stmt : decls.fDeclaration->fVars) {
if (stmt->fKind == Statement::kNop_Kind) { if (stmt->kind() == Statement::Kind::kNop) {
continue; continue;
} }
VarDeclaration& vd = stmt->as<VarDeclaration>(); VarDeclaration& vd = stmt->as<VarDeclaration>();
@ -546,12 +547,12 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
nullptr, s }); nullptr, s });
break; break;
} }
case Statement::kDiscard_Kind: case Statement::Kind::kDiscard:
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
nullptr, s }); nullptr, s });
cfg.fCurrent = cfg.newIsolatedBlock(); cfg.fCurrent = cfg.newIsolatedBlock();
break; break;
case Statement::kReturn_Kind: { case Statement::Kind::kReturn: {
ReturnStatement& r = (*s)->as<ReturnStatement>(); ReturnStatement& r = (*s)->as<ReturnStatement>();
if (r.fExpression) { if (r.fExpression) {
this->addExpression(cfg, &r.fExpression, /*constantPropagate=*/true); this->addExpression(cfg, &r.fExpression, /*constantPropagate=*/true);
@ -561,19 +562,19 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
cfg.fCurrent = cfg.newIsolatedBlock(); cfg.fCurrent = cfg.newIsolatedBlock();
break; break;
} }
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
nullptr, s }); nullptr, s });
cfg.addExit(cfg.fCurrent, fLoopExits.top()); cfg.addExit(cfg.fCurrent, fLoopExits.top());
cfg.fCurrent = cfg.newIsolatedBlock(); cfg.fCurrent = cfg.newIsolatedBlock();
break; break;
case Statement::kContinue_Kind: case Statement::Kind::kContinue:
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
nullptr, s }); nullptr, s });
cfg.addExit(cfg.fCurrent, fLoopContinues.top()); cfg.addExit(cfg.fCurrent, fLoopContinues.top());
cfg.fCurrent = cfg.newIsolatedBlock(); cfg.fCurrent = cfg.newIsolatedBlock();
break; break;
case Statement::kWhile_Kind: { case Statement::Kind::kWhile: {
WhileStatement& w = (*s)->as<WhileStatement>(); WhileStatement& w = (*s)->as<WhileStatement>();
BlockId loopStart = cfg.newBlock(); BlockId loopStart = cfg.newBlock();
fLoopContinues.push(loopStart); fLoopContinues.push(loopStart);
@ -592,7 +593,7 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
cfg.fCurrent = loopExit; cfg.fCurrent = loopExit;
break; break;
} }
case Statement::kDo_Kind: { case Statement::Kind::kDo: {
DoStatement& d = (*s)->as<DoStatement>(); DoStatement& d = (*s)->as<DoStatement>();
BlockId loopStart = cfg.newBlock(); BlockId loopStart = cfg.newBlock();
fLoopContinues.push(loopStart); fLoopContinues.push(loopStart);
@ -607,7 +608,7 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
cfg.fCurrent = loopExit; cfg.fCurrent = loopExit;
break; break;
} }
case Statement::kFor_Kind: { case Statement::Kind::kFor: {
ForStatement& f = (*s)->as<ForStatement>(); ForStatement& f = (*s)->as<ForStatement>();
if (f.fInitializer) { if (f.fInitializer) {
this->addStatement(cfg, &f.fInitializer); this->addStatement(cfg, &f.fInitializer);
@ -641,7 +642,7 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
cfg.fCurrent = loopExit; cfg.fCurrent = loopExit;
break; break;
} }
case Statement::kSwitch_Kind: { case Statement::Kind::kSwitch: {
SwitchStatement& ss = (*s)->as<SwitchStatement>(); SwitchStatement& ss = (*s)->as<SwitchStatement>();
this->addExpression(cfg, &ss.fValue, /*constantPropagate=*/true); this->addExpression(cfg, &ss.fValue, /*constantPropagate=*/true);
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false, cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kStatement_Kind, false,
@ -671,7 +672,7 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
cfg.fCurrent = switchExit; cfg.fCurrent = switchExit;
break; break;
} }
case Statement::kNop_Kind: case Statement::Kind::kNop:
break; break;
default: default:
#ifdef SK_DEBUG #ifdef SK_DEBUG

View File

@ -21,7 +21,7 @@ namespace SkSL {
static bool needs_uniform_var(const Variable& var) { static bool needs_uniform_var(const Variable& var) {
return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) && return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
var.fType.kind() != Type::kSampler_Kind; var.fType.typeKind() != Type::TypeKind::kSampler;
} }
CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program, CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
@ -82,15 +82,15 @@ void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
if (precedence >= parentPrecedence) { if (precedence >= parentPrecedence) {
this->write(")"); this->write(")");
} }
} else if (b.fLeft->fKind == Expression::kNullLiteral_Kind || } else if (b.fLeft->kind() == Expression::Kind::kNullLiteral ||
b.fRight->fKind == Expression::kNullLiteral_Kind) { b.fRight->kind() == Expression::Kind::kNullLiteral) {
const Variable* var; const Variable* var;
if (b.fLeft->fKind != Expression::kNullLiteral_Kind) { if (b.fLeft->kind() != Expression::Kind::kNullLiteral) {
var = &b.fLeft->as<VariableReference>().fVariable; var = &b.fLeft->as<VariableReference>().fVariable;
} else { } else {
var = &b.fRight->as<VariableReference>().fVariable; var = &b.fRight->as<VariableReference>().fVariable;
} }
SkASSERT(var->fType.kind() == Type::kNullable_Kind && SkASSERT(var->fType.typeKind() == Type::TypeKind::kNullable &&
var->fType.componentType() == *fContext.fFragmentProcessor_Type); var->fType.componentType() == *fContext.fFragmentProcessor_Type);
this->write("%s"); this->write("%s");
const char* op = ""; const char* op = "";
@ -116,10 +116,10 @@ static String default_value(const Type& type) {
if (type.fName == "bool") { if (type.fName == "bool") {
return "false"; return "false";
} }
switch (type.kind()) { switch (type.typeKind()) {
case Type::kScalar_Kind: return "0"; case Type::TypeKind::kScalar: return "0";
case Type::kVector_Kind: return type.name() + "(0)"; case Type::TypeKind::kVector: return type.name() + "(0)";
case Type::kMatrix_Kind: return type.name() + "(1)"; case Type::TypeKind::kMatrix: return type.name() + "(1)";
default: ABORT("unsupported default_value type\n"); default: ABORT("unsupported default_value type\n");
} }
} }
@ -141,14 +141,14 @@ static bool is_private(const Variable& var) {
static bool is_uniform_in(const Variable& var) { static bool is_uniform_in(const Variable& var) {
return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) && return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
(var.fModifiers.fFlags & Modifiers::kIn_Flag) && (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
var.fType.kind() != Type::kSampler_Kind; var.fType.typeKind() != Type::TypeKind::kSampler;
} }
String CPPCodeGenerator::formatRuntimeValue(const Type& type, String CPPCodeGenerator::formatRuntimeValue(const Type& type,
const Layout& layout, const Layout& layout,
const String& cppCode, const String& cppCode,
std::vector<String>* formatArgs) { std::vector<String>* formatArgs) {
if (type.kind() == Type::kArray_Kind) { if (type.typeKind() == Type::TypeKind::kArray) {
String result("["); String result("[");
const char* separator = ""; const char* separator = "";
for (int i = 0; i < type.columns(); i++) { for (int i = 0; i < type.columns(); i++) {
@ -215,7 +215,7 @@ String CPPCodeGenerator::formatRuntimeValue(const Type& type,
} }
return type.name() + "(%f, %f, %f, %f)"; return type.name() + "(%f, %f, %f, %f)";
} }
if (type.kind() == Type::kMatrix_Kind) { if (type.typeKind() == Type::TypeKind::kMatrix) {
SkASSERT(type.componentType() == *fContext.fFloat_Type || SkASSERT(type.componentType() == *fContext.fFloat_Type ||
type.componentType() == *fContext.fHalf_Type); type.componentType() == *fContext.fHalf_Type);
@ -232,7 +232,7 @@ String CPPCodeGenerator::formatRuntimeValue(const Type& type,
format.back() = ')'; format.back() = ')';
return format; return format;
} }
if (type.kind() == Type::kEnum_Kind) { if (type.typeKind() == Type::TypeKind::kEnum) {
formatArgs->push_back("(int) " + cppCode); formatArgs->push_back("(int) " + cppCode);
return "%d"; return "%d";
} }
@ -269,7 +269,7 @@ String CPPCodeGenerator::getSamplerHandle(const Variable& var) {
if (&var == param) { if (&var == param) {
return "args.fTexSamplers[" + to_string(samplerCount) + "]"; return "args.fTexSamplers[" + to_string(samplerCount) + "]";
} }
if (param->fType.kind() == Type::kSampler_Kind) { if (param->fType.typeKind() == Type::TypeKind::kSampler) {
++samplerCount; ++samplerCount;
} }
} }
@ -327,7 +327,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
this->write("sk_Height"); this->write("sk_Height");
break; break;
default: default:
if (ref.fVariable.fType.kind() == Type::kSampler_Kind) { if (ref.fVariable.fType.typeKind() == Type::TypeKind::kSampler) {
this->write("%s"); this->write("%s");
fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerVariable(" + fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerVariable(" +
this->getSamplerHandle(ref.fVariable) + ")"); this->getSamplerHandle(ref.fVariable) + ")");
@ -383,7 +383,7 @@ void CPPCodeGenerator::writeFieldAccess(const FieldAccess& access) {
if (access.fBase->fType.name() == "fragmentProcessor") { if (access.fBase->fType.name() == "fragmentProcessor") {
// Special field access on fragment processors are converted into function calls on // Special field access on fragment processors are converted into function calls on
// GrFragmentProcessor's getters. // GrFragmentProcessor's getters.
if (access.fBase->fKind != Expression::kVariableReference_Kind) { if (access.fBase->kind() != Expression::Kind::kVariableReference) {
fErrors.error(access.fBase->fOffset, "fragmentProcessor must be a reference\n"); fErrors.error(access.fBase->fOffset, "fragmentProcessor must be a reference\n");
return; return;
} }
@ -408,7 +408,7 @@ int CPPCodeGenerator::getChildFPIndex(const Variable& var) const {
int index = 0; int index = 0;
bool found = false; bool found = false;
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
for (const auto& raw : decls.fVars) { for (const auto& raw : decls.fVars) {
const VarDeclaration& decl = raw->as<VarDeclaration>(); const VarDeclaration& decl = raw->as<VarDeclaration>();
@ -429,7 +429,7 @@ int CPPCodeGenerator::getChildFPIndex(const Variable& var) const {
void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) { void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" && if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" &&
c.fArguments[0]->fType.kind() != Type::Kind::kSampler_Kind) { c.fArguments[0]->fType.typeKind() != Type::TypeKind::kSampler) {
// Validity checks that are detected by function definition in sksl_fp.inc // Validity checks that are detected by function definition in sksl_fp.inc
SkASSERT(c.fArguments.size() >= 1 && c.fArguments.size() <= 3); SkASSERT(c.fArguments.size() >= 1 && c.fArguments.size() <= 3);
SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() || SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() ||
@ -438,7 +438,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
// Actually fail during compilation if arguments with valid types are // Actually fail during compilation if arguments with valid types are
// provided that are not variable references, since sample() is a // provided that are not variable references, since sample() is a
// special function that impacts code emission. // special function that impacts code emission.
if (c.fArguments[0]->fKind != Expression::kVariableReference_Kind) { if (c.fArguments[0]->kind() != Expression::Kind::kVariableReference) {
fErrors.error(c.fArguments[0]->fOffset, fErrors.error(c.fArguments[0]->fOffset,
"sample()'s fragmentProcessor argument must be a variable reference\n"); "sample()'s fragmentProcessor argument must be a variable reference\n");
return; return;
@ -511,7 +511,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (c.fFunction.fBuiltin && c.fFunction.fName == "sample") { if (c.fFunction.fBuiltin && c.fFunction.fName == "sample") {
this->write(".%s"); this->write(".%s");
SkASSERT(c.fArguments.size() >= 1); SkASSERT(c.fArguments.size() >= 1);
SkASSERT(c.fArguments[0]->fKind == Expression::kVariableReference_Kind); SkASSERT(c.fArguments[0]->kind() == Expression::Kind::kVariableReference);
String sampler = this->getSamplerHandle(c.fArguments[0]->as<VariableReference>().fVariable); String sampler = this->getSamplerHandle(c.fArguments[0]->as<VariableReference>().fVariable);
fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerSwizzle(" + sampler + fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerSwizzle(" + sampler +
").asString().c_str()"); ").asString().c_str()");
@ -583,7 +583,7 @@ static const char* glsltype_string(const Context& context, const Type& type) {
return "kVoid_GrSLType"; return "kVoid_GrSLType";
} else if (type == *context.fBool_Type) { } else if (type == *context.fBool_Type) {
return "kBool_GrSLType"; return "kBool_GrSLType";
} else if (type.kind() == Type::kEnum_Kind) { } else if (type.typeKind() == Type::TypeKind::kEnum) {
return "int"; return "int";
} }
SkASSERT(false); SkASSERT(false);
@ -652,19 +652,23 @@ bool CPPCodeGenerator::writeSection(const char* name, const char* prefix) {
} }
void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) { void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) {
if (p.fKind == ProgramElement::kSection_Kind) { switch (p.kind()) {
return; case ProgramElement::Kind::kSection:
}
if (p.fKind == ProgramElement::kVar_Kind) {
const VarDeclarations& decls = p.as<VarDeclarations>();
if (!decls.fVars.size()) {
return;
}
const Variable& var = *decls.fVars[0]->as<VarDeclaration>().fVar;
if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
-1 != var.fModifiers.fLayout.fBuiltin) {
return; return;
case ProgramElement::Kind::kVar: {
const VarDeclarations& decls = p.as<VarDeclarations>();
if (!decls.fVars.size()) {
return;
}
const Variable& var = *decls.fVars[0]->as<VarDeclaration>().fVar;
if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
-1 != var.fModifiers.fLayout.fBuiltin) {
return;
}
break;
} }
default:
break;
} }
INHERITED::writeProgramElement(p); INHERITED::writeProgramElement(p);
} }
@ -677,7 +681,7 @@ void CPPCodeGenerator::addUniform(const Variable& var) {
this->writef(" if (%s) {\n ", String(var.fModifiers.fLayout.fWhen).c_str()); this->writef(" if (%s) {\n ", String(var.fModifiers.fLayout.fWhen).c_str());
} }
String name(var.fName); String name(var.fName);
if (var.fType.kind() != Type::kArray_Kind) { if (var.fType.typeKind() != Type::TypeKind::kArray) {
this->writef(" %sVar = args.fUniformHandler->addUniform(&_outer, " this->writef(" %sVar = args.fUniformHandler->addUniform(&_outer, "
"kFragment_GrShaderFlag, %s, \"%s\");\n", "kFragment_GrShaderFlag, %s, \"%s\");\n",
HCodeGenerator::FieldName(name.c_str()).c_str(), HCodeGenerator::FieldName(name.c_str()).c_str(),
@ -701,7 +705,7 @@ void CPPCodeGenerator::writeInputVars() {
void CPPCodeGenerator::writePrivateVars() { void CPPCodeGenerator::writePrivateVars() {
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
for (const auto& raw : decls.fVars) { for (const auto& raw : decls.fVars) {
VarDeclaration& decl = raw->as<VarDeclaration>(); VarDeclaration& decl = raw->as<VarDeclaration>();
@ -741,7 +745,7 @@ void CPPCodeGenerator::writePrivateVars() {
void CPPCodeGenerator::writePrivateVarValues() { void CPPCodeGenerator::writePrivateVarValues() {
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
for (const auto& raw : decls.fVars) { for (const auto& raw : decls.fVars) {
VarDeclaration& decl = raw->as<VarDeclaration>(); VarDeclaration& decl = raw->as<VarDeclaration>();
@ -759,8 +763,8 @@ void CPPCodeGenerator::writePrivateVarValues() {
static bool is_accessible(const Variable& var) { static bool is_accessible(const Variable& var) {
const Type& type = var.fType.nonnullable(); const Type& type = var.fType.nonnullable();
return Type::kSampler_Kind != type.kind() && return Type::TypeKind::kSampler != type.typeKind() &&
Type::kOther_Kind != type.kind(); Type::TypeKind::kOther != type.typeKind();
} }
void CPPCodeGenerator::newExtraEmitCodeBlock() { void CPPCodeGenerator::newExtraEmitCodeBlock() {
@ -958,7 +962,7 @@ bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
" (void) _outer;\n", " (void) _outer;\n",
fFullName.c_str(), fFullName.c_str()); fFullName.c_str(), fFullName.c_str());
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
for (const auto& raw : decls.fVars) { for (const auto& raw : decls.fVars) {
VarDeclaration& decl = raw->as<VarDeclaration>(); VarDeclaration& decl = raw->as<VarDeclaration>();
@ -1074,14 +1078,14 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
if (section) { if (section) {
int samplerIndex = 0; int samplerIndex = 0;
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
for (const std::unique_ptr<Statement>& raw : decls.fVars) { for (const std::unique_ptr<Statement>& raw : decls.fVars) {
const VarDeclaration& decl = raw->as<VarDeclaration>(); const VarDeclaration& decl = raw->as<VarDeclaration>();
const Variable& variable = *decl.fVar; const Variable& variable = *decl.fVar;
String nameString(variable.fName); String nameString(variable.fName);
const char* name = nameString.c_str(); const char* name = nameString.c_str();
if (variable.fType.kind() == Type::kSampler_Kind) { if (variable.fType.typeKind() == Type::TypeKind::kSampler) {
this->writef(" const GrSurfaceProxyView& %sView = " this->writef(" const GrSurfaceProxyView& %sView = "
"_outer.textureSampler(%d).view();\n", "_outer.textureSampler(%d).view();\n",
name, samplerIndex); name, samplerIndex);
@ -1118,7 +1122,7 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
void CPPCodeGenerator::writeOnTextureSampler() { void CPPCodeGenerator::writeOnTextureSampler() {
bool foundSampler = false; bool foundSampler = false;
for (const auto& param : fSectionAndParameterHelper.getParameters()) { for (const auto& param : fSectionAndParameterHelper.getParameters()) {
if (param->fType.kind() == Type::kSampler_Kind) { if (param->fType.typeKind() == Type::TypeKind::kSampler) {
if (!foundSampler) { if (!foundSampler) {
this->writef( this->writef(
"const GrFragmentProcessor::TextureSampler& %s::onTextureSampler(int " "const GrFragmentProcessor::TextureSampler& %s::onTextureSampler(int "
@ -1159,7 +1163,7 @@ void CPPCodeGenerator::writeClone() {
this->writef(" this->cloneAndRegisterAllChildProcessors(src);\n"); this->writef(" this->cloneAndRegisterAllChildProcessors(src);\n");
int samplerCount = 0; int samplerCount = 0;
for (const auto& param : fSectionAndParameterHelper.getParameters()) { for (const auto& param : fSectionAndParameterHelper.getParameters()) {
if (param->fType.kind() == Type::kSampler_Kind) { if (param->fType.typeKind() == Type::TypeKind::kSampler) {
++samplerCount; ++samplerCount;
} }
} }
@ -1248,7 +1252,7 @@ void CPPCodeGenerator::writeGetKey() {
"GrProcessorKeyBuilder* b) const {\n", "GrProcessorKeyBuilder* b) const {\n",
fFullName.c_str()); fFullName.c_str());
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
for (const auto& raw : decls.fVars) { for (const auto& raw : decls.fVars) {
const VarDeclaration& decl = raw->as<VarDeclaration>(); const VarDeclaration& decl = raw->as<VarDeclaration>();
@ -1295,7 +1299,7 @@ void CPPCodeGenerator::writeGetKey() {
this->writef(" b->add32(sk_bit_cast<uint32_t>(%s));\n", this->writef(" b->add32(sk_bit_cast<uint32_t>(%s));\n",
HCodeGenerator::FieldName(name).c_str()); HCodeGenerator::FieldName(name).c_str());
} else if (var.fType.isInteger() || var.fType == *fContext.fBool_Type || } else if (var.fType.isInteger() || var.fType == *fContext.fBool_Type ||
var.fType.kind() == Type::kEnum_Kind) { var.fType.typeKind() == Type::TypeKind::kEnum) {
this->writef(" b->add32((uint32_t) %s);\n", this->writef(" b->add32((uint32_t) %s);\n",
HCodeGenerator::FieldName(name).c_str()); HCodeGenerator::FieldName(name).c_str());
} else { } else {
@ -1307,7 +1311,7 @@ void CPPCodeGenerator::writeGetKey() {
} }
break; break;
case Layout::kIdentity_Key: case Layout::kIdentity_Key:
if (var.fType.kind() != Type::kMatrix_Kind) { if (var.fType.typeKind() != Type::TypeKind::kMatrix) {
fErrors.error(var.fOffset, fErrors.error(var.fOffset,
"layout(key=identity) requires matrix type"); "layout(key=identity) requires matrix type");
} }
@ -1326,12 +1330,12 @@ void CPPCodeGenerator::writeGetKey() {
bool CPPCodeGenerator::generateCode() { bool CPPCodeGenerator::generateCode() {
std::vector<const Variable*> uniforms; std::vector<const Variable*> uniforms;
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
for (const auto& raw : decls.fVars) { for (const auto& raw : decls.fVars) {
VarDeclaration& decl = raw->as<VarDeclaration>(); VarDeclaration& decl = raw->as<VarDeclaration>();
if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) && if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
decl.fVar->fType.kind() != Type::kSampler_Kind) { decl.fVar->fType.typeKind() != Type::TypeKind::kSampler) {
uniforms.push_back(decl.fVar); uniforms.push_back(decl.fVar);
} }

View File

@ -253,7 +253,7 @@ static const std::vector<UniformCTypeMapper>& get_mappers() {
// ctype and supports the sksl type of the variable. // ctype and supports the sksl type of the variable.
const UniformCTypeMapper* UniformCTypeMapper::Get(const Context& context, const Type& type, const UniformCTypeMapper* UniformCTypeMapper::Get(const Context& context, const Type& type,
const Layout& layout) { const Layout& layout) {
if (type.kind() == Type::kArray_Kind) { if (type.typeKind() == Type::TypeKind::kArray) {
const UniformCTypeMapper* base = Get(context, type.componentType(), layout); const UniformCTypeMapper* base = Get(context, type.componentType(), layout);
return base ? base->arrayMapper(type.columns()) : nullptr; return base ? base->arrayMapper(type.columns()) : nullptr;
} }

View File

@ -74,8 +74,8 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
IRIntrinsicMap* target) { IRIntrinsicMap* target) {
for (auto iter = src->begin(); iter != src->end(); ) { for (auto iter = src->begin(); iter != src->end(); ) {
std::unique_ptr<ProgramElement>& element = *iter; std::unique_ptr<ProgramElement>& element = *iter;
switch (element->fKind) { switch (element->kind()) {
case ProgramElement::kFunction_Kind: { case ProgramElement::Kind::kFunction: {
FunctionDefinition& f = element->as<FunctionDefinition>(); FunctionDefinition& f = element->as<FunctionDefinition>();
SkASSERT(f.fDeclaration.fBuiltin); SkASSERT(f.fDeclaration.fBuiltin);
String key = f.fDeclaration.description(); String key = f.fDeclaration.description();
@ -84,7 +84,7 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
iter = src->erase(iter); iter = src->erase(iter);
break; break;
} }
case ProgramElement::kEnum_Kind: { case ProgramElement::Kind::kEnum: {
Enum& e = element->as<Enum>(); Enum& e = element->as<Enum>();
StringFragment name = e.fTypeName; StringFragment name = e.fTypeName;
SkASSERT(target->find(name) == target->end()); SkASSERT(target->find(name) == target->end());
@ -376,15 +376,15 @@ void Compiler::processIncludeFile(Program::Kind kind, const char* path,
// add the definition created by assigning to the lvalue to the definition set // add the definition created by assigning to the lvalue to the definition set
void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr, void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
DefinitionMap* definitions) { DefinitionMap* definitions) {
switch (lvalue->fKind) { switch (lvalue->kind()) {
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const Variable& var = lvalue->as<VariableReference>().fVariable; const Variable& var = lvalue->as<VariableReference>().fVariable;
if (var.fStorage == Variable::kLocal_Storage) { if (var.fStorage == Variable::kLocal_Storage) {
(*definitions)[&var] = expr; (*definitions)[&var] = expr;
} }
break; break;
} }
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
// We consider the variable written to as long as at least some of its components have // We consider the variable written to as long as at least some of its components have
// been written to. This will lead to some false negatives (we won't catch it if you // been written to. This will lead to some false negatives (we won't catch it if you
// write to foo.x and then read foo.y), but being stricter could lead to false positives // write to foo.x and then read foo.y), but being stricter could lead to false positives
@ -395,19 +395,19 @@ void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expressio
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression, (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
definitions); definitions);
break; break;
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
// see comments in Swizzle // see comments in Swizzle
this->addDefinition(lvalue->as<IndexExpression>().fBase.get(), this->addDefinition(lvalue->as<IndexExpression>().fBase.get(),
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression, (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
definitions); definitions);
break; break;
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
// see comments in Swizzle // see comments in Swizzle
this->addDefinition(lvalue->as<FieldAccess>().fBase.get(), this->addDefinition(lvalue->as<FieldAccess>().fBase.get(),
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression, (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
definitions); definitions);
break; break;
case Expression::kTernary_Kind: case Expression::Kind::kTernary:
// To simplify analysis, we just pretend that we write to both sides of the ternary. // To simplify analysis, we just pretend that we write to both sides of the ternary.
// This allows for false positives (meaning we fail to detect that a variable might not // This allows for false positives (meaning we fail to detect that a variable might not
// have been assigned), but is preferable to false negatives. // have been assigned), but is preferable to false negatives.
@ -418,7 +418,7 @@ void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expressio
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression, (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
definitions); definitions);
break; break;
case Expression::kExternalValue_Kind: case Expression::Kind::kExternalValue:
break; break;
default: default:
// not an lvalue, can't happen // not an lvalue, can't happen
@ -433,8 +433,8 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
case BasicBlock::Node::kExpression_Kind: { case BasicBlock::Node::kExpression_Kind: {
SkASSERT(node.expression()); SkASSERT(node.expression());
Expression* expr = node.expression()->get(); Expression* expr = node.expression()->get();
switch (expr->fKind) { switch (expr->kind()) {
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
BinaryExpression* b = &expr->as<BinaryExpression>(); BinaryExpression* b = &expr->as<BinaryExpression>();
if (b->fOperator == Token::Kind::TK_EQ) { if (b->fOperator == Token::Kind::TK_EQ) {
this->addDefinition(b->fLeft.get(), &b->fRight, definitions); this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
@ -447,7 +447,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
} }
break; break;
} }
case Expression::kFunctionCall_Kind: { case Expression::Kind::kFunctionCall: {
const FunctionCall& c = expr->as<FunctionCall>(); const FunctionCall& c = expr->as<FunctionCall>();
for (size_t i = 0; i < c.fFunction.fParameters.size(); ++i) { for (size_t i = 0; i < c.fFunction.fParameters.size(); ++i) {
if (c.fFunction.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) { if (c.fFunction.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
@ -459,7 +459,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
} }
break; break;
} }
case Expression::kPrefix_Kind: { case Expression::Kind::kPrefix: {
const PrefixExpression* p = &expr->as<PrefixExpression>(); const PrefixExpression* p = &expr->as<PrefixExpression>();
if (p->fOperator == Token::Kind::TK_MINUSMINUS || if (p->fOperator == Token::Kind::TK_MINUSMINUS ||
p->fOperator == Token::Kind::TK_PLUSPLUS) { p->fOperator == Token::Kind::TK_PLUSPLUS) {
@ -470,7 +470,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
} }
break; break;
} }
case Expression::kPostfix_Kind: { case Expression::Kind::kPostfix: {
const PostfixExpression* p = &expr->as<PostfixExpression>(); const PostfixExpression* p = &expr->as<PostfixExpression>();
if (p->fOperator == Token::Kind::TK_MINUSMINUS || if (p->fOperator == Token::Kind::TK_MINUSMINUS ||
p->fOperator == Token::Kind::TK_PLUSPLUS) { p->fOperator == Token::Kind::TK_PLUSPLUS) {
@ -481,7 +481,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
} }
break; break;
} }
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const VariableReference* v = &expr->as<VariableReference>(); const VariableReference* v = &expr->as<VariableReference>();
if (v->fRefKind != VariableReference::kRead_RefKind) { if (v->fRefKind != VariableReference::kRead_RefKind) {
this->addDefinition( this->addDefinition(
@ -498,7 +498,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
} }
case BasicBlock::Node::kStatement_Kind: { case BasicBlock::Node::kStatement_Kind: {
Statement* stmt = node.statement()->get(); Statement* stmt = node.statement()->get();
if (stmt->fKind == Statement::kVarDeclaration_Kind) { if (stmt->kind() == Statement::Kind::kVarDeclaration) {
VarDeclaration& vd = stmt->as<VarDeclaration>(); VarDeclaration& vd = stmt->as<VarDeclaration>();
if (vd.fValue) { if (vd.fValue) {
(*definitions)[vd.fVar] = &vd.fValue; (*definitions)[vd.fVar] = &vd.fValue;
@ -558,10 +558,10 @@ static DefinitionMap compute_start_state(const CFG& cfg) {
if (node.fKind == BasicBlock::Node::kStatement_Kind) { if (node.fKind == BasicBlock::Node::kStatement_Kind) {
SkASSERT(node.statement()); SkASSERT(node.statement());
const Statement* s = node.statement()->get(); const Statement* s = node.statement()->get();
if (s->fKind == Statement::kVarDeclarations_Kind) { if (s->kind() == Statement::Kind::kVarDeclarations) {
const VarDeclarationsStatement* vd = &s->as<VarDeclarationsStatement>(); const VarDeclarationsStatement* vd = &s->as<VarDeclarationsStatement>();
for (const auto& decl : vd->fDeclaration->fVars) { for (const auto& decl : vd->fDeclaration->fVars) {
if (decl->fKind == Statement::kVarDeclaration_Kind) { if (decl->kind() == Statement::Kind::kVarDeclaration) {
result[decl->as<VarDeclaration>().fVar] = nullptr; result[decl->as<VarDeclaration>().fVar] = nullptr;
} }
} }
@ -576,23 +576,23 @@ static DefinitionMap compute_start_state(const CFG& cfg) {
* Returns true if assigning to this lvalue has no effect. * Returns true if assigning to this lvalue has no effect.
*/ */
static bool is_dead(const Expression& lvalue) { static bool is_dead(const Expression& lvalue) {
switch (lvalue.fKind) { switch (lvalue.kind()) {
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
return lvalue.as<VariableReference>().fVariable.dead(); return lvalue.as<VariableReference>().fVariable.dead();
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
return is_dead(*lvalue.as<Swizzle>().fBase); return is_dead(*lvalue.as<Swizzle>().fBase);
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
return is_dead(*lvalue.as<FieldAccess>().fBase); return is_dead(*lvalue.as<FieldAccess>().fBase);
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
const IndexExpression& idx = lvalue.as<IndexExpression>(); const IndexExpression& idx = lvalue.as<IndexExpression>();
return is_dead(*idx.fBase) && return is_dead(*idx.fBase) &&
!idx.fIndex->hasProperty(Expression::Property::kSideEffects); !idx.fIndex->hasProperty(Expression::Property::kSideEffects);
} }
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
const TernaryExpression& t = lvalue.as<TernaryExpression>(); const TernaryExpression& t = lvalue.as<TernaryExpression>();
return !t.fTest->hasSideEffects() && is_dead(*t.fIfTrue) && is_dead(*t.fIfFalse); return !t.fTest->hasSideEffects() && is_dead(*t.fIfTrue) && is_dead(*t.fIfFalse);
} }
case Expression::kExternalValue_Kind: case Expression::Kind::kExternalValue:
return false; return false;
default: default:
#ifdef SK_DEBUG #ifdef SK_DEBUG
@ -650,21 +650,21 @@ static bool try_replace_expression(BasicBlock* b,
*/ */
template <typename T = double> template <typename T = double>
static bool is_constant(const Expression& expr, T value) { static bool is_constant(const Expression& expr, T value) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
return expr.as<IntLiteral>().fValue == value; return expr.as<IntLiteral>().fValue == value;
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
return expr.as<FloatLiteral>().fValue == value; return expr.as<FloatLiteral>().fValue == value;
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
const Constructor& constructor = expr.as<Constructor>(); const Constructor& constructor = expr.as<Constructor>();
if (constructor.isCompileTimeConstant()) { if (constructor.isCompileTimeConstant()) {
bool isFloat = constructor.fType.columns() > 1 bool isFloat = constructor.fType.columns() > 1
? constructor.fType.componentType().isFloat() ? constructor.fType.componentType().isFloat()
: constructor.fType.isFloat(); : constructor.fType.isFloat();
switch (constructor.fType.kind()) { switch (constructor.fType.typeKind()) {
case Type::kVector_Kind: case Type::TypeKind::kVector:
for (int i = 0; i < constructor.fType.columns(); ++i) { for (int i = 0; i < constructor.fType.columns(); ++i) {
if (isFloat) { if (isFloat) {
if (constructor.getFVecComponent(i) != value) { if (constructor.getFVecComponent(i) != value) {
@ -678,7 +678,7 @@ static bool is_constant(const Expression& expr, T value) {
} }
return true; return true;
case Type::kScalar_Kind: case Type::TypeKind::kScalar:
SkASSERT(constructor.fArguments.size() == 1); SkASSERT(constructor.fArguments.size() == 1);
return is_constant<T>(*constructor.fArguments[0], value); return is_constant<T>(*constructor.fArguments[0], value);
@ -768,7 +768,7 @@ static void delete_right(BasicBlock* b,
static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) { static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) {
std::vector<std::unique_ptr<Expression>> args; std::vector<std::unique_ptr<Expression>> args;
args.push_back(std::move(v)); args.push_back(std::move(v));
auto result = std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args))); std::unique_ptr<Expression> result = std::make_unique<Constructor>(-1, type, std::move(args));
return result; return result;
} }
@ -782,9 +782,9 @@ static void vectorize(BasicBlock* b,
std::unique_ptr<Expression>* otherExpression, std::unique_ptr<Expression>* otherExpression,
bool* outUpdated, bool* outUpdated,
bool* outNeedsRescan) { bool* outNeedsRescan) {
SkASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind); SkASSERT((*(*iter)->expression())->kind() == Expression::Kind::kBinary);
SkASSERT(type.kind() == Type::kVector_Kind); SkASSERT(type.typeKind() == Type::TypeKind::kVector);
SkASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind); SkASSERT((*otherExpression)->fType.typeKind() == Type::TypeKind::kScalar);
*outUpdated = true; *outUpdated = true;
std::unique_ptr<Expression>* target = (*iter)->expression(); std::unique_ptr<Expression>* target = (*iter)->expression();
if (!b->tryRemoveExpression(iter)) { if (!b->tryRemoveExpression(iter)) {
@ -824,18 +824,18 @@ static void vectorize_right(BasicBlock* b,
// Mark that an expression which we were writing to is no longer being written to // Mark that an expression which we were writing to is no longer being written to
static void clear_write(Expression& expr) { static void clear_write(Expression& expr) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
expr.as<VariableReference>().setRefKind(VariableReference::kRead_RefKind); expr.as<VariableReference>().setRefKind(VariableReference::kRead_RefKind);
break; break;
} }
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
clear_write(*expr.as<FieldAccess>().fBase); clear_write(*expr.as<FieldAccess>().fBase);
break; break;
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
clear_write(*expr.as<Swizzle>().fBase); clear_write(*expr.as<Swizzle>().fBase);
break; break;
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
clear_write(*expr.as<IndexExpression>().fBase); clear_write(*expr.as<IndexExpression>().fBase);
break; break;
default: default:
@ -864,8 +864,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
expr = (*iter)->expression()->get(); expr = (*iter)->expression()->get();
} }
} }
switch (expr->fKind) { switch (expr->kind()) {
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const VariableReference& ref = expr->as<VariableReference>(); const VariableReference& ref = expr->as<VariableReference>();
const Variable& var = ref.fVariable; const Variable& var = ref.fVariable;
if (ref.refKind() != VariableReference::kWrite_RefKind && if (ref.refKind() != VariableReference::kWrite_RefKind &&
@ -878,9 +878,9 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
} }
break; break;
} }
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
TernaryExpression* t = &expr->as<TernaryExpression>(); TernaryExpression* t = &expr->as<TernaryExpression>();
if (t->fTest->fKind == Expression::kBoolLiteral_Kind) { if (t->fTest->kind() == Expression::Kind::kBoolLiteral) {
// ternary has a constant test, replace it with either the true or // ternary has a constant test, replace it with either the true or
// false branch // false branch
if (t->fTest->as<BoolLiteral>().fValue) { if (t->fTest->as<BoolLiteral>().fValue) {
@ -893,24 +893,24 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
} }
break; break;
} }
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
BinaryExpression* bin = &expr->as<BinaryExpression>(); BinaryExpression* bin = &expr->as<BinaryExpression>();
if (dead_assignment(*bin)) { if (dead_assignment(*bin)) {
delete_left(&b, iter, outUpdated, outNeedsRescan); delete_left(&b, iter, outUpdated, outNeedsRescan);
break; break;
} }
// collapse useless expressions like x * 1 or x + 0 // collapse useless expressions like x * 1 or x + 0
if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) && if (((bin->fLeft->fType.typeKind() != Type::TypeKind::kScalar) &&
(bin->fLeft->fType.kind() != Type::kVector_Kind)) || (bin->fLeft->fType.typeKind() != Type::TypeKind::kVector)) ||
((bin->fRight->fType.kind() != Type::kScalar_Kind) && ((bin->fRight->fType.typeKind() != Type::TypeKind::kScalar) &&
(bin->fRight->fType.kind() != Type::kVector_Kind))) { (bin->fRight->fType.typeKind() != Type::TypeKind::kVector))) {
break; break;
} }
switch (bin->fOperator) { switch (bin->fOperator) {
case Token::Kind::TK_STAR: case Token::Kind::TK_STAR:
if (is_constant(*bin->fLeft, 1)) { if (is_constant(*bin->fLeft, 1)) {
if (bin->fLeft->fType.kind() == Type::kVector_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kVector &&
bin->fRight->fType.kind() == Type::kScalar_Kind) { bin->fRight->fType.typeKind() == Type::TypeKind::kScalar) {
// float4(1) * x -> float4(x) // float4(1) * x -> float4(x)
vectorize_right(&b, iter, outUpdated, outNeedsRescan); vectorize_right(&b, iter, outUpdated, outNeedsRescan);
} else { } else {
@ -921,8 +921,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
} }
} }
else if (is_constant(*bin->fLeft, 0)) { else if (is_constant(*bin->fLeft, 0)) {
if (bin->fLeft->fType.kind() == Type::kScalar_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kScalar &&
bin->fRight->fType.kind() == Type::kVector_Kind && bin->fRight->fType.typeKind() == Type::TypeKind::kVector &&
!bin->fRight->hasSideEffects()) { !bin->fRight->hasSideEffects()) {
// 0 * float4(x) -> float4(0) // 0 * float4(x) -> float4(0)
vectorize_left(&b, iter, outUpdated, outNeedsRescan); vectorize_left(&b, iter, outUpdated, outNeedsRescan);
@ -936,8 +936,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
} }
} }
else if (is_constant(*bin->fRight, 1)) { else if (is_constant(*bin->fRight, 1)) {
if (bin->fLeft->fType.kind() == Type::kScalar_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kScalar &&
bin->fRight->fType.kind() == Type::kVector_Kind) { bin->fRight->fType.typeKind() == Type::TypeKind::kVector) {
// x * float4(1) -> float4(x) // x * float4(1) -> float4(x)
vectorize_left(&b, iter, outUpdated, outNeedsRescan); vectorize_left(&b, iter, outUpdated, outNeedsRescan);
} else { } else {
@ -948,8 +948,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
} }
} }
else if (is_constant(*bin->fRight, 0)) { else if (is_constant(*bin->fRight, 0)) {
if (bin->fLeft->fType.kind() == Type::kVector_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kVector &&
bin->fRight->fType.kind() == Type::kScalar_Kind && bin->fRight->fType.typeKind() == Type::TypeKind::kScalar &&
!bin->fLeft->hasSideEffects()) { !bin->fLeft->hasSideEffects()) {
// float4(x) * 0 -> float4(0) // float4(x) * 0 -> float4(0)
vectorize_right(&b, iter, outUpdated, outNeedsRescan); vectorize_right(&b, iter, outUpdated, outNeedsRescan);
@ -965,8 +965,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
break; break;
case Token::Kind::TK_PLUS: case Token::Kind::TK_PLUS:
if (is_constant(*bin->fLeft, 0)) { if (is_constant(*bin->fLeft, 0)) {
if (bin->fLeft->fType.kind() == Type::kVector_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kVector &&
bin->fRight->fType.kind() == Type::kScalar_Kind) { bin->fRight->fType.typeKind() == Type::TypeKind::kScalar) {
// float4(0) + x -> float4(x) // float4(0) + x -> float4(x)
vectorize_right(&b, iter, outUpdated, outNeedsRescan); vectorize_right(&b, iter, outUpdated, outNeedsRescan);
} else { } else {
@ -976,8 +976,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
delete_left(&b, iter, outUpdated, outNeedsRescan); delete_left(&b, iter, outUpdated, outNeedsRescan);
} }
} else if (is_constant(*bin->fRight, 0)) { } else if (is_constant(*bin->fRight, 0)) {
if (bin->fLeft->fType.kind() == Type::kScalar_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kScalar &&
bin->fRight->fType.kind() == Type::kVector_Kind) { bin->fRight->fType.typeKind() == Type::TypeKind::kVector) {
// x + float4(0) -> float4(x) // x + float4(0) -> float4(x)
vectorize_left(&b, iter, outUpdated, outNeedsRescan); vectorize_left(&b, iter, outUpdated, outNeedsRescan);
} else { } else {
@ -990,8 +990,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
break; break;
case Token::Kind::TK_MINUS: case Token::Kind::TK_MINUS:
if (is_constant(*bin->fRight, 0)) { if (is_constant(*bin->fRight, 0)) {
if (bin->fLeft->fType.kind() == Type::kScalar_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kScalar &&
bin->fRight->fType.kind() == Type::kVector_Kind) { bin->fRight->fType.typeKind() == Type::TypeKind::kVector) {
// x - float4(0) -> float4(x) // x - float4(0) -> float4(x)
vectorize_left(&b, iter, outUpdated, outNeedsRescan); vectorize_left(&b, iter, outUpdated, outNeedsRescan);
} else { } else {
@ -1004,8 +1004,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
break; break;
case Token::Kind::TK_SLASH: case Token::Kind::TK_SLASH:
if (is_constant(*bin->fRight, 1)) { if (is_constant(*bin->fRight, 1)) {
if (bin->fLeft->fType.kind() == Type::kScalar_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kScalar &&
bin->fRight->fType.kind() == Type::kVector_Kind) { bin->fRight->fType.typeKind() == Type::TypeKind::kVector) {
// x / float4(1) -> float4(x) // x / float4(1) -> float4(x)
vectorize_left(&b, iter, outUpdated, outNeedsRescan); vectorize_left(&b, iter, outUpdated, outNeedsRescan);
} else { } else {
@ -1015,8 +1015,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
delete_right(&b, iter, outUpdated, outNeedsRescan); delete_right(&b, iter, outUpdated, outNeedsRescan);
} }
} else if (is_constant(*bin->fLeft, 0)) { } else if (is_constant(*bin->fLeft, 0)) {
if (bin->fLeft->fType.kind() == Type::kScalar_Kind && if (bin->fLeft->fType.typeKind() == Type::TypeKind::kScalar &&
bin->fRight->fType.kind() == Type::kVector_Kind && bin->fRight->fType.typeKind() == Type::TypeKind::kVector &&
!bin->fRight->hasSideEffects()) { !bin->fRight->hasSideEffects()) {
// 0 / float4(x) -> float4(0) // 0 / float4(x) -> float4(0)
vectorize_left(&b, iter, outUpdated, outNeedsRescan); vectorize_left(&b, iter, outUpdated, outNeedsRescan);
@ -1059,7 +1059,7 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
} }
break; break;
} }
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
Swizzle& s = expr->as<Swizzle>(); Swizzle& s = expr->as<Swizzle>();
// detect identity swizzles like foo.rgba // detect identity swizzles like foo.rgba
if ((int) s.fComponents.size() == s.fBase->fType.columns()) { if ((int) s.fComponents.size() == s.fBase->fType.columns()) {
@ -1081,7 +1081,7 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
} }
} }
// detect swizzles of swizzles, e.g. replace foo.argb.r000 with foo.a000 // detect swizzles of swizzles, e.g. replace foo.argb.r000 with foo.a000
if (s.fBase->fKind == Expression::kSwizzle_Kind) { if (s.fBase->kind() == Expression::Kind::kSwizzle) {
Swizzle& base = s.fBase->as<Swizzle>(); Swizzle& base = s.fBase->as<Swizzle>();
std::vector<int> final; std::vector<int> final;
for (int c : s.fComponents) { for (int c : s.fComponents) {
@ -1113,14 +1113,14 @@ static bool contains_conditional_break(Statement& stmt) {
class ContainsConditionalBreak : public ProgramVisitor { class ContainsConditionalBreak : public ProgramVisitor {
public: public:
bool visitStatement(const Statement& stmt) override { bool visitStatement(const Statement& stmt) override {
switch (stmt.fKind) { switch (stmt.kind()) {
case Statement::kBlock_Kind: case Statement::Kind::kBlock:
return this->INHERITED::visitStatement(stmt); return this->INHERITED::visitStatement(stmt);
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
return fInConditional > 0; return fInConditional > 0;
case Statement::kIf_Kind: { case Statement::Kind::kIf: {
++fInConditional; ++fInConditional;
bool result = this->INHERITED::visitStatement(stmt); bool result = this->INHERITED::visitStatement(stmt);
--fInConditional; --fInConditional;
@ -1145,11 +1145,11 @@ static bool contains_unconditional_break(Statement& stmt) {
class ContainsUnconditionalBreak : public ProgramVisitor { class ContainsUnconditionalBreak : public ProgramVisitor {
public: public:
bool visitStatement(const Statement& stmt) override { bool visitStatement(const Statement& stmt) override {
switch (stmt.fKind) { switch (stmt.kind()) {
case Statement::kBlock_Kind: case Statement::Kind::kBlock:
return this->INHERITED::visitStatement(stmt); return this->INHERITED::visitStatement(stmt);
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
return true; return true;
default: default:
@ -1165,8 +1165,8 @@ static bool contains_unconditional_break(Statement& stmt) {
static void move_all_but_break(std::unique_ptr<Statement>& stmt, static void move_all_but_break(std::unique_ptr<Statement>& stmt,
std::vector<std::unique_ptr<Statement>>* target) { std::vector<std::unique_ptr<Statement>>* target) {
switch (stmt->fKind) { switch (stmt->kind()) {
case Statement::kBlock_Kind: { case Statement::Kind::kBlock: {
// Recurse into the block. // Recurse into the block.
Block& block = static_cast<Block&>(*stmt); Block& block = static_cast<Block&>(*stmt);
@ -1181,7 +1181,7 @@ static void move_all_but_break(std::unique_ptr<Statement>& stmt,
break; break;
} }
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
// Do not append a break to the target. // Do not append a break to the target.
break; break;
@ -1273,8 +1273,8 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
bool* outUpdated, bool* outUpdated,
bool* outNeedsRescan) { bool* outNeedsRescan) {
Statement* stmt = (*iter)->statement()->get(); Statement* stmt = (*iter)->statement()->get();
switch (stmt->fKind) { switch (stmt->kind()) {
case Statement::kVarDeclaration_Kind: { case Statement::Kind::kVarDeclaration: {
const auto& varDecl = stmt->as<VarDeclaration>(); const auto& varDecl = stmt->as<VarDeclaration>();
if (varDecl.fVar->dead() && if (varDecl.fVar->dead() &&
(!varDecl.fValue || (!varDecl.fValue ||
@ -1290,9 +1290,9 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
} }
break; break;
} }
case Statement::kIf_Kind: { case Statement::Kind::kIf: {
IfStatement& i = stmt->as<IfStatement>(); IfStatement& i = stmt->as<IfStatement>();
if (i.fTest->fKind == Expression::kBoolLiteral_Kind) { if (i.fTest->kind() == Expression::Kind::kBoolLiteral) {
// constant if, collapse down to a single branch // constant if, collapse down to a single branch
if (i.fTest->as<BoolLiteral>().fValue) { if (i.fTest->as<BoolLiteral>().fValue) {
SkASSERT(i.fIfTrue); SkASSERT(i.fIfTrue);
@ -1330,7 +1330,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
} }
break; break;
} }
case Statement::kSwitch_Kind: { case Statement::Kind::kSwitch: {
SwitchStatement& s = stmt->as<SwitchStatement>(); SwitchStatement& s = stmt->as<SwitchStatement>();
if (s.fValue->isCompileTimeConstant()) { if (s.fValue->isCompileTimeConstant()) {
// switch is constant, replace it with the case that matches // switch is constant, replace it with the case that matches
@ -1380,7 +1380,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
} }
break; break;
} }
case Statement::kExpression_Kind: { case Statement::Kind::kExpression: {
ExpressionStatement& e = stmt->as<ExpressionStatement>(); ExpressionStatement& e = stmt->as<ExpressionStatement>();
SkASSERT((*iter)->statement()->get() == &e); SkASSERT((*iter)->statement()->get() == &e);
if (!e.fExpression->hasSideEffects()) { if (!e.fExpression->hasSideEffects()) {
@ -1414,8 +1414,8 @@ void Compiler::scanCFG(FunctionDefinition& f) {
break; break;
case BasicBlock::Node::kExpression_Kind: case BasicBlock::Node::kExpression_Kind:
offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset; offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset;
if ((*cfg.fBlocks[i].fNodes[0].expression())->fKind == if ((*cfg.fBlocks[i].fNodes[0].expression())->kind() ==
Expression::kBoolLiteral_Kind) { Expression::Kind::kBoolLiteral) {
// Function inlining can generate do { ... } while(false) loops which always // Function inlining can generate do { ... } while(false) loops which always
// break, so the boolean condition is considered unreachable. Since not // break, so the boolean condition is considered unreachable. Since not
// being able to reach a literal is a non-issue in the first place, we // being able to reach a literal is a non-issue in the first place, we
@ -1452,7 +1452,7 @@ void Compiler::scanCFG(FunctionDefinition& f) {
// have not been properly assigned. Kill it. // have not been properly assigned. Kill it.
for (BasicBlock::Node& node : b.fNodes) { for (BasicBlock::Node& node : b.fNodes) {
if (node.fKind == BasicBlock::Node::kStatement_Kind && if (node.fKind == BasicBlock::Node::kStatement_Kind &&
(*node.statement())->fKind != Statement::kNop_Kind) { (*node.statement())->kind() != Statement::Kind::kNop) {
node.setStatement(std::unique_ptr<Statement>(new Nop())); node.setStatement(std::unique_ptr<Statement>(new Nop()));
} }
} }
@ -1485,25 +1485,25 @@ void Compiler::scanCFG(FunctionDefinition& f) {
for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) { for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) {
if (iter->fKind == BasicBlock::Node::kStatement_Kind) { if (iter->fKind == BasicBlock::Node::kStatement_Kind) {
const Statement& s = **iter->statement(); const Statement& s = **iter->statement();
switch (s.fKind) { switch (s.kind()) {
case Statement::kIf_Kind: case Statement::Kind::kIf:
if (s.as<IfStatement>().fIsStatic && if (s.as<IfStatement>().fIsStatic &&
!(fFlags & kPermitInvalidStaticTests_Flag)) { !(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fOffset, "static if has non-static test"); this->error(s.fOffset, "static if has non-static test");
} }
++iter; ++iter;
break; break;
case Statement::kSwitch_Kind: case Statement::Kind::kSwitch:
if (s.as<SwitchStatement>().fIsStatic && if (s.as<SwitchStatement>().fIsStatic &&
!(fFlags & kPermitInvalidStaticTests_Flag)) { !(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fOffset, "static switch has non-static test"); this->error(s.fOffset, "static switch has non-static test");
} }
++iter; ++iter;
break; break;
case Statement::kVarDeclarations_Kind: { case Statement::Kind::kVarDeclarations: {
VarDeclarations& decls = *s.as<VarDeclarationsStatement>().fDeclaration; VarDeclarations& decls = *s.as<VarDeclarationsStatement>().fDeclaration;
for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) { for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) {
if ((*varIter)->fKind == Statement::kNop_Kind) { if ((*varIter)->kind() == Statement::Kind::kNop) {
varIter = decls.fVars.erase(varIter); varIter = decls.fVars.erase(varIter);
} else { } else {
++varIter; ++varIter;
@ -1644,7 +1644,7 @@ bool Compiler::optimize(Program& program) {
// Scan and optimize based on the control-flow graph for each function. // Scan and optimize based on the control-flow graph for each function.
for (ProgramElement& element : program) { for (ProgramElement& element : program) {
if (element.fKind == ProgramElement::kFunction_Kind) { if (element.kind() == ProgramElement::Kind::kFunction) {
this->scanCFG(element.as<FunctionDefinition>()); this->scanCFG(element.as<FunctionDefinition>());
} }
} }
@ -1656,7 +1656,7 @@ bool Compiler::optimize(Program& program) {
std::remove_if(program.fElements.begin(), std::remove_if(program.fElements.begin(),
program.fElements.end(), program.fElements.end(),
[](const std::unique_ptr<ProgramElement>& pe) { [](const std::unique_ptr<ProgramElement>& pe) {
if (pe->fKind != ProgramElement::kFunction_Kind) { if (pe->kind() != ProgramElement::Kind::kFunction) {
return false; return false;
} }
const FunctionDefinition& fn = pe->as<FunctionDefinition>(); const FunctionDefinition& fn = pe->as<FunctionDefinition>();
@ -1669,7 +1669,7 @@ bool Compiler::optimize(Program& program) {
if (program.fKind != Program::kFragmentProcessor_Kind) { if (program.fKind != Program::kFragmentProcessor_Kind) {
// Remove dead variables. // Remove dead variables.
for (ProgramElement& element : program) { for (ProgramElement& element : program) {
if (element.fKind == ProgramElement::kVar_Kind) { if (element.kind() == ProgramElement::Kind::kVar) {
VarDeclarations& vars = element.as<VarDeclarations>(); VarDeclarations& vars = element.as<VarDeclarations>();
vars.fVars.erase( vars.fVars.erase(
std::remove_if(vars.fVars.begin(), vars.fVars.end(), std::remove_if(vars.fVars.begin(), vars.fVars.end(),
@ -1684,7 +1684,7 @@ bool Compiler::optimize(Program& program) {
program.fElements.erase( program.fElements.erase(
std::remove_if(program.fElements.begin(), program.fElements.end(), std::remove_if(program.fElements.begin(), program.fElements.end(),
[](const std::unique_ptr<ProgramElement>& element) { [](const std::unique_ptr<ProgramElement>& element) {
return element->fKind == ProgramElement::kVar_Kind && return element->kind() == ProgramElement::Kind::kVar &&
element->as<VarDeclarations>().fVars.empty(); element->as<VarDeclarations>().fVars.empty();
}), }),
program.fElements.end()); program.fElements.end());

View File

@ -24,41 +24,41 @@ public:
: fInvalid_Type(new Type("<INVALID>")) : fInvalid_Type(new Type("<INVALID>"))
, fVoid_Type(new Type("void")) , fVoid_Type(new Type("void"))
, fNull_Type(new Type("null")) , fNull_Type(new Type("null"))
, fFloatLiteral_Type(new Type("$floatLiteral", Type::kFloat_NumberKind, 3)) , fFloatLiteral_Type(new Type("$floatLiteral", Type::NumberKind::kFloat, 3))
, fIntLiteral_Type(new Type("$intLiteral", Type::kSigned_NumberKind, 1)) , fIntLiteral_Type(new Type("$intLiteral", Type::NumberKind::kSigned, 1))
, fFloat_Type(new Type("float", Type::kFloat_NumberKind, 5, true)) , fFloat_Type(new Type("float", Type::NumberKind::kFloat, 5, true))
, fFloat2_Type(new Type("float2", *fFloat_Type, 2)) , fFloat2_Type(new Type("float2", *fFloat_Type, 2))
, fFloat3_Type(new Type("float3", *fFloat_Type, 3)) , fFloat3_Type(new Type("float3", *fFloat_Type, 3))
, fFloat4_Type(new Type("float4", *fFloat_Type, 4)) , fFloat4_Type(new Type("float4", *fFloat_Type, 4))
, fHalf_Type(new Type("half", Type::kFloat_NumberKind, 4)) , fHalf_Type(new Type("half", Type::NumberKind::kFloat, 4))
, fHalf2_Type(new Type("half2", *fHalf_Type, 2)) , fHalf2_Type(new Type("half2", *fHalf_Type, 2))
, fHalf3_Type(new Type("half3", *fHalf_Type, 3)) , fHalf3_Type(new Type("half3", *fHalf_Type, 3))
, fHalf4_Type(new Type("half4", *fHalf_Type, 4)) , fHalf4_Type(new Type("half4", *fHalf_Type, 4))
, fUInt_Type(new Type("uint", Type::kUnsigned_NumberKind, 2, true)) , fUInt_Type(new Type("uint", Type::NumberKind::kUnsigned, 2, true))
, fUInt2_Type(new Type("uint2", *fUInt_Type, 2)) , fUInt2_Type(new Type("uint2", *fUInt_Type, 2))
, fUInt3_Type(new Type("uint3", *fUInt_Type, 3)) , fUInt3_Type(new Type("uint3", *fUInt_Type, 3))
, fUInt4_Type(new Type("uint4", *fUInt_Type, 4)) , fUInt4_Type(new Type("uint4", *fUInt_Type, 4))
, fInt_Type(new Type("int", Type::kSigned_NumberKind, 2, true)) , fInt_Type(new Type("int", Type::NumberKind::kSigned, 2, true))
, fInt2_Type(new Type("int2", *fInt_Type, 2)) , fInt2_Type(new Type("int2", *fInt_Type, 2))
, fInt3_Type(new Type("int3", *fInt_Type, 3)) , fInt3_Type(new Type("int3", *fInt_Type, 3))
, fInt4_Type(new Type("int4", *fInt_Type, 4)) , fInt4_Type(new Type("int4", *fInt_Type, 4))
, fUShort_Type(new Type("ushort", Type::kUnsigned_NumberKind, 0)) , fUShort_Type(new Type("ushort", Type::NumberKind::kUnsigned, 0))
, fUShort2_Type(new Type("ushort2", *fUShort_Type, 2)) , fUShort2_Type(new Type("ushort2", *fUShort_Type, 2))
, fUShort3_Type(new Type("ushort3", *fUShort_Type, 3)) , fUShort3_Type(new Type("ushort3", *fUShort_Type, 3))
, fUShort4_Type(new Type("ushort4", *fUShort_Type, 4)) , fUShort4_Type(new Type("ushort4", *fUShort_Type, 4))
, fShort_Type(new Type("short", Type::kSigned_NumberKind, 0)) , fShort_Type(new Type("short", Type::NumberKind::kSigned, 0))
, fShort2_Type(new Type("short2", *fShort_Type, 2)) , fShort2_Type(new Type("short2", *fShort_Type, 2))
, fShort3_Type(new Type("short3", *fShort_Type, 3)) , fShort3_Type(new Type("short3", *fShort_Type, 3))
, fShort4_Type(new Type("short4", *fShort_Type, 4)) , fShort4_Type(new Type("short4", *fShort_Type, 4))
, fUByte_Type(new Type("ubyte", Type::kUnsigned_NumberKind, 0)) , fUByte_Type(new Type("ubyte", Type::NumberKind::kUnsigned, 0))
, fUByte2_Type(new Type("ubyte2", *fUByte_Type, 2)) , fUByte2_Type(new Type("ubyte2", *fUByte_Type, 2))
, fUByte3_Type(new Type("ubyte3", *fUByte_Type, 3)) , fUByte3_Type(new Type("ubyte3", *fUByte_Type, 3))
, fUByte4_Type(new Type("ubyte4", *fUByte_Type, 4)) , fUByte4_Type(new Type("ubyte4", *fUByte_Type, 4))
, fByte_Type(new Type("byte", Type::kSigned_NumberKind, 0)) , fByte_Type(new Type("byte", Type::NumberKind::kSigned, 0))
, fByte2_Type(new Type("byte2", *fByte_Type, 2)) , fByte2_Type(new Type("byte2", *fByte_Type, 2))
, fByte3_Type(new Type("byte3", *fByte_Type, 3)) , fByte3_Type(new Type("byte3", *fByte_Type, 3))
, fByte4_Type(new Type("byte4", *fByte_Type, 4)) , fByte4_Type(new Type("byte4", *fByte_Type, 4))
, fBool_Type(new Type("bool", Type::kNonnumeric_NumberKind, -1)) , fBool_Type(new Type("bool", Type::NumberKind::kNonnumeric, -1))
, fBool2_Type(new Type("bool2", *fBool_Type, 2)) , fBool2_Type(new Type("bool2", *fBool_Type, 2))
, fBool3_Type(new Type("bool3", *fBool_Type, 3)) , fBool3_Type(new Type("bool3", *fBool_Type, 3))
, fBool4_Type(new Type("bool4", *fBool_Type, 4)) , fBool4_Type(new Type("bool4", *fBool_Type, 4))
@ -111,7 +111,7 @@ public:
// Related to below FIXME, gsampler*s don't currently expand to cover integer case. // Related to below FIXME, gsampler*s don't currently expand to cover integer case.
, fISampler2D_Type(new Type("isampler2D", *fITexture2D_Type)) , fISampler2D_Type(new Type("isampler2D", *fITexture2D_Type))
, fSampler_Type(new Type("sampler", Type::kSeparateSampler_Kind)) , fSampler_Type(new Type("sampler", Type::TypeKind::kSeparateSampler))
// FIXME express these as "gimage2D" that expand to image2D, iimage2D, and uimage2D. // FIXME express these as "gimage2D" that expand to image2D, iimage2D, and uimage2D.
, fImage2D_Type(new Type("image2D", 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)) , fIImage2D_Type(new Type("iimage2D", SpvDim2D, false, false, false, true))
@ -351,7 +351,7 @@ public:
private: private:
class Defined : public Expression { class Defined : public Expression {
public: public:
static constexpr Kind kExpressionKind = kDefined_Kind; static constexpr Kind kExpressionKind = Kind::kDefined;
Defined(const Type& type) Defined(const Type& type)
: INHERITED(-1, kExpressionKind, type) {} : INHERITED(-1, kExpressionKind, type) {}

View File

@ -142,8 +142,8 @@ void Dehydrator::write(const Symbol& s) {
this->writeU16(id); this->writeU16(id);
return; return;
} }
switch (s.fKind) { switch (s.kind()) {
case Symbol::kFunctionDeclaration_Kind: { case Symbol::Kind::kFunctionDeclaration: {
const FunctionDeclaration& f = s.as<FunctionDeclaration>(); const FunctionDeclaration& f = s.as<FunctionDeclaration>();
this->writeU8(Rehydrator::kFunctionDeclaration_Command); this->writeU8(Rehydrator::kFunctionDeclaration_Command);
this->writeId(&f); this->writeId(&f);
@ -156,7 +156,7 @@ void Dehydrator::write(const Symbol& s) {
this->write(f.fReturnType); this->write(f.fReturnType);
break; break;
} }
case Symbol::kUnresolvedFunction_Kind: { case Symbol::Kind::kUnresolvedFunction: {
const UnresolvedFunction& f = s.as<UnresolvedFunction>(); const UnresolvedFunction& f = s.as<UnresolvedFunction>();
this->writeU8(Rehydrator::kUnresolvedFunction_Command); this->writeU8(Rehydrator::kUnresolvedFunction_Command);
this->writeId(&f); this->writeId(&f);
@ -166,26 +166,26 @@ void Dehydrator::write(const Symbol& s) {
} }
break; break;
} }
case Symbol::kType_Kind: { case Symbol::Kind::kType: {
const Type& t = s.as<Type>(); const Type& t = s.as<Type>();
switch (t.kind()) { switch (t.typeKind()) {
case Type::kArray_Kind: case Type::TypeKind::kArray:
this->writeU8(Rehydrator::kArrayType_Command); this->writeU8(Rehydrator::kArrayType_Command);
this->writeId(&t); this->writeId(&t);
this->write(t.componentType()); this->write(t.componentType());
this->writeU8(t.columns()); this->writeU8(t.columns());
break; break;
case Type::kEnum_Kind: case Type::TypeKind::kEnum:
this->writeU8(Rehydrator::kEnumType_Command); this->writeU8(Rehydrator::kEnumType_Command);
this->writeId(&t); this->writeId(&t);
this->write(t.fName); this->write(t.fName);
break; break;
case Type::kNullable_Kind: case Type::TypeKind::kNullable:
this->writeU8(Rehydrator::kNullableType_Command); this->writeU8(Rehydrator::kNullableType_Command);
this->writeId(&t); this->writeId(&t);
this->write(t.componentType()); this->write(t.componentType());
break; break;
case Type::kStruct_Kind: case Type::TypeKind::kStruct:
this->writeU8(Rehydrator::kStructType_Command); this->writeU8(Rehydrator::kStructType_Command);
this->writeId(&t); this->writeId(&t);
this->write(t.fName); this->write(t.fName);
@ -203,7 +203,7 @@ void Dehydrator::write(const Symbol& s) {
} }
break; break;
} }
case Symbol::kVariable_Kind: { case Symbol::Kind::kVariable: {
const Variable& v = s.as<Variable>(); const Variable& v = s.as<Variable>();
this->writeU8(Rehydrator::kVariable_Command); this->writeU8(Rehydrator::kVariable_Command);
this->writeId(&v); this->writeId(&v);
@ -213,14 +213,14 @@ void Dehydrator::write(const Symbol& s) {
this->writeU8(v.fStorage); this->writeU8(v.fStorage);
break; break;
} }
case Symbol::kField_Kind: { case Symbol::Kind::kField: {
const Field& f = s.as<Field>(); const Field& f = s.as<Field>();
this->writeU8(Rehydrator::kField_Command); this->writeU8(Rehydrator::kField_Command);
this->writeU16(this->symbolId(&f.fOwner)); this->writeU16(this->symbolId(&f.fOwner));
this->writeU8(f.fFieldIndex); this->writeU8(f.fFieldIndex);
break; break;
} }
case Symbol::kExternal_Kind: case Symbol::Kind::kExternal:
SkASSERT(false); SkASSERT(false);
break; break;
} }
@ -253,8 +253,8 @@ void Dehydrator::write(const SymbolTable& symbols) {
void Dehydrator::write(const Expression* e) { void Dehydrator::write(const Expression* e) {
if (e) { if (e) {
switch (e->fKind) { switch (e->kind()) {
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
const BinaryExpression& b = e->as<BinaryExpression>(); const BinaryExpression& b = e->as<BinaryExpression>();
this->writeU8(Rehydrator::kBinary_Command); this->writeU8(Rehydrator::kBinary_Command);
this->write(b.fLeft.get()); this->write(b.fLeft.get());
@ -263,13 +263,13 @@ void Dehydrator::write(const Expression* e) {
this->write(b.fType); this->write(b.fType);
break; break;
} }
case Expression::kBoolLiteral_Kind: { case Expression::Kind::kBoolLiteral: {
const BoolLiteral& b = e->as<BoolLiteral>(); const BoolLiteral& b = e->as<BoolLiteral>();
this->writeU8(Rehydrator::kBoolLiteral_Command); this->writeU8(Rehydrator::kBoolLiteral_Command);
this->writeU8(b.fValue); this->writeU8(b.fValue);
break; break;
} }
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
const Constructor& c = e->as<Constructor>(); const Constructor& c = e->as<Constructor>();
this->writeU8(Rehydrator::kConstructor_Command); this->writeU8(Rehydrator::kConstructor_Command);
this->write(c.fType); this->write(c.fType);
@ -279,13 +279,13 @@ void Dehydrator::write(const Expression* e) {
} }
break; break;
} }
case Expression::kExternalFunctionCall_Kind: case Expression::Kind::kExternalFunctionCall:
case Expression::kExternalValue_Kind: case Expression::Kind::kExternalValue:
// not implemented; doesn't seem like we'll ever need them from within an include // not implemented; doesn't seem like we'll ever need them from within an include
// file // file
SkASSERT(false); SkASSERT(false);
break; break;
case Expression::kFieldAccess_Kind: { case Expression::Kind::kFieldAccess: {
const FieldAccess& f = e->as<FieldAccess>(); const FieldAccess& f = e->as<FieldAccess>();
this->writeU8(Rehydrator::kFieldAccess_Command); this->writeU8(Rehydrator::kFieldAccess_Command);
this->write(f.fBase.get()); this->write(f.fBase.get());
@ -293,7 +293,7 @@ void Dehydrator::write(const Expression* e) {
this->writeU8(f.fOwnerKind); this->writeU8(f.fOwnerKind);
break; break;
} }
case Expression::kFloatLiteral_Kind: { case Expression::Kind::kFloatLiteral: {
const FloatLiteral& f = e->as<FloatLiteral>(); const FloatLiteral& f = e->as<FloatLiteral>();
this->writeU8(Rehydrator::kFloatLiteral_Command); this->writeU8(Rehydrator::kFloatLiteral_Command);
FloatIntUnion u; FloatIntUnion u;
@ -301,7 +301,7 @@ void Dehydrator::write(const Expression* e) {
this->writeS32(u.fInt); this->writeS32(u.fInt);
break; break;
} }
case Expression::kFunctionCall_Kind: { case Expression::Kind::kFunctionCall: {
const FunctionCall& f = e->as<FunctionCall>(); const FunctionCall& f = e->as<FunctionCall>();
this->writeU8(Rehydrator::kFunctionCall_Command); this->writeU8(Rehydrator::kFunctionCall_Command);
this->write(f.fType); this->write(f.fType);
@ -312,44 +312,44 @@ void Dehydrator::write(const Expression* e) {
} }
break; break;
} }
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
const IndexExpression& i = e->as<IndexExpression>(); const IndexExpression& i = e->as<IndexExpression>();
this->writeU8(Rehydrator::kIndex_Command); this->writeU8(Rehydrator::kIndex_Command);
this->write(i.fBase.get()); this->write(i.fBase.get());
this->write(i.fIndex.get()); this->write(i.fIndex.get());
break; break;
} }
case Expression::kIntLiteral_Kind: { case Expression::Kind::kIntLiteral: {
const IntLiteral& i = e->as<IntLiteral>(); const IntLiteral& i = e->as<IntLiteral>();
this->writeU8(Rehydrator::kIntLiteral_Command); this->writeU8(Rehydrator::kIntLiteral_Command);
this->writeS32(i.fValue); this->writeS32(i.fValue);
break; break;
} }
case Expression::kNullLiteral_Kind: case Expression::Kind::kNullLiteral:
this->writeU8(Rehydrator::kNullLiteral_Command); this->writeU8(Rehydrator::kNullLiteral_Command);
break; break;
case Expression::kPostfix_Kind: { case Expression::Kind::kPostfix: {
const PostfixExpression& p = e->as<PostfixExpression>(); const PostfixExpression& p = e->as<PostfixExpression>();
this->writeU8(Rehydrator::kPostfix_Command); this->writeU8(Rehydrator::kPostfix_Command);
this->writeU8((int) p.fOperator); this->writeU8((int) p.fOperator);
this->write(p.fOperand.get()); this->write(p.fOperand.get());
break; break;
} }
case Expression::kPrefix_Kind: { case Expression::Kind::kPrefix: {
const PrefixExpression& p = e->as<PrefixExpression>(); const PrefixExpression& p = e->as<PrefixExpression>();
this->writeU8(Rehydrator::kPrefix_Command); this->writeU8(Rehydrator::kPrefix_Command);
this->writeU8((int) p.fOperator); this->writeU8((int) p.fOperator);
this->write(p.fOperand.get()); this->write(p.fOperand.get());
break; break;
} }
case Expression::kSetting_Kind: { case Expression::Kind::kSetting: {
const Setting& s = e->as<Setting>(); const Setting& s = e->as<Setting>();
this->writeU8(Rehydrator::kSetting_Command); this->writeU8(Rehydrator::kSetting_Command);
this->write(s.fName); this->write(s.fName);
this->write(s.fValue.get()); this->write(s.fValue.get());
break; break;
} }
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
const Swizzle& s = e->as<Swizzle>(); const Swizzle& s = e->as<Swizzle>();
this->writeU8(Rehydrator::kSwizzle_Command); this->writeU8(Rehydrator::kSwizzle_Command);
this->write(s.fBase.get()); this->write(s.fBase.get());
@ -359,7 +359,7 @@ void Dehydrator::write(const Expression* e) {
} }
break; break;
} }
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
const TernaryExpression& t = e->as<TernaryExpression>(); const TernaryExpression& t = e->as<TernaryExpression>();
this->writeU8(Rehydrator::kTernary_Command); this->writeU8(Rehydrator::kTernary_Command);
this->write(t.fTest.get()); this->write(t.fTest.get());
@ -367,16 +367,16 @@ void Dehydrator::write(const Expression* e) {
this->write(t.fIfFalse.get()); this->write(t.fIfFalse.get());
break; break;
} }
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const VariableReference& v = e->as<VariableReference>(); const VariableReference& v = e->as<VariableReference>();
this->writeU8(Rehydrator::kVariableReference_Command); this->writeU8(Rehydrator::kVariableReference_Command);
this->writeId(&v.fVariable); this->writeId(&v.fVariable);
this->writeU8(v.fRefKind); this->writeU8(v.fRefKind);
break; break;
} }
case Expression::kFunctionReference_Kind: case Expression::Kind::kFunctionReference:
case Expression::kTypeReference_Kind: case Expression::Kind::kTypeReference:
case Expression::kDefined_Kind: case Expression::Kind::kDefined:
// shouldn't appear in finished code // shouldn't appear in finished code
SkASSERT(false); SkASSERT(false);
break; break;
@ -388,8 +388,8 @@ void Dehydrator::write(const Expression* e) {
void Dehydrator::write(const Statement* s) { void Dehydrator::write(const Statement* s) {
if (s) { if (s) {
switch (s->fKind) { switch (s->kind()) {
case Statement::kBlock_Kind: { case Statement::Kind::kBlock: {
const Block& b = s->as<Block>(); const Block& b = s->as<Block>();
this->writeU8(Rehydrator::kBlock_Command); this->writeU8(Rehydrator::kBlock_Command);
AutoDehydratorSymbolTable symbols(this, b.fSymbols); AutoDehydratorSymbolTable symbols(this, b.fSymbols);
@ -400,29 +400,29 @@ void Dehydrator::write(const Statement* s) {
this->writeU8(b.fIsScope); this->writeU8(b.fIsScope);
break; break;
} }
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
this->writeU8(Rehydrator::kBreak_Command); this->writeU8(Rehydrator::kBreak_Command);
break; break;
case Statement::kContinue_Kind: case Statement::Kind::kContinue:
this->writeU8(Rehydrator::kContinue_Command); this->writeU8(Rehydrator::kContinue_Command);
break; break;
case Statement::kDiscard_Kind: case Statement::Kind::kDiscard:
this->writeU8(Rehydrator::kDiscard_Command); this->writeU8(Rehydrator::kDiscard_Command);
break; break;
case Statement::kDo_Kind: { case Statement::Kind::kDo: {
const DoStatement& d = s->as<DoStatement>(); const DoStatement& d = s->as<DoStatement>();
this->writeU8(Rehydrator::kDo_Command); this->writeU8(Rehydrator::kDo_Command);
this->write(d.fStatement.get()); this->write(d.fStatement.get());
this->write(d.fTest.get()); this->write(d.fTest.get());
break; break;
} }
case Statement::kExpression_Kind: { case Statement::Kind::kExpression: {
const ExpressionStatement& e = s->as<ExpressionStatement>(); const ExpressionStatement& e = s->as<ExpressionStatement>();
this->writeU8(Rehydrator::kExpressionStatement_Command); this->writeU8(Rehydrator::kExpressionStatement_Command);
this->write(e.fExpression.get()); this->write(e.fExpression.get());
break; break;
} }
case Statement::kFor_Kind: { case Statement::Kind::kFor: {
const ForStatement& f = s->as<ForStatement>(); const ForStatement& f = s->as<ForStatement>();
this->writeU8(Rehydrator::kFor_Command); this->writeU8(Rehydrator::kFor_Command);
this->write(f.fInitializer.get()); this->write(f.fInitializer.get());
@ -432,7 +432,7 @@ void Dehydrator::write(const Statement* s) {
this->write(f.fSymbols); this->write(f.fSymbols);
break; break;
} }
case Statement::kIf_Kind: { case Statement::Kind::kIf: {
const IfStatement& i = s->as<IfStatement>(); const IfStatement& i = s->as<IfStatement>();
this->writeU8(Rehydrator::kIf_Command); this->writeU8(Rehydrator::kIf_Command);
this->writeU8(i.fIsStatic); this->writeU8(i.fIsStatic);
@ -441,16 +441,16 @@ void Dehydrator::write(const Statement* s) {
this->write(i.fIfFalse.get()); this->write(i.fIfFalse.get());
break; break;
} }
case Statement::kNop_Kind: case Statement::Kind::kNop:
SkASSERT(false); SkASSERT(false);
break; break;
case Statement::kReturn_Kind: { case Statement::Kind::kReturn: {
const ReturnStatement& r = s->as<ReturnStatement>(); const ReturnStatement& r = s->as<ReturnStatement>();
this->writeU8(Rehydrator::kReturn_Command); this->writeU8(Rehydrator::kReturn_Command);
this->write(r.fExpression.get()); this->write(r.fExpression.get());
break; break;
} }
case Statement::kSwitch_Kind: { case Statement::Kind::kSwitch: {
const SwitchStatement& ss = s->as<SwitchStatement>(); const SwitchStatement& ss = s->as<SwitchStatement>();
this->writeU8(Rehydrator::kSwitch_Command); this->writeU8(Rehydrator::kSwitch_Command);
this->writeU8(ss.fIsStatic); this->writeU8(ss.fIsStatic);
@ -466,7 +466,7 @@ void Dehydrator::write(const Statement* s) {
} }
break; break;
} }
case Statement::kVarDeclaration_Kind: { case Statement::Kind::kVarDeclaration: {
const VarDeclaration& v = s->as<VarDeclaration>(); const VarDeclaration& v = s->as<VarDeclaration>();
this->writeU8(Rehydrator::kVarDeclaration_Command); this->writeU8(Rehydrator::kVarDeclaration_Command);
this->writeU16(this->symbolId(v.fVar)); this->writeU16(this->symbolId(v.fVar));
@ -477,12 +477,12 @@ void Dehydrator::write(const Statement* s) {
this->write(v.fValue.get()); this->write(v.fValue.get());
break; break;
} }
case Statement::kVarDeclarations_Kind: { case Statement::Kind::kVarDeclarations: {
const VarDeclarationsStatement& v = s->as<VarDeclarationsStatement>(); const VarDeclarationsStatement& v = s->as<VarDeclarationsStatement>();
this->write(*v.fDeclaration); this->write(*v.fDeclaration);
break; break;
} }
case Statement::kWhile_Kind: { case Statement::Kind::kWhile: {
const WhileStatement& w = s->as<WhileStatement>(); const WhileStatement& w = s->as<WhileStatement>();
this->writeU8(Rehydrator::kWhile_Command); this->writeU8(Rehydrator::kWhile_Command);
this->write(w.fTest.get()); this->write(w.fTest.get());
@ -496,14 +496,14 @@ void Dehydrator::write(const Statement* s) {
} }
void Dehydrator::write(const ProgramElement& e) { void Dehydrator::write(const ProgramElement& e) {
switch (e.fKind) { switch (e.kind()) {
case ProgramElement::kEnum_Kind: { case ProgramElement::Kind::kEnum: {
const Enum& en = e.as<Enum>(); const Enum& en = e.as<Enum>();
this->writeU8(Rehydrator::kEnum_Command); this->writeU8(Rehydrator::kEnum_Command);
this->write(en.fTypeName); this->write(en.fTypeName);
AutoDehydratorSymbolTable symbols(this, en.fSymbols); AutoDehydratorSymbolTable symbols(this, en.fSymbols);
for (const std::unique_ptr<const Symbol>& s : en.fSymbols->fOwnedSymbols) { for (const std::unique_ptr<const Symbol>& s : en.fSymbols->fOwnedSymbols) {
SkASSERT(s->fKind == Symbol::kVariable_Kind); SkASSERT(s->kind() == Symbol::Kind::kVariable);
Variable& v = (Variable&) *s; Variable& v = (Variable&) *s;
SkASSERT(v.fInitialValue); SkASSERT(v.fInitialValue);
const IntLiteral& i = v.fInitialValue->as<IntLiteral>(); const IntLiteral& i = v.fInitialValue->as<IntLiteral>();
@ -511,10 +511,10 @@ void Dehydrator::write(const ProgramElement& e) {
} }
break; break;
} }
case ProgramElement::kExtension_Kind: case ProgramElement::Kind::kExtension:
SkASSERT(false); SkASSERT(false);
break; break;
case ProgramElement::kFunction_Kind: { case ProgramElement::Kind::kFunction: {
const FunctionDefinition& f = e.as<FunctionDefinition>(); const FunctionDefinition& f = e.as<FunctionDefinition>();
this->writeU8(Rehydrator::kFunctionDefinition_Command); this->writeU8(Rehydrator::kFunctionDefinition_Command);
this->writeU16(this->symbolId(&f.fDeclaration)); this->writeU16(this->symbolId(&f.fDeclaration));
@ -529,7 +529,7 @@ void Dehydrator::write(const ProgramElement& e) {
} }
break; break;
} }
case ProgramElement::kInterfaceBlock_Kind: { case ProgramElement::Kind::kInterfaceBlock: {
const InterfaceBlock& i = e.as<InterfaceBlock>(); const InterfaceBlock& i = e.as<InterfaceBlock>();
this->writeU8(Rehydrator::kInterfaceBlock_Command); this->writeU8(Rehydrator::kInterfaceBlock_Command);
this->write(i.fVariable); this->write(i.fVariable);
@ -541,13 +541,13 @@ void Dehydrator::write(const ProgramElement& e) {
} }
break; break;
} }
case ProgramElement::kModifiers_Kind: case ProgramElement::Kind::kModifiers:
SkASSERT(false); SkASSERT(false);
break; break;
case ProgramElement::kSection_Kind: case ProgramElement::Kind::kSection:
SkASSERT(false); SkASSERT(false);
break; break;
case ProgramElement::kVar_Kind: { case ProgramElement::Kind::kVar: {
const VarDeclarations& v = e.as<VarDeclarations>(); const VarDeclarations& v = e.as<VarDeclarations>();
this->writeU8(Rehydrator::kVarDeclarations_Command); this->writeU8(Rehydrator::kVarDeclarations_Command);
this->write(v.fBaseType); this->write(v.fBaseType);

View File

@ -17,7 +17,7 @@ class Type;
class ExternalValue : public Symbol { class ExternalValue : public Symbol {
public: public:
static constexpr Kind kSymbolKind = kExternal_Kind; static constexpr Kind kSymbolKind = Kind::kExternal;
ExternalValue(const char* name, const Type& type) ExternalValue(const char* name, const Type& type)
: INHERITED(-1, kSymbolKind, name) : INHERITED(-1, kSymbolKind, name)

View File

@ -82,8 +82,8 @@ bool GLSLCodeGenerator::usesPrecisionModifiers() const {
} }
String GLSLCodeGenerator::getTypeName(const Type& type) { String GLSLCodeGenerator::getTypeName(const Type& type) {
switch (type.kind()) { switch (type.typeKind()) {
case Type::kVector_Kind: { case Type::TypeKind::kVector: {
const Type& component = type.componentType(); const Type& component = type.componentType();
String result; String result;
if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) { if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
@ -104,7 +104,7 @@ String GLSLCodeGenerator::getTypeName(const Type& type) {
result += to_string(type.columns()); result += to_string(type.columns());
return result; return result;
} }
case Type::kMatrix_Kind: { case Type::TypeKind::kMatrix: {
String result; String result;
const Type& component = type.componentType(); const Type& component = type.componentType();
if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) { if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
@ -120,7 +120,7 @@ String GLSLCodeGenerator::getTypeName(const Type& type) {
} }
return result; return result;
} }
case Type::kArray_Kind: { case Type::TypeKind::kArray: {
String result = this->getTypeName(type.componentType()) + "["; String result = this->getTypeName(type.componentType()) + "[";
if (type.columns() != -1) { if (type.columns() != -1) {
result += to_string(type.columns()); result += to_string(type.columns());
@ -128,7 +128,7 @@ String GLSLCodeGenerator::getTypeName(const Type& type) {
result += "]"; result += "]";
return result; return result;
} }
case Type::kScalar_Kind: { case Type::TypeKind::kScalar: {
if (type == *fContext.fHalf_Type) { if (type == *fContext.fHalf_Type) {
return "float"; return "float";
} }
@ -149,7 +149,7 @@ String GLSLCodeGenerator::getTypeName(const Type& type) {
} }
break; break;
} }
case Type::kEnum_Kind: case Type::TypeKind::kEnum:
return "int"; return "int";
default: default:
return type.name(); return type.name();
@ -157,7 +157,7 @@ String GLSLCodeGenerator::getTypeName(const Type& type) {
} }
void GLSLCodeGenerator::writeType(const Type& type) { void GLSLCodeGenerator::writeType(const Type& type) {
if (type.kind() == Type::kStruct_Kind) { if (type.typeKind() == Type::TypeKind::kStruct) {
for (const Type* search : fWrittenStructs) { for (const Type* search : fWrittenStructs) {
if (*search == type) { if (*search == type) {
// already written // already written
@ -187,47 +187,47 @@ void GLSLCodeGenerator::writeType(const Type& type) {
} }
void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) { void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kBinary_Kind: case Expression::Kind::kBinary:
this->writeBinaryExpression(expr.as<BinaryExpression>(), parentPrecedence); this->writeBinaryExpression(expr.as<BinaryExpression>(), parentPrecedence);
break; break;
case Expression::kBoolLiteral_Kind: case Expression::Kind::kBoolLiteral:
this->writeBoolLiteral(expr.as<BoolLiteral>()); this->writeBoolLiteral(expr.as<BoolLiteral>());
break; break;
case Expression::kConstructor_Kind: case Expression::Kind::kConstructor:
this->writeConstructor(expr.as<Constructor>(), parentPrecedence); this->writeConstructor(expr.as<Constructor>(), parentPrecedence);
break; break;
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
this->writeIntLiteral(expr.as<IntLiteral>()); this->writeIntLiteral(expr.as<IntLiteral>());
break; break;
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
this->writeFieldAccess(expr.as<FieldAccess>()); this->writeFieldAccess(expr.as<FieldAccess>());
break; break;
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
this->writeFloatLiteral(expr.as<FloatLiteral>()); this->writeFloatLiteral(expr.as<FloatLiteral>());
break; break;
case Expression::kFunctionCall_Kind: case Expression::Kind::kFunctionCall:
this->writeFunctionCall(expr.as<FunctionCall>()); this->writeFunctionCall(expr.as<FunctionCall>());
break; break;
case Expression::kPrefix_Kind: case Expression::Kind::kPrefix:
this->writePrefixExpression(expr.as<PrefixExpression>(), parentPrecedence); this->writePrefixExpression(expr.as<PrefixExpression>(), parentPrecedence);
break; break;
case Expression::kPostfix_Kind: case Expression::Kind::kPostfix:
this->writePostfixExpression(expr.as<PostfixExpression>(), parentPrecedence); this->writePostfixExpression(expr.as<PostfixExpression>(), parentPrecedence);
break; break;
case Expression::kSetting_Kind: case Expression::Kind::kSetting:
this->writeSetting(expr.as<Setting>()); this->writeSetting(expr.as<Setting>());
break; break;
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
this->writeSwizzle(expr.as<Swizzle>()); this->writeSwizzle(expr.as<Swizzle>());
break; break;
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
this->writeVariableReference(expr.as<VariableReference>()); this->writeVariableReference(expr.as<VariableReference>());
break; break;
case Expression::kTernary_Kind: case Expression::Kind::kTernary:
this->writeTernaryExpression(expr.as<TernaryExpression>(), parentPrecedence); this->writeTernaryExpression(expr.as<TernaryExpression>(), parentPrecedence);
break; break;
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
this->writeIndexExpression(expr.as<IndexExpression>()); this->writeIndexExpression(expr.as<IndexExpression>());
break; break;
default: default:
@ -239,7 +239,7 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren
} }
static bool is_abs(Expression& expr) { static bool is_abs(Expression& expr) {
if (expr.fKind != Expression::kFunctionCall_Kind) { if (expr.kind() != Expression::Kind::kFunctionCall) {
return false; return false;
} }
return expr.as<FunctionCall>().fFunction.fName == "abs"; return expr.as<FunctionCall>().fFunction.fName == "abs";
@ -506,7 +506,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
case FunctionClass::kAtan: case FunctionClass::kAtan:
if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() && if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() &&
c.fArguments.size() == 2 && c.fArguments.size() == 2 &&
c.fArguments[1]->fKind == Expression::kPrefix_Kind) { c.fArguments[1]->kind() == Expression::Kind::kPrefix) {
const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1]; const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1];
if (p.fOperator == Token::Kind::TK_MINUS) { if (p.fOperator == Token::Kind::TK_MINUS) {
this->write("atan("); this->write("atan(");
@ -713,7 +713,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) { void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) {
if (c.fArguments.size() == 1 && if (c.fArguments.size() == 1 &&
(this->getTypeName(c.fType) == this->getTypeName(c.fArguments[0]->fType) || (this->getTypeName(c.fType) == this->getTypeName(c.fArguments[0]->fType) ||
(c.fType.kind() == Type::kScalar_Kind && (c.fType.typeKind() == Type::TypeKind::kScalar &&
c.fArguments[0]->fType == *fContext.fFloatLiteral_Type))) { c.fArguments[0]->fType == *fContext.fFloatLiteral_Type))) {
// in cases like half(float), they're different types as far as SkSL is concerned but the // in cases like half(float), they're different types as far as SkSL is concerned but the
// same type as far as GLSL is concerned. We avoid a redundant float(float) by just writing // same type as far as GLSL is concerned. We avoid a redundant float(float) by just writing
@ -1097,7 +1097,7 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
} }
bool positionWorkaround = fProgramKind == Program::Kind::kVertex_Kind && bool positionWorkaround = fProgramKind == Program::Kind::kVertex_Kind &&
Compiler::IsAssignment(b.fOperator) && Compiler::IsAssignment(b.fOperator) &&
Expression::kFieldAccess_Kind == b.fLeft->fKind && b.fLeft->kind() == Expression::Kind::kFieldAccess &&
is_sk_position((FieldAccess&) *b.fLeft) && is_sk_position((FieldAccess&) *b.fLeft) &&
!b.fRight->containsRTAdjust() && !b.fRight->containsRTAdjust() &&
!fProgram.fSettings.fCaps->canUseFragCoord(); !fProgram.fSettings.fCaps->canUseFragCoord();
@ -1227,7 +1227,7 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->writeModifiers(param->fModifiers, false); this->writeModifiers(param->fModifiers, false);
std::vector<int> sizes; std::vector<int> sizes;
const Type* type = &param->fType; const Type* type = &param->fType;
while (type->kind() == Type::kArray_Kind) { while (type->typeKind() == Type::TypeKind::kArray) {
sizes.push_back(type->columns()); sizes.push_back(type->columns());
type = &type->componentType(); type = &type->componentType();
} }
@ -1350,7 +1350,7 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
this->writeLine(intf.fTypeName + " {"); this->writeLine(intf.fTypeName + " {");
fIndentation++; fIndentation++;
const Type* structType = &intf.fVariable.fType; const Type* structType = &intf.fVariable.fType;
while (structType->kind() == Type::kArray_Kind) { while (structType->typeKind() == Type::TypeKind::kArray) {
structType = &structType->componentType(); structType = &structType->componentType();
} }
for (const auto& f : structType->fields()) { for (const auto& f : structType->fields()) {
@ -1381,8 +1381,8 @@ void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expressio
const char* GLSLCodeGenerator::getTypePrecision(const Type& type) { const char* GLSLCodeGenerator::getTypePrecision(const Type& type) {
if (usesPrecisionModifiers()) { if (usesPrecisionModifiers()) {
switch (type.kind()) { switch (type.typeKind()) {
case Type::kScalar_Kind: case Type::TypeKind::kScalar:
if (type == *fContext.fShort_Type || type == *fContext.fUShort_Type || if (type == *fContext.fShort_Type || type == *fContext.fUShort_Type ||
type == *fContext.fByte_Type || type == *fContext.fUByte_Type) { type == *fContext.fByte_Type || type == *fContext.fUByte_Type) {
if (fProgram.fSettings.fForceHighPrecision || if (fProgram.fSettings.fForceHighPrecision ||
@ -1399,8 +1399,8 @@ const char* GLSLCodeGenerator::getTypePrecision(const Type& type) {
return "highp "; return "highp ";
} }
return ""; return "";
case Type::kVector_Kind: // fall through case Type::TypeKind::kVector: // fall through
case Type::kMatrix_Kind: case Type::TypeKind::kMatrix:
return this->getTypePrecision(type.componentType()); return this->getTypePrecision(type.componentType());
default: default:
break; break;
@ -1461,45 +1461,45 @@ void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool g
} }
void GLSLCodeGenerator::writeStatement(const Statement& s) { void GLSLCodeGenerator::writeStatement(const Statement& s) {
switch (s.fKind) { switch (s.kind()) {
case Statement::kBlock_Kind: case Statement::Kind::kBlock:
this->writeBlock(s.as<Block>()); this->writeBlock(s.as<Block>());
break; break;
case Statement::kExpression_Kind: case Statement::Kind::kExpression:
this->writeExpression(*s.as<ExpressionStatement>().fExpression, kTopLevel_Precedence); this->writeExpression(*s.as<ExpressionStatement>().fExpression, kTopLevel_Precedence);
this->write(";"); this->write(";");
break; break;
case Statement::kReturn_Kind: case Statement::Kind::kReturn:
this->writeReturnStatement(s.as<ReturnStatement>()); this->writeReturnStatement(s.as<ReturnStatement>());
break; break;
case Statement::kVarDeclarations_Kind: case Statement::Kind::kVarDeclarations:
this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration, false); this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration, false);
break; break;
case Statement::kIf_Kind: case Statement::Kind::kIf:
this->writeIfStatement(s.as<IfStatement>()); this->writeIfStatement(s.as<IfStatement>());
break; break;
case Statement::kFor_Kind: case Statement::Kind::kFor:
this->writeForStatement(s.as<ForStatement>()); this->writeForStatement(s.as<ForStatement>());
break; break;
case Statement::kWhile_Kind: case Statement::Kind::kWhile:
this->writeWhileStatement(s.as<WhileStatement>()); this->writeWhileStatement(s.as<WhileStatement>());
break; break;
case Statement::kDo_Kind: case Statement::Kind::kDo:
this->writeDoStatement(s.as<DoStatement>()); this->writeDoStatement(s.as<DoStatement>());
break; break;
case Statement::kSwitch_Kind: case Statement::Kind::kSwitch:
this->writeSwitchStatement(s.as<SwitchStatement>()); this->writeSwitchStatement(s.as<SwitchStatement>());
break; break;
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
this->write("break;"); this->write("break;");
break; break;
case Statement::kContinue_Kind: case Statement::Kind::kContinue:
this->write("continue;"); this->write("continue;");
break; break;
case Statement::kDiscard_Kind: case Statement::Kind::kDiscard:
this->write("discard;"); this->write("discard;");
break; break;
case Statement::kNop_Kind: case Statement::Kind::kNop:
this->write(";"); this->write(";");
break; break;
default: default:
@ -1667,11 +1667,11 @@ void GLSLCodeGenerator::writeHeader() {
} }
void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
switch (e.fKind) { switch (e.kind()) {
case ProgramElement::kExtension_Kind: case ProgramElement::Kind::kExtension:
this->writeExtension(e.as<Extension>().fName); this->writeExtension(e.as<Extension>().fName);
break; break;
case ProgramElement::kVar_Kind: { case ProgramElement::Kind::kVar: {
const VarDeclarations& decl = e.as<VarDeclarations>(); const VarDeclarations& decl = e.as<VarDeclarations>();
if (decl.fVars.size() > 0) { if (decl.fVars.size() > 0) {
int builtin = decl.fVars[0]->as<VarDeclaration>().fVar->fModifiers.fLayout.fBuiltin; int builtin = decl.fVars[0]->as<VarDeclaration>().fVar->fModifiers.fLayout.fBuiltin;
@ -1695,13 +1695,13 @@ void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
} }
break; break;
} }
case ProgramElement::kInterfaceBlock_Kind: case ProgramElement::Kind::kInterfaceBlock:
this->writeInterfaceBlock(e.as<InterfaceBlock>()); this->writeInterfaceBlock(e.as<InterfaceBlock>());
break; break;
case ProgramElement::kFunction_Kind: case ProgramElement::Kind::kFunction:
this->writeFunction(e.as<FunctionDefinition>()); this->writeFunction(e.as<FunctionDefinition>());
break; break;
case ProgramElement::kModifiers_Kind: { case ProgramElement::Kind::kModifiers: {
const Modifiers& modifiers = e.as<ModifiersDeclaration>().fModifiers; const Modifiers& modifiers = e.as<ModifiersDeclaration>().fModifiers;
if (!fFoundGSInvocations && modifiers.fLayout.fInvocations >= 0) { if (!fFoundGSInvocations && modifiers.fLayout.fInvocations >= 0) {
if (fProgram.fSettings.fCaps->gsInvocationsExtensionString()) { if (fProgram.fSettings.fCaps->gsInvocationsExtensionString()) {
@ -1713,7 +1713,7 @@ void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
this->writeLine(";"); this->writeLine(";");
break; break;
} }
case ProgramElement::kEnum_Kind: case ProgramElement::Kind::kEnum:
break; break;
default: default:
#ifdef SK_DEBUG #ifdef SK_DEBUG

View File

@ -33,7 +33,7 @@ HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
String HCodeGenerator::ParameterType(const Context& context, const Type& type, String HCodeGenerator::ParameterType(const Context& context, const Type& type,
const Layout& layout) { const Layout& layout) {
if (type.kind() == Type::kArray_Kind) { if (type.typeKind() == Type::TypeKind::kArray) {
return String::printf("std::array<%s>", ParameterType(context, type.componentType(), return String::printf("std::array<%s>", ParameterType(context, type.componentType(),
layout).c_str()); layout).c_str());
} }
@ -46,11 +46,11 @@ String HCodeGenerator::ParameterType(const Context& context, const Type& type,
Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type& type, Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type& type,
const Layout& layout) { const Layout& layout) {
SkASSERT(type.kind() != Type::kArray_Kind); SkASSERT(type.typeKind() != Type::TypeKind::kArray);
if (layout.fCType != Layout::CType::kDefault) { if (layout.fCType != Layout::CType::kDefault) {
return layout.fCType; return layout.fCType;
} }
if (type.kind() == Type::kNullable_Kind) { if (type.typeKind() == Type::TypeKind::kNullable) {
return ParameterCType(context, type.componentType(), layout); return ParameterCType(context, type.componentType(), layout);
} else if (type == *context.fFloat_Type || type == *context.fHalf_Type) { } else if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
return Layout::CType::kFloat; return Layout::CType::kFloat;
@ -74,7 +74,7 @@ Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type&
return Layout::CType::kSkMatrix; return Layout::CType::kSkMatrix;
} else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) { } else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) {
return Layout::CType::kSkM44; return Layout::CType::kSkM44;
} else if (type.kind() == Type::kSampler_Kind) { } else if (type.typeKind() == Type::TypeKind::kSampler) {
return Layout::CType::kGrSurfaceProxyView; return Layout::CType::kGrSurfaceProxyView;
} else if (type == *context.fFragmentProcessor_Type) { } else if (type == *context.fFragmentProcessor_Type) {
return Layout::CType::kGrFragmentProcessor; return Layout::CType::kGrFragmentProcessor;
@ -84,7 +84,7 @@ Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type&
String HCodeGenerator::FieldType(const Context& context, const Type& type, String HCodeGenerator::FieldType(const Context& context, const Type& type,
const Layout& layout) { const Layout& layout) {
if (type.kind() == Type::kSampler_Kind) { if (type.typeKind() == Type::TypeKind::kSampler) {
return "TextureSampler"; return "TextureSampler";
} else if (type == *context.fFragmentProcessor_Type) { } else if (type == *context.fFragmentProcessor_Type) {
// we don't store fragment processors in fields, they get registered via // we don't store fragment processors in fields, they get registered via
@ -201,7 +201,7 @@ void HCodeGenerator::writeMake() {
separator = ""; separator = "";
for (const auto& param : fSectionAndParameterHelper.getParameters()) { for (const auto& param : fSectionAndParameterHelper.getParameters()) {
if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type || if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type ||
param->fType.nonnullable().kind() == Type::kSampler_Kind) { param->fType.nonnullable().typeKind() == Type::TypeKind::kSampler) {
this->writef("%sstd::move(%s)", separator, String(param->fName).c_str()); this->writef("%sstd::move(%s)", separator, String(param->fName).c_str());
} else { } else {
this->writef("%s%s", separator, String(param->fName).c_str()); this->writef("%s%s", separator, String(param->fName).c_str());
@ -250,7 +250,7 @@ void HCodeGenerator::writeConstructor() {
String nameString(param->fName); String nameString(param->fName);
const char* name = nameString.c_str(); const char* name = nameString.c_str();
const Type& type = param->fType.nonnullable(); const Type& type = param->fType.nonnullable();
if (type.kind() == Type::kSampler_Kind) { if (type.typeKind() == Type::TypeKind::kSampler) {
this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name); this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name);
for (const Section* s : fSectionAndParameterHelper.getSections( for (const Section* s : fSectionAndParameterHelper.getSections(
kSamplerParamsSection)) { kSamplerParamsSection)) {
@ -274,10 +274,10 @@ void HCodeGenerator::writeConstructor() {
int samplerCount = 0; int samplerCount = 0;
for (const Variable* param : fSectionAndParameterHelper.getParameters()) { for (const Variable* param : fSectionAndParameterHelper.getParameters()) {
if (param->fType.kind() == Type::kSampler_Kind) { if (param->fType.typeKind() == Type::TypeKind::kSampler) {
++samplerCount; ++samplerCount;
} else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) { } else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
if (param->fType.kind() != Type::kNullable_Kind) { if (param->fType.typeKind() != Type::TypeKind::kNullable) {
this->writef(" SkASSERT(%s);", String(param->fName).c_str()); this->writef(" SkASSERT(%s);", String(param->fName).c_str());
} }
@ -355,7 +355,7 @@ bool HCodeGenerator::generateCode() {
"public:\n", "public:\n",
fFullName.c_str()); fFullName.c_str());
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kEnum_Kind == p.fKind && !((Enum&) p).fBuiltin) { if (p.kind() == ProgramElement::Kind::kEnum && !((Enum&) p).fBuiltin) {
this->writef("%s\n", ((Enum&) p).code().c_str()); this->writef("%s\n", ((Enum&) p).code().c_str());
} }
} }
@ -374,7 +374,7 @@ bool HCodeGenerator::generateCode() {
"GrProcessorKeyBuilder*) const override;\n" "GrProcessorKeyBuilder*) const override;\n"
" bool onIsEqual(const GrFragmentProcessor&) const override;\n"); " bool onIsEqual(const GrFragmentProcessor&) const override;\n");
for (const auto& param : fSectionAndParameterHelper.getParameters()) { for (const auto& param : fSectionAndParameterHelper.getParameters()) {
if (param->fType.kind() == Type::kSampler_Kind) { if (param->fType.typeKind() == Type::TypeKind::kSampler) {
this->writef(" const TextureSampler& onTextureSampler(int) const override;"); this->writef(" const TextureSampler& onTextureSampler(int) const override;");
break; break;
} }

View File

@ -185,7 +185,7 @@ void IRGenerator::start(const Program::Settings* settings,
fTmpSwizzleCounter = 0; fTmpSwizzleCounter = 0;
if (inherited) { if (inherited) {
for (const auto& e : *inherited) { for (const auto& e : *inherited) {
if (e->fKind == ProgramElement::kInterfaceBlock_Kind) { if (e->kind() == ProgramElement::Kind::kInterfaceBlock) {
InterfaceBlock& intf = e->as<InterfaceBlock>(); InterfaceBlock& intf = e->as<InterfaceBlock>();
if (intf.fVariable.fName == Compiler::PERVERTEX_NAME) { if (intf.fVariable.fName == Compiler::PERVERTEX_NAME) {
SkASSERT(!fSkPerVertex); SkASSERT(!fSkPerVertex);
@ -243,10 +243,10 @@ std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& st
default: default:
// it's an expression // it's an expression
std::unique_ptr<Statement> result = this->convertExpressionStatement(statement); std::unique_ptr<Statement> result = this->convertExpressionStatement(statement);
if (fRTAdjust && Program::kGeometry_Kind == fKind) { if (fRTAdjust && fKind == Program::kGeometry_Kind) {
SkASSERT(result->fKind == Statement::kExpression_Kind); SkASSERT(result->kind() == Statement::Kind::kExpression);
Expression& expr = *result->as<ExpressionStatement>().fExpression; Expression& expr = *result->as<ExpressionStatement>().fExpression;
if (expr.fKind == Expression::kFunctionCall_Kind) { if (expr.kind() == Expression::Kind::kFunctionCall) {
FunctionCall& fc = expr.as<FunctionCall>(); FunctionCall& fc = expr.as<FunctionCall>();
if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") { if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
std::vector<std::unique_ptr<Statement>> statements; std::vector<std::unique_ptr<Statement>> statements;
@ -320,7 +320,7 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNo
} }
if (fKind != Program::kFragmentProcessor_Kind) { if (fKind != Program::kFragmentProcessor_Kind) {
if ((modifiers.fFlags & Modifiers::kIn_Flag) && if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
baseType->kind() == Type::Kind::kMatrix_Kind) { baseType->typeKind() == Type::TypeKind::kMatrix) {
fErrors.error(decls.fOffset, "'in' variables may not have matrix type"); fErrors.error(decls.fOffset, "'in' variables may not have matrix type");
} }
if ((modifiers.fFlags & Modifiers::kIn_Flag) && if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
@ -370,10 +370,10 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNo
"'srgb_unpremul' is only permitted on 'uniform' variables"); "'srgb_unpremul' is only permitted on 'uniform' variables");
} }
auto validColorXformType = [](const Type& t) { auto validColorXformType = [](const Type& t) {
return t.kind() == Type::kVector_Kind && t.componentType().isFloat() && return t.typeKind() == Type::TypeKind::kVector && t.componentType().isFloat() &&
(t.columns() == 3 || t.columns() == 4); (t.columns() == 3 || t.columns() == 4);
}; };
if (!validColorXformType(*baseType) && !(baseType->kind() == Type::kArray_Kind && if (!validColorXformType(*baseType) && !(baseType->typeKind() == Type::TypeKind::kArray &&
validColorXformType(baseType->componentType()))) { validColorXformType(baseType->componentType()))) {
fErrors.error(decls.fOffset, fErrors.error(decls.fOffset,
"'srgb_unpremul' is only permitted on half3, half4, float3, or float4 " "'srgb_unpremul' is only permitted on half3, half4, float3, or float4 "
@ -385,7 +385,8 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNo
fErrors.error(decls.fOffset, "'varying' is only permitted in runtime effects"); fErrors.error(decls.fOffset, "'varying' is only permitted in runtime effects");
} }
if (!baseType->isFloat() && if (!baseType->isFloat() &&
!(baseType->kind() == Type::kVector_Kind && baseType->componentType().isFloat())) { !(baseType->typeKind() == Type::TypeKind::kVector &&
baseType->componentType().isFloat())) {
fErrors.error(decls.fOffset, "'varying' must be float scalar or vector"); fErrors.error(decls.fOffset, "'varying' must be float scalar or vector");
} }
} }
@ -421,7 +422,7 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNo
} }
String name(type->fName); String name(type->fName);
int64_t count; int64_t count;
if (size->fKind == Expression::kIntLiteral_Kind) { if (size->kind() == Expression::Kind::kIntLiteral) {
count = size->as<IntLiteral>().fValue; count = size->as<IntLiteral>().fValue;
if (count <= 0) { if (count <= 0) {
fErrors.error(size->fOffset, "array size must be positive"); fErrors.error(size->fOffset, "array size must be positive");
@ -433,11 +434,11 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNo
return nullptr; return nullptr;
} }
type = fSymbolTable->takeOwnershipOfSymbol( type = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count)); std::make_unique<Type>(name, Type::TypeKind::kArray, *type, (int)count));
sizes.push_back(std::move(size)); sizes.push_back(std::move(size));
} else { } else {
type = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>( type = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
type->name() + "[]", Type::kArray_Kind, *type, /*columns=*/-1)); type->name() + "[]", Type::TypeKind::kArray, *type, /*columns=*/-1));
sizes.push_back(nullptr); sizes.push_back(nullptr);
} }
} }
@ -465,7 +466,7 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNo
if (symbol && storage == Variable::kGlobal_Storage && var->fName == "sk_FragColor") { if (symbol && storage == Variable::kGlobal_Storage && var->fName == "sk_FragColor") {
// Already defined, ignore. // Already defined, ignore.
} else if (symbol && storage == Variable::kGlobal_Storage && } else if (symbol && storage == Variable::kGlobal_Storage &&
symbol->fKind == Symbol::kVariable_Kind && symbol->kind() == Symbol::Kind::kVariable &&
symbol->as<Variable>().fModifiers.fLayout.fBuiltin >= 0) { symbol->as<Variable>().fModifiers.fLayout.fBuiltin >= 0) {
// Already defined, just update the modifiers. // Already defined, just update the modifiers.
symbol->as<Variable>().fModifiers = var->fModifiers; symbol->as<Variable>().fModifiers = var->fModifiers;
@ -514,7 +515,7 @@ std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(c
static void ensure_scoped_blocks(Statement* stmt) { static void ensure_scoped_blocks(Statement* stmt) {
// No changes necessary if this statement isn't actually a block. // No changes necessary if this statement isn't actually a block.
if (stmt->fKind != Statement::kBlock_Kind) { if (stmt->kind() != Statement::Kind::kBlock) {
return; return;
} }
@ -538,7 +539,7 @@ static void ensure_scoped_blocks(Statement* stmt) {
block.fIsScope = true; block.fIsScope = true;
return; return;
} }
if (nestedBlock->fStatements[0]->fKind != Statement::kBlock_Kind) { if (nestedBlock->fStatements[0]->kind() != Statement::Kind::kBlock) {
// This block has exactly one thing inside, and it's not another block. No need to scope // This block has exactly one thing inside, and it's not another block. No need to scope
// it. // it.
return; return;
@ -569,7 +570,7 @@ std::unique_ptr<Statement> IRGenerator::convertIf(const ASTNode& n) {
} }
ensure_scoped_blocks(ifFalse.get()); ensure_scoped_blocks(ifFalse.get());
} }
if (test->fKind == Expression::kBoolLiteral_Kind) { if (test->kind() == Expression::Kind::kBoolLiteral) {
// static boolean value, fold down to a single branch // static boolean value, fold down to a single branch
if (test->as<BoolLiteral>().fValue) { if (test->as<BoolLiteral>().fValue) {
return ifTrue; return ifTrue;
@ -674,7 +675,8 @@ std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTNode& s) {
if (!value) { if (!value) {
return nullptr; return nullptr;
} }
if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) { if (value->fType != *fContext.fUInt_Type &&
value->fType.typeKind() != Type::TypeKind::kEnum) {
value = this->coerce(std::move(value), *fContext.fInt_Type); value = this->coerce(std::move(value), *fContext.fInt_Type);
if (!value) { if (!value) {
return nullptr; return nullptr;
@ -972,7 +974,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
int size = (param.begin() + j)->getInt(); int size = (param.begin() + j)->getInt();
String name = type->name() + "[" + to_string(size) + "]"; String name = type->name() + "[" + to_string(size) + "]";
type = fSymbolTable->takeOwnershipOfSymbol( type = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(std::move(name), Type::kArray_Kind, *type, size)); std::make_unique<Type>(std::move(name), Type::TypeKind::kArray, *type, size));
} }
// Only the (builtin) declarations of 'sample' are allowed to have FP parameters // Only the (builtin) declarations of 'sample' are allowed to have FP parameters
if ((type->nonnullable() == *fContext.fFragmentProcessor_Type && !fIsBuiltinCode) || if ((type->nonnullable() == *fContext.fFragmentProcessor_Type && !fIsBuiltinCode) ||
@ -1029,11 +1031,11 @@ void IRGenerator::convertFunction(const ASTNode& f) {
const Symbol* entry = (*fSymbolTable)[funcData.fName]; const Symbol* entry = (*fSymbolTable)[funcData.fName];
if (entry) { if (entry) {
std::vector<const FunctionDeclaration*> functions; std::vector<const FunctionDeclaration*> functions;
switch (entry->fKind) { switch (entry->kind()) {
case Symbol::kUnresolvedFunction_Kind: case Symbol::Kind::kUnresolvedFunction:
functions = entry->as<UnresolvedFunction>().fFunctions; functions = entry->as<UnresolvedFunction>().fFunctions;
break; break;
case Symbol::kFunctionDeclaration_Kind: case Symbol::Kind::kFunctionDeclaration:
functions.push_back(&entry->as<FunctionDeclaration>()); functions.push_back(&entry->as<FunctionDeclaration>());
break; break;
default: default:
@ -1172,7 +1174,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
fErrors.error(decl->fOffset, fErrors.error(decl->fOffset,
"initializers are not permitted on interface block fields"); "initializers are not permitted on interface block fields");
} }
if (vd.fVar->fType.kind() == Type::kArray_Kind && if (vd.fVar->fType.typeKind() == Type::TypeKind::kArray &&
vd.fVar->fType.columns() == -1) { vd.fVar->fType.columns() == -1) {
haveRuntimeArray = true; haveRuntimeArray = true;
} }
@ -1191,7 +1193,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
} }
String name = type->fName; String name = type->fName;
int64_t count; int64_t count;
if (converted->fKind == Expression::kIntLiteral_Kind) { if (converted->kind() == Expression::Kind::kIntLiteral) {
count = converted->as<IntLiteral>().fValue; count = converted->as<IntLiteral>().fValue;
if (count <= 0) { if (count <= 0) {
fErrors.error(converted->fOffset, "array size must be positive"); fErrors.error(converted->fOffset, "array size must be positive");
@ -1203,7 +1205,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
return nullptr; return nullptr;
} }
type = symbols->takeOwnershipOfSymbol( type = symbols->takeOwnershipOfSymbol(
std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count)); std::make_unique<Type>(name, Type::TypeKind::kArray, *type, (int)count));
sizes.push_back(std::move(converted)); sizes.push_back(std::move(converted));
} else { } else {
fErrors.error(intf.fOffset, "array size must be specified"); fErrors.error(intf.fOffset, "array size must be specified");
@ -1235,11 +1237,11 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
} }
bool IRGenerator::getConstantInt(const Expression& value, int64_t* out) { bool IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
switch (value.fKind) { switch (value.kind()) {
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
*out = static_cast<const IntLiteral&>(value).fValue; *out = static_cast<const IntLiteral&>(value).fValue;
return true; return true;
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const Variable& var = static_cast<const VariableReference&>(value).fVariable; const Variable& var = static_cast<const VariableReference&>(value).fVariable;
return (var.fModifiers.fFlags & Modifiers::kConst_Flag) && return (var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
var.fInitialValue && var.fInitialValue &&
@ -1292,7 +1294,7 @@ void IRGenerator::convertEnum(const ASTNode& e) {
const Type* IRGenerator::convertType(const ASTNode& type) { const Type* IRGenerator::convertType(const ASTNode& type) {
ASTNode::TypeData td = type.getTypeData(); ASTNode::TypeData td = type.getTypeData();
const Symbol* result = (*fSymbolTable)[td.fName]; const Symbol* result = (*fSymbolTable)[td.fName];
if (result && result->fKind == Symbol::kType_Kind) { if (result && result->kind() == Symbol::Kind::kType) {
if (td.fIsNullable) { if (td.fIsNullable) {
if (result->as<Type>() == *fContext.fFragmentProcessor_Type) { if (result->as<Type>() == *fContext.fFragmentProcessor_Type) {
if (type.begin() != type.end()) { if (type.begin() != type.end()) {
@ -1300,7 +1302,7 @@ const Type* IRGenerator::convertType(const ASTNode& type) {
"an array"); "an array");
} }
result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>( result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
String(result->fName) + "?", Type::kNullable_Kind, result->as<Type>())); String(result->fName) + "?", Type::TypeKind::kNullable, result->as<Type>()));
} else { } else {
fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable"); fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable");
} }
@ -1313,7 +1315,7 @@ const Type* IRGenerator::convertType(const ASTNode& type) {
} }
name += "]"; name += "]";
result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>( result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
name, Type::kArray_Kind, result->as<Type>(), size ? size.getInt() : 0)); name, Type::TypeKind::kArray, result->as<Type>(), size ? size.getInt() : 0));
} }
return &result->as<Type>(); return &result->as<Type>();
} }
@ -1365,18 +1367,18 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.getString() + "'"); fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.getString() + "'");
return nullptr; return nullptr;
} }
switch (result->fKind) { switch (result->kind()) {
case Symbol::kFunctionDeclaration_Kind: { case Symbol::Kind::kFunctionDeclaration: {
std::vector<const FunctionDeclaration*> f = { std::vector<const FunctionDeclaration*> f = {
&result->as<FunctionDeclaration>() &result->as<FunctionDeclaration>()
}; };
return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f); return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f);
} }
case Symbol::kUnresolvedFunction_Kind: { case Symbol::Kind::kUnresolvedFunction: {
const UnresolvedFunction* f = &result->as<UnresolvedFunction>(); const UnresolvedFunction* f = &result->as<UnresolvedFunction>();
return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f->fFunctions); return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f->fFunctions);
} }
case Symbol::kVariable_Kind: { case Symbol::Kind::kVariable: {
const Variable* var = &result->as<Variable>(); const Variable* var = &result->as<Variable>();
switch (var->fModifiers.fLayout.fBuiltin) { switch (var->fModifiers.fLayout.fBuiltin) {
case SK_WIDTH_BUILTIN: case SK_WIDTH_BUILTIN:
@ -1401,7 +1403,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
!var->fModifiers.fLayout.fKey && !var->fModifiers.fLayout.fKey &&
var->fModifiers.fLayout.fBuiltin == -1 && var->fModifiers.fLayout.fBuiltin == -1 &&
var->fType.nonnullable() != *fContext.fFragmentProcessor_Type && var->fType.nonnullable() != *fContext.fFragmentProcessor_Type &&
var->fType.kind() != Type::kSampler_Kind) { var->fType.typeKind() != Type::TypeKind::kSampler) {
bool valid = false; bool valid = false;
for (const auto& decl : fFile->root()) { for (const auto& decl : fFile->root()) {
if (decl.fKind == ASTNode::Kind::kSection) { if (decl.fKind == ASTNode::Kind::kSection) {
@ -1423,7 +1425,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
*var, *var,
VariableReference::kRead_RefKind); VariableReference::kRead_RefKind);
} }
case Symbol::kField_Kind: { case Symbol::Kind::kField: {
const Field* field = &result->as<Field>(); const Field* field = &result->as<Field>();
VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner, VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
VariableReference::kRead_RefKind); VariableReference::kRead_RefKind);
@ -1432,16 +1434,16 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
field->fFieldIndex, field->fFieldIndex,
FieldAccess::kAnonymousInterfaceBlock_OwnerKind)); FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
} }
case Symbol::kType_Kind: { case Symbol::Kind::kType: {
const Type* t = &result->as<Type>(); const Type* t = &result->as<Type>();
return std::make_unique<TypeReference>(fContext, identifier.fOffset, *t); return std::make_unique<TypeReference>(fContext, identifier.fOffset, t);
} }
case Symbol::kExternal_Kind: { case Symbol::Kind::kExternal: {
const ExternalValue* r = &result->as<ExternalValue>(); const ExternalValue* r = &result->as<ExternalValue>();
return std::make_unique<ExternalValueReference>(identifier.fOffset, r); return std::make_unique<ExternalValueReference>(identifier.fOffset, r);
} }
default: default:
ABORT("unsupported symbol type %d\n", result->fKind); ABORT("unsupported symbol type %d\n", (int) result->kind());
} }
} }
@ -1474,7 +1476,7 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
expr->fType.displayName() + "'"); expr->fType.displayName() + "'");
return nullptr; return nullptr;
} }
if (type.kind() == Type::kScalar_Kind) { if (type.typeKind() == Type::TypeKind::kScalar) {
std::vector<std::unique_ptr<Expression>> args; std::vector<std::unique_ptr<Expression>> args;
args.push_back(std::move(expr)); args.push_back(std::move(expr));
std::unique_ptr<Expression> ctor; std::unique_ptr<Expression> ctor;
@ -1494,8 +1496,8 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
SkASSERT(ctor); SkASSERT(ctor);
return this->call(-1, std::move(ctor), std::move(args)); return this->call(-1, std::move(ctor), std::move(args));
} }
if (expr->fKind == Expression::kNullLiteral_Kind) { if (expr->kind() == Expression::Kind::kNullLiteral) {
SkASSERT(type.kind() == Type::kNullable_Kind); SkASSERT(type.typeKind() == Type::TypeKind::kNullable);
return std::unique_ptr<Expression>(new NullLiteral(expr->fOffset, type)); return std::unique_ptr<Expression>(new NullLiteral(expr->fOffset, type));
} }
std::vector<std::unique_ptr<Expression>> args; std::vector<std::unique_ptr<Expression>> args;
@ -1504,10 +1506,12 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
} }
static bool is_matrix_multiply(const Type& left, const Type& right) { static bool is_matrix_multiply(const Type& left, const Type& right) {
if (left.kind() == Type::kMatrix_Kind) { if (left.typeKind() == Type::TypeKind::kMatrix) {
return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind; return right.typeKind() == Type::TypeKind::kMatrix ||
right.typeKind() == Type::TypeKind::kVector;
} }
return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind; return left.typeKind() == Type::TypeKind::kVector &&
right.typeKind() == Type::TypeKind::kMatrix;
} }
/** /**
@ -1563,7 +1567,7 @@ static bool determine_binary_type(const Context& context,
return left.canCoerceTo(*context.fBool_Type) && return left.canCoerceTo(*context.fBool_Type) &&
right.canCoerceTo(*context.fBool_Type); right.canCoerceTo(*context.fBool_Type);
case Token::Kind::TK_STAREQ: case Token::Kind::TK_STAREQ:
if (left.kind() == Type::kScalar_Kind) { if (left.typeKind() == Type::TypeKind::kScalar) {
*outLeftType = &left; *outLeftType = &left;
*outRightType = &left; *outRightType = &left;
*outResultType = &left; *outResultType = &left;
@ -1584,7 +1588,7 @@ static bool determine_binary_type(const Context& context,
int leftRows = left.rows(); int leftRows = left.rows();
int rightColumns; int rightColumns;
int rightRows; int rightRows;
if (right.kind() == Type::kVector_Kind) { if (right.typeKind() == Type::TypeKind::kVector) {
// matrix * vector treats the vector as a column vector, so we need to // matrix * vector treats the vector as a column vector, so we need to
// transpose it // transpose it
rightColumns = right.rows(); rightColumns = right.rows();
@ -1616,7 +1620,7 @@ static bool determine_binary_type(const Context& context,
case Token::Kind::TK_PERCENTEQ: case Token::Kind::TK_PERCENTEQ:
case Token::Kind::TK_SHLEQ: case Token::Kind::TK_SHLEQ:
case Token::Kind::TK_SHREQ: case Token::Kind::TK_SHREQ:
if (left.kind() == Type::kScalar_Kind) { if (left.typeKind() == Type::TypeKind::kScalar) {
*outLeftType = &left; *outLeftType = &left;
*outRightType = &left; *outRightType = &left;
*outResultType = &left; *outResultType = &left;
@ -1638,8 +1642,9 @@ static bool determine_binary_type(const Context& context,
isLogical = false; isLogical = false;
validMatrixOrVectorOp = false; validMatrixOrVectorOp = false;
} }
bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind; bool isVectorOrMatrix = left.typeKind() == Type::TypeKind::kVector ||
if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind && left.typeKind() == Type::TypeKind::kMatrix;
if (left.typeKind() == Type::TypeKind::kScalar && right.typeKind() == Type::TypeKind::kScalar &&
right.canCoerceTo(left)) { right.canCoerceTo(left)) {
if (left.priority() > right.priority()) { if (left.priority() > right.priority()) {
*outLeftType = &left; *outLeftType = &left;
@ -1665,8 +1670,9 @@ static bool determine_binary_type(const Context& context,
} }
return true; return true;
} }
if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) && if ((left.typeKind() == Type::TypeKind::kVector ||
(right.kind() == Type::kScalar_Kind)) { left.typeKind() == Type::TypeKind::kMatrix) &&
(right.typeKind() == Type::TypeKind::kScalar)) {
if (determine_binary_type(context, op, left.componentType(), right, outLeftType, if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
outRightType, outResultType, false)) { outRightType, outResultType, false)) {
*outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows()); *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
@ -1689,7 +1695,7 @@ static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
const Expression& left, const Expression& left,
Token::Kind op, Token::Kind op,
const Expression& right) { const Expression& right) {
SkASSERT(left.fKind == Expression::kBoolLiteral_Kind); SkASSERT(left.kind() == Expression::Kind::kBoolLiteral);
bool leftVal = left.as<BoolLiteral>().fValue; bool leftVal = left.as<BoolLiteral>().fValue;
if (op == Token::Kind::TK_LOGICALAND) { if (op == Token::Kind::TK_LOGICALAND) {
// (true && expr) -> (expr) and (false && expr) -> (false) // (true && expr) -> (expr) and (false && expr) -> (false)
@ -1715,9 +1721,9 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
const Expression& right) const { const Expression& right) const {
// If the left side is a constant boolean literal, the right side does not need to be constant // If the left side is a constant boolean literal, the right side does not need to be constant
// for short circuit optimizations to allow the constant to be folded. // for short circuit optimizations to allow the constant to be folded.
if (left.fKind == Expression::kBoolLiteral_Kind && !right.isCompileTimeConstant()) { if (left.kind() == Expression::Kind::kBoolLiteral && !right.isCompileTimeConstant()) {
return short_circuit_boolean(fContext, left, op, right); return short_circuit_boolean(fContext, left, op, right);
} else if (right.fKind == Expression::kBoolLiteral_Kind && !left.isCompileTimeConstant()) { } else if (right.kind() == Expression::Kind::kBoolLiteral && !left.isCompileTimeConstant()) {
// There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
// (right OP left) for short-circuit optimizations // (right OP left) for short-circuit optimizations
return short_circuit_boolean(fContext, right, op, left); return short_circuit_boolean(fContext, right, op, left);
@ -1731,8 +1737,8 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
// precision to calculate the results and hope the result makes sense. The plan is to move the // precision to calculate the results and hope the result makes sense. The plan is to move the
// Skia caps into SkSL, so we have access to all of them including the precisions of the various // Skia caps into SkSL, so we have access to all of them including the precisions of the various
// types, which will let us be more intelligent about this. // types, which will let us be more intelligent about this.
if (left.fKind == Expression::kBoolLiteral_Kind && if (left.kind() == Expression::Kind::kBoolLiteral &&
right.fKind == Expression::kBoolLiteral_Kind) { right.kind() == Expression::Kind::kBoolLiteral) {
bool leftVal = left.as<BoolLiteral>().fValue; bool leftVal = left.as<BoolLiteral>().fValue;
bool rightVal = right.as<BoolLiteral>().fValue; bool rightVal = right.as<BoolLiteral>().fValue;
bool result; bool result;
@ -1749,7 +1755,8 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
#define URESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \ #define URESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
(uint32_t) leftVal op \ (uint32_t) leftVal op \
(uint32_t) rightVal) (uint32_t) rightVal)
if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) { if (left.kind() == Expression::Kind::kIntLiteral &&
right.kind() == Expression::Kind::kIntLiteral) {
int64_t leftVal = left.as<IntLiteral>().fValue; int64_t leftVal = left.as<IntLiteral>().fValue;
int64_t rightVal = right.as<IntLiteral>().fValue; int64_t rightVal = right.as<IntLiteral>().fValue;
switch (op) { switch (op) {
@ -1802,8 +1809,8 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
return nullptr; return nullptr;
} }
} }
if (left.fKind == Expression::kFloatLiteral_Kind && if (left.kind() == Expression::Kind::kFloatLiteral &&
right.fKind == Expression::kFloatLiteral_Kind) { right.kind() == Expression::Kind::kFloatLiteral) {
double leftVal = left.as<FloatLiteral>().fValue; double leftVal = left.as<FloatLiteral>().fValue;
double rightVal = right.as<FloatLiteral>().fValue; double rightVal = right.as<FloatLiteral>().fValue;
switch (op) { switch (op) {
@ -1825,7 +1832,7 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
default: return nullptr; default: return nullptr;
} }
} }
if (left.fType.kind() == Type::kVector_Kind && left.fType.componentType().isFloat() && if (left.fType.typeKind() == Type::TypeKind::kVector && left.fType.componentType().isFloat() &&
left.fType == right.fType) { left.fType == right.fType) {
std::vector<std::unique_ptr<Expression>> args; std::vector<std::unique_ptr<Expression>> args;
#define RETURN_VEC_COMPONENTWISE_RESULT(op) \ #define RETURN_VEC_COMPONENTWISE_RESULT(op) \
@ -1858,12 +1865,13 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
} }
return std::unique_ptr<Expression>(new Constructor(-1, left.fType, return std::unique_ptr<Expression>(new Constructor(-1, left.fType,
std::move(args))); std::move(args)));
default: return nullptr; default:
return nullptr;
} }
} }
if (left.fType.kind() == Type::kMatrix_Kind && if (left.fType.typeKind() == Type::TypeKind::kMatrix &&
right.fType.kind() == Type::kMatrix_Kind && right.fType.typeKind() == Type::TypeKind::kMatrix &&
left.fKind == right.fKind) { left.kind() == right.kind()) {
switch (op) { switch (op) {
case Token::Kind::TK_EQEQ: case Token::Kind::TK_EQEQ:
return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
@ -1902,13 +1910,13 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode&
const Type* rightType; const Type* rightType;
const Type* resultType; const Type* resultType;
const Type* rawLeftType; const Type* rawLeftType;
if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) { if (left->kind() == Expression::Kind::kIntLiteral && right->fType.isInteger()) {
rawLeftType = &right->fType; rawLeftType = &right->fType;
} else { } else {
rawLeftType = &left->fType; rawLeftType = &left->fType;
} }
const Type* rawRightType; const Type* rawRightType;
if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) { if (right->kind() == Expression::Kind::kIntLiteral && left->fType.isInteger()) {
rawRightType = &left->fType; rawRightType = &left->fType;
} else { } else {
rawRightType = &right->fType; rawRightType = &right->fType;
@ -1985,7 +1993,7 @@ std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode&
if (!ifFalse) { if (!ifFalse) {
return nullptr; return nullptr;
} }
if (test->fKind == Expression::kBoolLiteral_Kind) { if (test->kind() == Expression::Kind::kBoolLiteral) {
// static boolean test, just return one of the branches // static boolean test, just return one of the branches
if (test->as<BoolLiteral>().fValue) { if (test->as<BoolLiteral>().fValue) {
return ifTrue; return ifTrue;
@ -2108,12 +2116,12 @@ int IRGenerator::callCost(const FunctionDeclaration& function,
std::unique_ptr<Expression> IRGenerator::call(int offset, std::unique_ptr<Expression> IRGenerator::call(int offset,
std::unique_ptr<Expression> functionValue, std::unique_ptr<Expression> functionValue,
std::vector<std::unique_ptr<Expression>> arguments) { std::vector<std::unique_ptr<Expression>> arguments) {
switch (functionValue->fKind) { switch (functionValue->kind()) {
case Expression::kTypeReference_Kind: case Expression::Kind::kTypeReference:
return this->convertConstructor(offset, return this->convertConstructor(offset,
functionValue->as<TypeReference>().fValue, functionValue->as<TypeReference>().fValue,
std::move(arguments)); std::move(arguments));
case Expression::kExternalValue_Kind: { case Expression::Kind::kExternalValue: {
const ExternalValue* v = functionValue->as<ExternalValueReference>().fValue; const ExternalValue* v = functionValue->as<ExternalValueReference>().fValue;
if (!v->canCall()) { if (!v->canCall()) {
fErrors.error(offset, "this external value is not a function"); fErrors.error(offset, "this external value is not a function");
@ -2135,10 +2143,10 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
return nullptr; return nullptr;
} }
} }
return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, v->callReturnType(), return std::make_unique<ExternalFunctionCall>(offset, v->callReturnType(), v,
v, std::move(arguments))); std::move(arguments));
} }
case Expression::kFunctionReference_Kind: { case Expression::Kind::kFunctionReference: {
const FunctionReference& ref = functionValue->as<FunctionReference>(); const FunctionReference& ref = functionValue->as<FunctionReference>();
int bestCost = INT_MAX; int bestCost = INT_MAX;
const FunctionDeclaration* best = nullptr; const FunctionDeclaration* best = nullptr;
@ -2186,15 +2194,15 @@ std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
if (type == args[0]->fType) { if (type == args[0]->fType) {
return std::move(args[0]); return std::move(args[0]);
} }
if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) { if (type.isFloat() && args.size() == 1 && args[0]->kind() == Expression::Kind::kFloatLiteral) {
double value = args[0]->as<FloatLiteral>().fValue; double value = args[0]->as<FloatLiteral>().fValue;
return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type)); return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type));
} }
if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) { if (type.isFloat() && args.size() == 1 && args[0]->kind() == Expression::Kind::kIntLiteral) {
int64_t value = args[0]->as<IntLiteral>().fValue; int64_t value = args[0]->as<IntLiteral>().fValue;
return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type)); return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type));
} }
if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type || if (args[0]->kind() == Expression::Kind::kIntLiteral && (type == *fContext.fInt_Type ||
type == *fContext.fUInt_Type)) { type == *fContext.fUInt_Type)) {
return std::unique_ptr<Expression>(new IntLiteral(offset, return std::unique_ptr<Expression>(new IntLiteral(offset,
args[0]->as<IntLiteral>().fValue, args[0]->as<IntLiteral>().fValue,
@ -2219,10 +2227,10 @@ std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
} }
static int component_count(const Type& type) { static int component_count(const Type& type) {
switch (type.kind()) { switch (type.typeKind()) {
case Type::kVector_Kind: case Type::TypeKind::kVector:
return type.columns(); return type.columns();
case Type::kMatrix_Kind: case Type::TypeKind::kMatrix:
return type.columns() * type.rows(); return type.columns() * type.rows();
default: default:
return 1; return 1;
@ -2233,9 +2241,10 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
int offset, int offset,
const Type& type, const Type& type,
std::vector<std::unique_ptr<Expression>> args) { std::vector<std::unique_ptr<Expression>> args) {
SkASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind); SkASSERT(type.typeKind() == Type::TypeKind::kVector ||
if (type.kind() == Type::kMatrix_Kind && args.size() == 1 && type.typeKind() == Type::TypeKind::kMatrix);
args[0]->fType.kind() == Type::kMatrix_Kind) { if (type.typeKind() == Type::TypeKind::kMatrix && args.size() == 1 &&
args[0]->fType.typeKind() == Type::TypeKind::kMatrix) {
// matrix from matrix is always legal // matrix from matrix is always legal
return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args))); return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
} }
@ -2244,7 +2253,7 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
if (args.size() != 1 || expected != component_count(args[0]->fType) || if (args.size() != 1 || expected != component_count(args[0]->fType) ||
type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) { type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
for (size_t i = 0; i < args.size(); i++) { for (size_t i = 0; i < args.size(); i++) {
if (args[i]->fType.kind() == Type::kVector_Kind) { if (args[i]->fType.typeKind() == Type::TypeKind::kVector) {
if (type.componentType().isNumber() != if (type.componentType().isNumber() !=
args[i]->fType.componentType().isNumber()) { args[i]->fType.componentType().isNumber()) {
fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid " fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
@ -2253,9 +2262,9 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
return nullptr; return nullptr;
} }
actual += args[i]->fType.columns(); actual += args[i]->fType.columns();
} else if (args[i]->fType.kind() == Type::kScalar_Kind) { } else if (args[i]->fType.typeKind() == Type::TypeKind::kScalar) {
actual += 1; actual += 1;
if (type.kind() != Type::kScalar_Kind) { if (type.typeKind() != Type::TypeKind::kScalar) {
args[i] = this->coerce(std::move(args[i]), type.componentType()); args[i] = this->coerce(std::move(args[i]), type.componentType());
if (!args[i]) { if (!args[i]) {
return nullptr; return nullptr;
@ -2287,10 +2296,10 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
// argument is already the right type, just return it // argument is already the right type, just return it
return std::move(args[0]); return std::move(args[0]);
} }
Type::Kind kind = type.kind(); Type::TypeKind kind = type.typeKind();
if (type.isNumber()) { if (type.isNumber()) {
return this->convertNumberConstructor(offset, type, std::move(args)); return this->convertNumberConstructor(offset, type, std::move(args));
} else if (kind == Type::kArray_Kind) { } else if (kind == Type::TypeKind::kArray) {
const Type& base = type.componentType(); const Type& base = type.componentType();
for (size_t i = 0; i < args.size(); i++) { for (size_t i = 0; i < args.size(); i++) {
args[i] = this->coerce(std::move(args[i]), base); args[i] = this->coerce(std::move(args[i]), base);
@ -2298,8 +2307,8 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
return nullptr; return nullptr;
} }
} }
return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args))); return std::make_unique<Constructor>(offset, type, std::move(args));
} else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) { } else if (kind == Type::TypeKind::kVector || kind == Type::TypeKind::kMatrix) {
return this->convertCompoundConstructor(offset, type, std::move(args)); return this->convertCompoundConstructor(offset, type, std::move(args));
} else { } else {
fErrors.error(offset, "cannot construct '" + type.displayName() + "'"); fErrors.error(offset, "cannot construct '" + type.displayName() + "'");
@ -2315,7 +2324,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
} }
switch (expression.getToken().fKind) { switch (expression.getToken().fKind) {
case Token::Kind::TK_PLUS: case Token::Kind::TK_PLUS:
if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind && if (!base->fType.isNumber() && base->fType.typeKind() != Type::TypeKind::kVector &&
base->fType != *fContext.fFloatLiteral_Type) { base->fType != *fContext.fFloatLiteral_Type) {
fErrors.error(expression.fOffset, fErrors.error(expression.fOffset,
"'+' cannot operate on '" + base->fType.displayName() + "'"); "'+' cannot operate on '" + base->fType.displayName() + "'");
@ -2323,16 +2332,16 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
} }
return base; return base;
case Token::Kind::TK_MINUS: case Token::Kind::TK_MINUS:
if (base->fKind == Expression::kIntLiteral_Kind) { if (base->kind() == Expression::Kind::kIntLiteral) {
return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset, return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
-base->as<IntLiteral>().fValue)); -base->as<IntLiteral>().fValue));
} }
if (base->fKind == Expression::kFloatLiteral_Kind) { if (base->kind() == Expression::Kind::kFloatLiteral) {
double value = -base->as<FloatLiteral>().fValue; double value = -base->as<FloatLiteral>().fValue;
return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset, return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
value)); value));
} }
if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) { if (!base->fType.isNumber() && base->fType.typeKind() != Type::TypeKind::kVector) {
fErrors.error(expression.fOffset, fErrors.error(expression.fOffset,
"'-' cannot operate on '" + base->fType.displayName() + "'"); "'-' cannot operate on '" + base->fType.displayName() + "'");
return nullptr; return nullptr;
@ -2364,7 +2373,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
"' cannot operate on '" + base->fType.displayName() + "'"); "' cannot operate on '" + base->fType.displayName() + "'");
return nullptr; return nullptr;
} }
if (base->fKind == Expression::kBoolLiteral_Kind) { if (base->kind() == Expression::Kind::kBoolLiteral) {
return std::unique_ptr<Expression>( return std::unique_ptr<Expression>(
new BoolLiteral(fContext, base->fOffset, !base->as<BoolLiteral>().fValue)); new BoolLiteral(fContext, base->fOffset, !base->as<BoolLiteral>().fValue));
} }
@ -2386,22 +2395,23 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base, std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
const ASTNode& index) { const ASTNode& index) {
if (base->fKind == Expression::kTypeReference_Kind) { if (base->kind() == Expression::Kind::kTypeReference) {
if (index.fKind == ASTNode::Kind::kInt) { if (index.fKind == ASTNode::Kind::kInt) {
const Type& oldType = base->as<TypeReference>().fValue; const Type& oldType = base->as<TypeReference>().fValue;
SKSL_INT size = index.getInt(); SKSL_INT size = index.getInt();
const Type* newType = fSymbolTable->takeOwnershipOfSymbol( const Type* newType = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(oldType.name() + "[" + to_string(size) + "]", std::make_unique<Type>(oldType.name() + "[" + to_string(size) + "]",
Type::kArray_Kind, oldType, size)); Type::TypeKind::kArray, oldType, size));
return std::make_unique<TypeReference>(fContext, base->fOffset, *newType); return std::make_unique<TypeReference>(fContext, base->fOffset, newType);
} else { } else {
fErrors.error(base->fOffset, "array size must be a constant"); fErrors.error(base->fOffset, "array size must be a constant");
return nullptr; return nullptr;
} }
} }
if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind && if (base->fType.typeKind() != Type::TypeKind::kArray &&
base->fType.kind() != Type::kVector_Kind) { base->fType.typeKind() != Type::TypeKind::kMatrix &&
base->fType.typeKind() != Type::TypeKind::kVector) {
fErrors.error(base->fOffset, "expected array, but found '" + base->fType.displayName() + fErrors.error(base->fOffset, "expected array, but found '" + base->fType.displayName() +
"'"); "'");
return nullptr; return nullptr;
@ -2416,13 +2426,12 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression
return nullptr; return nullptr;
} }
} }
return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base), return std::make_unique<IndexExpression>(fContext, std::move(base), std::move(converted));
std::move(converted)));
} }
std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base, std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
StringFragment field) { StringFragment field) {
if (base->fKind == Expression::kExternalValue_Kind) { if (base->kind() == Expression::Kind::kExternalValue) {
const ExternalValue& ev = *base->as<ExternalValueReference>().fValue; const ExternalValue& ev = *base->as<ExternalValueReference>().fValue;
ExternalValue* result = ev.getChild(String(field).c_str()); ExternalValue* result = ev.getChild(String(field).c_str());
if (!result) { if (!result) {
@ -2460,7 +2469,7 @@ static int count_contiguous_swizzle_chunks(const std::vector<int>& components) {
std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base, std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
StringFragment fields) { StringFragment fields) {
if (base->fType.kind() != Type::kVector_Kind && !base->fType.isNumber()) { if (base->fType.typeKind() != Type::TypeKind::kVector && !base->fType.isNumber()) {
fErrors.error(base->fOffset, "cannot swizzle value of type '" + base->fType.displayName() + fErrors.error(base->fOffset, "cannot swizzle value of type '" + base->fType.displayName() +
"'"); "'");
return nullptr; return nullptr;
@ -2530,10 +2539,10 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
// 1) // 1)
int offset = base->fOffset; int offset = base->fOffset;
std::unique_ptr<Expression> expr; std::unique_ptr<Expression> expr;
switch (base->fKind) { switch (base->kind()) {
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
// the value being swizzled is just a constant or variable reference, so we can // the value being swizzled is just a constant or variable reference, so we can
// safely re-use copies of it without reevaluation concerns // safely re-use copies of it without reevaluation concerns
expr = std::move(base); expr = std::move(base);
@ -2623,7 +2632,7 @@ std::unique_ptr<Expression> IRGenerator::findEnumRef(
StringFragment field, StringFragment field,
std::vector<std::unique_ptr<ProgramElement>>& elements) { std::vector<std::unique_ptr<ProgramElement>>& elements) {
for (const auto& e : elements) { for (const auto& e : elements) {
if (e->fKind == ProgramElement::kEnum_Kind && type.name() == e->as<Enum>().fTypeName) { if (e->kind() == ProgramElement::Kind::kEnum && type.name() == e->as<Enum>().fTypeName) {
std::shared_ptr<SymbolTable> old = fSymbolTable; std::shared_ptr<SymbolTable> old = fSymbolTable;
fSymbolTable = e->as<Enum>().fSymbols; fSymbolTable = e->as<Enum>().fSymbols;
std::unique_ptr<Expression> result = convertIdentifier(ASTNode(&fFile->fNodes, offset, std::unique_ptr<Expression> result = convertIdentifier(ASTNode(&fFile->fNodes, offset,
@ -2671,12 +2680,11 @@ std::unique_ptr<Expression> IRGenerator::convertIndexExpression(const ASTNode& i
} }
if (iter != index.end()) { if (iter != index.end()) {
return this->convertIndex(std::move(base), *(iter++)); return this->convertIndex(std::move(base), *(iter++));
} else if (base->fKind == Expression::kTypeReference_Kind) { } else if (base->kind() == Expression::Kind::kTypeReference) {
const Type& oldType = base->as<TypeReference>().fValue; const Type& oldType = base->as<TypeReference>().fValue;
const Type* newType = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>( const Type* newType = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
oldType.name() + "[]", Type::kArray_Kind, oldType, /*columns=*/-1)); oldType.name() + "[]", Type::TypeKind::kArray, oldType, /*columns=*/-1));
return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset, return std::make_unique<TypeReference>(fContext, base->fOffset, newType);
*newType));
} }
fErrors.error(index.fOffset, "'[]' must follow a type name"); fErrors.error(index.fOffset, "'[]' must follow a type name");
return nullptr; return nullptr;
@ -2709,16 +2717,16 @@ std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& f
if (base->fType == *fContext.fSkCaps_Type) { if (base->fType == *fContext.fSkCaps_Type) {
return this->getCap(fieldNode.fOffset, field); return this->getCap(fieldNode.fOffset, field);
} }
if (base->fKind == Expression::kTypeReference_Kind) { if (base->kind() == Expression::Kind::kTypeReference) {
return this->convertTypeField(base->fOffset, base->as<TypeReference>().fValue, return this->convertTypeField(base->fOffset, base->as<TypeReference>().fValue,
field); field);
} }
if (base->fKind == Expression::kExternalValue_Kind) { if (base->kind() == Expression::Kind::kExternalValue) {
return this->convertField(std::move(base), field); return this->convertField(std::move(base), field);
} }
switch (base->fType.kind()) { switch (base->fType.typeKind()) {
case Type::kOther_Kind: case Type::TypeKind::kOther:
case Type::kStruct_Kind: case Type::TypeKind::kStruct:
return this->convertField(std::move(base), field); return this->convertField(std::move(base), field);
default: default:
return this->convertSwizzle(std::move(base), field); return this->convertSwizzle(std::move(base), field);
@ -2742,11 +2750,11 @@ std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode&
} }
void IRGenerator::checkValid(const Expression& expr) { void IRGenerator::checkValid(const Expression& expr) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kFunctionReference_Kind: case Expression::Kind::kFunctionReference:
fErrors.error(expr.fOffset, "expected '(' to begin function call"); fErrors.error(expr.fOffset, "expected '(' to begin function call");
break; break;
case Expression::kTypeReference_Kind: case Expression::Kind::kTypeReference:
fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation"); fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
break; break;
default: default:
@ -2776,8 +2784,8 @@ bool IRGenerator::checkSwizzleWrite(const Swizzle& swizzle) {
} }
bool IRGenerator::setRefKind(Expression& expr, VariableReference::RefKind kind) { bool IRGenerator::setRefKind(Expression& expr, VariableReference::RefKind kind) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const Variable& var = expr.as<VariableReference>().fVariable; const Variable& var = expr.as<VariableReference>().fVariable;
if (var.fModifiers.fFlags & if (var.fModifiers.fFlags &
(Modifiers::kConst_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag)) { (Modifiers::kConst_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag)) {
@ -2787,19 +2795,19 @@ bool IRGenerator::setRefKind(Expression& expr, VariableReference::RefKind kind)
expr.as<VariableReference>().setRefKind(kind); expr.as<VariableReference>().setRefKind(kind);
return true; return true;
} }
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
return this->setRefKind(*expr.as<FieldAccess>().fBase, kind); return this->setRefKind(*expr.as<FieldAccess>().fBase, kind);
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
const Swizzle& swizzle = expr.as<Swizzle>(); const Swizzle& swizzle = expr.as<Swizzle>();
return this->checkSwizzleWrite(swizzle) && this->setRefKind(*swizzle.fBase, kind); return this->checkSwizzleWrite(swizzle) && this->setRefKind(*swizzle.fBase, kind);
} }
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
return this->setRefKind(*expr.as<IndexExpression>().fBase, kind); return this->setRefKind(*expr.as<IndexExpression>().fBase, kind);
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
const TernaryExpression& t = expr.as<TernaryExpression>(); const TernaryExpression& t = expr.as<TernaryExpression>();
return this->setRefKind(*t.fIfTrue, kind) && this->setRefKind(*t.fIfFalse, kind); return this->setRefKind(*t.fIfTrue, kind) && this->setRefKind(*t.fIfFalse, kind);
} }
case Expression::kExternalValue_Kind: { case Expression::Kind::kExternalValue: {
const ExternalValue& v = *expr.as<ExternalValueReference>().fValue; const ExternalValue& v = *expr.as<ExternalValueReference>().fValue;
if (!v.canWrite()) { if (!v.canWrite()) {
fErrors.error(expr.fOffset, fErrors.error(expr.fOffset,

View File

@ -64,8 +64,8 @@ static int count_all_returns(const FunctionDefinition& funcDef) {
} }
bool visitStatement(const Statement& stmt) override { bool visitStatement(const Statement& stmt) override {
switch (stmt.fKind) { switch (stmt.kind()) {
case Statement::kReturn_Kind: case Statement::Kind::kReturn:
++fNumReturns; ++fNumReturns;
[[fallthrough]]; [[fallthrough]];
@ -89,21 +89,21 @@ static int count_returns_at_end_of_control_flow(const FunctionDefinition& funcDe
} }
bool visitStatement(const Statement& stmt) override { bool visitStatement(const Statement& stmt) override {
switch (stmt.fKind) { switch (stmt.kind()) {
case Statement::kBlock_Kind: { case Statement::Kind::kBlock: {
// Check only the last statement of a block. // Check only the last statement of a block.
const auto& blockStmts = stmt.as<Block>().fStatements; const auto& blockStmts = stmt.as<Block>().fStatements;
return (blockStmts.size() > 0) ? this->visitStatement(*blockStmts.back()) return (blockStmts.size() > 0) ? this->visitStatement(*blockStmts.back())
: false; : false;
} }
case Statement::kSwitch_Kind: case Statement::Kind::kSwitch:
case Statement::kWhile_Kind: case Statement::Kind::kWhile:
case Statement::kDo_Kind: case Statement::Kind::kDo:
case Statement::kFor_Kind: case Statement::Kind::kFor:
// Don't introspect switches or loop structures at all. // Don't introspect switches or loop structures at all.
return false; return false;
case Statement::kReturn_Kind: case Statement::Kind::kReturn:
++fNumReturns; ++fNumReturns;
[[fallthrough]]; [[fallthrough]];
@ -127,18 +127,18 @@ static int count_returns_in_breakable_constructs(const FunctionDefinition& funcD
} }
bool visitStatement(const Statement& stmt) override { bool visitStatement(const Statement& stmt) override {
switch (stmt.fKind) { switch (stmt.kind()) {
case Statement::kSwitch_Kind: case Statement::Kind::kSwitch:
case Statement::kWhile_Kind: case Statement::Kind::kWhile:
case Statement::kDo_Kind: case Statement::Kind::kDo:
case Statement::kFor_Kind: { case Statement::Kind::kFor: {
++fInsideBreakableConstruct; ++fInsideBreakableConstruct;
bool result = this->INHERITED::visitStatement(stmt); bool result = this->INHERITED::visitStatement(stmt);
--fInsideBreakableConstruct; --fInsideBreakableConstruct;
return result; return result;
} }
case Statement::kReturn_Kind: case Statement::Kind::kReturn:
fNumReturns += (fInsideBreakableConstruct > 0) ? 1 : 0; fNumReturns += (fInsideBreakableConstruct > 0) ? 1 : 0;
[[fallthrough]]; [[fallthrough]];
@ -166,7 +166,7 @@ static bool has_early_return(const FunctionDefinition& funcDef) {
} }
static const Type* copy_if_needed(const Type* src, SymbolTable& symbolTable) { static const Type* copy_if_needed(const Type* src, SymbolTable& symbolTable) {
if (src->kind() == Type::kArray_Kind) { if (src->typeKind() == Type::TypeKind::kArray) {
return symbolTable.takeOwnershipOfSymbol(std::make_unique<Type>(*src)); return symbolTable.takeOwnershipOfSymbol(std::make_unique<Type>(*src));
} }
return src; return src;
@ -199,8 +199,8 @@ std::unique_ptr<Expression> Inliner::inlineExpression(int offset,
return args; return args;
}; };
switch (expression.fKind) { switch (expression.kind()) {
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
const BinaryExpression& b = expression.as<BinaryExpression>(); const BinaryExpression& b = expression.as<BinaryExpression>();
return std::make_unique<BinaryExpression>(offset, return std::make_unique<BinaryExpression>(offset,
expr(b.fLeft), expr(b.fLeft),
@ -208,59 +208,59 @@ std::unique_ptr<Expression> Inliner::inlineExpression(int offset,
expr(b.fRight), expr(b.fRight),
b.fType); b.fType);
} }
case Expression::kBoolLiteral_Kind: case Expression::Kind::kBoolLiteral:
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
case Expression::kNullLiteral_Kind: case Expression::Kind::kNullLiteral:
return expression.clone(); return expression.clone();
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
const Constructor& constructor = expression.as<Constructor>(); const Constructor& constructor = expression.as<Constructor>();
return std::make_unique<Constructor>(offset, constructor.fType, return std::make_unique<Constructor>(offset, constructor.fType,
argList(constructor.fArguments)); argList(constructor.fArguments));
} }
case Expression::kExternalFunctionCall_Kind: { case Expression::Kind::kExternalFunctionCall: {
const ExternalFunctionCall& externalCall = expression.as<ExternalFunctionCall>(); const ExternalFunctionCall& externalCall = expression.as<ExternalFunctionCall>();
return std::make_unique<ExternalFunctionCall>(offset, externalCall.fType, return std::make_unique<ExternalFunctionCall>(offset, externalCall.fType,
externalCall.fFunction, externalCall.fFunction,
argList(externalCall.fArguments)); argList(externalCall.fArguments));
} }
case Expression::kExternalValue_Kind: case Expression::Kind::kExternalValue:
return expression.clone(); return expression.clone();
case Expression::kFieldAccess_Kind: { case Expression::Kind::kFieldAccess: {
const FieldAccess& f = expression.as<FieldAccess>(); const FieldAccess& f = expression.as<FieldAccess>();
return std::make_unique<FieldAccess>(expr(f.fBase), f.fFieldIndex, f.fOwnerKind); return std::make_unique<FieldAccess>(expr(f.fBase), f.fFieldIndex, f.fOwnerKind);
} }
case Expression::kFunctionCall_Kind: { case Expression::Kind::kFunctionCall: {
const FunctionCall& funcCall = expression.as<FunctionCall>(); const FunctionCall& funcCall = expression.as<FunctionCall>();
return std::make_unique<FunctionCall>(offset, funcCall.fType, funcCall.fFunction, return std::make_unique<FunctionCall>(offset, funcCall.fType, funcCall.fFunction,
argList(funcCall.fArguments)); argList(funcCall.fArguments));
} }
case Expression::kFunctionReference_Kind: case Expression::Kind::kFunctionReference:
return expression.clone(); return expression.clone();
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
const IndexExpression& idx = expression.as<IndexExpression>(); const IndexExpression& idx = expression.as<IndexExpression>();
return std::make_unique<IndexExpression>(*fContext, expr(idx.fBase), expr(idx.fIndex)); return std::make_unique<IndexExpression>(*fContext, expr(idx.fBase), expr(idx.fIndex));
} }
case Expression::kPrefix_Kind: { case Expression::Kind::kPrefix: {
const PrefixExpression& p = expression.as<PrefixExpression>(); const PrefixExpression& p = expression.as<PrefixExpression>();
return std::make_unique<PrefixExpression>(p.fOperator, expr(p.fOperand)); return std::make_unique<PrefixExpression>(p.fOperator, expr(p.fOperand));
} }
case Expression::kPostfix_Kind: { case Expression::Kind::kPostfix: {
const PostfixExpression& p = expression.as<PostfixExpression>(); const PostfixExpression& p = expression.as<PostfixExpression>();
return std::make_unique<PostfixExpression>(expr(p.fOperand), p.fOperator); return std::make_unique<PostfixExpression>(expr(p.fOperand), p.fOperator);
} }
case Expression::kSetting_Kind: case Expression::Kind::kSetting:
return expression.clone(); return expression.clone();
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
const Swizzle& s = expression.as<Swizzle>(); const Swizzle& s = expression.as<Swizzle>();
return std::make_unique<Swizzle>(*fContext, expr(s.fBase), s.fComponents); return std::make_unique<Swizzle>(*fContext, expr(s.fBase), s.fComponents);
} }
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
const TernaryExpression& t = expression.as<TernaryExpression>(); const TernaryExpression& t = expression.as<TernaryExpression>();
return std::make_unique<TernaryExpression>(offset, expr(t.fTest), return std::make_unique<TernaryExpression>(offset, expr(t.fTest),
expr(t.fIfTrue), expr(t.fIfFalse)); expr(t.fIfTrue), expr(t.fIfFalse));
} }
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const VariableReference& v = expression.as<VariableReference>(); const VariableReference& v = expression.as<VariableReference>();
auto found = varMap->find(&v.fVariable); auto found = varMap->find(&v.fVariable);
if (found != varMap->end()) { if (found != varMap->end()) {
@ -300,26 +300,26 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
} }
return nullptr; return nullptr;
}; };
switch (statement.fKind) { switch (statement.kind()) {
case Statement::kBlock_Kind: { case Statement::Kind::kBlock: {
const Block& b = statement.as<Block>(); const Block& b = statement.as<Block>();
return std::make_unique<Block>(offset, stmts(b.fStatements), b.fSymbols, b.fIsScope); return std::make_unique<Block>(offset, stmts(b.fStatements), b.fSymbols, b.fIsScope);
} }
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
case Statement::kContinue_Kind: case Statement::Kind::kContinue:
case Statement::kDiscard_Kind: case Statement::Kind::kDiscard:
return statement.clone(); return statement.clone();
case Statement::kDo_Kind: { case Statement::Kind::kDo: {
const DoStatement& d = statement.as<DoStatement>(); const DoStatement& d = statement.as<DoStatement>();
return std::make_unique<DoStatement>(offset, stmt(d.fStatement), expr(d.fTest)); return std::make_unique<DoStatement>(offset, stmt(d.fStatement), expr(d.fTest));
} }
case Statement::kExpression_Kind: { case Statement::Kind::kExpression: {
const ExpressionStatement& e = statement.as<ExpressionStatement>(); const ExpressionStatement& e = statement.as<ExpressionStatement>();
return std::make_unique<ExpressionStatement>(expr(e.fExpression)); return std::make_unique<ExpressionStatement>(expr(e.fExpression));
} }
case Statement::kFor_Kind: { case Statement::Kind::kFor: {
const ForStatement& f = statement.as<ForStatement>(); const ForStatement& f = statement.as<ForStatement>();
// need to ensure initializer is evaluated first so that we've already remapped its // need to ensure initializer is evaluated first so that we've already remapped its
// declarations by the time we evaluate test & next // declarations by the time we evaluate test & next
@ -327,14 +327,14 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
return std::make_unique<ForStatement>(offset, std::move(initializer), expr(f.fTest), return std::make_unique<ForStatement>(offset, std::move(initializer), expr(f.fTest),
expr(f.fNext), stmt(f.fStatement), f.fSymbols); expr(f.fNext), stmt(f.fStatement), f.fSymbols);
} }
case Statement::kIf_Kind: { case Statement::Kind::kIf: {
const IfStatement& i = statement.as<IfStatement>(); const IfStatement& i = statement.as<IfStatement>();
return std::make_unique<IfStatement>(offset, i.fIsStatic, expr(i.fTest), return std::make_unique<IfStatement>(offset, i.fIsStatic, expr(i.fTest),
stmt(i.fIfTrue), stmt(i.fIfFalse)); stmt(i.fIfTrue), stmt(i.fIfFalse));
} }
case Statement::kNop_Kind: case Statement::Kind::kNop:
return statement.clone(); return statement.clone();
case Statement::kReturn_Kind: { case Statement::Kind::kReturn: {
const ReturnStatement& r = statement.as<ReturnStatement>(); const ReturnStatement& r = statement.as<ReturnStatement>();
if (r.fExpression) { if (r.fExpression) {
auto assignment = std::make_unique<ExpressionStatement>( auto assignment = std::make_unique<ExpressionStatement>(
@ -362,7 +362,7 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
} }
} }
} }
case Statement::kSwitch_Kind: { case Statement::Kind::kSwitch: {
const SwitchStatement& ss = statement.as<SwitchStatement>(); const SwitchStatement& ss = statement.as<SwitchStatement>();
std::vector<std::unique_ptr<SwitchCase>> cases; std::vector<std::unique_ptr<SwitchCase>> cases;
for (const auto& sc : ss.fCases) { for (const auto& sc : ss.fCases) {
@ -372,7 +372,7 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
return std::make_unique<SwitchStatement>(offset, ss.fIsStatic, expr(ss.fValue), return std::make_unique<SwitchStatement>(offset, ss.fIsStatic, expr(ss.fValue),
std::move(cases), ss.fSymbols); std::move(cases), ss.fSymbols);
} }
case Statement::kVarDeclaration_Kind: { case Statement::Kind::kVarDeclaration: {
const VarDeclaration& decl = statement.as<VarDeclaration>(); const VarDeclaration& decl = statement.as<VarDeclaration>();
std::vector<std::unique_ptr<Expression>> sizes; std::vector<std::unique_ptr<Expression>> sizes;
for (const auto& size : decl.fSizes) { for (const auto& size : decl.fSizes) {
@ -396,7 +396,7 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
return std::make_unique<VarDeclaration>(clone, std::move(sizes), return std::make_unique<VarDeclaration>(clone, std::move(sizes),
std::move(initialValue)); std::move(initialValue));
} }
case Statement::kVarDeclarations_Kind: { case Statement::Kind::kVarDeclarations: {
const VarDeclarations& decls = *statement.as<VarDeclarationsStatement>().fDeclaration; const VarDeclarations& decls = *statement.as<VarDeclarationsStatement>().fDeclaration;
std::vector<std::unique_ptr<VarDeclaration>> vars; std::vector<std::unique_ptr<VarDeclaration>> vars;
for (const auto& var : decls.fVars) { for (const auto& var : decls.fVars) {
@ -406,7 +406,7 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
return std::unique_ptr<Statement>(new VarDeclarationsStatement( return std::unique_ptr<Statement>(new VarDeclarationsStatement(
std::make_unique<VarDeclarations>(offset, typePtr, std::move(vars)))); std::make_unique<VarDeclarations>(offset, typePtr, std::move(vars))));
} }
case Statement::kWhile_Kind: { case Statement::Kind::kWhile: {
const WhileStatement& w = statement.as<WhileStatement>(); const WhileStatement& w = statement.as<WhileStatement>();
return std::make_unique<WhileStatement>(offset, expr(w.fTest), stmt(w.fStatement)); return std::make_unique<WhileStatement>(offset, expr(w.fTest), stmt(w.fStatement));
} }
@ -508,7 +508,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
for (int i = 0; i < (int) arguments.size(); ++i) { for (int i = 0; i < (int) arguments.size(); ++i) {
const Variable* param = function.fDeclaration.fParameters[i]; const Variable* param = function.fDeclaration.fParameters[i];
if (arguments[i]->fKind == Expression::kVariableReference_Kind) { if (arguments[i]->kind() == Expression::Kind::kVariableReference) {
// The argument is just a variable, so we only need to copy it if it's an out parameter // The argument is just a variable, so we only need to copy it if it's an out parameter
// or it's written to within the function. // or it's written to within the function.
if ((param->fModifiers.fFlags & Modifiers::kOut_Flag) || if ((param->fModifiers.fFlags & Modifiers::kOut_Flag) ||
@ -549,7 +549,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
const Variable* p = function.fDeclaration.fParameters[i]; const Variable* p = function.fDeclaration.fParameters[i];
if (p->fModifiers.fFlags & Modifiers::kOut_Flag) { if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
SkASSERT(varMap.find(p) != varMap.end()); SkASSERT(varMap.find(p) != varMap.end());
if (arguments[i]->fKind == Expression::kVariableReference_Kind && if (arguments[i]->kind() == Expression::Kind::kVariableReference &&
&arguments[i]->as<VariableReference>().fVariable == varMap[p]) { &arguments[i]->as<VariableReference>().fVariable == varMap[p]) {
// We didn't create a temporary for this parameter, so there's nothing to copy back // We didn't create a temporary for this parameter, so there's nothing to copy back
// out. // out.

View File

@ -46,17 +46,17 @@ public:
*/ */
size_t alignment(const Type& type) const { size_t alignment(const Type& type) const {
// See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout // See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout
switch (type.kind()) { switch (type.typeKind()) {
case Type::kScalar_Kind: case Type::TypeKind::kScalar:
return this->size(type); return this->size(type);
case Type::kVector_Kind: case Type::TypeKind::kVector:
return vector_alignment(this->size(type.componentType()), type.columns()); return vector_alignment(this->size(type.componentType()), type.columns());
case Type::kMatrix_Kind: case Type::TypeKind::kMatrix:
return this->roundUpIfNeeded(vector_alignment(this->size(type.componentType()), return this->roundUpIfNeeded(vector_alignment(this->size(type.componentType()),
type.rows())); type.rows()));
case Type::kArray_Kind: case Type::TypeKind::kArray:
return this->roundUpIfNeeded(this->alignment(type.componentType())); return this->roundUpIfNeeded(this->alignment(type.componentType()));
case Type::kStruct_Kind: { case Type::TypeKind::kStruct: {
size_t result = 0; size_t result = 0;
for (const auto& f : type.fields()) { for (const auto& f : type.fields()) {
size_t alignment = this->alignment(*f.fType); size_t alignment = this->alignment(*f.fType);
@ -76,12 +76,12 @@ public:
* the case of matrices) to the start of the next. * the case of matrices) to the start of the next.
*/ */
size_t stride(const Type& type) const { size_t stride(const Type& type) const {
switch (type.kind()) { switch (type.typeKind()) {
case Type::kMatrix_Kind: { case Type::TypeKind::kMatrix: {
size_t base = vector_alignment(this->size(type.componentType()), type.rows()); size_t base = vector_alignment(this->size(type.componentType()), type.rows());
return this->roundUpIfNeeded(base); return this->roundUpIfNeeded(base);
} }
case Type::kArray_Kind: { case Type::TypeKind::kArray: {
int stride = this->size(type.componentType()); int stride = this->size(type.componentType());
if (stride > 0) { if (stride > 0) {
int align = this->alignment(type.componentType()); int align = this->alignment(type.componentType());
@ -100,23 +100,23 @@ public:
* Returns the size of a type in bytes. * Returns the size of a type in bytes.
*/ */
size_t size(const Type& type) const { size_t size(const Type& type) const {
switch (type.kind()) { switch (type.typeKind()) {
case Type::kScalar_Kind: case Type::TypeKind::kScalar:
if (type.name() == "bool") { if (type.name() == "bool") {
return 1; return 1;
} }
// FIXME need to take precision into account, once we figure out how we want to // FIXME need to take precision into account, once we figure out how we want to
// handle it... // handle it...
return 4; return 4;
case Type::kVector_Kind: case Type::TypeKind::kVector:
if (fStd == kMetal_Standard && type.columns() == 3) { if (fStd == kMetal_Standard && type.columns() == 3) {
return 4 * this->size(type.componentType()); return 4 * this->size(type.componentType());
} }
return type.columns() * this->size(type.componentType()); return type.columns() * this->size(type.componentType());
case Type::kMatrix_Kind: // fall through case Type::TypeKind::kMatrix: // fall through
case Type::kArray_Kind: case Type::TypeKind::kArray:
return type.columns() * this->stride(type); return type.columns() * this->stride(type);
case Type::kStruct_Kind: { case Type::TypeKind::kStruct: {
size_t total = 0; size_t total = 0;
for (const auto& f : type.fields()) { for (const auto& f : type.fields()) {
size_t alignment = this->alignment(*f.fType); size_t alignment = this->alignment(*f.fType);

View File

@ -77,13 +77,13 @@ void MetalCodeGenerator::writeExtension(const Extension& ext) {
} }
String MetalCodeGenerator::typeName(const Type& type) { String MetalCodeGenerator::typeName(const Type& type) {
switch (type.kind()) { switch (type.typeKind()) {
case Type::kVector_Kind: case Type::TypeKind::kVector:
return this->typeName(type.componentType()) + to_string(type.columns()); return this->typeName(type.componentType()) + to_string(type.columns());
case Type::kMatrix_Kind: case Type::TypeKind::kMatrix:
return this->typeName(type.componentType()) + to_string(type.columns()) + "x" + return this->typeName(type.componentType()) + to_string(type.columns()) + "x" +
to_string(type.rows()); to_string(type.rows());
case Type::kSampler_Kind: case Type::TypeKind::kSampler:
return "texture2d<float>"; // FIXME - support other texture types; return "texture2d<float>"; // FIXME - support other texture types;
default: default:
if (type == *fContext.fHalf_Type) { if (type == *fContext.fHalf_Type) {
@ -100,7 +100,7 @@ String MetalCodeGenerator::typeName(const Type& type) {
} }
void MetalCodeGenerator::writeType(const Type& type) { void MetalCodeGenerator::writeType(const Type& type) {
if (type.kind() == Type::kStruct_Kind) { if (type.typeKind() == Type::TypeKind::kStruct) {
for (const Type* search : fWrittenStructs) { for (const Type* search : fWrittenStructs) {
if (*search == type) { if (*search == type) {
// already written // already written
@ -120,47 +120,47 @@ void MetalCodeGenerator::writeType(const Type& type) {
} }
void MetalCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) { void MetalCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kBinary_Kind: case Expression::Kind::kBinary:
this->writeBinaryExpression(expr.as<BinaryExpression>(), parentPrecedence); this->writeBinaryExpression(expr.as<BinaryExpression>(), parentPrecedence);
break; break;
case Expression::kBoolLiteral_Kind: case Expression::Kind::kBoolLiteral:
this->writeBoolLiteral(expr.as<BoolLiteral>()); this->writeBoolLiteral(expr.as<BoolLiteral>());
break; break;
case Expression::kConstructor_Kind: case Expression::Kind::kConstructor:
this->writeConstructor(expr.as<Constructor>(), parentPrecedence); this->writeConstructor(expr.as<Constructor>(), parentPrecedence);
break; break;
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
this->writeIntLiteral(expr.as<IntLiteral>()); this->writeIntLiteral(expr.as<IntLiteral>());
break; break;
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
this->writeFieldAccess(expr.as<FieldAccess>()); this->writeFieldAccess(expr.as<FieldAccess>());
break; break;
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
this->writeFloatLiteral(expr.as<FloatLiteral>()); this->writeFloatLiteral(expr.as<FloatLiteral>());
break; break;
case Expression::kFunctionCall_Kind: case Expression::Kind::kFunctionCall:
this->writeFunctionCall(expr.as<FunctionCall>()); this->writeFunctionCall(expr.as<FunctionCall>());
break; break;
case Expression::kPrefix_Kind: case Expression::Kind::kPrefix:
this->writePrefixExpression(expr.as<PrefixExpression>(), parentPrecedence); this->writePrefixExpression(expr.as<PrefixExpression>(), parentPrecedence);
break; break;
case Expression::kPostfix_Kind: case Expression::Kind::kPostfix:
this->writePostfixExpression(expr.as<PostfixExpression>(), parentPrecedence); this->writePostfixExpression(expr.as<PostfixExpression>(), parentPrecedence);
break; break;
case Expression::kSetting_Kind: case Expression::Kind::kSetting:
this->writeSetting(expr.as<Setting>()); this->writeSetting(expr.as<Setting>());
break; break;
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
this->writeSwizzle(expr.as<Swizzle>()); this->writeSwizzle(expr.as<Swizzle>());
break; break;
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
this->writeVariableReference(expr.as<VariableReference>()); this->writeVariableReference(expr.as<VariableReference>());
break; break;
case Expression::kTernary_Kind: case Expression::Kind::kTernary:
this->writeTernaryExpression(expr.as<TernaryExpression>(), parentPrecedence); this->writeTernaryExpression(expr.as<TernaryExpression>(), parentPrecedence);
break; break;
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
this->writeIndexExpression(expr.as<IndexExpression>()); this->writeIndexExpression(expr.as<IndexExpression>());
break; break;
default: default:
@ -447,16 +447,16 @@ void MetalCodeGenerator::assembleMatrixFromExpressions(
if (argIndex < args.size()) { if (argIndex < args.size()) {
const Type& argType = args[argIndex]->fType; const Type& argType = args[argIndex]->fType;
switch (argType.kind()) { switch (argType.typeKind()) {
case Type::kScalar_Kind: { case Type::TypeKind::kScalar: {
fExtraFunctions.printf("x%zu", argIndex); fExtraFunctions.printf("x%zu", argIndex);
break; break;
} }
case Type::kVector_Kind: { case Type::TypeKind::kVector: {
fExtraFunctions.printf("x%zu[%d]", argIndex, argPosition); fExtraFunctions.printf("x%zu[%d]", argIndex, argPosition);
break; break;
} }
case Type::kMatrix_Kind: { case Type::TypeKind::kMatrix: {
fExtraFunctions.printf("x%zu[%d][%d]", argIndex, fExtraFunctions.printf("x%zu[%d][%d]", argIndex,
argPosition / argType.rows(), argPosition / argType.rows(),
argPosition % argType.rows()); argPosition % argType.rows());
@ -527,7 +527,7 @@ String MetalCodeGenerator::getMatrixConstructHelper(const Constructor& c) {
fExtraFunctions.printf(") {\n return float%dx%d(", columns, rows); fExtraFunctions.printf(") {\n return float%dx%d(", columns, rows);
if (args.size() == 1 && args.front()->fType.kind() == Type::kMatrix_Kind) { if (args.size() == 1 && args.front()->fType.typeKind() == Type::TypeKind::kMatrix) {
this->assembleMatrixFromMatrix(args.front()->fType, rows, columns); this->assembleMatrixFromMatrix(args.front()->fType, rows, columns);
} else { } else {
this->assembleMatrixFromExpressions(args, rows, columns); this->assembleMatrixFromExpressions(args, rows, columns);
@ -549,7 +549,7 @@ bool MetalCodeGenerator::canCoerce(const Type& t1, const Type& t2) {
bool MetalCodeGenerator::matrixConstructHelperIsNeeded(const Constructor& c) { bool MetalCodeGenerator::matrixConstructHelperIsNeeded(const Constructor& c) {
// A matrix construct helper is only necessary if we are, in fact, constructing a matrix. // A matrix construct helper is only necessary if we are, in fact, constructing a matrix.
if (c.fType.kind() != Type::kMatrix_Kind) { if (c.fType.typeKind() != Type::TypeKind::kMatrix) {
return false; return false;
} }
@ -577,7 +577,7 @@ bool MetalCodeGenerator::matrixConstructHelperIsNeeded(const Constructor& c) {
int position = 0; int position = 0;
for (const std::unique_ptr<Expression>& expr : c.fArguments) { for (const std::unique_ptr<Expression>& expr : c.fArguments) {
// If an input argument is a matrix, we need a helper function. // If an input argument is a matrix, we need a helper function.
if (expr->fType.kind() == Type::kMatrix_Kind) { if (expr->fType.typeKind() == Type::TypeKind::kMatrix) {
return true; return true;
} }
position += expr->fType.columns(); position += expr->fType.columns();
@ -606,7 +606,7 @@ void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence paren
// Metal supports creating matrices with a scalar on the diagonal via the single-argument // Metal supports creating matrices with a scalar on the diagonal via the single-argument
// matrix constructor. // matrix constructor.
if (c.fType.kind() == Type::kMatrix_Kind && arg.fType.isNumber()) { if (c.fType.typeKind() == Type::TypeKind::kMatrix && arg.fType.isNumber()) {
const Type& matrix = c.fType; const Type& matrix = c.fType;
this->write("float"); this->write("float");
this->write(to_string(matrix.columns())); this->write(to_string(matrix.columns()));
@ -641,7 +641,8 @@ void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence paren
for (const std::unique_ptr<Expression>& arg : c.fArguments) { for (const std::unique_ptr<Expression>& arg : c.fArguments) {
this->write(separator); this->write(separator);
separator = ", "; separator = ", ";
if (Type::kMatrix_Kind == c.fType.kind() && arg->fType.columns() < c.fType.rows()) { if (c.fType.typeKind() == Type::TypeKind::kMatrix &&
arg->fType.columns() < c.fType.rows()) {
// Merge scalars and smaller vectors together. // Merge scalars and smaller vectors together.
if (!scalarCount) { if (!scalarCount) {
this->writeType(c.fType.componentType()); this->writeType(c.fType.componentType());
@ -695,7 +696,7 @@ void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) {
} else if (ref.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag) { } else if (ref.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag) {
this->write("_out->"); this->write("_out->");
} else if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag && } else if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag &&
ref.fVariable.fType.kind() != Type::kSampler_Kind) { ref.fVariable.fType.typeKind() != Type::TypeKind::kSampler) {
this->write("_uniforms."); this->write("_uniforms.");
} else { } else {
this->write("_globals->"); this->write("_globals->");
@ -818,13 +819,13 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
bool needParens = precedence >= parentPrecedence; bool needParens = precedence >= parentPrecedence;
switch (b.fOperator) { switch (b.fOperator) {
case Token::Kind::TK_EQEQ: case Token::Kind::TK_EQEQ:
if (b.fLeft->fType.kind() == Type::kVector_Kind) { if (b.fLeft->fType.typeKind() == Type::TypeKind::kVector) {
this->write("all"); this->write("all");
needParens = true; needParens = true;
} }
break; break;
case Token::Kind::TK_NEQ: case Token::Kind::TK_NEQ:
if (b.fLeft->fType.kind() == Type::kVector_Kind) { if (b.fLeft->fType.typeKind() == Type::TypeKind::kVector) {
this->write("any"); this->write("any");
needParens = true; needParens = true;
} }
@ -836,20 +837,21 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
this->write("("); this->write("(");
} }
if (Compiler::IsAssignment(b.fOperator) && if (Compiler::IsAssignment(b.fOperator) &&
Expression::kVariableReference_Kind == b.fLeft->fKind && Expression::Kind::kVariableReference == b.fLeft->kind() &&
Variable::kParameter_Storage == ((VariableReference&) *b.fLeft).fVariable.fStorage && Variable::kParameter_Storage == ((VariableReference&) *b.fLeft).fVariable.fStorage &&
(((VariableReference&) *b.fLeft).fVariable.fModifiers.fFlags & Modifiers::kOut_Flag)) { (((VariableReference&) *b.fLeft).fVariable.fModifiers.fFlags & Modifiers::kOut_Flag)) {
// writing to an out parameter. Since we have to turn those into pointers, we have to // writing to an out parameter. Since we have to turn those into pointers, we have to
// dereference it here. // dereference it here.
this->write("*"); this->write("*");
} }
if (b.fOperator == Token::Kind::TK_STAREQ && b.fLeft->fType.kind() == Type::kMatrix_Kind && if (b.fOperator == Token::Kind::TK_STAREQ &&
b.fRight->fType.kind() == Type::kMatrix_Kind) { b.fLeft->fType.typeKind() == Type::TypeKind::kMatrix &&
b.fRight->fType.typeKind() == Type::TypeKind::kMatrix) {
this->writeMatrixTimesEqualHelper(b.fLeft->fType, b.fRight->fType, b.fType); this->writeMatrixTimesEqualHelper(b.fLeft->fType, b.fRight->fType, b.fType);
} }
this->writeExpression(*b.fLeft, precedence); this->writeExpression(*b.fLeft, precedence);
if (b.fOperator != Token::Kind::TK_EQ && Compiler::IsAssignment(b.fOperator) && if (b.fOperator != Token::Kind::TK_EQ && Compiler::IsAssignment(b.fOperator) &&
Expression::kSwizzle_Kind == b.fLeft->fKind && !b.fLeft->hasSideEffects()) { b.fLeft->kind() == Expression::Kind::kSwizzle && !b.fLeft->hasSideEffects()) {
// This doesn't compile in Metal: // This doesn't compile in Metal:
// float4 x = float4(1); // float4 x = float4(1);
// x.xy *= float2x2(...); // x.xy *= float2x2(...);
@ -951,14 +953,14 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
to_string(fUniformBuffer) + ")]]"); to_string(fUniformBuffer) + ")]]");
} }
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (ProgramElement::kVar_Kind == e.fKind) { if (e.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = e.as<VarDeclarations>(); const VarDeclarations& decls = e.as<VarDeclarations>();
if (!decls.fVars.size()) { if (!decls.fVars.size()) {
continue; continue;
} }
for (const auto& stmt: decls.fVars) { for (const auto& stmt: decls.fVars) {
VarDeclaration& var = stmt->as<VarDeclaration>(); VarDeclaration& var = stmt->as<VarDeclaration>();
if (var.fVar->fType.kind() == Type::kSampler_Kind) { if (var.fVar->fType.typeKind() == Type::TypeKind::kSampler) {
if (var.fVar->fModifiers.fLayout.fBinding < 0) { if (var.fVar->fModifiers.fLayout.fBinding < 0) {
fErrors.error(decls.fOffset, fErrors.error(decls.fOffset,
"Metal samplers must have 'layout(binding=...)'"); "Metal samplers must have 'layout(binding=...)'");
@ -976,7 +978,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->write(")]]"); this->write(")]]");
} }
} }
} else if (ProgramElement::kInterfaceBlock_Kind == e.fKind) { } else if (e.kind() == ProgramElement::Kind::kInterfaceBlock) {
InterfaceBlock& intf = (InterfaceBlock&) e; InterfaceBlock& intf = (InterfaceBlock&) e;
if ("sk_PerVertex" == intf.fTypeName) { if ("sk_PerVertex" == intf.fTypeName) {
continue; continue;
@ -1038,7 +1040,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->writeModifiers(param->fModifiers, false); this->writeModifiers(param->fModifiers, false);
std::vector<int> sizes; std::vector<int> sizes;
const Type* type = &param->fType; const Type* type = &param->fType;
while (Type::kArray_Kind == type->kind()) { while (type->typeKind() == Type::TypeKind::kArray) {
sizes.push_back(type->columns()); sizes.push_back(type->columns());
type = &type->componentType(); type = &type->componentType();
} }
@ -1112,7 +1114,7 @@ void MetalCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
this->writeLine(intf.fTypeName + " {"); this->writeLine(intf.fTypeName + " {");
const Type* structType = &intf.fVariable.fType; const Type* structType = &intf.fVariable.fType;
fWrittenStructs.push_back(structType); fWrittenStructs.push_back(structType);
while (Type::kArray_Kind == structType->kind()) { while (structType->typeKind() == Type::TypeKind::kArray) {
structType = &structType->componentType(); structType = &structType->componentType();
} }
fIndentation++; fIndentation++;
@ -1168,7 +1170,7 @@ void MetalCodeGenerator::writeFields(const std::vector<Type::Field>& fields, int
} }
currentOffset += memoryLayout.size(*fieldType); currentOffset += memoryLayout.size(*fieldType);
std::vector<int> sizes; std::vector<int> sizes;
while (fieldType->kind() == Type::kArray_Kind) { while (fieldType->typeKind() == Type::TypeKind::kArray) {
sizes.push_back(fieldType->columns()); sizes.push_back(fieldType->columns());
fieldType = &fieldType->componentType(); fieldType = &fieldType->componentType();
} }
@ -1236,45 +1238,45 @@ void MetalCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool
} }
void MetalCodeGenerator::writeStatement(const Statement& s) { void MetalCodeGenerator::writeStatement(const Statement& s) {
switch (s.fKind) { switch (s.kind()) {
case Statement::kBlock_Kind: case Statement::Kind::kBlock:
this->writeBlock(s.as<Block>()); this->writeBlock(s.as<Block>());
break; break;
case Statement::kExpression_Kind: case Statement::Kind::kExpression:
this->writeExpression(*s.as<ExpressionStatement>().fExpression, kTopLevel_Precedence); this->writeExpression(*s.as<ExpressionStatement>().fExpression, kTopLevel_Precedence);
this->write(";"); this->write(";");
break; break;
case Statement::kReturn_Kind: case Statement::Kind::kReturn:
this->writeReturnStatement(s.as<ReturnStatement>()); this->writeReturnStatement(s.as<ReturnStatement>());
break; break;
case Statement::kVarDeclarations_Kind: case Statement::Kind::kVarDeclarations:
this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration, false); this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration, false);
break; break;
case Statement::kIf_Kind: case Statement::Kind::kIf:
this->writeIfStatement(s.as<IfStatement>()); this->writeIfStatement(s.as<IfStatement>());
break; break;
case Statement::kFor_Kind: case Statement::Kind::kFor:
this->writeForStatement(s.as<ForStatement>()); this->writeForStatement(s.as<ForStatement>());
break; break;
case Statement::kWhile_Kind: case Statement::Kind::kWhile:
this->writeWhileStatement(s.as<WhileStatement>()); this->writeWhileStatement(s.as<WhileStatement>());
break; break;
case Statement::kDo_Kind: case Statement::Kind::kDo:
this->writeDoStatement(s.as<DoStatement>()); this->writeDoStatement(s.as<DoStatement>());
break; break;
case Statement::kSwitch_Kind: case Statement::Kind::kSwitch:
this->writeSwitchStatement(s.as<SwitchStatement>()); this->writeSwitchStatement(s.as<SwitchStatement>());
break; break;
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
this->write("break;"); this->write("break;");
break; break;
case Statement::kContinue_Kind: case Statement::Kind::kContinue:
this->write("continue;"); this->write("continue;");
break; break;
case Statement::kDiscard_Kind: case Statement::Kind::kDiscard:
this->write("discard_fragment();"); this->write("discard_fragment();");
break; break;
case Statement::kNop_Kind: case Statement::Kind::kNop:
this->write(";"); this->write(";");
break; break;
default: default:
@ -1391,14 +1393,14 @@ void MetalCodeGenerator::writeHeader() {
void MetalCodeGenerator::writeUniformStruct() { void MetalCodeGenerator::writeUniformStruct() {
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (ProgramElement::kVar_Kind == e.fKind) { if (e.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = e.as<VarDeclarations>(); const VarDeclarations& decls = e.as<VarDeclarations>();
if (!decls.fVars.size()) { if (!decls.fVars.size()) {
continue; continue;
} }
const Variable& first = *decls.fVars[0]->as<VarDeclaration>().fVar; const Variable& first = *decls.fVars[0]->as<VarDeclaration>().fVar;
if (first.fModifiers.fFlags & Modifiers::kUniform_Flag && if (first.fModifiers.fFlags & Modifiers::kUniform_Flag &&
first.fType.kind() != Type::kSampler_Kind) { first.fType.typeKind() != Type::TypeKind::kSampler) {
if (-1 == fUniformBuffer) { if (-1 == fUniformBuffer) {
this->write("struct Uniforms {\n"); this->write("struct Uniforms {\n");
fUniformBuffer = first.fModifiers.fLayout.fSet; fUniformBuffer = first.fModifiers.fLayout.fSet;
@ -1430,7 +1432,7 @@ void MetalCodeGenerator::writeUniformStruct() {
void MetalCodeGenerator::writeInputStruct() { void MetalCodeGenerator::writeInputStruct() {
this->write("struct Inputs {\n"); this->write("struct Inputs {\n");
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (ProgramElement::kVar_Kind == e.fKind) { if (e.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = e.as<VarDeclarations>(); const VarDeclarations& decls = e.as<VarDeclarations>();
if (!decls.fVars.size()) { if (!decls.fVars.size()) {
continue; continue;
@ -1469,7 +1471,7 @@ void MetalCodeGenerator::writeOutputStruct() {
this->write(" float4 sk_FragColor [[color(0)]];\n"); this->write(" float4 sk_FragColor [[color(0)]];\n");
} }
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (ProgramElement::kVar_Kind == e.fKind) { if (e.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = e.as<VarDeclarations>(); const VarDeclarations& decls = e.as<VarDeclarations>();
if (!decls.fVars.size()) { if (!decls.fVars.size()) {
continue; continue;
@ -1509,7 +1511,7 @@ void MetalCodeGenerator::writeOutputStruct() {
void MetalCodeGenerator::writeInterfaceBlocks() { void MetalCodeGenerator::writeInterfaceBlocks() {
bool wroteInterfaceBlock = false; bool wroteInterfaceBlock = false;
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (ProgramElement::kInterfaceBlock_Kind == e.fKind) { if (e.kind() == ProgramElement::Kind::kInterfaceBlock) {
this->writeInterfaceBlock(e.as<InterfaceBlock>()); this->writeInterfaceBlock(e.as<InterfaceBlock>());
wroteInterfaceBlock = true; wroteInterfaceBlock = true;
} }
@ -1527,7 +1529,7 @@ void MetalCodeGenerator::visitGlobalStruct(GlobalStructVisitor* visitor) {
visitor->VisitInterfaceBlock(*interfaceType, interfaceName); visitor->VisitInterfaceBlock(*interfaceType, interfaceName);
} }
for (const ProgramElement& element : fProgram) { for (const ProgramElement& element : fProgram) {
if (element.fKind != ProgramElement::kVar_Kind) { if (element.kind() != ProgramElement::Kind::kVar) {
continue; continue;
} }
const VarDeclarations& decls = static_cast<const VarDeclarations&>(element); const VarDeclarations& decls = static_cast<const VarDeclarations&>(element);
@ -1536,11 +1538,11 @@ void MetalCodeGenerator::visitGlobalStruct(GlobalStructVisitor* visitor) {
} }
const Variable& first = *((VarDeclaration&) *decls.fVars[0]).fVar; const Variable& first = *((VarDeclaration&) *decls.fVars[0]).fVar;
if ((!first.fModifiers.fFlags && -1 == first.fModifiers.fLayout.fBuiltin) || if ((!first.fModifiers.fFlags && -1 == first.fModifiers.fLayout.fBuiltin) ||
first.fType.kind() == Type::kSampler_Kind) { first.fType.typeKind() == Type::TypeKind::kSampler) {
for (const auto& stmt : decls.fVars) { for (const auto& stmt : decls.fVars) {
VarDeclaration& var = static_cast<VarDeclaration&>(*stmt); VarDeclaration& var = static_cast<VarDeclaration&>(*stmt);
if (var.fVar->fType.kind() == Type::kSampler_Kind) { if (var.fVar->fType.typeKind() == Type::TypeKind::kSampler) {
// Samplers are represented as a "texture/sampler" duo in the global struct. // Samplers are represented as a "texture/sampler" duo in the global struct.
visitor->VisitTexture(first.fType, var.fVar->fName); visitor->VisitTexture(first.fType, var.fVar->fName);
visitor->VisitSampler(first.fType, String(var.fVar->fName) + SAMPLER_SUFFIX); visitor->VisitSampler(first.fType, String(var.fVar->fName) + SAMPLER_SUFFIX);
@ -1658,10 +1660,10 @@ void MetalCodeGenerator::writeGlobalInit() {
} }
void MetalCodeGenerator::writeProgramElement(const ProgramElement& e) { void MetalCodeGenerator::writeProgramElement(const ProgramElement& e) {
switch (e.fKind) { switch (e.kind()) {
case ProgramElement::kExtension_Kind: case ProgramElement::Kind::kExtension:
break; break;
case ProgramElement::kVar_Kind: { case ProgramElement::Kind::kVar: {
const VarDeclarations& decl = e.as<VarDeclarations>(); const VarDeclarations& decl = e.as<VarDeclarations>();
if (decl.fVars.size() > 0) { if (decl.fVars.size() > 0) {
int builtin = decl.fVars[0]->as<VarDeclaration>().fVar->fModifiers.fLayout.fBuiltin; int builtin = decl.fVars[0]->as<VarDeclaration>().fVar->fModifiers.fLayout.fBuiltin;
@ -1675,13 +1677,13 @@ void MetalCodeGenerator::writeProgramElement(const ProgramElement& e) {
} }
break; break;
} }
case ProgramElement::kInterfaceBlock_Kind: case ProgramElement::Kind::kInterfaceBlock:
// handled in writeInterfaceBlocks, do nothing // handled in writeInterfaceBlocks, do nothing
break; break;
case ProgramElement::kFunction_Kind: case ProgramElement::Kind::kFunction:
this->writeFunction(e.as<FunctionDefinition>()); this->writeFunction(e.as<FunctionDefinition>());
break; break;
case ProgramElement::kModifiers_Kind: case ProgramElement::Kind::kModifiers:
this->writeModifiers(e.as<ModifiersDeclaration>().fModifiers, true); this->writeModifiers(e.as<ModifiersDeclaration>().fModifiers, true);
this->writeLine(";"); this->writeLine(";");
break; break;
@ -1697,8 +1699,8 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
if (!e) { if (!e) {
return kNo_Requirements; return kNo_Requirements;
} }
switch (e->fKind) { switch (e->kind()) {
case Expression::kFunctionCall_Kind: { case Expression::Kind::kFunctionCall: {
const FunctionCall& f = e->as<FunctionCall>(); const FunctionCall& f = e->as<FunctionCall>();
Requirements result = this->requirements(f.fFunction); Requirements result = this->requirements(f.fFunction);
for (const auto& arg : f.fArguments) { for (const auto& arg : f.fArguments) {
@ -1706,7 +1708,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
} }
return result; return result;
} }
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
const Constructor& c = e->as<Constructor>(); const Constructor& c = e->as<Constructor>();
Requirements result = kNo_Requirements; Requirements result = kNo_Requirements;
for (const auto& arg : c.fArguments) { for (const auto& arg : c.fArguments) {
@ -1714,33 +1716,34 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
} }
return result; return result;
} }
case Expression::kFieldAccess_Kind: { case Expression::Kind::kFieldAccess: {
const FieldAccess& f = e->as<FieldAccess>(); const FieldAccess& f = e->as<FieldAccess>();
if (FieldAccess::kAnonymousInterfaceBlock_OwnerKind == f.fOwnerKind) { if (FieldAccess::kAnonymousInterfaceBlock_OwnerKind == f.fOwnerKind) {
return kGlobals_Requirement; return kGlobals_Requirement;
} }
return this->requirements(f.fBase.get()); return this->requirements(f.fBase.get());
} }
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
return this->requirements(e->as<Swizzle>().fBase.get()); return this->requirements(e->as<Swizzle>().fBase.get());
case Expression::kBinary_Kind: { case Expression::Kind::kBinary: {
const BinaryExpression& b = e->as<BinaryExpression>(); const BinaryExpression& bin = e->as<BinaryExpression>();
return this->requirements(b.fLeft.get()) | this->requirements(b.fRight.get()); return this->requirements(bin.fLeft.get()) |
this->requirements(bin.fRight.get());
} }
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
const IndexExpression& idx = e->as<IndexExpression>(); const IndexExpression& idx = e->as<IndexExpression>();
return this->requirements(idx.fBase.get()) | this->requirements(idx.fIndex.get()); return this->requirements(idx.fBase.get()) | this->requirements(idx.fIndex.get());
} }
case Expression::kPrefix_Kind: case Expression::Kind::kPrefix:
return this->requirements(e->as<PrefixExpression>().fOperand.get()); return this->requirements(e->as<PrefixExpression>().fOperand.get());
case Expression::kPostfix_Kind: case Expression::Kind::kPostfix:
return this->requirements(e->as<PostfixExpression>().fOperand.get()); return this->requirements(e->as<PostfixExpression>().fOperand.get());
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
const TernaryExpression& t = e->as<TernaryExpression>(); const TernaryExpression& t = e->as<TernaryExpression>();
return this->requirements(t.fTest.get()) | this->requirements(t.fIfTrue.get()) | return this->requirements(t.fTest.get()) | this->requirements(t.fIfTrue.get()) |
this->requirements(t.fIfFalse.get()); this->requirements(t.fIfFalse.get());
} }
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const VariableReference& v = e->as<VariableReference>(); const VariableReference& v = e->as<VariableReference>();
Requirements result = kNo_Requirements; Requirements result = kNo_Requirements;
if (v.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) { if (v.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
@ -1751,7 +1754,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
} else if (v.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag) { } else if (v.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag) {
result = kOutputs_Requirement; result = kOutputs_Requirement;
} else if (v.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag && } else if (v.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag &&
v.fVariable.fType.kind() != Type::kSampler_Kind) { v.fVariable.fType.typeKind() != Type::TypeKind::kSampler) {
result = kUniforms_Requirement; result = kUniforms_Requirement;
} else { } else {
result = kGlobals_Requirement; result = kGlobals_Requirement;
@ -1768,19 +1771,19 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Statemen
if (!s) { if (!s) {
return kNo_Requirements; return kNo_Requirements;
} }
switch (s->fKind) { switch (s->kind()) {
case Statement::kBlock_Kind: { case Statement::Kind::kBlock: {
Requirements result = kNo_Requirements; Requirements result = kNo_Requirements;
for (const auto& child : s->as<Block>().fStatements) { for (const auto& child : s->as<Block>().fStatements) {
result |= this->requirements(child.get()); result |= this->requirements(child.get());
} }
return result; return result;
} }
case Statement::kVarDeclaration_Kind: { case Statement::Kind::kVarDeclaration: {
const VarDeclaration& var = s->as<VarDeclaration>(); const VarDeclaration& var = s->as<VarDeclaration>();
return this->requirements(var.fValue.get()); return this->requirements(var.fValue.get());
} }
case Statement::kVarDeclarations_Kind: { case Statement::Kind::kVarDeclarations: {
Requirements result = kNo_Requirements; Requirements result = kNo_Requirements;
const VarDeclarations& decls = *s->as<VarDeclarationsStatement>().fDeclaration; const VarDeclarations& decls = *s->as<VarDeclarationsStatement>().fDeclaration;
for (const auto& stmt : decls.fVars) { for (const auto& stmt : decls.fVars) {
@ -1788,36 +1791,36 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Statemen
} }
return result; return result;
} }
case Statement::kExpression_Kind: case Statement::Kind::kExpression:
return this->requirements(s->as<ExpressionStatement>().fExpression.get()); return this->requirements(s->as<ExpressionStatement>().fExpression.get());
case Statement::kReturn_Kind: { case Statement::Kind::kReturn: {
const ReturnStatement& r = s->as<ReturnStatement>(); const ReturnStatement& r = s->as<ReturnStatement>();
return this->requirements(r.fExpression.get()); return this->requirements(r.fExpression.get());
} }
case Statement::kIf_Kind: { case Statement::Kind::kIf: {
const IfStatement& i = s->as<IfStatement>(); const IfStatement& i = s->as<IfStatement>();
return this->requirements(i.fTest.get()) | return this->requirements(i.fTest.get()) |
this->requirements(i.fIfTrue.get()) | this->requirements(i.fIfTrue.get()) |
this->requirements(i.fIfFalse.get()); this->requirements(i.fIfFalse.get());
} }
case Statement::kFor_Kind: { case Statement::Kind::kFor: {
const ForStatement& f = s->as<ForStatement>(); const ForStatement& f = s->as<ForStatement>();
return this->requirements(f.fInitializer.get()) | return this->requirements(f.fInitializer.get()) |
this->requirements(f.fTest.get()) | this->requirements(f.fTest.get()) |
this->requirements(f.fNext.get()) | this->requirements(f.fNext.get()) |
this->requirements(f.fStatement.get()); this->requirements(f.fStatement.get());
} }
case Statement::kWhile_Kind: { case Statement::Kind::kWhile: {
const WhileStatement& w = s->as<WhileStatement>(); const WhileStatement& w = s->as<WhileStatement>();
return this->requirements(w.fTest.get()) | return this->requirements(w.fTest.get()) |
this->requirements(w.fStatement.get()); this->requirements(w.fStatement.get());
} }
case Statement::kDo_Kind: { case Statement::Kind::kDo: {
const DoStatement& d = s->as<DoStatement>(); const DoStatement& d = s->as<DoStatement>();
return this->requirements(d.fTest.get()) | return this->requirements(d.fTest.get()) |
this->requirements(d.fStatement.get()); this->requirements(d.fStatement.get());
} }
case Statement::kSwitch_Kind: { case Statement::Kind::kSwitch: {
const SwitchStatement& sw = s->as<SwitchStatement>(); const SwitchStatement& sw = s->as<SwitchStatement>();
Requirements result = this->requirements(sw.fValue.get()); Requirements result = this->requirements(sw.fValue.get());
for (const auto& c : sw.fCases) { for (const auto& c : sw.fCases) {
@ -1840,7 +1843,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Function
if (found == fRequirements.end()) { if (found == fRequirements.end()) {
fRequirements[&f] = kNo_Requirements; fRequirements[&f] = kNo_Requirements;
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (ProgramElement::kFunction_Kind == e.fKind) { if (e.kind() == ProgramElement::Kind::kFunction) {
const FunctionDefinition& def = e.as<FunctionDefinition>(); const FunctionDefinition& def = e.as<FunctionDefinition>();
if (&def.fDeclaration == &f) { if (&def.fDeclaration == &f) {
Requirements reqs = this->requirements(def.fBody.get()); Requirements reqs = this->requirements(def.fBody.get());

View File

@ -255,7 +255,7 @@ void Parser::error(int offset, String msg) {
bool Parser::isType(StringFragment name) { bool Parser::isType(StringFragment name) {
const Symbol* s = fSymbols[name]; const Symbol* s = fSymbols[name];
return s && s->fKind == Symbol::kType_Kind; return s && s->kind() == Symbol::Kind::kType;
} }
/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? | /* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
@ -357,7 +357,7 @@ ASTNode::ID Parser::enumDeclaration() {
if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) { if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
return ASTNode::ID::Invalid(); return ASTNode::ID::Invalid();
} }
fSymbols.add(this->text(name), std::make_unique<Type>(this->text(name), Type::kEnum_Kind)); fSymbols.add(this->text(name), std::make_unique<Type>(this->text(name), Type::TypeKind::kEnum));
CREATE_NODE(result, name.fOffset, ASTNode::Kind::kEnum, this->text(name)); CREATE_NODE(result, name.fOffset, ASTNode::Kind::kEnum, this->text(name));
if (!this->checkNext(Token::Kind::TK_RBRACE)) { if (!this->checkNext(Token::Kind::TK_RBRACE)) {
Token id; Token id;
@ -504,7 +504,7 @@ ASTNode::ID Parser::structDeclaration() {
} }
ASTNode& declsNode = getNode(decls); ASTNode& declsNode = getNode(decls);
const Symbol* symbol = fSymbols[(declsNode.begin() + 1)->getTypeData().fName]; const Symbol* symbol = fSymbols[(declsNode.begin() + 1)->getTypeData().fName];
SkASSERT(symbol && symbol->fKind == Symbol::kType_Kind); SkASSERT(symbol && symbol->kind() == Symbol::Kind::kType);
const Type* type = (const Type*) symbol; const Type* type = (const Type*) symbol;
for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) { for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) {
ASTNode& var = *iter; ASTNode& var = *iter;
@ -518,7 +518,8 @@ ASTNode::ID Parser::structDeclaration() {
uint64_t columns = size.getInt(); uint64_t columns = size.getInt();
String typeName = type->name() + "[" + to_string(columns) + "]"; String typeName = type->name() + "[" + to_string(columns) + "]";
type = fSymbols.takeOwnershipOfSymbol( type = fSymbols.takeOwnershipOfSymbol(
std::make_unique<Type>(typeName, Type::kArray_Kind, *type, (int)columns)); std::make_unique<Type>(typeName, Type::TypeKind::kArray, *type,
(int)columns));
} }
fields.push_back(Type::Field(declsNode.begin()->getModifiers(), vd.fName, type)); fields.push_back(Type::Field(declsNode.begin()->getModifiers(), vd.fName, type));
if (vd.fSizeCount ? (var.begin() + (vd.fSizeCount - 1))->fNext : var.fFirstChild) { if (vd.fSizeCount ? (var.begin() + (vd.fSizeCount - 1))->fNext : var.fFirstChild) {

View File

@ -34,15 +34,15 @@ String PipelineStageCodeGenerator::getTypeName(const Type& type) {
void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) { void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" && if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" &&
c.fArguments[0]->fType.kind() != Type::Kind::kSampler_Kind) { c.fArguments[0]->fType.typeKind() != Type::TypeKind::kSampler) {
SkASSERT(c.fArguments.size() <= 2); SkASSERT(c.fArguments.size() <= 2);
SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() || SkASSERT("fragmentProcessor" == c.fArguments[0]->fType.name() ||
"fragmentProcessor?" == c.fArguments[0]->fType.name()); "fragmentProcessor?" == c.fArguments[0]->fType.name());
SkASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind); SkASSERT(c.fArguments[0]->kind() == Expression::Kind::kVariableReference);
int index = 0; int index = 0;
bool found = false; bool found = false;
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
for (const std::unique_ptr<Statement>& raw : decls.fVars) { for (const std::unique_ptr<Statement>& raw : decls.fVars) {
VarDeclaration& decl = raw->as<VarDeclaration>(); VarDeclaration& decl = raw->as<VarDeclaration>();
@ -60,8 +60,8 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
SkASSERT(found); SkASSERT(found);
size_t childCallIndex = fArgs->fFormatArgs.size(); size_t childCallIndex = fArgs->fFormatArgs.size();
this->write(Compiler::kFormatArgPlaceholderStr); this->write(Compiler::kFormatArgPlaceholderStr);
bool matrixCall = bool matrixCall = c.fArguments.size() == 2 &&
c.fArguments.size() == 2 && c.fArguments[1]->fType.kind() == Type::kMatrix_Kind; c.fArguments[1]->fType.typeKind() == Type::TypeKind::kMatrix;
fArgs->fFormatArgs.push_back(Compiler::FormatArg( fArgs->fFormatArgs.push_back(Compiler::FormatArg(
matrixCall ? Compiler::FormatArg::Kind::kChildProcessorWithMatrix matrixCall ? Compiler::FormatArg::Kind::kChildProcessorWithMatrix
: Compiler::FormatArg::Kind::kChildProcessor, : Compiler::FormatArg::Kind::kChildProcessor,
@ -81,7 +81,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
} else { } else {
int index = 0; int index = 0;
for (const ProgramElement& e : fProgram) { for (const ProgramElement& e : fProgram) {
if (e.fKind == ProgramElement::kFunction_Kind) { if (e.kind() == ProgramElement::Kind::kFunction) {
if (&e.as<FunctionDefinition>().fDeclaration == &c.fFunction) { if (&e.as<FunctionDefinition>().fDeclaration == &c.fFunction) {
break; break;
} }
@ -124,7 +124,7 @@ void PipelineStageCodeGenerator::writeVariableReference(const VariableReference&
if (found) { if (found) {
break; break;
} }
if (e.fKind == ProgramElement::Kind::kVar_Kind) { if (e.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = e.as<VarDeclarations>(); const VarDeclarations& decls = e.as<VarDeclarations>();
for (const auto& decl : decls.fVars) { for (const auto& decl : decls.fVars) {
const Variable& var = *decl->as<VarDeclaration>().fVar; const Variable& var = *decl->as<VarDeclaration>().fVar;
@ -212,10 +212,10 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
} }
void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) { void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) {
if (p.fKind == ProgramElement::kSection_Kind) { if (p.kind() == ProgramElement::Kind::kSection) {
return; return;
} }
if (p.fKind == ProgramElement::kVar_Kind) { if (p.kind() == ProgramElement::Kind::kVar) {
const VarDeclarations& decls = p.as<VarDeclarations>(); const VarDeclarations& decls = p.as<VarDeclarations>();
if (!decls.fVars.size()) { if (!decls.fVars.size()) {
return; return;

View File

@ -134,7 +134,7 @@ const Symbol* Rehydrator::symbol() {
uint8_t count = this->readU8(); uint8_t count = this->readU8();
const Type* result = fSymbolTable->takeOwnershipOfSymbol( const Type* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(componentType->name() + "[" + to_string(count) + "]", std::make_unique<Type>(componentType->name() + "[" + to_string(count) + "]",
Type::kArray_Kind, *componentType, count)); Type::TypeKind::kArray, *componentType, count));
this->addSymbol(id, result); this->addSymbol(id, result);
return result; return result;
} }
@ -142,7 +142,7 @@ const Symbol* Rehydrator::symbol() {
uint16_t id = this->readU16(); uint16_t id = this->readU16();
StringFragment name = this->readString(); StringFragment name = this->readString();
const Type* result = fSymbolTable->takeOwnershipOfSymbol( const Type* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(name, Type::kEnum_Kind)); std::make_unique<Type>(name, Type::TypeKind::kEnum));
this->addSymbol(id, result); this->addSymbol(id, result);
return result; return result;
} }
@ -154,7 +154,7 @@ const Symbol* Rehydrator::symbol() {
std::vector<const Variable*> parameters; std::vector<const Variable*> parameters;
parameters.reserve(parameterCount); parameters.reserve(parameterCount);
for (int i = 0; i < parameterCount; ++i) { for (int i = 0; i < parameterCount; ++i) {
parameters.push_back(this->symbolRef<Variable>(Symbol::kVariable_Kind)); parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
} }
const Type* returnType = this->type(); const Type* returnType = this->type();
const FunctionDeclaration* result = const FunctionDeclaration* result =
@ -165,7 +165,7 @@ const Symbol* Rehydrator::symbol() {
return result; return result;
} }
case kField_Command: { case kField_Command: {
const Variable* owner = this->symbolRef<Variable>(Symbol::kVariable_Kind); const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
uint8_t index = this->readU8(); uint8_t index = this->readU8();
const Field* result = fSymbolTable->takeOwnershipOfSymbol( const Field* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Field>(/*offset=*/-1, *owner, index)); std::make_unique<Field>(/*offset=*/-1, *owner, index));
@ -175,7 +175,7 @@ const Symbol* Rehydrator::symbol() {
uint16_t id = this->readU16(); uint16_t id = this->readU16();
const Type* base = this->type(); const Type* base = this->type();
const Type* result = fSymbolTable->takeOwnershipOfSymbol( const Type* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(base->name() + "?", Type::kNullable_Kind, *base)); std::make_unique<Type>(base->name() + "?", Type::TypeKind::kNullable, *base));
this->addSymbol(id, result); this->addSymbol(id, result);
return result; return result;
} }
@ -205,7 +205,7 @@ const Symbol* Rehydrator::symbol() {
uint16_t id = this->readU16(); uint16_t id = this->readU16();
StringFragment name = this->readString(); StringFragment name = this->readString();
const Symbol* result = (*fSymbolTable)[name]; const Symbol* result = (*fSymbolTable)[name];
SkASSERT(result && result->fKind == Symbol::kType_Kind); SkASSERT(result && result->kind() == Symbol::Kind::kType);
this->addSymbol(id, result); this->addSymbol(id, result);
return result; return result;
} }
@ -216,7 +216,7 @@ const Symbol* Rehydrator::symbol() {
functions.reserve(length); functions.reserve(length);
for (int i = 0; i < length; ++i) { for (int i = 0; i < length; ++i) {
const Symbol* f = this->symbol(); const Symbol* f = this->symbol();
SkASSERT(f && f->fKind == Symbol::kFunctionDeclaration_Kind); SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
functions.push_back((const FunctionDeclaration*) f); functions.push_back((const FunctionDeclaration*) f);
} }
const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol( const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
@ -244,7 +244,7 @@ const Symbol* Rehydrator::symbol() {
const Type* Rehydrator::type() { const Type* Rehydrator::type() {
const Symbol* result = this->symbol(); const Symbol* result = this->symbol();
SkASSERT(result->fKind == Symbol::kType_Kind); SkASSERT(result->kind() == Symbol::Kind::kType);
return (const Type*) result; return (const Type*) result;
} }
@ -267,7 +267,7 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
StringFragment typeName = this->readString(); StringFragment typeName = this->readString();
std::shared_ptr<SymbolTable> symbols = this->symbolTable(); std::shared_ptr<SymbolTable> symbols = this->symbolTable();
for (auto& s : symbols->fOwnedSymbols) { for (auto& s : symbols->fOwnedSymbols) {
SkASSERT(s->fKind == Symbol::kVariable_Kind); SkASSERT(s->kind() == Symbol::Kind::kVariable);
Variable& v = (Variable&) *s; Variable& v = (Variable&) *s;
int value = this->readS32(); int value = this->readS32();
v.fInitialValue = symbols->takeOwnershipOfIRNode( v.fInitialValue = symbols->takeOwnershipOfIRNode(
@ -278,13 +278,13 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
} }
case Rehydrator::kFunctionDefinition_Command: { case Rehydrator::kFunctionDefinition_Command: {
const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>( const FunctionDeclaration* decl = this->symbolRef<FunctionDeclaration>(
Symbol::kFunctionDeclaration_Kind); Symbol::Kind::kFunctionDeclaration);
std::unique_ptr<Statement> body = this->statement(); std::unique_ptr<Statement> body = this->statement();
std::unordered_set<const FunctionDeclaration*> refs; std::unordered_set<const FunctionDeclaration*> refs;
uint8_t refCount = this->readU8(); uint8_t refCount = this->readU8();
for (int i = 0; i < refCount; ++i) { for (int i = 0; i < refCount; ++i) {
refs.insert(this->symbolRef<FunctionDeclaration>( refs.insert(this->symbolRef<FunctionDeclaration>(
Symbol::kFunctionDeclaration_Kind)); Symbol::Kind::kFunctionDeclaration));
} }
FunctionDefinition* result = new FunctionDefinition(-1, *decl, std::move(body), FunctionDefinition* result = new FunctionDefinition(-1, *decl, std::move(body),
std::move(refs)); std::move(refs));
@ -293,7 +293,7 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
} }
case Rehydrator::kInterfaceBlock_Command: { case Rehydrator::kInterfaceBlock_Command: {
const Symbol* var = this->symbol(); const Symbol* var = this->symbol();
SkASSERT(var && var->fKind == Symbol::kVariable_Kind); SkASSERT(var && var->kind() == Symbol::Kind::kVariable);
StringFragment typeName = this->readString(); StringFragment typeName = this->readString();
StringFragment instanceName = this->readString(); StringFragment instanceName = this->readString();
uint8_t sizeCount = this->readU8(); uint8_t sizeCount = this->readU8();
@ -313,7 +313,7 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
vars.reserve(count); vars.reserve(count);
for (int i = 0 ; i < count; ++i) { for (int i = 0 ; i < count; ++i) {
std::unique_ptr<Statement> s = this->statement(); std::unique_ptr<Statement> s = this->statement();
SkASSERT(s->fKind == Statement::kVarDeclaration_Kind); SkASSERT(s->kind() == Statement::Kind::kVarDeclaration);
vars.emplace_back((VarDeclaration*) s.release()); vars.emplace_back((VarDeclaration*) s.release());
} }
return std::unique_ptr<ProgramElement>(new VarDeclarations(-1, baseType, return std::unique_ptr<ProgramElement>(new VarDeclarations(-1, baseType,
@ -407,7 +407,7 @@ std::unique_ptr<Statement> Rehydrator::statement() {
fSymbolTable)); fSymbolTable));
} }
case Rehydrator::kVarDeclaration_Command: { case Rehydrator::kVarDeclaration_Command: {
Variable* var = this->symbolRef<Variable>(Symbol::kVariable_Kind); Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
uint8_t sizeCount = this->readU8(); uint8_t sizeCount = this->readU8();
std::vector<std::unique_ptr<Expression>> sizes; std::vector<std::unique_ptr<Expression>> sizes;
sizes.reserve(sizeCount); sizes.reserve(sizeCount);
@ -431,7 +431,7 @@ std::unique_ptr<Statement> Rehydrator::statement() {
vars.reserve(count); vars.reserve(count);
for (int i = 0 ; i < count; ++i) { for (int i = 0 ; i < count; ++i) {
std::unique_ptr<Statement> s = this->statement(); std::unique_ptr<Statement> s = this->statement();
SkASSERT(s->fKind == Statement::kVarDeclaration_Kind); SkASSERT(s->kind() == Statement::Kind::kVarDeclaration);
vars.emplace_back((VarDeclaration*) s.release()); vars.emplace_back((VarDeclaration*) s.release());
} }
return std::make_unique<VarDeclarationsStatement>( return std::make_unique<VarDeclarationsStatement>(
@ -489,16 +489,16 @@ std::unique_ptr<Expression> Rehydrator::expression() {
return std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, u.fFloat)); return std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, u.fFloat));
} }
case Rehydrator::kFunctionCall_Command: { case Rehydrator::kFunctionCall_Command: {
const Type* type = this->type(); const Type& type = *this->type();
const FunctionDeclaration* f = this->symbolRef<FunctionDeclaration>( const FunctionDeclaration* f = this->symbolRef<FunctionDeclaration>(
Symbol::kFunctionDeclaration_Kind); Symbol::Kind::kFunctionDeclaration);
uint8_t argCount = this->readU8(); uint8_t argCount = this->readU8();
std::vector<std::unique_ptr<Expression>> args; std::vector<std::unique_ptr<Expression>> args;
args.reserve(argCount); args.reserve(argCount);
for (int i = 0; i < argCount; ++i) { for (int i = 0; i < argCount; ++i) {
args.push_back(this->expression()); args.push_back(this->expression());
} }
return std::unique_ptr<Expression>(new FunctionCall(-1, *type, *f, std::move(args))); return std::make_unique<FunctionCall>(-1, type, *f, std::move(args));
} }
case Rehydrator::kIndex_Command: { case Rehydrator::kIndex_Command: {
std::unique_ptr<Expression> base = this->expression(); std::unique_ptr<Expression> base = this->expression();
@ -547,7 +547,7 @@ std::unique_ptr<Expression> Rehydrator::expression() {
std::move(ifTrue))); std::move(ifTrue)));
} }
case Rehydrator::kVariableReference_Command: { case Rehydrator::kVariableReference_Command: {
const Variable* var = this->symbolRef<Variable>(Symbol::kVariable_Kind); const Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8(); VariableReference::RefKind refKind = (VariableReference::RefKind) this->readU8();
return std::unique_ptr<Expression>(new VariableReference(-1, *var, refKind)); return std::unique_ptr<Expression>(new VariableReference(-1, *var, refKind));
} }

View File

@ -156,7 +156,7 @@ static bool is_float(const Context& context, const Type& type) {
} }
static bool is_signed(const Context& context, const Type& type) { static bool is_signed(const Context& context, const Type& type) {
if (type.kind() == Type::kVector_Kind) { if (type.typeKind() == Type::TypeKind::kVector) {
return is_signed(context, type.componentType()); return is_signed(context, type.componentType());
} }
return type == *context.fInt_Type || type == *context.fShort_Type || return type == *context.fInt_Type || type == *context.fShort_Type ||
@ -164,7 +164,7 @@ static bool is_signed(const Context& context, const Type& type) {
} }
static bool is_unsigned(const Context& context, const Type& type) { static bool is_unsigned(const Context& context, const Type& type) {
if (type.kind() == Type::kVector_Kind) { if (type.typeKind() == Type::TypeKind::kVector) {
return is_unsigned(context, type.componentType()); return is_unsigned(context, type.componentType());
} }
return type == *context.fUInt_Type || type == *context.fUShort_Type || return type == *context.fUInt_Type || type == *context.fUShort_Type ||
@ -172,7 +172,7 @@ static bool is_unsigned(const Context& context, const Type& type) {
} }
static bool is_bool(const Context& context, const Type& type) { static bool is_bool(const Context& context, const Type& type) {
if (type.kind() == Type::kVector_Kind) { if (type.typeKind() == Type::TypeKind::kVector) {
return is_bool(context, type.componentType()); return is_bool(context, type.componentType());
} }
return type == *context.fBool_Type; return type == *context.fBool_Type;
@ -423,7 +423,7 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor
this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset, this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset,
(SpvId) offset, fDecorationBuffer); (SpvId) offset, fDecorationBuffer);
} }
if (field.fType->kind() == Type::kMatrix_Kind) { if (field.fType->typeKind() == Type::TypeKind::kMatrix) {
this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationColMajor, this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationColMajor,
fDecorationBuffer); fDecorationBuffer);
this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationMatrixStride, this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationMatrixStride,
@ -435,8 +435,9 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor
SpvDecorationRelaxedPrecision, fDecorationBuffer); SpvDecorationRelaxedPrecision, fDecorationBuffer);
} }
offset += size; offset += size;
Type::Kind kind = field.fType->kind(); Type::TypeKind kind = field.fType->typeKind();
if ((kind == Type::kArray_Kind || kind == Type::kStruct_Kind) && offset % alignment != 0) { if ((kind == Type::TypeKind::kArray || kind == Type::TypeKind::kStruct) &&
offset % alignment != 0) {
offset += alignment - offset % alignment; offset += alignment - offset % alignment;
} }
} }
@ -452,7 +453,7 @@ Type SPIRVCodeGenerator::getActualType(const Type& type) {
if (type.isUnsigned()) { if (type.isUnsigned()) {
return *fContext.fUInt_Type; return *fContext.fUInt_Type;
} }
if (type.kind() == Type::kMatrix_Kind || type.kind() == Type::kVector_Kind) { if (type.typeKind() == Type::TypeKind::kMatrix || type.typeKind() == Type::TypeKind::kVector) {
if (type.componentType() == *fContext.fHalf_Type) { if (type.componentType() == *fContext.fHalf_Type) {
return fContext.fFloat_Type->toCompound(fContext, type.columns(), type.rows()); return fContext.fFloat_Type->toCompound(fContext, type.columns(), type.rows());
} }
@ -478,8 +479,8 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
auto entry = fTypeMap.find(key); auto entry = fTypeMap.find(key);
if (entry == fTypeMap.end()) { if (entry == fTypeMap.end()) {
SpvId result = this->nextId(); SpvId result = this->nextId();
switch (type.kind()) { switch (type.typeKind()) {
case Type::kScalar_Kind: case Type::TypeKind::kScalar:
if (type == *fContext.fBool_Type) { if (type == *fContext.fBool_Type) {
this->writeInstruction(SpvOpTypeBool, result, fConstantBuffer); this->writeInstruction(SpvOpTypeBool, result, fConstantBuffer);
} else if (type == *fContext.fInt_Type || type == *fContext.fShort_Type || } else if (type == *fContext.fInt_Type || type == *fContext.fShort_Type ||
@ -494,20 +495,20 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
SkASSERT(false); SkASSERT(false);
} }
break; break;
case Type::kVector_Kind: case Type::TypeKind::kVector:
this->writeInstruction(SpvOpTypeVector, result, this->writeInstruction(SpvOpTypeVector, result,
this->getType(type.componentType(), layout), this->getType(type.componentType(), layout),
type.columns(), fConstantBuffer); type.columns(), fConstantBuffer);
break; break;
case Type::kMatrix_Kind: case Type::TypeKind::kMatrix:
this->writeInstruction(SpvOpTypeMatrix, result, this->writeInstruction(SpvOpTypeMatrix, result,
this->getType(index_type(fContext, type), layout), this->getType(index_type(fContext, type), layout),
type.columns(), fConstantBuffer); type.columns(), fConstantBuffer);
break; break;
case Type::kStruct_Kind: case Type::TypeKind::kStruct:
this->writeStruct(type, layout, result); this->writeStruct(type, layout, result);
break; break;
case Type::kArray_Kind: { case Type::TypeKind::kArray: {
if (type.columns() > 0) { if (type.columns() > 0) {
IntLiteral count(fContext, -1, type.columns()); IntLiteral count(fContext, -1, type.columns());
this->writeInstruction(SpvOpTypeArray, result, this->writeInstruction(SpvOpTypeArray, result,
@ -527,7 +528,7 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
} }
break; break;
} }
case Type::kSampler_Kind: { case Type::TypeKind::kSampler: {
SpvId image = result; SpvId image = result;
if (SpvDimSubpassData != type.dimensions()) { if (SpvDimSubpassData != type.dimensions()) {
image = this->getType(type.textureType(), layout); image = this->getType(type.textureType(), layout);
@ -540,11 +541,11 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
} }
break; break;
} }
case Type::kSeparateSampler_Kind: { case Type::TypeKind::kSeparateSampler: {
this->writeInstruction(SpvOpTypeSampler, result, fConstantBuffer); this->writeInstruction(SpvOpTypeSampler, result, fConstantBuffer);
break; break;
} }
case Type::kTexture_Kind: { case Type::TypeKind::kTexture: {
this->writeInstruction(SpvOpTypeImage, result, this->writeInstruction(SpvOpTypeImage, result,
this->getType(*fContext.fFloat_Type, layout), this->getType(*fContext.fFloat_Type, layout),
type.dimensions(), type.isDepth(), type.isArrayed(), type.dimensions(), type.isDepth(), type.isArrayed(),
@ -569,7 +570,7 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
} }
SpvId SPIRVCodeGenerator::getImageType(const Type& type) { SpvId SPIRVCodeGenerator::getImageType(const Type& type) {
SkASSERT(type.kind() == Type::kSampler_Kind); SkASSERT(type.typeKind() == Type::TypeKind::kSampler);
this->getType(type); this->getType(type);
String key = type.name() + to_string((int) fDefaultLayout.fStd); String key = type.name() + to_string((int) fDefaultLayout.fStd);
SkASSERT(fImageTypeMap.find(key) != fImageTypeMap.end()); SkASSERT(fImageTypeMap.find(key) != fImageTypeMap.end());
@ -653,32 +654,32 @@ SpvId SPIRVCodeGenerator::getPointerType(const Type& rawType, const MemoryLayout
} }
SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, OutputStream& out) { SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, OutputStream& out) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kBinary_Kind: case Expression::Kind::kBinary:
return this->writeBinaryExpression(expr.as<BinaryExpression>(), out); return this->writeBinaryExpression(expr.as<BinaryExpression>(), out);
case Expression::kBoolLiteral_Kind: case Expression::Kind::kBoolLiteral:
return this->writeBoolLiteral(expr.as<BoolLiteral>()); return this->writeBoolLiteral(expr.as<BoolLiteral>());
case Expression::kConstructor_Kind: case Expression::Kind::kConstructor:
return this->writeConstructor(expr.as<Constructor>(), out); return this->writeConstructor(expr.as<Constructor>(), out);
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
return this->writeIntLiteral(expr.as<IntLiteral>()); return this->writeIntLiteral(expr.as<IntLiteral>());
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
return this->writeFieldAccess(expr.as<FieldAccess>(), out); return this->writeFieldAccess(expr.as<FieldAccess>(), out);
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
return this->writeFloatLiteral(expr.as<FloatLiteral>()); return this->writeFloatLiteral(expr.as<FloatLiteral>());
case Expression::kFunctionCall_Kind: case Expression::Kind::kFunctionCall:
return this->writeFunctionCall(expr.as<FunctionCall>(), out); return this->writeFunctionCall(expr.as<FunctionCall>(), out);
case Expression::kPrefix_Kind: case Expression::Kind::kPrefix:
return this->writePrefixExpression(expr.as<PrefixExpression>(), out); return this->writePrefixExpression(expr.as<PrefixExpression>(), out);
case Expression::kPostfix_Kind: case Expression::Kind::kPostfix:
return this->writePostfixExpression(expr.as<PostfixExpression>(), out); return this->writePostfixExpression(expr.as<PostfixExpression>(), out);
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
return this->writeSwizzle(expr.as<Swizzle>(), out); return this->writeSwizzle(expr.as<Swizzle>(), out);
case Expression::kVariableReference_Kind: case Expression::Kind::kVariableReference:
return this->writeVariableReference(expr.as<VariableReference>(), out); return this->writeVariableReference(expr.as<VariableReference>(), out);
case Expression::kTernary_Kind: case Expression::Kind::kTernary:
return this->writeTernaryExpression(expr.as<TernaryExpression>(), out); return this->writeTernaryExpression(expr.as<TernaryExpression>(), out);
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
return this->writeIndexExpression(expr.as<IndexExpression>(), out); return this->writeIndexExpression(expr.as<IndexExpression>(), out);
default: default:
#ifdef SK_DEBUG #ifdef SK_DEBUG
@ -764,7 +765,7 @@ std::vector<SpvId> SPIRVCodeGenerator::vectorize(
OutputStream& out) { OutputStream& out) {
int vectorSize = 0; int vectorSize = 0;
for (const auto& a : args) { for (const auto& a : args) {
if (a->fType.kind() == Type::kVector_Kind) { if (a->fType.typeKind() == Type::TypeKind::kVector) {
if (vectorSize) { if (vectorSize) {
SkASSERT(a->fType.columns() == vectorSize); SkASSERT(a->fType.columns() == vectorSize);
} }
@ -776,7 +777,7 @@ std::vector<SpvId> SPIRVCodeGenerator::vectorize(
std::vector<SpvId> result; std::vector<SpvId> result;
for (const auto& a : args) { for (const auto& a : args) {
SpvId raw = this->writeExpression(*a, out); SpvId raw = this->writeExpression(*a, out);
if (vectorSize && a->fType.kind() == Type::kScalar_Kind) { if (vectorSize && a->fType.typeKind() == Type::TypeKind::kScalar) {
SpvId vector = this->nextId(); SpvId vector = this->nextId();
this->writeOpCode(SpvOpCompositeConstruct, 3 + vectorSize, out); this->writeOpCode(SpvOpCompositeConstruct, 3 + vectorSize, out);
this->writeWord(this->getType(a->fType.toCompound(fContext, vectorSize, 1)), out); this->writeWord(this->getType(a->fType.toCompound(fContext, vectorSize, 1)), out);
@ -1071,7 +1072,7 @@ SpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, OutputStream&
} }
SpvId SPIRVCodeGenerator::writeConstantVector(const Constructor& c) { SpvId SPIRVCodeGenerator::writeConstantVector(const Constructor& c) {
SkASSERT(c.fType.kind() == Type::kVector_Kind && c.isCompileTimeConstant()); SkASSERT(c.fType.typeKind() == Type::TypeKind::kVector && c.isCompileTimeConstant());
SpvId result = this->nextId(); SpvId result = this->nextId();
std::vector<SpvId> arguments; std::vector<SpvId> arguments;
for (size_t i = 0; i < c.fArguments.size(); i++) { for (size_t i = 0; i < c.fArguments.size(); i++) {
@ -1180,8 +1181,8 @@ void SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const
void SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcType, void SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcType,
const Type& dstType, OutputStream& out) { const Type& dstType, OutputStream& out) {
SkASSERT(srcType.kind() == Type::kMatrix_Kind); SkASSERT(srcType.typeKind() == Type::TypeKind::kMatrix);
SkASSERT(dstType.kind() == Type::kMatrix_Kind); SkASSERT(dstType.typeKind() == Type::TypeKind::kMatrix);
SkASSERT(srcType.componentType() == dstType.componentType()); SkASSERT(srcType.componentType() == dstType.componentType());
SpvId srcColumnType = this->getType(srcType.componentType().toCompound(fContext, SpvId srcColumnType = this->getType(srcType.componentType().toCompound(fContext,
srcType.rows(), srcType.rows(),
@ -1288,7 +1289,7 @@ void SPIRVCodeGenerator::addColumnEntry(SpvId columnType, Precision precision,
} }
SpvId SPIRVCodeGenerator::writeMatrixConstructor(const Constructor& c, OutputStream& out) { SpvId SPIRVCodeGenerator::writeMatrixConstructor(const Constructor& c, OutputStream& out) {
SkASSERT(c.fType.kind() == Type::kMatrix_Kind); SkASSERT(c.fType.typeKind() == Type::TypeKind::kMatrix);
// go ahead and write the arguments so we don't try to write new instructions in the middle of // go ahead and write the arguments so we don't try to write new instructions in the middle of
// an instruction // an instruction
std::vector<SpvId> arguments; std::vector<SpvId> arguments;
@ -1298,11 +1299,13 @@ SpvId SPIRVCodeGenerator::writeMatrixConstructor(const Constructor& c, OutputStr
SpvId result = this->nextId(); SpvId result = this->nextId();
int rows = c.fType.rows(); int rows = c.fType.rows();
int columns = c.fType.columns(); int columns = c.fType.columns();
if (arguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kScalar_Kind) { if (arguments.size() == 1 && c.fArguments[0]->fType.typeKind() == Type::TypeKind::kScalar) {
this->writeUniformScaleMatrix(result, arguments[0], c.fType, out); this->writeUniformScaleMatrix(result, arguments[0], c.fType, out);
} else if (arguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kMatrix_Kind) { } else if (arguments.size() == 1 &&
c.fArguments[0]->fType.typeKind() == Type::TypeKind::kMatrix) {
this->writeMatrixCopy(result, arguments[0], c.fArguments[0]->fType, c.fType, out); this->writeMatrixCopy(result, arguments[0], c.fArguments[0]->fType, c.fType, out);
} else if (arguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kVector_Kind) { } else if (arguments.size() == 1 &&
c.fArguments[0]->fType.typeKind() == Type::TypeKind::kVector) {
SkASSERT(c.fType.rows() == 2 && c.fType.columns() == 2); SkASSERT(c.fType.rows() == 2 && c.fType.columns() == 2);
SkASSERT(c.fArguments[0]->fType.columns() == 4); SkASSERT(c.fArguments[0]->fType.columns() == 4);
SpvId componentType = this->getType(c.fType.componentType()); SpvId componentType = this->getType(c.fType.componentType());
@ -1327,8 +1330,9 @@ SpvId SPIRVCodeGenerator::writeMatrixConstructor(const Constructor& c, OutputStr
int currentCount = 0; int currentCount = 0;
Precision precision = c.fType.highPrecision() ? Precision::kHigh : Precision::kLow; Precision precision = c.fType.highPrecision() ? Precision::kHigh : Precision::kLow;
for (size_t i = 0; i < arguments.size(); i++) { for (size_t i = 0; i < arguments.size(); i++) {
if (currentCount == 0 && c.fArguments[i]->fType.kind() == Type::kVector_Kind && if (currentCount == 0 &&
c.fArguments[i]->fType.columns() == c.fType.rows()) { c.fArguments[i]->fType.typeKind() == Type::TypeKind::kVector &&
c.fArguments[i]->fType.columns() == c.fType.rows()) {
// this is a complete column by itself // this is a complete column by itself
columnIds.push_back(arguments[i]); columnIds.push_back(arguments[i]);
} else { } else {
@ -1360,7 +1364,7 @@ SpvId SPIRVCodeGenerator::writeMatrixConstructor(const Constructor& c, OutputStr
} }
SpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, OutputStream& out) { SpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, OutputStream& out) {
SkASSERT(c.fType.kind() == Type::kVector_Kind); SkASSERT(c.fType.typeKind() == Type::TypeKind::kVector);
if (c.isCompileTimeConstant()) { if (c.isCompileTimeConstant()) {
return this->writeConstantVector(c); return this->writeConstantVector(c);
} }
@ -1368,7 +1372,7 @@ SpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, OutputStr
// an instruction // an instruction
std::vector<SpvId> arguments; std::vector<SpvId> arguments;
for (size_t i = 0; i < c.fArguments.size(); i++) { for (size_t i = 0; i < c.fArguments.size(); i++) {
if (c.fArguments[i]->fType.kind() == Type::kVector_Kind) { if (c.fArguments[i]->fType.typeKind() == Type::TypeKind::kVector) {
// SPIR-V doesn't support vector(vector-of-different-type) directly, so we need to // SPIR-V doesn't support vector(vector-of-different-type) directly, so we need to
// extract the components and convert them in that case manually. On top of that, // extract the components and convert them in that case manually. On top of that,
// as of this writing there's a bug in the Intel Vulkan driver where OpCreateComposite // as of this writing there's a bug in the Intel Vulkan driver where OpCreateComposite
@ -1448,7 +1452,7 @@ SpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, OutputStr
} }
} }
SpvId result = this->nextId(); SpvId result = this->nextId();
if (arguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kScalar_Kind) { if (arguments.size() == 1 && c.fArguments[0]->fType.typeKind() == Type::TypeKind::kScalar) {
this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.columns(), out); this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.columns(), out);
this->writeWord(this->getType(c.fType), out); this->writeWord(this->getType(c.fType), out);
this->writeWord(result, out); this->writeWord(result, out);
@ -1468,7 +1472,7 @@ SpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, OutputStr
} }
SpvId SPIRVCodeGenerator::writeArrayConstructor(const Constructor& c, OutputStream& out) { SpvId SPIRVCodeGenerator::writeArrayConstructor(const Constructor& c, OutputStream& out) {
SkASSERT(c.fType.kind() == Type::kArray_Kind); SkASSERT(c.fType.typeKind() == Type::TypeKind::kArray);
// go ahead and write the arguments so we don't try to write new instructions in the middle of // go ahead and write the arguments so we don't try to write new instructions in the middle of
// an instruction // an instruction
std::vector<SpvId> arguments; std::vector<SpvId> arguments;
@ -1501,12 +1505,12 @@ SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, OutputStream& o
c.fType == *fContext.fUByte_Type) { c.fType == *fContext.fUByte_Type) {
return this->writeUIntConstructor(c, out); return this->writeUIntConstructor(c, out);
} }
switch (c.fType.kind()) { switch (c.fType.typeKind()) {
case Type::kVector_Kind: case Type::TypeKind::kVector:
return this->writeVectorConstructor(c, out); return this->writeVectorConstructor(c, out);
case Type::kMatrix_Kind: case Type::TypeKind::kMatrix:
return this->writeMatrixConstructor(c, out); return this->writeMatrixConstructor(c, out);
case Type::kArray_Kind: case Type::TypeKind::kArray:
return this->writeArrayConstructor(c, out); return this->writeArrayConstructor(c, out);
default: default:
#ifdef SK_DEBUG #ifdef SK_DEBUG
@ -1534,8 +1538,8 @@ SpvStorageClass_ get_storage_class(const Modifiers& modifiers) {
} }
SpvStorageClass_ get_storage_class(const Expression& expr) { SpvStorageClass_ get_storage_class(const Expression& expr) {
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
const Variable& var = ((VariableReference&) expr).fVariable; const Variable& var = ((VariableReference&) expr).fVariable;
if (var.fStorage != Variable::kGlobal_Storage) { if (var.fStorage != Variable::kGlobal_Storage) {
return SpvStorageClassFunction; return SpvStorageClassFunction;
@ -1546,9 +1550,9 @@ SpvStorageClass_ get_storage_class(const Expression& expr) {
} }
return result; return result;
} }
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
return get_storage_class(*((FieldAccess&) expr).fBase); return get_storage_class(*((FieldAccess&) expr).fBase);
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
return get_storage_class(*((IndexExpression&) expr).fBase); return get_storage_class(*((IndexExpression&) expr).fBase);
default: default:
return SpvStorageClassFunction; return SpvStorageClassFunction;
@ -1557,14 +1561,14 @@ SpvStorageClass_ get_storage_class(const Expression& expr) {
std::vector<SpvId> SPIRVCodeGenerator::getAccessChain(const Expression& expr, OutputStream& out) { std::vector<SpvId> SPIRVCodeGenerator::getAccessChain(const Expression& expr, OutputStream& out) {
std::vector<SpvId> chain; std::vector<SpvId> chain;
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kIndex_Kind: { case Expression::Kind::kIndex: {
IndexExpression& indexExpr = (IndexExpression&) expr; IndexExpression& indexExpr = (IndexExpression&) expr;
chain = this->getAccessChain(*indexExpr.fBase, out); chain = this->getAccessChain(*indexExpr.fBase, out);
chain.push_back(this->writeExpression(*indexExpr.fIndex, out)); chain.push_back(this->writeExpression(*indexExpr.fIndex, out));
break; break;
} }
case Expression::kFieldAccess_Kind: { case Expression::Kind::kFieldAccess: {
FieldAccess& fieldExpr = (FieldAccess&) expr; FieldAccess& fieldExpr = (FieldAccess&) expr;
chain = this->getAccessChain(*fieldExpr.fBase, out); chain = this->getAccessChain(*fieldExpr.fBase, out);
IntLiteral index(fContext, -1, fieldExpr.fFieldIndex); IntLiteral index(fContext, -1, fieldExpr.fFieldIndex);
@ -1695,13 +1699,13 @@ private:
std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const Expression& expr, std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const Expression& expr,
OutputStream& out) { OutputStream& out) {
Precision precision = expr.fType.highPrecision() ? Precision::kHigh : Precision::kLow; Precision precision = expr.fType.highPrecision() ? Precision::kHigh : Precision::kLow;
switch (expr.fKind) { switch (expr.kind()) {
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
SpvId type; SpvId type;
const Variable& var = ((VariableReference&) expr).fVariable; const Variable& var = ((VariableReference&) expr).fVariable;
if (var.fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) { if (var.fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
type = this->getType(Type("sk_in", Type::kArray_Kind, var.fType.componentType(), type = this->getType(Type("sk_in", Type::TypeKind::kArray,
fSkInCount)); var.fType.componentType(), fSkInCount));
} else { } else {
type = this->getType(expr.fType); type = this->getType(expr.fType);
} }
@ -1712,8 +1716,8 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const
type, type,
precision)); precision));
} }
case Expression::kIndex_Kind: // fall through case Expression::Kind::kIndex: // fall through
case Expression::kFieldAccess_Kind: { case Expression::Kind::kFieldAccess: {
std::vector<SpvId> chain = this->getAccessChain(expr, out); std::vector<SpvId> chain = this->getAccessChain(expr, out);
SpvId member = this->nextId(); SpvId member = this->nextId();
this->writeOpCode(SpvOpAccessChain, (SpvId) (3 + chain.size()), out); this->writeOpCode(SpvOpAccessChain, (SpvId) (3 + chain.size()), out);
@ -1728,7 +1732,7 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const
this->getType(expr.fType), this->getType(expr.fType),
precision)); precision));
} }
case Expression::kSwizzle_Kind: { case Expression::Kind::kSwizzle: {
Swizzle& swizzle = (Swizzle&) expr; Swizzle& swizzle = (Swizzle&) expr;
size_t count = swizzle.fComponents.size(); size_t count = swizzle.fComponents.size();
SpvId base = this->getLValue(*swizzle.fBase, out)->getPointer(); SpvId base = this->getLValue(*swizzle.fBase, out)->getPointer();
@ -1758,7 +1762,7 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const
precision)); precision));
} }
} }
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
TernaryExpression& t = (TernaryExpression&) expr; TernaryExpression& t = (TernaryExpression&) expr;
SpvId test = this->writeExpression(*t.fTest, out); SpvId test = this->writeExpression(*t.fTest, out);
SpvId end = this->nextId(); SpvId end = this->nextId();
@ -1929,7 +1933,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
} }
SpvId SPIRVCodeGenerator::writeIndexExpression(const IndexExpression& expr, OutputStream& out) { SpvId SPIRVCodeGenerator::writeIndexExpression(const IndexExpression& expr, OutputStream& out) {
if (expr.fBase->fType.kind() == Type::Kind::kVector_Kind) { if (expr.fBase->fType.typeKind() == Type::TypeKind::kVector) {
SpvId base = this->writeExpression(*expr.fBase, out); SpvId base = this->writeExpression(*expr.fBase, out);
SpvId index = this->writeExpression(*expr.fIndex, out); SpvId index = this->writeExpression(*expr.fIndex, out);
SpvId result = this->nextId(); SpvId result = this->nextId();
@ -2018,7 +2022,7 @@ SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType,
SpvId SPIRVCodeGenerator::foldToBool(SpvId id, const Type& operandType, SpvOp op, SpvId SPIRVCodeGenerator::foldToBool(SpvId id, const Type& operandType, SpvOp op,
OutputStream& out) { OutputStream& out) {
if (operandType.kind() == Type::kVector_Kind) { if (operandType.typeKind() == Type::TypeKind::kVector) {
SpvId result = this->nextId(); SpvId result = this->nextId();
this->writeInstruction(op, this->getType(*fContext.fBool_Type), result, id, out); this->writeInstruction(op, this->getType(*fContext.fBool_Type), result, id, out);
return result; return result;
@ -2031,7 +2035,7 @@ SpvId SPIRVCodeGenerator::writeMatrixComparison(const Type& operandType, SpvId l
SpvOp_ vectorMergeOperator, SpvOp_ mergeOperator, SpvOp_ vectorMergeOperator, SpvOp_ mergeOperator,
OutputStream& out) { OutputStream& out) {
SpvOp_ compareOp = is_float(fContext, operandType) ? floatOperator : intOperator; SpvOp_ compareOp = is_float(fContext, operandType) ? floatOperator : intOperator;
SkASSERT(operandType.kind() == Type::kMatrix_Kind); SkASSERT(operandType.typeKind() == Type::TypeKind::kMatrix);
SpvId columnType = this->getType(operandType.componentType().toCompound(fContext, SpvId columnType = this->getType(operandType.componentType().toCompound(fContext,
operandType.rows(), operandType.rows(),
1)); 1));
@ -2066,7 +2070,7 @@ SpvId SPIRVCodeGenerator::writeComponentwiseMatrixBinary(const Type& operandType
SpvOp_ intOperator, SpvOp_ intOperator,
OutputStream& out) { OutputStream& out) {
SpvOp_ op = is_float(fContext, operandType) ? floatOperator : intOperator; SpvOp_ op = is_float(fContext, operandType) ? floatOperator : intOperator;
SkASSERT(operandType.kind() == Type::kMatrix_Kind); SkASSERT(operandType.typeKind() == Type::TypeKind::kMatrix);
SpvId columnType = this->getType(operandType.componentType().toCompound(fContext, SpvId columnType = this->getType(operandType.componentType().toCompound(fContext,
operandType.rows(), operandType.rows(),
1)); 1));
@ -2109,7 +2113,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
// IR allows mismatched types in expressions (e.g. float2 * float), but they need special // IR allows mismatched types in expressions (e.g. float2 * float), but they need special
// handling in SPIR-V // handling in SPIR-V
if (this->getActualType(leftType) != this->getActualType(rightType)) { if (this->getActualType(leftType) != this->getActualType(rightType)) {
if (leftType.kind() == Type::kVector_Kind && rightType.isNumber()) { if (leftType.typeKind() == Type::TypeKind::kVector && rightType.isNumber()) {
if (op == Token::Kind::TK_SLASH) { if (op == Token::Kind::TK_SLASH) {
SpvId one = this->writeExpression(*create_literal_1(fContext, rightType), out); SpvId one = this->writeExpression(*create_literal_1(fContext, rightType), out);
SpvId inverse = this->nextId(); SpvId inverse = this->nextId();
@ -2134,7 +2138,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
} }
rhs = vec; rhs = vec;
operandType = &leftType; operandType = &leftType;
} else if (rightType.kind() == Type::kVector_Kind && leftType.isNumber()) { } else if (rightType.typeKind() == Type::TypeKind::kVector && leftType.isNumber()) {
if (op == Token::Kind::TK_STAR) { if (op == Token::Kind::TK_STAR) {
SpvId result = this->nextId(); SpvId result = this->nextId();
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType), this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
@ -2152,26 +2156,26 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
} }
lhs = vec; lhs = vec;
operandType = &rightType; operandType = &rightType;
} else if (leftType.kind() == Type::kMatrix_Kind) { } else if (leftType.typeKind() == Type::TypeKind::kMatrix) {
SpvOp_ spvop; SpvOp_ spvop;
if (rightType.kind() == Type::kMatrix_Kind) { if (rightType.typeKind() == Type::TypeKind::kMatrix) {
spvop = SpvOpMatrixTimesMatrix; spvop = SpvOpMatrixTimesMatrix;
} else if (rightType.kind() == Type::kVector_Kind) { } else if (rightType.typeKind() == Type::TypeKind::kVector) {
spvop = SpvOpMatrixTimesVector; spvop = SpvOpMatrixTimesVector;
} else { } else {
SkASSERT(rightType.kind() == Type::kScalar_Kind); SkASSERT(rightType.typeKind() == Type::TypeKind::kScalar);
spvop = SpvOpMatrixTimesScalar; spvop = SpvOpMatrixTimesScalar;
} }
SpvId result = this->nextId(); SpvId result = this->nextId();
this->writeInstruction(spvop, this->getType(resultType), result, lhs, rhs, out); this->writeInstruction(spvop, this->getType(resultType), result, lhs, rhs, out);
return result; return result;
} else if (rightType.kind() == Type::kMatrix_Kind) { } else if (rightType.typeKind() == Type::TypeKind::kMatrix) {
SpvId result = this->nextId(); SpvId result = this->nextId();
if (leftType.kind() == Type::kVector_Kind) { if (leftType.typeKind() == Type::TypeKind::kVector) {
this->writeInstruction(SpvOpVectorTimesMatrix, this->getType(resultType), result, this->writeInstruction(SpvOpVectorTimesMatrix, this->getType(resultType), result,
lhs, rhs, out); lhs, rhs, out);
} else { } else {
SkASSERT(leftType.kind() == Type::kScalar_Kind); SkASSERT(leftType.typeKind() == Type::TypeKind::kScalar);
this->writeInstruction(SpvOpMatrixTimesScalar, this->getType(resultType), result, this->writeInstruction(SpvOpMatrixTimesScalar, this->getType(resultType), result,
rhs, lhs, out); rhs, lhs, out);
} }
@ -2187,13 +2191,13 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
} }
switch (op) { switch (op) {
case Token::Kind::TK_EQEQ: { case Token::Kind::TK_EQEQ: {
if (operandType->kind() == Type::kMatrix_Kind) { if (operandType->typeKind() == Type::TypeKind::kMatrix) {
return this->writeMatrixComparison(*operandType, lhs, rhs, SpvOpFOrdEqual, return this->writeMatrixComparison(*operandType, lhs, rhs, SpvOpFOrdEqual,
SpvOpIEqual, SpvOpAll, SpvOpLogicalAnd, out); SpvOpIEqual, SpvOpAll, SpvOpLogicalAnd, out);
} }
SkASSERT(resultType == *fContext.fBool_Type); SkASSERT(resultType == *fContext.fBool_Type);
const Type* tmpType; const Type* tmpType;
if (operandType->kind() == Type::kVector_Kind) { if (operandType->typeKind() == Type::TypeKind::kVector) {
tmpType = &fContext.fBool_Type->toCompound(fContext, tmpType = &fContext.fBool_Type->toCompound(fContext,
operandType->columns(), operandType->columns(),
operandType->rows()); operandType->rows());
@ -2206,13 +2210,13 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
*operandType, SpvOpAll, out); *operandType, SpvOpAll, out);
} }
case Token::Kind::TK_NEQ: case Token::Kind::TK_NEQ:
if (operandType->kind() == Type::kMatrix_Kind) { if (operandType->typeKind() == Type::TypeKind::kMatrix) {
return this->writeMatrixComparison(*operandType, lhs, rhs, SpvOpFOrdNotEqual, return this->writeMatrixComparison(*operandType, lhs, rhs, SpvOpFOrdNotEqual,
SpvOpINotEqual, SpvOpAny, SpvOpLogicalOr, out); SpvOpINotEqual, SpvOpAny, SpvOpLogicalOr, out);
} }
SkASSERT(resultType == *fContext.fBool_Type); SkASSERT(resultType == *fContext.fBool_Type);
const Type* tmpType; const Type* tmpType;
if (operandType->kind() == Type::kVector_Kind) { if (operandType->typeKind() == Type::TypeKind::kVector) {
tmpType = &fContext.fBool_Type->toCompound(fContext, tmpType = &fContext.fBool_Type->toCompound(fContext,
operandType->columns(), operandType->columns(),
operandType->rows()); operandType->rows());
@ -2244,8 +2248,8 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
SpvOpFOrdLessThanEqual, SpvOpSLessThanEqual, SpvOpFOrdLessThanEqual, SpvOpSLessThanEqual,
SpvOpULessThanEqual, SpvOpUndef, out); SpvOpULessThanEqual, SpvOpUndef, out);
case Token::Kind::TK_PLUS: case Token::Kind::TK_PLUS:
if (leftType.kind() == Type::kMatrix_Kind && if (leftType.typeKind() == Type::TypeKind::kMatrix &&
rightType.kind() == Type::kMatrix_Kind) { rightType.typeKind() == Type::TypeKind::kMatrix) {
SkASSERT(leftType == rightType); SkASSERT(leftType == rightType);
return this->writeComponentwiseMatrixBinary(leftType, lhs, rhs, return this->writeComponentwiseMatrixBinary(leftType, lhs, rhs,
SpvOpFAdd, SpvOpIAdd, out); SpvOpFAdd, SpvOpIAdd, out);
@ -2253,8 +2257,8 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd, return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd,
SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out); SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out);
case Token::Kind::TK_MINUS: case Token::Kind::TK_MINUS:
if (leftType.kind() == Type::kMatrix_Kind && if (leftType.typeKind() == Type::TypeKind::kMatrix &&
rightType.kind() == Type::kMatrix_Kind) { rightType.typeKind() == Type::TypeKind::kMatrix) {
SkASSERT(leftType == rightType); SkASSERT(leftType == rightType);
return this->writeComponentwiseMatrixBinary(leftType, lhs, rhs, return this->writeComponentwiseMatrixBinary(leftType, lhs, rhs,
SpvOpFSub, SpvOpISub, out); SpvOpFSub, SpvOpISub, out);
@ -2262,8 +2266,8 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub, return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub,
SpvOpISub, SpvOpISub, SpvOpUndef, out); SpvOpISub, SpvOpISub, SpvOpUndef, out);
case Token::Kind::TK_STAR: case Token::Kind::TK_STAR:
if (leftType.kind() == Type::kMatrix_Kind && if (leftType.typeKind() == Type::TypeKind::kMatrix &&
rightType.kind() == Type::kMatrix_Kind) { rightType.typeKind() == Type::TypeKind::kMatrix) {
// matrix multiply // matrix multiply
SpvId result = this->nextId(); SpvId result = this->nextId();
this->writeInstruction(SpvOpMatrixTimesMatrix, this->getType(resultType), result, this->writeInstruction(SpvOpMatrixTimesMatrix, this->getType(resultType), result,
@ -2701,13 +2705,15 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a
SpvId typeId; SpvId typeId;
if (intf.fVariable.fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) { if (intf.fVariable.fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (e.fKind == ProgramElement::kModifiers_Kind) { if (e.kind() == ProgramElement::Kind::kModifiers) {
const Modifiers& m = ((ModifiersDeclaration&) e).fModifiers; const Modifiers& m = ((ModifiersDeclaration&) e).fModifiers;
update_sk_in_count(m, &fSkInCount); update_sk_in_count(m, &fSkInCount);
} }
} }
typeId = this->getType(Type("sk_in", Type::kArray_Kind, intf.fVariable.fType.componentType(), typeId = this->getType(Type("sk_in", Type::TypeKind::kArray,
fSkInCount), memoryLayout); intf.fVariable.fType.componentType(),
fSkInCount),
memoryLayout);
} else { } else {
typeId = this->getType(*type, memoryLayout); typeId = this->getType(*type, memoryLayout);
} }
@ -2762,7 +2768,7 @@ bool is_dead(const Variable& var) {
void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl, void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl,
OutputStream& out) { OutputStream& out) {
for (size_t i = 0; i < decl.fVars.size(); i++) { for (size_t i = 0; i < decl.fVars.size(); i++) {
if (decl.fVars[i]->fKind == Statement::kNop_Kind) { if (decl.fVars[i]->kind() == Statement::Kind::kNop) {
continue; continue;
} }
const VarDeclaration& varDecl = (VarDeclaration&) *decl.fVars[i]; const VarDeclaration& varDecl = (VarDeclaration&) *decl.fVars[i];
@ -2791,9 +2797,9 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio
} else if (var->fModifiers.fFlags & Modifiers::kOut_Flag) { } else if (var->fModifiers.fFlags & Modifiers::kOut_Flag) {
storageClass = SpvStorageClassOutput; storageClass = SpvStorageClassOutput;
} else if (var->fModifiers.fFlags & Modifiers::kUniform_Flag) { } else if (var->fModifiers.fFlags & Modifiers::kUniform_Flag) {
if (var->fType.kind() == Type::kSampler_Kind || if (var->fType.typeKind() == Type::TypeKind::kSampler ||
var->fType.kind() == Type::kSeparateSampler_Kind || var->fType.typeKind() == Type::TypeKind::kSeparateSampler ||
var->fType.kind() == Type::kTexture_Kind) { var->fType.typeKind() == Type::TypeKind::kTexture) {
storageClass = SpvStorageClassUniformConstant; storageClass = SpvStorageClassUniformConstant;
} else { } else {
storageClass = SpvStorageClassUniform; storageClass = SpvStorageClassUniform;
@ -2805,7 +2811,7 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio
fVariableMap[var] = id; fVariableMap[var] = id;
SpvId type; SpvId type;
if (var->fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) { if (var->fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
type = this->getPointerType(Type("sk_in", Type::kArray_Kind, type = this->getPointerType(Type("sk_in", Type::TypeKind::kArray,
var->fType.componentType(), fSkInCount), var->fType.componentType(), fSkInCount),
storageClass); storageClass);
} else { } else {
@ -2834,7 +2840,7 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio
void SPIRVCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, OutputStream& out) { void SPIRVCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, OutputStream& out) {
for (const auto& stmt : decl.fVars) { for (const auto& stmt : decl.fVars) {
SkASSERT(stmt->fKind == Statement::kVarDeclaration_Kind); SkASSERT(stmt->kind() == Statement::Kind::kVarDeclaration);
VarDeclaration& varDecl = (VarDeclaration&) *stmt; VarDeclaration& varDecl = (VarDeclaration&) *stmt;
const Variable* var = varDecl.fVar; const Variable* var = varDecl.fVar;
// These haven't been implemented in our SPIR-V generator yet and we only currently use them // These haven't been implemented in our SPIR-V generator yet and we only currently use them
@ -2857,43 +2863,43 @@ void SPIRVCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, Outpu
} }
void SPIRVCodeGenerator::writeStatement(const Statement& s, OutputStream& out) { void SPIRVCodeGenerator::writeStatement(const Statement& s, OutputStream& out) {
switch (s.fKind) { switch (s.kind()) {
case Statement::kNop_Kind: case Statement::Kind::kNop:
break; break;
case Statement::kBlock_Kind: case Statement::Kind::kBlock:
this->writeBlock((Block&) s, out); this->writeBlock((Block&) s, out);
break; break;
case Statement::kExpression_Kind: case Statement::Kind::kExpression:
this->writeExpression(*s.as<ExpressionStatement>().fExpression, out); this->writeExpression(*s.as<ExpressionStatement>().fExpression, out);
break; break;
case Statement::kReturn_Kind: case Statement::Kind::kReturn:
this->writeReturnStatement(s.as<ReturnStatement>(), out); this->writeReturnStatement(s.as<ReturnStatement>(), out);
break; break;
case Statement::kVarDeclarations_Kind: case Statement::Kind::kVarDeclarations:
this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration, out); this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration, out);
break; break;
case Statement::kIf_Kind: case Statement::Kind::kIf:
this->writeIfStatement(s.as<IfStatement>(), out); this->writeIfStatement(s.as<IfStatement>(), out);
break; break;
case Statement::kFor_Kind: case Statement::Kind::kFor:
this->writeForStatement(s.as<ForStatement>(), out); this->writeForStatement(s.as<ForStatement>(), out);
break; break;
case Statement::kWhile_Kind: case Statement::Kind::kWhile:
this->writeWhileStatement(s.as<WhileStatement>(), out); this->writeWhileStatement(s.as<WhileStatement>(), out);
break; break;
case Statement::kDo_Kind: case Statement::Kind::kDo:
this->writeDoStatement(s.as<DoStatement>(), out); this->writeDoStatement(s.as<DoStatement>(), out);
break; break;
case Statement::kSwitch_Kind: case Statement::Kind::kSwitch:
this->writeSwitchStatement(s.as<SwitchStatement>(), out); this->writeSwitchStatement(s.as<SwitchStatement>(), out);
break; break;
case Statement::kBreak_Kind: case Statement::Kind::kBreak:
this->writeInstruction(SpvOpBranch, fBreakTarget.top(), out); this->writeInstruction(SpvOpBranch, fBreakTarget.top(), out);
break; break;
case Statement::kContinue_Kind: case Statement::Kind::kContinue:
this->writeInstruction(SpvOpBranch, fContinueTarget.top(), out); this->writeInstruction(SpvOpBranch, fContinueTarget.top(), out);
break; break;
case Statement::kDiscard_Kind: case Statement::Kind::kDiscard:
this->writeInstruction(SpvOpKill, out); this->writeInstruction(SpvOpKill, out);
break; break;
default: default:
@ -3084,7 +3090,7 @@ void SPIRVCodeGenerator::writeGeometryShaderExecutionMode(SpvId entryPoint, Outp
SkASSERT(fProgram.fKind == Program::kGeometry_Kind); SkASSERT(fProgram.fKind == Program::kGeometry_Kind);
int invocations = 1; int invocations = 1;
for (const auto& e : fProgram) { for (const auto& e : fProgram) {
if (e.fKind == ProgramElement::kModifiers_Kind) { if (e.kind() == ProgramElement::Kind::kModifiers) {
const Modifiers& m = ((ModifiersDeclaration&) e).fModifiers; const Modifiers& m = ((ModifiersDeclaration&) e).fModifiers;
if (m.fFlags & Modifiers::kIn_Flag) { if (m.fFlags & Modifiers::kIn_Flag) {
if (m.fLayout.fInvocations != -1) { if (m.fLayout.fInvocations != -1) {
@ -3153,13 +3159,13 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
// assign IDs to functions, determine sk_in size // assign IDs to functions, determine sk_in size
int skInSize = -1; int skInSize = -1;
for (const auto& e : program) { for (const auto& e : program) {
switch (e.fKind) { switch (e.kind()) {
case ProgramElement::kFunction_Kind: { case ProgramElement::Kind::kFunction: {
FunctionDefinition& f = (FunctionDefinition&) e; FunctionDefinition& f = (FunctionDefinition&) e;
fFunctionMap[&f.fDeclaration] = this->nextId(); fFunctionMap[&f.fDeclaration] = this->nextId();
break; break;
} }
case ProgramElement::kModifiers_Kind: { case ProgramElement::Kind::kModifiers: {
Modifiers& m = ((ModifiersDeclaration&) e).fModifiers; Modifiers& m = ((ModifiersDeclaration&) e).fModifiers;
if (m.fFlags & Modifiers::kIn_Flag) { if (m.fFlags & Modifiers::kIn_Flag) {
switch (m.fLayout.fPrimitive) { switch (m.fLayout.fPrimitive) {
@ -3185,7 +3191,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
} }
} }
for (const auto& e : program) { for (const auto& e : program) {
if (e.fKind == ProgramElement::kInterfaceBlock_Kind) { if (e.kind() == ProgramElement::Kind::kInterfaceBlock) {
InterfaceBlock& intf = (InterfaceBlock&) e; InterfaceBlock& intf = (InterfaceBlock&) e;
if (SK_IN_BUILTIN == intf.fVariable.fModifiers.fLayout.fBuiltin) { if (SK_IN_BUILTIN == intf.fVariable.fModifiers.fLayout.fBuiltin) {
SkASSERT(skInSize != -1); SkASSERT(skInSize != -1);
@ -3201,12 +3207,12 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
} }
} }
for (const auto& e : program) { for (const auto& e : program) {
if (e.fKind == ProgramElement::kVar_Kind) { if (e.kind() == ProgramElement::Kind::kVar) {
this->writeGlobalVars(program.fKind, ((VarDeclarations&) e), body); this->writeGlobalVars(program.fKind, ((VarDeclarations&) e), body);
} }
} }
for (const auto& e : program) { for (const auto& e : program) {
if (e.fKind == ProgramElement::kFunction_Kind) { if (e.kind() == ProgramElement::Kind::kFunction) {
this->writeFunction(((FunctionDefinition&) e), body); this->writeFunction(((FunctionDefinition&) e), body);
} }
} }
@ -3262,7 +3268,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
out); out);
} }
for (const auto& e : program) { for (const auto& e : program) {
if (e.fKind == ProgramElement::kExtension_Kind) { if (e.kind() == ProgramElement::Kind::kExtension) {
this->writeInstruction(SpvOpSourceExtension, ((Extension&) e).fName.c_str(), out); this->writeInstruction(SpvOpSourceExtension, ((Extension&) e).fName.c_str(), out);
} }
} }

View File

@ -29,8 +29,8 @@ namespace SkSL {
SectionAndParameterHelper::SectionAndParameterHelper(const Program* program, ErrorReporter& errors) SectionAndParameterHelper::SectionAndParameterHelper(const Program* program, ErrorReporter& errors)
: fProgram(*program) { : fProgram(*program) {
for (const auto& p : fProgram) { for (const auto& p : fProgram) {
switch (p.fKind) { switch (p.kind()) {
case ProgramElement::kVar_Kind: { case ProgramElement::Kind::kVar: {
const VarDeclarations& decls = (const VarDeclarations&) p; const VarDeclarations& decls = (const VarDeclarations&) p;
for (const auto& raw : decls.fVars) { for (const auto& raw : decls.fVars) {
const VarDeclaration& decl = (VarDeclaration&) *raw; const VarDeclaration& decl = (VarDeclaration&) *raw;
@ -40,7 +40,7 @@ SectionAndParameterHelper::SectionAndParameterHelper(const Program* program, Err
} }
break; break;
} }
case ProgramElement::kSection_Kind: { case ProgramElement::Kind::kSection: {
const Section& s = (const Section&) p; const Section& s = (const Section&) p;
if (IsSupportedSection(s.fName.c_str())) { if (IsSupportedSection(s.fName.c_str())) {
if (SectionRequiresArgument(s.fName.c_str()) && !s.fArgument.size()) { if (SectionRequiresArgument(s.fName.c_str()) && !s.fArgument.size()) {

View File

@ -20,20 +20,20 @@
namespace SkSL { namespace SkSL {
static inline bool check_ref(Expression* expr) { static inline bool check_ref(Expression* expr) {
switch (expr->fKind) { switch (expr->kind()) {
case Expression::kExternalValue_Kind: case Expression::Kind::kExternalValue:
return true; return true;
case Expression::kFieldAccess_Kind: case Expression::Kind::kFieldAccess:
return check_ref(((FieldAccess*) expr)->fBase.get()); return check_ref(((FieldAccess*) expr)->fBase.get());
case Expression::kIndex_Kind: case Expression::Kind::kIndex:
return check_ref(((IndexExpression*) expr)->fBase.get()); return check_ref(((IndexExpression*) expr)->fBase.get());
case Expression::kSwizzle_Kind: case Expression::Kind::kSwizzle:
return check_ref(((Swizzle*) expr)->fBase.get()); return check_ref(((Swizzle*) expr)->fBase.get());
case Expression::kTernary_Kind: { case Expression::Kind::kTernary: {
TernaryExpression* t = (TernaryExpression*) expr; TernaryExpression* t = (TernaryExpression*) expr;
return check_ref(t->fIfTrue.get()) && check_ref(t->fIfFalse.get()); return check_ref(t->fIfTrue.get()) && check_ref(t->fIfFalse.get());
} }
case Expression::kVariableReference_Kind: { case Expression::Kind::kVariableReference: {
VariableReference* ref = (VariableReference*) expr; VariableReference* ref = (VariableReference*) expr;
return ref->fRefKind == VariableReference::kWrite_RefKind || return ref->fRefKind == VariableReference::kWrite_RefKind ||
ref->fRefKind == VariableReference::kReadWrite_RefKind; ref->fRefKind == VariableReference::kReadWrite_RefKind;
@ -47,7 +47,7 @@ static inline bool check_ref(Expression* expr) {
* A binary operation. * A binary operation.
*/ */
struct BinaryExpression : public Expression { struct BinaryExpression : public Expression {
static constexpr Kind kExpressionKind = kBinary_Kind; static constexpr Kind kExpressionKind = Kind::kBinary;
BinaryExpression(int offset, 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) std::unique_ptr<Expression> right, const Type& type)

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A block of multiple statements functioning as a single statement. * A block of multiple statements functioning as a single statement.
*/ */
struct Block : public Statement { struct Block : public Statement {
static constexpr Kind kStatementKind = kBlock_Kind; static constexpr Kind kStatementKind = Kind::kBlock;
Block(int offset, std::vector<std::unique_ptr<Statement>> statements, Block(int offset, std::vector<std::unique_ptr<Statement>> statements,
const std::shared_ptr<SymbolTable> symbols = nullptr, bool isScope = true) const std::shared_ptr<SymbolTable> symbols = nullptr, bool isScope = true)

View File

@ -17,7 +17,7 @@ namespace SkSL {
* Represents 'true' or 'false'. * Represents 'true' or 'false'.
*/ */
struct BoolLiteral : public Expression { struct BoolLiteral : public Expression {
static constexpr Kind kExpressionKind = kBoolLiteral_Kind; static constexpr Kind kExpressionKind = Kind::kBoolLiteral;
BoolLiteral(const Context& context, int offset, bool value) BoolLiteral(const Context& context, int offset, bool value)
: INHERITED(offset, kExpressionKind, *context.fBool_Type) : INHERITED(offset, kExpressionKind, *context.fBool_Type)

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A 'break' statement. * A 'break' statement.
*/ */
struct BreakStatement : public Statement { struct BreakStatement : public Statement {
static constexpr Kind kStatementKind = kBreak_Kind; static constexpr Kind kStatementKind = Kind::kBreak;
BreakStatement(int offset) BreakStatement(int offset)
: INHERITED(offset, kStatementKind) {} : INHERITED(offset, kStatementKind) {}

View File

@ -26,7 +26,7 @@ namespace SkSL {
* collection of vectors and scalars totalling exactly the right number of scalar components. * collection of vectors and scalars totalling exactly the right number of scalar components.
*/ */
struct Constructor : public Expression { struct Constructor : public Expression {
static constexpr Kind kExpressionKind = kConstructor_Kind; static constexpr Kind kExpressionKind = Kind::kConstructor;
Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments) Constructor(int offset, const Type& type, std::vector<std::unique_ptr<Expression>> arguments)
: INHERITED(offset, kExpressionKind, type) : INHERITED(offset, kExpressionKind, type)
@ -34,7 +34,7 @@ struct Constructor : public Expression {
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override { const DefinitionMap& definitions) override {
if (fArguments.size() == 1 && fArguments[0]->fKind == Expression::kIntLiteral_Kind) { if (fArguments.size() == 1 && fArguments[0]->kind() == Expression::Kind::kIntLiteral) {
if (fType.isFloat()) { if (fType.isFloat()) {
// promote float(1) to 1.0 // promote float(1) to 1.0
int64_t intValue = fArguments[0]->as<IntLiteral>().fValue; int64_t intValue = fArguments[0]->as<IntLiteral>().fValue;
@ -100,9 +100,9 @@ struct Constructor : public Expression {
} }
bool compareConstant(const Context& context, const Expression& other) const override { bool compareConstant(const Context& context, const Expression& other) const override {
SkASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType); SkASSERT(other.kind() == Expression::Kind::kConstructor && other.fType == fType);
Constructor& c = (Constructor&) other; Constructor& c = (Constructor&) other;
if (c.fType.kind() == Type::kVector_Kind) { if (c.fType.typeKind() == Type::TypeKind::kVector) {
bool isFloat = c.fType.columns() > 1 ? c.fType.componentType().isFloat() bool isFloat = c.fType.columns() > 1 ? c.fType.componentType().isFloat()
: c.fType.isFloat(); : c.fType.isFloat();
for (int i = 0; i < fType.columns(); i++) { for (int i = 0; i < fType.columns(); i++) {
@ -119,7 +119,7 @@ struct Constructor : public Expression {
// shouldn't be possible to have a constant constructor that isn't a vector or matrix; // shouldn't be possible to have a constant constructor that isn't a vector or matrix;
// a constant scalar constructor should have been collapsed down to the appropriate // a constant scalar constructor should have been collapsed down to the appropriate
// literal // literal
SkASSERT(fType.kind() == Type::kMatrix_Kind); SkASSERT(fType.typeKind() == Type::TypeKind::kMatrix);
for (int col = 0; col < fType.columns(); col++) { for (int col = 0; col < fType.columns(); col++) {
for (int row = 0; row < fType.rows(); row++) { for (int row = 0; row < fType.rows(); row++) {
if (getMatComponent(col, row) != c.getMatComponent(col, row)) { if (getMatComponent(col, row) != c.getMatComponent(col, row)) {
@ -132,8 +132,8 @@ struct Constructor : public Expression {
template <typename type> template <typename type>
type getVecComponent(int index) const { type getVecComponent(int index) const {
SkASSERT(fType.kind() == Type::kVector_Kind); SkASSERT(fType.typeKind() == Type::TypeKind::kVector);
if (fArguments.size() == 1 && fArguments[0]->fType.kind() == Type::kScalar_Kind) { if (fArguments.size() == 1 && fArguments[0]->fType.typeKind() == Type::TypeKind::kScalar) {
// This constructor just wraps a scalar. Propagate out the value. // This constructor just wraps a scalar. Propagate out the value.
if (std::is_floating_point<type>::value) { if (std::is_floating_point<type>::value) {
return fArguments[0]->getConstantFloat(); return fArguments[0]->getConstantFloat();
@ -150,7 +150,7 @@ struct Constructor : public Expression {
break; break;
} }
if (arg->fType.kind() == Type::kScalar_Kind) { if (arg->fType.typeKind() == Type::TypeKind::kScalar) {
if (index == current) { if (index == current) {
// We're on the proper argument, and it's a scalar; fetch it. // We're on the proper argument, and it's a scalar; fetch it.
if (std::is_floating_point<type>::value) { if (std::is_floating_point<type>::value) {
@ -163,8 +163,8 @@ struct Constructor : public Expression {
continue; continue;
} }
switch (arg->fKind) { switch (arg->kind()) {
case kConstructor_Kind: { case Kind::kConstructor: {
const Constructor& constructor = static_cast<const Constructor&>(*arg); const Constructor& constructor = static_cast<const Constructor&>(*arg);
if (current + constructor.fType.columns() > index) { if (current + constructor.fType.columns() > index) {
// We've found a constructor that overlaps the proper argument. Descend into // We've found a constructor that overlaps the proper argument. Descend into
@ -177,7 +177,7 @@ struct Constructor : public Expression {
} }
break; break;
} }
case kPrefix_Kind: { case Kind::kPrefix: {
const PrefixExpression& prefix = static_cast<const PrefixExpression&>(*arg); const PrefixExpression& prefix = static_cast<const PrefixExpression&>(*arg);
if (current + prefix.fType.columns() > index) { if (current + prefix.fType.columns() > index) {
// We found a prefix operator that contains the proper argument. Descend // We found a prefix operator that contains the proper argument. Descend
@ -186,7 +186,7 @@ struct Constructor : public Expression {
SkASSERT(prefix.fOperator == Token::Kind::TK_MINUS); SkASSERT(prefix.fOperator == Token::Kind::TK_MINUS);
// We expect the - prefix to always be attached to a constructor. // We expect the - prefix to always be attached to a constructor.
SkASSERT(prefix.fOperand->fKind == kConstructor_Kind); SkASSERT(prefix.fOperand->kind() == Kind::kConstructor);
const Constructor& constructor = const Constructor& constructor =
static_cast<const Constructor&>(*prefix.fOperand); static_cast<const Constructor&>(*prefix.fOperand);
@ -227,10 +227,10 @@ struct Constructor : public Expression {
SKSL_FLOAT getMatComponent(int col, int row) const override { SKSL_FLOAT getMatComponent(int col, int row) const override {
SkASSERT(this->isCompileTimeConstant()); SkASSERT(this->isCompileTimeConstant());
SkASSERT(fType.kind() == Type::kMatrix_Kind); SkASSERT(fType.typeKind() == Type::TypeKind::kMatrix);
SkASSERT(col < fType.columns() && row < fType.rows()); SkASSERT(col < fType.columns() && row < fType.rows());
if (fArguments.size() == 1) { if (fArguments.size() == 1) {
if (fArguments[0]->fType.kind() == Type::kScalar_Kind) { if (fArguments[0]->fType.typeKind() == Type::TypeKind::kScalar) {
// single scalar argument, so matrix is of the form: // single scalar argument, so matrix is of the form:
// x 0 0 // x 0 0
// 0 x 0 // 0 x 0
@ -238,8 +238,8 @@ struct Constructor : public Expression {
// return x if col == row // return x if col == row
return col == row ? fArguments[0]->getConstantFloat() : 0.0; return col == row ? fArguments[0]->getConstantFloat() : 0.0;
} }
if (fArguments[0]->fType.kind() == Type::kMatrix_Kind) { if (fArguments[0]->fType.typeKind() == Type::TypeKind::kMatrix) {
SkASSERT(fArguments[0]->fKind == Expression::kConstructor_Kind); SkASSERT(fArguments[0]->kind() == Expression::Kind::kConstructor);
// single matrix argument. make sure we're within the argument's bounds. // single matrix argument. make sure we're within the argument's bounds.
const Type& argType = ((Constructor&) *fArguments[0]).fType; const Type& argType = ((Constructor&) *fArguments[0]).fType;
if (col < argType.columns() && row < argType.rows()) { if (col < argType.columns() && row < argType.rows()) {

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A 'continue' statement. * A 'continue' statement.
*/ */
struct ContinueStatement : public Statement { struct ContinueStatement : public Statement {
static constexpr Kind kStatementKind = kContinue_Kind; static constexpr Kind kStatementKind = Kind::kContinue;
ContinueStatement(int offset) ContinueStatement(int offset)
: INHERITED(offset, kStatementKind) {} : INHERITED(offset, kStatementKind) {}

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A 'discard' statement. * A 'discard' statement.
*/ */
struct DiscardStatement : public Statement { struct DiscardStatement : public Statement {
static constexpr Kind kStatementKind = kDiscard_Kind; static constexpr Kind kStatementKind = Kind::kDiscard;
DiscardStatement(int offset) DiscardStatement(int offset)
: INHERITED(offset, kStatementKind) {} : INHERITED(offset, kStatementKind) {}

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A 'do' statement. * A 'do' statement.
*/ */
struct DoStatement : public Statement { struct DoStatement : public Statement {
static constexpr Kind kStatementKind = kDo_Kind; static constexpr Kind kStatementKind = Kind::kDo;
DoStatement(int offset, std::unique_ptr<Statement> statement, DoStatement(int offset, std::unique_ptr<Statement> statement,
std::unique_ptr<Expression> test) std::unique_ptr<Expression> test)

View File

@ -21,7 +21,7 @@ namespace SkSL {
struct Symbol; struct Symbol;
struct Enum : public ProgramElement { struct Enum : public ProgramElement {
static constexpr Kind kProgramElementKind = kEnum_Kind; static constexpr Kind kProgramElementKind = Kind::kEnum;
Enum(int offset, StringFragment typeName, std::shared_ptr<SymbolTable> symbols, Enum(int offset, StringFragment typeName, std::shared_ptr<SymbolTable> symbols,
bool isBuiltin = true) bool isBuiltin = true)

View File

@ -8,6 +8,7 @@
#ifndef SKSL_EXPRESSION #ifndef SKSL_EXPRESSION
#define SKSL_EXPRESSION #define SKSL_EXPRESSION
#include "src/sksl/ir/SkSLStatement.h"
#include "src/sksl/ir/SkSLType.h" #include "src/sksl/ir/SkSLType.h"
#include <unordered_map> #include <unordered_map>
@ -24,27 +25,30 @@ typedef std::unordered_map<const Variable*, std::unique_ptr<Expression>*> Defini
* Abstract supertype of all expressions. * Abstract supertype of all expressions.
*/ */
struct Expression : public IRNode { struct Expression : public IRNode {
enum Kind { enum class Kind {
kBinary_Kind, kBinary = (int) Statement::Kind::kLast + 1,
kBoolLiteral_Kind, kBoolLiteral,
kConstructor_Kind, kConstructor,
kExternalFunctionCall_Kind, kDefined,
kExternalValue_Kind, kExternalFunctionCall,
kIntLiteral_Kind, kExternalValue,
kFieldAccess_Kind, kIntLiteral,
kFloatLiteral_Kind, kFieldAccess,
kFunctionReference_Kind, kFloatLiteral,
kFunctionCall_Kind, kFunctionReference,
kIndex_Kind, kFunctionCall,
kNullLiteral_Kind, kIndex,
kPrefix_Kind, kNullLiteral,
kPostfix_Kind, kPrefix,
kSetting_Kind, kPostfix,
kSwizzle_Kind, kSetting,
kTernary_Kind, kSwizzle,
kTypeReference_Kind, kTernary,
kVariableReference_Kind, kTypeReference,
kDefined_Kind kVariableReference,
kFirst = kBinary,
kLast = kVariableReference
}; };
enum class Property { enum class Property {
@ -53,9 +57,15 @@ struct Expression : public IRNode {
}; };
Expression(int offset, Kind kind, const Type& type) Expression(int offset, Kind kind, const Type& type)
: INHERITED(offset) : INHERITED(offset, (int) kind)
, fKind(kind) , fType(std::move(type)) {
, fType(std::move(type)) {} SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
}
Kind kind() const {
return (Kind) fKind;
}
/** /**
* Use is<T> to check the type of an expression. * Use is<T> to check the type of an expression.
@ -63,7 +73,7 @@ struct Expression : public IRNode {
*/ */
template <typename T> template <typename T>
bool is() const { bool is() const {
return this->fKind == T::kExpressionKind; return this->kind() == T::kExpressionKind;
} }
/** /**
@ -179,7 +189,6 @@ struct Expression : public IRNode {
virtual std::unique_ptr<Expression> clone() const = 0; virtual std::unique_ptr<Expression> clone() const = 0;
const Kind fKind;
const Type& fType; const Type& fType;
using INHERITED = IRNode; using INHERITED = IRNode;

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A lone expression being used as a statement. * A lone expression being used as a statement.
*/ */
struct ExpressionStatement : public Statement { struct ExpressionStatement : public Statement {
static constexpr Kind kStatementKind = kExpression_Kind; static constexpr Kind kStatementKind = Kind::kExpression;
ExpressionStatement(std::unique_ptr<Expression> expression) ExpressionStatement(std::unique_ptr<Expression> expression)
: INHERITED(expression->fOffset, kStatementKind) : INHERITED(expression->fOffset, kStatementKind)

View File

@ -16,7 +16,7 @@ namespace SkSL {
* An extension declaration. * An extension declaration.
*/ */
struct Extension : public ProgramElement { struct Extension : public ProgramElement {
static constexpr Kind kProgramElementKind = kExtension_Kind; static constexpr Kind kProgramElementKind = Kind::kExtension;
Extension(int offset, String name) Extension(int offset, String name)
: INHERITED(offset, kProgramElementKind) : INHERITED(offset, kProgramElementKind)

View File

@ -18,7 +18,7 @@ namespace SkSL {
* An external function invocation. * An external function invocation.
*/ */
struct ExternalFunctionCall : public Expression { struct ExternalFunctionCall : public Expression {
static constexpr Kind kExpressionKind = kExternalFunctionCall_Kind; static constexpr Kind kExpressionKind = Kind::kExternalFunctionCall;
ExternalFunctionCall(int offset, const Type& type, const ExternalValue* function, ExternalFunctionCall(int offset, const Type& type, const ExternalValue* function,
std::vector<std::unique_ptr<Expression>> arguments) std::vector<std::unique_ptr<Expression>> arguments)

View File

@ -17,7 +17,7 @@ namespace SkSL {
* Represents an identifier referring to an ExternalValue. * Represents an identifier referring to an ExternalValue.
*/ */
struct ExternalValueReference : public Expression { struct ExternalValueReference : public Expression {
static constexpr Kind kExpressionKind = kExternalValue_Kind; static constexpr Kind kExpressionKind = Kind::kExternalValue;
ExternalValueReference(int offset, const ExternalValue* ev) ExternalValueReference(int offset, const ExternalValue* ev)
: INHERITED(offset, kExpressionKind, ev->type()) : INHERITED(offset, kExpressionKind, ev->type())

View File

@ -22,7 +22,7 @@ namespace SkSL {
* result of declaring anonymous interface blocks. * result of declaring anonymous interface blocks.
*/ */
struct Field : public Symbol { struct Field : public Symbol {
static constexpr Kind kSymbolKind = kField_Kind; static constexpr Kind kSymbolKind = Kind::kField;
Field(int offset, const Variable& owner, int fieldIndex) Field(int offset, const Variable& owner, int fieldIndex)
: INHERITED(offset, kSymbolKind, owner.fType.fields()[fieldIndex].fName) : INHERITED(offset, kSymbolKind, owner.fType.fields()[fieldIndex].fName)

View File

@ -24,7 +24,7 @@ struct FieldAccess : public Expression {
kAnonymousInterfaceBlock_OwnerKind kAnonymousInterfaceBlock_OwnerKind
}; };
static constexpr Kind kExpressionKind = kFieldAccess_Kind; static constexpr Kind kExpressionKind = Kind::kFieldAccess;
FieldAccess(std::unique_ptr<Expression> base, int fieldIndex, FieldAccess(std::unique_ptr<Expression> base, int fieldIndex,
OwnerKind ownerKind = kDefault_OwnerKind) OwnerKind ownerKind = kDefault_OwnerKind)

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A literal floating point number. * A literal floating point number.
*/ */
struct FloatLiteral : public Expression { struct FloatLiteral : public Expression {
static constexpr Kind kExpressionKind = kFloatLiteral_Kind; static constexpr Kind kExpressionKind = Kind::kFloatLiteral;
FloatLiteral(const Context& context, int offset, double value) FloatLiteral(const Context& context, int offset, double value)
: INHERITED(offset, kExpressionKind, *context.fFloatLiteral_Type) : INHERITED(offset, kExpressionKind, *context.fFloatLiteral_Type)

View File

@ -18,7 +18,7 @@ namespace SkSL {
* A 'for' statement. * A 'for' statement.
*/ */
struct ForStatement : public Statement { struct ForStatement : public Statement {
static constexpr Kind kStatementKind = kFor_Kind; static constexpr Kind kStatementKind = Kind::kFor;
ForStatement(int offset, 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<Expression> test, std::unique_ptr<Expression> next,

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A function invocation. * A function invocation.
*/ */
struct FunctionCall : public Expression { struct FunctionCall : public Expression {
static constexpr Kind kExpressionKind = kFunctionCall_Kind; static constexpr Kind kExpressionKind = Kind::kFunctionCall;
FunctionCall(int offset, const Type& type, const FunctionDeclaration& function, FunctionCall(int offset, const Type& type, const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments) std::vector<std::unique_ptr<Expression>> arguments)

View File

@ -25,7 +25,7 @@ struct FunctionDefinition;
* A function declaration (not a definition -- does not contain a body). * A function declaration (not a definition -- does not contain a body).
*/ */
struct FunctionDeclaration : public Symbol { struct FunctionDeclaration : public Symbol {
static constexpr Kind kSymbolKind = kFunctionDeclaration_Kind; static constexpr Kind kSymbolKind = Kind::kFunctionDeclaration;
FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name, FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
std::vector<const Variable*> parameters, const Type& returnType, std::vector<const Variable*> parameters, const Type& returnType,
@ -81,7 +81,7 @@ struct FunctionDeclaration : public Symbol {
SkASSERT(arguments.size() == fParameters.size()); SkASSERT(arguments.size() == fParameters.size());
int genericIndex = -1; int genericIndex = -1;
for (size_t i = 0; i < arguments.size(); i++) { for (size_t i = 0; i < arguments.size(); i++) {
if (fParameters[i]->fType.kind() == Type::kGeneric_Kind) { if (fParameters[i]->fType.typeKind() == Type::TypeKind::kGeneric) {
std::vector<const Type*> types = fParameters[i]->fType.coercibleTypes(); std::vector<const Type*> types = fParameters[i]->fType.coercibleTypes();
if (genericIndex == -1) { if (genericIndex == -1) {
for (size_t j = 0; j < types.size(); j++) { for (size_t j = 0; j < types.size(); j++) {
@ -99,7 +99,7 @@ struct FunctionDeclaration : public Symbol {
outParameterTypes->push_back(&fParameters[i]->fType); outParameterTypes->push_back(&fParameters[i]->fType);
} }
} }
if (fReturnType.kind() == Type::kGeneric_Kind) { if (fReturnType.typeKind() == Type::TypeKind::kGeneric) {
if (genericIndex == -1) { if (genericIndex == -1) {
return false; return false;
} }

View File

@ -22,7 +22,7 @@ struct ASTNode;
* A function definition (a declaration plus an associated block of code). * A function definition (a declaration plus an associated block of code).
*/ */
struct FunctionDefinition : public ProgramElement { struct FunctionDefinition : public ProgramElement {
static constexpr Kind kProgramElementKind = kFunction_Kind; static constexpr Kind kProgramElementKind = Kind::kFunction;
FunctionDefinition(int offset, FunctionDefinition(int offset,
const FunctionDeclaration& declaration, const FunctionDeclaration& declaration,

View File

@ -19,7 +19,7 @@ namespace SkSL {
* always eventually replaced by FunctionCalls in valid programs. * always eventually replaced by FunctionCalls in valid programs.
*/ */
struct FunctionReference : public Expression { struct FunctionReference : public Expression {
static constexpr Kind kExpressionKind = kFunctionReference_Kind; static constexpr Kind kExpressionKind = Kind::kFunctionReference;
FunctionReference(const Context& context, int offset, FunctionReference(const Context& context, int offset,
std::vector<const FunctionDeclaration*> function) std::vector<const FunctionDeclaration*> function)

View File

@ -18,8 +18,9 @@ namespace SkSL {
* version of the program (all types determined, everything validated), ready for code generation. * version of the program (all types determined, everything validated), ready for code generation.
*/ */
struct IRNode { struct IRNode {
IRNode(int offset) IRNode(int offset, int kind)
: fOffset(offset) {} : fOffset(offset)
, fKind(kind) {}
virtual ~IRNode() {} virtual ~IRNode() {}
@ -28,6 +29,9 @@ struct IRNode {
// character offset of this element within the program being compiled, for error reporting // character offset of this element within the program being compiled, for error reporting
// purposes // purposes
int fOffset; int fOffset;
protected:
int fKind;
}; };
} // namespace SkSL } // namespace SkSL

View File

@ -17,7 +17,7 @@ namespace SkSL {
* An 'if' statement. * An 'if' statement.
*/ */
struct IfStatement : public Statement { struct IfStatement : public Statement {
static constexpr Kind kStatementKind = kIf_Kind; static constexpr Kind kStatementKind = Kind::kIf;
IfStatement(int offset, 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) std::unique_ptr<Statement> ifTrue, std::unique_ptr<Statement> ifFalse)

View File

@ -18,7 +18,7 @@ namespace SkSL {
* Given a type, returns the type that will result from extracting an array value from it. * Given a type, returns the type that will result from extracting an array value from it.
*/ */
static const Type& index_type(const Context& context, const Type& type) { static const Type& index_type(const Context& context, const Type& type) {
if (type.kind() == Type::kMatrix_Kind) { if (type.typeKind() == Type::TypeKind::kMatrix) {
if (type.componentType() == *context.fFloat_Type) { if (type.componentType() == *context.fFloat_Type) {
switch (type.rows()) { switch (type.rows()) {
case 2: return *context.fFloat2_Type; case 2: return *context.fFloat2_Type;
@ -42,7 +42,7 @@ static const Type& index_type(const Context& context, const Type& type) {
* An expression which extracts a value from an array or matrix, as in 'm[2]'. * An expression which extracts a value from an array or matrix, as in 'm[2]'.
*/ */
struct IndexExpression : public Expression { struct IndexExpression : public Expression {
static constexpr Kind kExpressionKind = kIndex_Kind; static constexpr Kind kExpressionKind = Kind::kIndex;
IndexExpression(const Context& context, std::unique_ptr<Expression> base, IndexExpression(const Context& context, std::unique_ptr<Expression> base,
std::unique_ptr<Expression> index) std::unique_ptr<Expression> index)
@ -73,7 +73,7 @@ struct IndexExpression : public Expression {
private: private:
IndexExpression(std::unique_ptr<Expression> base, std::unique_ptr<Expression> index, IndexExpression(std::unique_ptr<Expression> base, std::unique_ptr<Expression> index,
const Type* type) const Type* type)
: INHERITED(base->fOffset, kIndex_Kind, *type) : INHERITED(base->fOffset, Kind::kIndex, *type)
, fBase(std::move(base)) , fBase(std::move(base))
, fIndex(std::move(index)) {} , fIndex(std::move(index)) {}
}; };

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A literal integer. * A literal integer.
*/ */
struct IntLiteral : public Expression { struct IntLiteral : public Expression {
static constexpr Kind kExpressionKind = kIntLiteral_Kind; static constexpr Kind kExpressionKind = Kind::kIntLiteral;
// FIXME: we will need to revisit this if/when we add full support for both signed and unsigned // 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 // 64-bit integers, but for right now an int64_t will hold every value we care about
@ -47,7 +47,7 @@ struct IntLiteral : public Expression {
int coercionCost(const Type& target) const override { int coercionCost(const Type& target) const override {
if (target.isSigned() || target.isUnsigned() || target.isFloat() || if (target.isSigned() || target.isUnsigned() || target.isFloat() ||
target.kind() == Type::kEnum_Kind) { target.typeKind() == Type::TypeKind::kEnum) {
return 0; return 0;
} }
return INHERITED::coercionCost(target); return INHERITED::coercionCost(target);

View File

@ -25,7 +25,7 @@ namespace SkSL {
* At the IR level, this is represented by a single variable of struct type. * At the IR level, this is represented by a single variable of struct type.
*/ */
struct InterfaceBlock : public ProgramElement { struct InterfaceBlock : public ProgramElement {
static constexpr Kind kProgramElementKind = kInterfaceBlock_Kind; static constexpr Kind kProgramElementKind = Kind::kInterfaceBlock;
InterfaceBlock(int offset, 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::vector<std::unique_ptr<Expression>> sizes,
@ -51,7 +51,7 @@ struct InterfaceBlock : public ProgramElement {
String description() const override { String description() const override {
String result = fVariable.fModifiers.description() + fTypeName + " {\n"; String result = fVariable.fModifiers.description() + fTypeName + " {\n";
const Type* structType = &fVariable.fType; const Type* structType = &fVariable.fType;
while (structType->kind() == Type::kArray_Kind) { while (structType->typeKind() == Type::TypeKind::kArray) {
structType = &structType->componentType(); structType = &structType->componentType();
} }
for (const auto& f : structType->fields()) { for (const auto& f : structType->fields()) {

View File

@ -19,7 +19,7 @@ namespace SkSL {
* layout(blend_support_all_equations) out; * layout(blend_support_all_equations) out;
*/ */
struct ModifiersDeclaration : public ProgramElement { struct ModifiersDeclaration : public ProgramElement {
static constexpr Kind kProgramElementKind = kModifiers_Kind; static constexpr Kind kProgramElementKind = Kind::kModifiers;
ModifiersDeclaration(Modifiers modifiers) ModifiersDeclaration(Modifiers modifiers)
: INHERITED(-1, kProgramElementKind) : INHERITED(-1, kProgramElementKind)

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A no-op statement that does nothing. * A no-op statement that does nothing.
*/ */
struct Nop : public Statement { struct Nop : public Statement {
static constexpr Kind kStatementKind = kNop_Kind; static constexpr Kind kStatementKind = Kind::kNop;
Nop() Nop()
: INHERITED(-1, kStatementKind) {} : INHERITED(-1, kStatementKind) {}

View File

@ -17,7 +17,7 @@ namespace SkSL {
* Represents 'null'. * Represents 'null'.
*/ */
struct NullLiteral : public Expression { struct NullLiteral : public Expression {
static constexpr Kind kExpressionKind = kNullLiteral_Kind; static constexpr Kind kExpressionKind = Kind::kNullLiteral;
NullLiteral(const Context& context, int offset) NullLiteral(const Context& context, int offset)
: INHERITED(offset, kExpressionKind, *context.fNull_Type) {} : INHERITED(offset, kExpressionKind, *context.fNull_Type) {}

View File

@ -18,7 +18,7 @@ namespace SkSL {
* An expression modified by a unary operator appearing after it, such as 'i++'. * An expression modified by a unary operator appearing after it, such as 'i++'.
*/ */
struct PostfixExpression : public Expression { struct PostfixExpression : public Expression {
static constexpr Kind kExpressionKind = kPostfix_Kind; static constexpr Kind kExpressionKind = Kind::kPostfix;
PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op) PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op)
: INHERITED(operand->fOffset, kExpressionKind, operand->fType) : INHERITED(operand->fOffset, kExpressionKind, operand->fType)

View File

@ -20,7 +20,7 @@ namespace SkSL {
* An expression modified by a unary operator appearing before it, such as '!flag'. * An expression modified by a unary operator appearing before it, such as '!flag'.
*/ */
struct PrefixExpression : public Expression { struct PrefixExpression : public Expression {
static constexpr Kind kExpressionKind = kPrefix_Kind; static constexpr Kind kExpressionKind = Kind::kPrefix;
PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand) PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand)
: INHERITED(operand->fOffset, kExpressionKind, operand->fType) : INHERITED(operand->fOffset, kExpressionKind, operand->fType)
@ -41,7 +41,7 @@ struct PrefixExpression : public Expression {
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override { const DefinitionMap& definitions) override {
if (fOperand->fKind == Expression::kFloatLiteral_Kind) { if (fOperand->kind() == Expression::Kind::kFloatLiteral) {
return std::unique_ptr<Expression>(new FloatLiteral( return std::unique_ptr<Expression>(new FloatLiteral(
irGenerator.fContext, irGenerator.fContext,
fOffset, fOffset,

View File

@ -18,19 +18,27 @@ namespace SkSL {
* Represents a top-level element (e.g. function or global variable) in a program. * Represents a top-level element (e.g. function or global variable) in a program.
*/ */
struct ProgramElement : public IRNode { struct ProgramElement : public IRNode {
enum Kind { enum class Kind {
kEnum_Kind, kEnum = 0,
kExtension_Kind, kExtension,
kFunction_Kind, kFunction,
kInterfaceBlock_Kind, kInterfaceBlock,
kModifiers_Kind, kModifiers,
kSection_Kind, kSection,
kVar_Kind kVar,
kFirst = kEnum,
kLast = kVar
}; };
ProgramElement(int offset, Kind kind) ProgramElement(int offset, Kind kind)
: INHERITED(offset) : INHERITED(offset, (int) kind) {
, fKind(kind) {} SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
}
Kind kind() const {
return (Kind) fKind;
}
/** /**
* Use is<T> to check the type of a program element. * Use is<T> to check the type of a program element.
@ -38,7 +46,7 @@ struct ProgramElement : public IRNode {
*/ */
template <typename T> template <typename T>
bool is() const { bool is() const {
return this->fKind == T::kProgramElementKind; return this->kind() == T::kProgramElementKind;
} }
/** /**
@ -56,8 +64,6 @@ struct ProgramElement : public IRNode {
return static_cast<T&>(*this); return static_cast<T&>(*this);
} }
Kind fKind;
virtual std::unique_ptr<ProgramElement> clone() const = 0; virtual std::unique_ptr<ProgramElement> clone() const = 0;
using INHERITED = IRNode; using INHERITED = IRNode;

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A 'return' statement. * A 'return' statement.
*/ */
struct ReturnStatement : public Statement { struct ReturnStatement : public Statement {
static constexpr Kind kStatementKind = kReturn_Kind; static constexpr Kind kStatementKind = Kind::kReturn;
ReturnStatement(int offset) ReturnStatement(int offset)
: INHERITED(offset, kStatementKind) {} : INHERITED(offset, kStatementKind) {}

View File

@ -16,7 +16,7 @@ namespace SkSL {
* A section declaration (e.g. @body { body code here }).. * A section declaration (e.g. @body { body code here })..
*/ */
struct Section : public ProgramElement { struct Section : public ProgramElement {
static constexpr Kind kProgramElementKind = kSection_Kind; static constexpr Kind kProgramElementKind = Kind::kSection;
Section(int offset, String name, String arg, String text) Section(int offset, String name, String arg, String text)
: INHERITED(offset, kProgramElementKind) : INHERITED(offset, kProgramElementKind)

View File

@ -18,7 +18,7 @@ namespace SkSL {
* collapsed down to their constant representations during the compilation process. * collapsed down to their constant representations during the compilation process.
*/ */
struct Setting : public Expression { struct Setting : public Expression {
static constexpr Kind kExpressionKind = kSetting_Kind; static constexpr Kind kExpressionKind = Kind::kSetting;
Setting(int offset, String name, std::unique_ptr<Expression> value) Setting(int offset, String name, std::unique_ptr<Expression> value)
: INHERITED(offset, kExpressionKind, value->fType) : INHERITED(offset, kExpressionKind, value->fType)

View File

@ -18,25 +18,33 @@ namespace SkSL {
*/ */
struct Statement : public IRNode { struct Statement : public IRNode {
enum Kind { enum Kind {
kBlock_Kind, kBlock = (int) Symbol::Kind::kLast + 1,
kBreak_Kind, kBreak,
kContinue_Kind, kContinue,
kDiscard_Kind, kDiscard,
kDo_Kind, kDo,
kExpression_Kind, kExpression,
kFor_Kind, kFor,
kIf_Kind, kIf,
kNop_Kind, kNop,
kReturn_Kind, kReturn,
kSwitch_Kind, kSwitch,
kVarDeclaration_Kind, kVarDeclaration,
kVarDeclarations_Kind, kVarDeclarations,
kWhile_Kind kWhile,
kFirst = kBlock,
kLast = kWhile
}; };
Statement(int offset, Kind kind) Statement(int offset, Kind kind)
: INHERITED(offset) : INHERITED(offset, (int) kind) {
, fKind(kind) {} SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
}
Kind kind() const {
return (Kind) fKind;
}
/** /**
* Use is<T> to check the type of a statement. * Use is<T> to check the type of a statement.
@ -69,8 +77,6 @@ struct Statement : public IRNode {
virtual std::unique_ptr<Statement> clone() const = 0; virtual std::unique_ptr<Statement> clone() const = 0;
const Kind fKind;
using INHERITED = IRNode; using INHERITED = IRNode;
}; };

View File

@ -19,7 +19,7 @@ namespace SkSL {
struct SwitchCase : public Statement { struct SwitchCase : public Statement {
SwitchCase(int offset, std::unique_ptr<Expression> value, SwitchCase(int offset, std::unique_ptr<Expression> value,
std::vector<std::unique_ptr<Statement>> statements) std::vector<std::unique_ptr<Statement>> statements)
: INHERITED(offset, kSwitch_Kind) : INHERITED(offset, Kind::kSwitch)
, fValue(std::move(value)) , fValue(std::move(value))
, fStatements(std::move(statements)) {} , fStatements(std::move(statements)) {}

View File

@ -19,7 +19,7 @@ class SymbolTable;
* A 'switch' statement. * A 'switch' statement.
*/ */
struct SwitchStatement : public Statement { struct SwitchStatement : public Statement {
static constexpr Kind kStatementKind = kSwitch_Kind; static constexpr Kind kStatementKind = Kind::kSwitch;
SwitchStatement(int offset, bool isStatic, std::unique_ptr<Expression> value, SwitchStatement(int offset, bool isStatic, std::unique_ptr<Expression> value,
std::vector<std::unique_ptr<SwitchCase>> cases, std::vector<std::unique_ptr<SwitchCase>> cases,

View File

@ -97,7 +97,7 @@ static const Type& get_type(const Context& context, Expression& value, size_t co
* Represents a vector swizzle operation such as 'float2(1, 2, 3).zyx'. * Represents a vector swizzle operation such as 'float2(1, 2, 3).zyx'.
*/ */
struct Swizzle : public Expression { struct Swizzle : public Expression {
static constexpr Kind kExpressionKind = kSwizzle_Kind; static constexpr Kind kExpressionKind = Kind::kSwizzle;
Swizzle(const Context& context, std::unique_ptr<Expression> base, std::vector<int> components) Swizzle(const Context& context, std::unique_ptr<Expression> base, std::vector<int> components)
: INHERITED(base->fOffset, kExpressionKind, get_type(context, *base, components.size())) : INHERITED(base->fOffset, kExpressionKind, get_type(context, *base, components.size()))
@ -108,7 +108,7 @@ struct Swizzle : public Expression {
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override { const DefinitionMap& definitions) override {
if (fBase->fKind == Expression::kConstructor_Kind) { if (fBase->kind() == Expression::Kind::kConstructor) {
Constructor& constructor = static_cast<Constructor&>(*fBase); Constructor& constructor = static_cast<Constructor&>(*fBase);
if (constructor.isCompileTimeConstant()) { if (constructor.isCompileTimeConstant()) {
// we're swizzling a constant vector, e.g. float4(1).x. Simplify it. // we're swizzling a constant vector, e.g. float4(1).x. Simplify it.
@ -151,7 +151,7 @@ struct Swizzle : public Expression {
private: private:
Swizzle(const Type& type, std::unique_ptr<Expression> base, std::vector<int> components) Swizzle(const Type& type, std::unique_ptr<Expression> base, std::vector<int> components)
: INHERITED(base->fOffset, kSwizzle_Kind, type) : INHERITED(base->fOffset, kExpressionKind, type)
, fBase(std::move(base)) , fBase(std::move(base))
, fComponents(std::move(components)) { , fComponents(std::move(components)) {
SkASSERT(fComponents.size() >= 1 && fComponents.size() <= 4); SkASSERT(fComponents.size() >= 1 && fComponents.size() <= 4);

View File

@ -9,6 +9,7 @@
#define SKSL_SYMBOL #define SKSL_SYMBOL
#include "src/sksl/ir/SkSLIRNode.h" #include "src/sksl/ir/SkSLIRNode.h"
#include "src/sksl/ir/SkSLProgramElement.h"
namespace SkSL { namespace SkSL {
@ -16,29 +17,37 @@ namespace SkSL {
* Represents a symboltable entry. * Represents a symboltable entry.
*/ */
struct Symbol : public IRNode { struct Symbol : public IRNode {
enum Kind { enum class Kind {
kFunctionDeclaration_Kind, kExternal = (int) ProgramElement::Kind::kLast + 1,
kUnresolvedFunction_Kind, kField,
kType_Kind, kFunctionDeclaration,
kVariable_Kind, kType,
kField_Kind, kUnresolvedFunction,
kExternal_Kind kVariable,
kFirst = kExternal,
kLast = kVariable
}; };
Symbol(int offset, Kind kind, StringFragment name) Symbol(int offset, Kind kind, StringFragment name)
: INHERITED(offset) : INHERITED(offset, (int) kind)
, fKind(kind) , fName(name) {
, fName(name) {} SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
}
~Symbol() override {} ~Symbol() override {}
Kind kind() const {
return (Kind) fKind;
}
/** /**
* Use is<T> to check the type of a symbol. * Use is<T> to check the type of a symbol.
* e.g. replace `sym.fKind == Symbol::kVariable_Kind` with `sym.is<Variable>()`. * e.g. replace `sym.fKind == Symbol::kVariable_Kind` with `sym.is<Variable>()`.
*/ */
template <typename T> template <typename T>
bool is() const { bool is() const {
return this->fKind == T::kSymbolKind; return this->kind() == T::kSymbolKind;
} }
/** /**
@ -56,7 +65,6 @@ struct Symbol : public IRNode {
return static_cast<T&>(*this); return static_cast<T&>(*this);
} }
Kind fKind;
StringFragment fName; StringFragment fName;
using INHERITED = IRNode; using INHERITED = IRNode;

View File

@ -11,10 +11,10 @@
namespace SkSL { namespace SkSL {
std::vector<const FunctionDeclaration*> SymbolTable::GetFunctions(const Symbol& s) { std::vector<const FunctionDeclaration*> SymbolTable::GetFunctions(const Symbol& s) {
switch (s.fKind) { switch (s.kind()) {
case Symbol::kFunctionDeclaration_Kind: case Symbol::Kind::kFunctionDeclaration:
return { &s.as<FunctionDeclaration>() }; return { &s.as<FunctionDeclaration>() };
case Symbol::kUnresolvedFunction_Kind: case Symbol::Kind::kUnresolvedFunction:
return s.as<UnresolvedFunction>().fFunctions; return s.as<UnresolvedFunction>().fFunctions;
default: default:
return std::vector<const FunctionDeclaration*>(); return std::vector<const FunctionDeclaration*>();
@ -70,16 +70,16 @@ void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol)
const auto& existing = fSymbols.find(name); const auto& existing = fSymbols.find(name);
if (existing == fSymbols.end()) { if (existing == fSymbols.end()) {
fSymbols[name] = symbol; fSymbols[name] = symbol;
} else if (symbol->fKind == Symbol::kFunctionDeclaration_Kind) { } else if (symbol->kind() == Symbol::Kind::kFunctionDeclaration) {
const Symbol* oldSymbol = existing->second; const Symbol* oldSymbol = existing->second;
if (oldSymbol->fKind == Symbol::kFunctionDeclaration_Kind) { if (oldSymbol->kind() == Symbol::Kind::kFunctionDeclaration) {
std::vector<const FunctionDeclaration*> functions; std::vector<const FunctionDeclaration*> functions;
functions.push_back(&oldSymbol->as<FunctionDeclaration>()); functions.push_back(&oldSymbol->as<FunctionDeclaration>());
functions.push_back(&symbol->as<FunctionDeclaration>()); functions.push_back(&symbol->as<FunctionDeclaration>());
std::unique_ptr<const Symbol> u = std::unique_ptr<const Symbol>( std::unique_ptr<const Symbol> u = std::unique_ptr<const Symbol>(
new UnresolvedFunction(std::move(functions))); new UnresolvedFunction(std::move(functions)));
fSymbols[name] = this->takeOwnershipOfSymbol(std::move(u)); fSymbols[name] = this->takeOwnershipOfSymbol(std::move(u));
} else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) { } else if (oldSymbol->kind() == Symbol::Kind::kUnresolvedFunction) {
std::vector<const FunctionDeclaration*> functions; std::vector<const FunctionDeclaration*> functions;
for (const auto* f : oldSymbol->as<UnresolvedFunction>().fFunctions) { for (const auto* f : oldSymbol->as<UnresolvedFunction>().fFunctions) {
functions.push_back(f); functions.push_back(f);

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A ternary expression (test ? ifTrue : ifFalse). * A ternary expression (test ? ifTrue : ifFalse).
*/ */
struct TernaryExpression : public Expression { struct TernaryExpression : public Expression {
static constexpr Kind kExpressionKind = kTernary_Kind; static constexpr Kind kExpressionKind = Kind::kTernary;
TernaryExpression(int offset, std::unique_ptr<Expression> test, TernaryExpression(int offset, std::unique_ptr<Expression> test,
std::unique_ptr<Expression> ifTrue, std::unique_ptr<Expression> ifFalse) std::unique_ptr<Expression> ifTrue, std::unique_ptr<Expression> ifFalse)

View File

@ -14,23 +14,23 @@ int Type::coercionCost(const Type& other) const {
if (*this == other) { if (*this == other) {
return 0; return 0;
} }
if (this->kind() == kNullable_Kind && other.kind() != kNullable_Kind) { if (this->typeKind() == TypeKind::kNullable && other.typeKind() != TypeKind::kNullable) {
int result = this->componentType().coercionCost(other); int result = this->componentType().coercionCost(other);
if (result != INT_MAX) { if (result != INT_MAX) {
++result; ++result;
} }
return result; return result;
} }
if (this->fName == "null" && other.kind() == kNullable_Kind) { if (this->fName == "null" && other.typeKind() == TypeKind::kNullable) {
return 0; return 0;
} }
if (this->kind() == kVector_Kind && other.kind() == kVector_Kind) { if (this->typeKind() == TypeKind::kVector && other.typeKind() == TypeKind::kVector) {
if (this->columns() == other.columns()) { if (this->columns() == other.columns()) {
return this->componentType().coercionCost(other.componentType()); return this->componentType().coercionCost(other.componentType());
} }
return INT_MAX; return INT_MAX;
} }
if (this->kind() == kMatrix_Kind) { if (this->typeKind() == TypeKind::kMatrix) {
if (this->columns() == other.columns() && this->rows() == other.rows()) { if (this->columns() == other.columns() && this->rows() == other.rows()) {
return this->componentType().coercionCost(other.componentType()); return this->componentType().coercionCost(other.componentType());
} }
@ -48,7 +48,7 @@ int Type::coercionCost(const Type& other) const {
} }
const Type& Type::toCompound(const Context& context, int columns, int rows) const { const Type& Type::toCompound(const Context& context, int columns, int rows) const {
SkASSERT(this->kind() == Type::kScalar_Kind); SkASSERT(this->typeKind() == Type::TypeKind::kScalar);
if (columns == 1 && rows == 1) { if (columns == 1 && rows == 1) {
return *this; return *this;
} }

View File

@ -26,7 +26,7 @@ class Context;
*/ */
class Type : public Symbol { class Type : public Symbol {
public: public:
static constexpr Kind kSymbolKind = kType_Kind; static constexpr Kind kSymbolKind = Kind::kType;
struct Field { struct Field {
Field(Modifiers modifiers, StringFragment name, const Type* type) Field(Modifiers modifiers, StringFragment name, const Type* type)
@ -43,26 +43,26 @@ public:
const Type* fType; const Type* fType;
}; };
enum Kind { enum class TypeKind {
kArray_Kind, kArray,
kEnum_Kind, kEnum,
kGeneric_Kind, kGeneric,
kNullable_Kind, kNullable,
kMatrix_Kind, kMatrix,
kOther_Kind, kOther,
kSampler_Kind, kSampler,
kSeparateSampler_Kind, kSeparateSampler,
kScalar_Kind, kScalar,
kStruct_Kind, kStruct,
kTexture_Kind, kTexture,
kVector_Kind kVector
}; };
enum NumberKind { enum class NumberKind {
kFloat_NumberKind, kFloat,
kSigned_NumberKind, kSigned,
kUnsigned_NumberKind, kUnsigned,
kNonnumeric_NumberKind kNonnumeric
}; };
// Create an "other" (special) type with the given name. These types cannot be directly // Create an "other" (special) type with the given name. These types cannot be directly
@ -70,8 +70,8 @@ public:
Type(const char* name) Type(const char* name)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(name) , fNameString(name)
, fTypeKind(kOther_Kind) , fTypeKind(TypeKind::kOther)
, fNumberKind(kNonnumeric_NumberKind) { , fNumberKind(NumberKind::kNonnumeric) {
fName.fChars = fNameString.c_str(); fName.fChars = fNameString.c_str();
fName.fLength = fNameString.size(); fName.fLength = fNameString.size();
} }
@ -80,19 +80,19 @@ public:
Type(const char* name, std::vector<Field> fields) Type(const char* name, std::vector<Field> fields)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(name) , fNameString(name)
, fTypeKind(kOther_Kind) , fTypeKind(TypeKind::kOther)
, fNumberKind(kNonnumeric_NumberKind) , fNumberKind(NumberKind::kNonnumeric)
, fFields(std::move(fields)) { , fFields(std::move(fields)) {
fName.fChars = fNameString.c_str(); fName.fChars = fNameString.c_str();
fName.fLength = fNameString.size(); fName.fLength = fNameString.size();
} }
// Create a simple type. // Create a simple type.
Type(String name, Kind kind) Type(String name, TypeKind kind)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(std::move(name)) , fNameString(std::move(name))
, fTypeKind(kind) , fTypeKind(kind)
, fNumberKind(kNonnumeric_NumberKind) { , fNumberKind(NumberKind::kNonnumeric) {
fName.fChars = fNameString.c_str(); fName.fChars = fNameString.c_str();
fName.fLength = fNameString.size(); fName.fLength = fNameString.size();
} }
@ -101,8 +101,8 @@ public:
Type(const char* name, std::vector<const Type*> types) Type(const char* name, std::vector<const Type*> types)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(name) , fNameString(name)
, fTypeKind(kGeneric_Kind) , fTypeKind(TypeKind::kGeneric)
, fNumberKind(kNonnumeric_NumberKind) , fNumberKind(NumberKind::kNonnumeric)
, fCoercibleTypes(std::move(types)) { , fCoercibleTypes(std::move(types)) {
fName.fChars = fNameString.c_str(); fName.fChars = fNameString.c_str();
fName.fLength = fNameString.size(); fName.fLength = fNameString.size();
@ -112,8 +112,8 @@ public:
Type(int offset, String name, std::vector<Field> fields) Type(int offset, String name, std::vector<Field> fields)
: INHERITED(offset, kSymbolKind, StringFragment()) : INHERITED(offset, kSymbolKind, StringFragment())
, fNameString(std::move(name)) , fNameString(std::move(name))
, fTypeKind(kStruct_Kind) , fTypeKind(TypeKind::kStruct)
, fNumberKind(kNonnumeric_NumberKind) , fNumberKind(NumberKind::kNonnumeric)
, fFields(std::move(fields)) { , fFields(std::move(fields)) {
fName.fChars = fNameString.c_str(); fName.fChars = fNameString.c_str();
fName.fLength = fNameString.size(); fName.fLength = fNameString.size();
@ -123,7 +123,7 @@ public:
Type(const char* name, NumberKind numberKind, int priority, bool highPrecision = false) Type(const char* name, NumberKind numberKind, int priority, bool highPrecision = false)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(name) , fNameString(name)
, fTypeKind(kScalar_Kind) , fTypeKind(TypeKind::kScalar)
, fNumberKind(numberKind) , fNumberKind(numberKind)
, fPriority(priority) , fPriority(priority)
, fColumns(1) , fColumns(1)
@ -140,7 +140,7 @@ public:
std::vector<const Type*> coercibleTypes) std::vector<const Type*> coercibleTypes)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(name) , fNameString(name)
, fTypeKind(kScalar_Kind) , fTypeKind(TypeKind::kScalar)
, fNumberKind(numberKind) , fNumberKind(numberKind)
, fPriority(priority) , fPriority(priority)
, fCoercibleTypes(std::move(coercibleTypes)) , fCoercibleTypes(std::move(coercibleTypes))
@ -151,11 +151,11 @@ public:
} }
// Create a nullable type. // Create a nullable type.
Type(String name, Kind kind, const Type& componentType) Type(String name, TypeKind kind, const Type& componentType)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(std::move(name)) , fNameString(std::move(name))
, fTypeKind(kind) , fTypeKind(kind)
, fNumberKind(kNonnumeric_NumberKind) , fNumberKind(NumberKind::kNonnumeric)
, fComponentType(&componentType) , fComponentType(&componentType)
, fColumns(1) , fColumns(1)
, fRows(1) , fRows(1)
@ -166,14 +166,14 @@ public:
// Create a vector type. // Create a vector type.
Type(const char* name, const Type& componentType, int columns) Type(const char* name, const Type& componentType, int columns)
: Type(name, kVector_Kind, componentType, columns) {} : Type(name, TypeKind::kVector, componentType, columns) {}
// Create a vector or array type. // Create a vector or array type.
Type(String name, Kind kind, const Type& componentType, int columns) Type(String name, TypeKind kind, const Type& componentType, int columns)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(std::move(name)) , fNameString(std::move(name))
, fTypeKind(kind) , fTypeKind(kind)
, fNumberKind(kNonnumeric_NumberKind) , fNumberKind(NumberKind::kNonnumeric)
, fComponentType(&componentType) , fComponentType(&componentType)
, fColumns(columns) , fColumns(columns)
, fRows(1) , fRows(1)
@ -186,8 +186,8 @@ public:
Type(const char* name, const Type& componentType, int columns, int rows) Type(const char* name, const Type& componentType, int columns, int rows)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(name) , fNameString(name)
, fTypeKind(kMatrix_Kind) , fTypeKind(TypeKind::kMatrix)
, fNumberKind(kNonnumeric_NumberKind) , fNumberKind(NumberKind::kNonnumeric)
, fComponentType(&componentType) , fComponentType(&componentType)
, fColumns(columns) , fColumns(columns)
, fRows(rows) , fRows(rows)
@ -201,8 +201,8 @@ public:
bool isSampled) bool isSampled)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(name) , fNameString(name)
, fTypeKind(kTexture_Kind) , fTypeKind(TypeKind::kTexture)
, fNumberKind(kNonnumeric_NumberKind) , fNumberKind(NumberKind::kNonnumeric)
, fDimensions(dimensions) , fDimensions(dimensions)
, fIsDepth(isDepth) , fIsDepth(isDepth)
, fIsArrayed(isArrayed) , fIsArrayed(isArrayed)
@ -217,8 +217,8 @@ public:
Type(const char* name, const Type& textureType) Type(const char* name, const Type& textureType)
: INHERITED(-1, kSymbolKind, StringFragment()) : INHERITED(-1, kSymbolKind, StringFragment())
, fNameString(name) , fNameString(name)
, fTypeKind(kSampler_Kind) , fTypeKind(TypeKind::kSampler)
, fNumberKind(kNonnumeric_NumberKind) , fNumberKind(NumberKind::kNonnumeric)
, fDimensions(textureType.dimensions()) , fDimensions(textureType.dimensions())
, fIsDepth(textureType.isDepth()) , fIsDepth(textureType.isDepth())
, fIsArrayed(textureType.isArrayed()) , fIsArrayed(textureType.isArrayed())
@ -259,7 +259,7 @@ public:
/** /**
* Returns the category (scalar, vector, matrix, etc.) of this type. * Returns the category (scalar, vector, matrix, etc.) of this type.
*/ */
Kind kind() const { TypeKind typeKind() const {
return fTypeKind; return fTypeKind;
} }
@ -267,28 +267,28 @@ public:
* Returns true if this is a numeric scalar type. * Returns true if this is a numeric scalar type.
*/ */
bool isNumber() const { bool isNumber() const {
return fNumberKind != kNonnumeric_NumberKind; return fNumberKind != NumberKind::kNonnumeric;
} }
/** /**
* Returns true if this is a floating-point scalar type (float or half). * Returns true if this is a floating-point scalar type (float or half).
*/ */
bool isFloat() const { bool isFloat() const {
return fNumberKind == kFloat_NumberKind; return fNumberKind == NumberKind::kFloat;
} }
/** /**
* Returns true if this is a signed scalar type (int or short). * Returns true if this is a signed scalar type (int or short).
*/ */
bool isSigned() const { bool isSigned() const {
return fNumberKind == kSigned_NumberKind; return fNumberKind == NumberKind::kSigned;
} }
/** /**
* Returns true if this is an unsigned scalar type (uint or ushort). * Returns true if this is an unsigned scalar type (uint or ushort).
*/ */
bool isUnsigned() const { bool isUnsigned() const {
return fNumberKind == kUnsigned_NumberKind; return fNumberKind == NumberKind::kUnsigned;
} }
/** /**
@ -343,7 +343,7 @@ public:
* For nullable types, returns the base type, otherwise returns the type itself. * For nullable types, returns the base type, otherwise returns the type itself.
*/ */
const Type& nonnullable() const { const Type& nonnullable() const {
if (fTypeKind == kNullable_Kind) { if (fTypeKind == TypeKind::kNullable) {
return this->componentType(); return this->componentType();
} }
return *this; return *this;
@ -355,8 +355,8 @@ public:
* For all other types, causes an SkASSERTion failure. * For all other types, causes an SkASSERTion failure.
*/ */
int columns() const { int columns() const {
SkASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind || SkASSERT(fTypeKind == TypeKind::kScalar || fTypeKind == TypeKind::kVector ||
fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind); fTypeKind == TypeKind::kMatrix || fTypeKind == TypeKind::kArray);
return fColumns; return fColumns;
} }
@ -370,7 +370,7 @@ public:
} }
const std::vector<Field>& fields() const { const std::vector<Field>& fields() const {
SkASSERT(fTypeKind == kStruct_Kind || fTypeKind == kOther_Kind); SkASSERT(fTypeKind == TypeKind::kStruct || fTypeKind == TypeKind::kOther);
return fFields; return fFields;
} }
@ -384,27 +384,27 @@ public:
} }
SpvDim_ dimensions() const { SpvDim_ dimensions() const {
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind); SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
return fDimensions; return fDimensions;
} }
bool isDepth() const { bool isDepth() const {
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind); SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
return fIsDepth; return fIsDepth;
} }
bool isArrayed() const { bool isArrayed() const {
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind); SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
return fIsArrayed; return fIsArrayed;
} }
bool isMultisampled() const { bool isMultisampled() const {
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind); SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
return fIsMultisampled; return fIsMultisampled;
} }
bool isSampled() const { bool isSampled() const {
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind); SkASSERT(TypeKind::kSampler == fTypeKind || TypeKind::kTexture == fTypeKind);
return fIsSampled; return fIsSampled;
} }
@ -425,7 +425,7 @@ private:
using INHERITED = Symbol; using INHERITED = Symbol;
String fNameString; String fNameString;
Kind fTypeKind; TypeKind fTypeKind;
// always kNonnumeric_NumberKind for non-scalar values // always kNonnumeric_NumberKind for non-scalar values
NumberKind fNumberKind; NumberKind fNumberKind;
int fPriority = -1; int fPriority = -1;

View File

@ -18,11 +18,11 @@ namespace SkSL {
* always eventually replaced by Constructors in valid programs. * always eventually replaced by Constructors in valid programs.
*/ */
struct TypeReference : public Expression { struct TypeReference : public Expression {
static constexpr Kind kExpressionKind = kTypeReference_Kind; static constexpr Kind kExpressionKind = Kind::kTypeReference;
TypeReference(const Context& context, int offset, const Type& value) TypeReference(const Context& context, int offset, const Type* value)
: INHERITED(offset, kExpressionKind, *context.fInvalid_Type) : INHERITED(offset, kExpressionKind, *context.fInvalid_Type)
, fValue(value) {} , fValue(*value) {}
bool hasProperty(Property property) const override { bool hasProperty(Property property) const override {
return false; return false;

View File

@ -16,7 +16,7 @@ namespace SkSL {
* A symbol representing multiple functions with the same name. * A symbol representing multiple functions with the same name.
*/ */
struct UnresolvedFunction : public Symbol { struct UnresolvedFunction : public Symbol {
static constexpr Kind kSymbolKind = kUnresolvedFunction_Kind; static constexpr Kind kSymbolKind = Kind::kUnresolvedFunction;
UnresolvedFunction(std::vector<const FunctionDeclaration*> funcs) UnresolvedFunction(std::vector<const FunctionDeclaration*> funcs)
: INHERITED(-1, kSymbolKind, funcs[0]->fName) : INHERITED(-1, kSymbolKind, funcs[0]->fName)

View File

@ -21,7 +21,7 @@ namespace SkSL {
* instances. * instances.
*/ */
struct VarDeclaration : public Statement { struct VarDeclaration : public Statement {
static constexpr Kind kStatementKind = kVarDeclaration_Kind; static constexpr Kind kStatementKind = Kind::kVarDeclaration;
VarDeclaration(const Variable* var, VarDeclaration(const Variable* var,
std::vector<std::unique_ptr<Expression>> sizes, std::vector<std::unique_ptr<Expression>> sizes,
@ -70,7 +70,7 @@ struct VarDeclaration : public Statement {
* A variable declaration statement, which may consist of one or more individual variables. * A variable declaration statement, which may consist of one or more individual variables.
*/ */
struct VarDeclarations : public ProgramElement { struct VarDeclarations : public ProgramElement {
static constexpr Kind kProgramElementKind = kVar_Kind; static constexpr Kind kProgramElementKind = Kind::kVar;
VarDeclarations(int offset, const Type* baseType, VarDeclarations(int offset, const Type* baseType,
std::vector<std::unique_ptr<VarDeclaration>> vars) std::vector<std::unique_ptr<VarDeclaration>> vars)
@ -97,8 +97,8 @@ struct VarDeclarations : public ProgramElement {
} }
String result; String result;
for (const auto& var : fVars) { for (const auto& var : fVars) {
if (var->fKind != Statement::kNop_Kind) { if (var->kind() != Statement::Kind::kNop) {
SkASSERT(var->fKind == Statement::kVarDeclaration_Kind); SkASSERT(var->kind() == Statement::Kind::kVarDeclaration);
result = ((const VarDeclaration&) *var).fVar->fModifiers.description(); result = ((const VarDeclaration&) *var).fVar->fModifiers.description();
break; break;
} }
@ -106,10 +106,10 @@ struct VarDeclarations : public ProgramElement {
result += fBaseType.description() + " "; result += fBaseType.description() + " ";
String separator; String separator;
for (const auto& rawVar : fVars) { for (const auto& rawVar : fVars) {
if (rawVar->fKind == Statement::kNop_Kind) { if (rawVar->kind() == Statement::Kind::kNop) {
continue; continue;
} }
SkASSERT(rawVar->fKind == Statement::kVarDeclaration_Kind); SkASSERT(rawVar->kind() == Statement::Kind::kVarDeclaration);
VarDeclaration& var = (VarDeclaration&) *rawVar; VarDeclaration& var = (VarDeclaration&) *rawVar;
result += separator; result += separator;
separator = ", "; separator = ", ";

View File

@ -17,7 +17,7 @@ namespace SkSL {
* One or more variable declarations appearing as a statement within a function. * One or more variable declarations appearing as a statement within a function.
*/ */
struct VarDeclarationsStatement : public Statement { struct VarDeclarationsStatement : public Statement {
static constexpr Kind kStatementKind = kVarDeclarations_Kind; static constexpr Kind kStatementKind = Kind::kVarDeclarations;
VarDeclarationsStatement(std::unique_ptr<VarDeclarations> decl) VarDeclarationsStatement(std::unique_ptr<VarDeclarations> decl)
: INHERITED(decl->fOffset, kStatementKind) : INHERITED(decl->fOffset, kStatementKind)

View File

@ -23,7 +23,7 @@ struct Expression;
* read or write that storage location. * read or write that storage location.
*/ */
struct Variable : public Symbol { struct Variable : public Symbol {
static constexpr Kind kSymbolKind = kVariable_Kind; static constexpr Kind kSymbolKind = Kind::kVariable;
enum Storage { enum Storage {
kGlobal_Storage, kGlobal_Storage,

View File

@ -54,21 +54,21 @@ void VariableReference::setRefKind(RefKind refKind) {
std::unique_ptr<Expression> VariableReference::copy_constant(const IRGenerator& irGenerator, std::unique_ptr<Expression> VariableReference::copy_constant(const IRGenerator& irGenerator,
const Expression* expr) { const Expression* expr) {
SkASSERT(expr->isCompileTimeConstant()); SkASSERT(expr->isCompileTimeConstant());
switch (expr->fKind) { switch (expr->kind()) {
case Expression::kIntLiteral_Kind: case Expression::Kind::kIntLiteral:
return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext, return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
-1, -1,
((IntLiteral*) expr)->fValue)); ((IntLiteral*) expr)->fValue));
case Expression::kFloatLiteral_Kind: case Expression::Kind::kFloatLiteral:
return std::unique_ptr<Expression>(new FloatLiteral( return std::unique_ptr<Expression>(new FloatLiteral(
irGenerator.fContext, irGenerator.fContext,
-1, -1,
((FloatLiteral*) expr)->fValue)); ((FloatLiteral*) expr)->fValue));
case Expression::kBoolLiteral_Kind: case Expression::Kind::kBoolLiteral:
return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext, return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext,
-1, -1,
((BoolLiteral*) expr)->fValue)); ((BoolLiteral*) expr)->fValue));
case Expression::kConstructor_Kind: { case Expression::Kind::kConstructor: {
const Constructor* c = (const Constructor*) expr; const Constructor* c = (const Constructor*) expr;
std::vector<std::unique_ptr<Expression>> args; std::vector<std::unique_ptr<Expression>> args;
for (const auto& arg : c->fArguments) { for (const auto& arg : c->fArguments) {
@ -77,7 +77,7 @@ std::unique_ptr<Expression> VariableReference::copy_constant(const IRGenerator&
return std::unique_ptr<Expression>(new Constructor(-1, c->fType, return std::unique_ptr<Expression>(new Constructor(-1, c->fType,
std::move(args))); std::move(args)));
} }
case Expression::kSetting_Kind: { case Expression::Kind::kSetting: {
const Setting* s = (const Setting*) expr; const Setting* s = (const Setting*) expr;
return std::unique_ptr<Expression>(new Setting(-1, s->fName, return std::unique_ptr<Expression>(new Setting(-1, s->fName,
copy_constant(irGenerator, copy_constant(irGenerator,
@ -94,7 +94,8 @@ std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerat
return nullptr; return nullptr;
} }
if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue && if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue &&
fVariable.fInitialValue->isCompileTimeConstant() && fType.kind() != Type::kArray_Kind) { fVariable.fInitialValue->isCompileTimeConstant() &&
fType.typeKind() != Type::TypeKind::kArray) {
return copy_constant(irGenerator, fVariable.fInitialValue); return copy_constant(irGenerator, fVariable.fInitialValue);
} }
auto exprIter = definitions.find(&fVariable); auto exprIter = definitions.find(&fVariable);

View File

@ -23,7 +23,7 @@ class IRGenerator;
* there is only one Variable 'x', but two VariableReferences to it. * there is only one Variable 'x', but two VariableReferences to it.
*/ */
struct VariableReference : public Expression { struct VariableReference : public Expression {
static constexpr Kind kExpressionKind = kVariableReference_Kind; static constexpr Kind kExpressionKind = Kind::kVariableReference;
enum RefKind { enum RefKind {
kRead_RefKind, kRead_RefKind,

View File

@ -17,7 +17,7 @@ namespace SkSL {
* A 'while' loop. * A 'while' loop.
*/ */
struct WhileStatement : public Statement { struct WhileStatement : public Statement {
static constexpr Kind kStatementKind = kWhile_Kind; static constexpr Kind kStatementKind = Kind::kWhile;
WhileStatement(int offset, std::unique_ptr<Expression> test, WhileStatement(int offset, std::unique_ptr<Expression> test,
std::unique_ptr<Statement> statement) std::unique_ptr<Statement> statement)

View File

@ -80,12 +80,14 @@ DEF_TEST(SkSLMemoryLayout140Test, r) {
REPORTER_ASSERT(r, 16 == layout.alignment(s5)); REPORTER_ASSERT(r, 16 == layout.alignment(s5));
// arrays // arrays
SkSL::Type array1(SkSL::String("float[4]"), SkSL::Type::kArray_Kind, *context.fFloat_Type, 4); SkSL::Type array1(SkSL::String("float[4]"), SkSL::Type::TypeKind::kArray, *context.fFloat_Type,
4);
REPORTER_ASSERT(r, 64 == layout.size(array1)); REPORTER_ASSERT(r, 64 == layout.size(array1));
REPORTER_ASSERT(r, 16 == layout.alignment(array1)); REPORTER_ASSERT(r, 16 == layout.alignment(array1));
REPORTER_ASSERT(r, 16 == layout.stride(array1)); REPORTER_ASSERT(r, 16 == layout.stride(array1));
SkSL::Type array2(SkSL::String("float4[4]"), SkSL::Type::kArray_Kind, *context.fFloat4_Type, 4); SkSL::Type array2(SkSL::String("float4[4]"), SkSL::Type::TypeKind::kArray,
*context.fFloat4_Type, 4);
REPORTER_ASSERT(r, 64 == layout.size(array2)); REPORTER_ASSERT(r, 64 == layout.size(array2));
REPORTER_ASSERT(r, 16 == layout.alignment(array2)); REPORTER_ASSERT(r, 16 == layout.alignment(array2));
REPORTER_ASSERT(r, 16 == layout.stride(array2)); REPORTER_ASSERT(r, 16 == layout.stride(array2));
@ -161,12 +163,14 @@ DEF_TEST(SkSLMemoryLayout430Test, r) {
REPORTER_ASSERT(r, 16 == layout.alignment(s5)); REPORTER_ASSERT(r, 16 == layout.alignment(s5));
// arrays // arrays
SkSL::Type array1(SkSL::String("float[4]"), SkSL::Type::kArray_Kind, *context.fFloat_Type, 4); SkSL::Type array1(SkSL::String("float[4]"), SkSL::Type::TypeKind::kArray, *context.fFloat_Type,
4);
REPORTER_ASSERT(r, 16 == layout.size(array1)); REPORTER_ASSERT(r, 16 == layout.size(array1));
REPORTER_ASSERT(r, 4 == layout.alignment(array1)); REPORTER_ASSERT(r, 4 == layout.alignment(array1));
REPORTER_ASSERT(r, 4 == layout.stride(array1)); REPORTER_ASSERT(r, 4 == layout.stride(array1));
SkSL::Type array2(SkSL::String("float4[4]"), SkSL::Type::kArray_Kind, *context.fFloat4_Type, 4); SkSL::Type array2(SkSL::String("float4[4]"), SkSL::Type::TypeKind::kArray,
*context.fFloat4_Type, 4);
REPORTER_ASSERT(r, 64 == layout.size(array2)); REPORTER_ASSERT(r, 64 == layout.size(array2));
REPORTER_ASSERT(r, 16 == layout.alignment(array2)); REPORTER_ASSERT(r, 16 == layout.alignment(array2));
REPORTER_ASSERT(r, 16 == layout.stride(array2)); REPORTER_ASSERT(r, 16 == layout.stride(array2));