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:
parent
a9b45b6a7c
commit
e659214bc6
@ -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") {
|
||||||
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
@ -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) {}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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 = ¶m->fType;
|
const Type* type = ¶m->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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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 = ¶m->fType;
|
const Type* type = ¶m->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());
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()) {
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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) {}
|
||||||
|
@ -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()) {
|
||||||
|
@ -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) {}
|
||||||
|
@ -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) {}
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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())
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)) {}
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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()) {
|
||||||
|
@ -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)
|
||||||
|
@ -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) {}
|
||||||
|
@ -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) {}
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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) {}
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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)) {}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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 = ", ";
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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));
|
||||||
|
Loading…
Reference in New Issue
Block a user