Revert "Moved SkSL data back into node classes"
This reverts commit f71e0be970
.
Reason for revert: breaking Build-Debian10-EMCC-wasm-Release-WasmGMTests
Original change's description:
> Moved SkSL data back into node classes
>
> The original goal of this rearchitecture had been to move all of the
> data into IRNode so that we could manage IRNode objects directly rather
> than std::unique_ptr<IRNode>. Other changes have rendered that original
> goal obsolete, so this is undoing most of the work that was done during
> this rearchitecture.
>
> Change-Id: Ic56ffb17bb013c8b4884d710215f5345a481468a
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/330297
> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
> Commit-Queue: John Stiles <johnstiles@google.com>
> Reviewed-by: John Stiles <johnstiles@google.com>
TBR=brianosman@google.com,ethannicholas@google.com,johnstiles@google.com
Change-Id: I7a043c8e3e5c711164303cf160846d7cf20ddfbe
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/330736
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
c21902c0d3
commit
9615bcf71f
@ -75,6 +75,7 @@ skia_sksl_sources = [
|
||||
"$_src/sksl/ir/SkSLFunctionDeclaration.h",
|
||||
"$_src/sksl/ir/SkSLFunctionDefinition.h",
|
||||
"$_src/sksl/ir/SkSLFunctionReference.h",
|
||||
"$_src/sksl/ir/SkSLIRNode.cpp",
|
||||
"$_src/sksl/ir/SkSLIRNode.h",
|
||||
"$_src/sksl/ir/SkSLIfStatement.h",
|
||||
"$_src/sksl/ir/SkSLIndexExpression.h",
|
||||
|
@ -470,8 +470,8 @@ bool TProgramVisitor<PROG, EXPR, STMT, ELEM>::visitExpression(EXPR e) {
|
||||
|
||||
case Expression::Kind::kBinary: {
|
||||
auto& b = e.template as<BinaryExpression>();
|
||||
return (b.left() && this->visitExpression(*b.left())) ||
|
||||
(b.right() && this->visitExpression(*b.right()));
|
||||
return (b.leftPointer() && this->visitExpression(b.left())) ||
|
||||
(b.rightPointer() && this->visitExpression(b.right()));
|
||||
}
|
||||
case Expression::Kind::kConstructor: {
|
||||
auto& c = e.template as<Constructor>();
|
||||
@ -572,10 +572,10 @@ bool TProgramVisitor<PROG, EXPR, STMT, ELEM>::visitStatement(STMT s) {
|
||||
return true;
|
||||
}
|
||||
for (const auto& c : sw.cases()) {
|
||||
if (c->value() && this->visitExpression(*c->value())) {
|
||||
if (c.value() && this->visitExpression(*c.value())) {
|
||||
return true;
|
||||
}
|
||||
for (auto& st : c->statements()) {
|
||||
for (auto& st : c.statements()) {
|
||||
if (st && this->visitStatement(*st)) {
|
||||
return true;
|
||||
}
|
||||
@ -585,8 +585,8 @@ bool TProgramVisitor<PROG, EXPR, STMT, ELEM>::visitStatement(STMT s) {
|
||||
}
|
||||
case Statement::Kind::kVarDeclaration: {
|
||||
auto& v = s.template as<VarDeclaration>();
|
||||
for (const std::unique_ptr<Expression>& size : v.sizes()) {
|
||||
if (size && this->visitExpression(*size)) {
|
||||
for (int i = 0; i < v.sizeCount(); ++i) {
|
||||
if (v.size(i) && this->visitExpression(*v.size(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -680,8 +680,8 @@ void ByteCodeGenerator::writeTypedInstruction(const Type& type,
|
||||
}
|
||||
|
||||
bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
const Expression& left = b.left();
|
||||
const Expression& right = b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
if (op == Token::Kind::TK_EQ) {
|
||||
std::unique_ptr<LValue> lvalue = this->getLValue(left);
|
||||
|
@ -181,13 +181,13 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
|
||||
case Expression::Kind::kBinary: {
|
||||
BinaryExpression& b = expr->as<BinaryExpression>();
|
||||
if (b.getOperator() == Token::Kind::TK_EQ) {
|
||||
if (!this->tryRemoveLValueBefore(iter, b.left().get())) {
|
||||
if (!this->tryRemoveLValueBefore(iter, &b.left())) {
|
||||
return false;
|
||||
}
|
||||
} else if (!this->tryRemoveExpressionBefore(iter, b.left().get())) {
|
||||
} else if (!this->tryRemoveExpressionBefore(iter, &b.left())) {
|
||||
return false;
|
||||
}
|
||||
if (!this->tryRemoveExpressionBefore(iter, b.right().get())) {
|
||||
if (!this->tryRemoveExpressionBefore(iter, &b.right())) {
|
||||
return false;
|
||||
}
|
||||
SkASSERT((*iter)->expression()->get() == expr);
|
||||
@ -281,12 +281,12 @@ bool BasicBlock::tryInsertExpression(std::vector<BasicBlock::Node>::iterator* it
|
||||
switch ((*expr)->kind()) {
|
||||
case Expression::Kind::kBinary: {
|
||||
BinaryExpression& b = expr->get()->as<BinaryExpression>();
|
||||
if (!this->tryInsertExpression(iter, &b.right())) {
|
||||
if (!this->tryInsertExpression(iter, &b.rightPointer())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
++(*iter);
|
||||
if (!this->tryInsertExpression(iter, &b.left())) {
|
||||
if (!this->tryInsertExpression(iter, &b.leftPointer())) {
|
||||
return false;
|
||||
}
|
||||
++(*iter);
|
||||
@ -341,10 +341,10 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
|
||||
// this isn't as precise as it could be -- we don't bother to track that if we
|
||||
// early exit from a logical and/or, we know which branch of an 'if' we're going
|
||||
// to hit -- but it won't make much difference in practice.
|
||||
this->addExpression(cfg, &b.left(), constantPropagate);
|
||||
this->addExpression(cfg, &b.leftPointer(), constantPropagate);
|
||||
BlockId start = cfg.fCurrent;
|
||||
cfg.newBlock();
|
||||
this->addExpression(cfg, &b.right(), constantPropagate);
|
||||
this->addExpression(cfg, &b.rightPointer(), constantPropagate);
|
||||
cfg.newBlock();
|
||||
cfg.addExit(start, cfg.fCurrent);
|
||||
cfg.currentBlock().fNodes.push_back(
|
||||
@ -352,16 +352,16 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
|
||||
break;
|
||||
}
|
||||
case Token::Kind::TK_EQ: {
|
||||
this->addExpression(cfg, &b.right(), constantPropagate);
|
||||
this->addLValue(cfg, &b.left());
|
||||
this->addExpression(cfg, &b.rightPointer(), constantPropagate);
|
||||
this->addLValue(cfg, &b.leftPointer());
|
||||
cfg.currentBlock().fNodes.push_back(
|
||||
BasicBlock::MakeExpression(e, constantPropagate));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
this->addExpression(cfg, &b.left(),
|
||||
this->addExpression(cfg, &b.leftPointer(),
|
||||
!Compiler::IsAssignment(b.getOperator()));
|
||||
this->addExpression(cfg, &b.right(), constantPropagate);
|
||||
this->addExpression(cfg, &b.rightPointer(), constantPropagate);
|
||||
cfg.currentBlock().fNodes.push_back(
|
||||
BasicBlock::MakeExpression(e, constantPropagate));
|
||||
}
|
||||
@ -634,18 +634,18 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
|
||||
for (auto& c : ss.cases()) {
|
||||
cfg.newBlock();
|
||||
cfg.addExit(start, cfg.fCurrent);
|
||||
if (c->value()) {
|
||||
if (c.value()) {
|
||||
// technically this should go in the start block, but it doesn't actually matter
|
||||
// because it must be constant. Not worth running two loops for.
|
||||
this->addExpression(cfg, &c->value(), /*constantPropagate=*/true);
|
||||
this->addExpression(cfg, &c.value(), /*constantPropagate=*/true);
|
||||
}
|
||||
for (auto& caseStatement : c->statements()) {
|
||||
for (auto& caseStatement : c.statements()) {
|
||||
this->addStatement(cfg, &caseStatement);
|
||||
}
|
||||
}
|
||||
cfg.addExit(cfg.fCurrent, switchExit);
|
||||
// note that unlike GLSL, our grammar requires the default case to be last
|
||||
if (ss.cases().empty() || ss.cases().back()->value()) {
|
||||
if (ss.cases().empty() || ss.cases().back().value()) {
|
||||
// switch does not have a default clause, mark that it can skip straight to the end
|
||||
cfg.addExit(start, switchExit);
|
||||
}
|
||||
|
@ -70,8 +70,8 @@ String CPPCodeGenerator::getTypeName(const Type& type) {
|
||||
|
||||
void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
Precedence parentPrecedence) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
const Expression& left = b.left();
|
||||
const Expression& right = b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
if (op == Token::Kind::TK_PERCENT) {
|
||||
// need to use "%%" instead of "%" b/c the code will be inside of a printf
|
||||
|
@ -454,10 +454,10 @@ void Compiler::addDefinitions(const BasicBlock::Node& node, DefinitionMap* defin
|
||||
case Expression::Kind::kBinary: {
|
||||
BinaryExpression* b = &expr->as<BinaryExpression>();
|
||||
if (b->getOperator() == Token::Kind::TK_EQ) {
|
||||
this->addDefinition(b->left().get(), &b->right(), definitions);
|
||||
this->addDefinition(&b->left(), &b->rightPointer(), definitions);
|
||||
} else if (Compiler::IsAssignment(b->getOperator())) {
|
||||
this->addDefinition(
|
||||
b->left().get(),
|
||||
&b->left(),
|
||||
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
|
||||
definitions);
|
||||
|
||||
@ -619,7 +619,7 @@ static bool dead_assignment(const BinaryExpression& b, ProgramUsage* usage) {
|
||||
if (!Compiler::IsAssignment(b.getOperator())) {
|
||||
return false;
|
||||
}
|
||||
return is_dead(*b.left(), usage);
|
||||
return is_dead(b.left(), usage);
|
||||
}
|
||||
|
||||
void Compiler::computeDataFlow(CFG* cfg) {
|
||||
@ -711,8 +711,8 @@ static void delete_left(BasicBlock* b,
|
||||
optimizationContext->fUpdated = true;
|
||||
std::unique_ptr<Expression>* target = (*iter)->expression();
|
||||
BinaryExpression& bin = (*target)->as<BinaryExpression>();
|
||||
Expression& left = *bin.left();
|
||||
std::unique_ptr<Expression>& rightPointer = bin.right();
|
||||
Expression& left = bin.left();
|
||||
std::unique_ptr<Expression>& rightPointer = bin.rightPointer();
|
||||
SkASSERT(!left.hasSideEffects());
|
||||
bool result;
|
||||
if (bin.getOperator() == Token::Kind::TK_EQ) {
|
||||
@ -750,8 +750,8 @@ static void delete_right(BasicBlock* b,
|
||||
optimizationContext->fUpdated = true;
|
||||
std::unique_ptr<Expression>* target = (*iter)->expression();
|
||||
BinaryExpression& bin = (*target)->as<BinaryExpression>();
|
||||
std::unique_ptr<Expression>& leftPointer = bin.left();
|
||||
Expression& right = *bin.right();
|
||||
std::unique_ptr<Expression>& leftPointer = bin.leftPointer();
|
||||
Expression& right = bin.right();
|
||||
SkASSERT(!right.hasSideEffects());
|
||||
// Remove references within RHS.
|
||||
optimizationContext->fUsage->remove(&right);
|
||||
@ -818,8 +818,8 @@ static void vectorize_left(BasicBlock* b,
|
||||
Compiler::OptimizationContext* optimizationContext) {
|
||||
BinaryExpression& bin = (*(*iter)->expression())->as<BinaryExpression>();
|
||||
// Remove references within RHS. Vectorization of LHS doesn't change reference counts.
|
||||
optimizationContext->fUsage->remove(bin.right().get());
|
||||
vectorize(b, iter, bin.right()->type(), &bin.left(), optimizationContext);
|
||||
optimizationContext->fUsage->remove(bin.rightPointer().get());
|
||||
vectorize(b, iter, bin.right().type(), &bin.leftPointer(), optimizationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -831,8 +831,8 @@ static void vectorize_right(BasicBlock* b,
|
||||
Compiler::OptimizationContext* optimizationContext) {
|
||||
BinaryExpression& bin = (*(*iter)->expression())->as<BinaryExpression>();
|
||||
// Remove references within LHS. Vectorization of RHS doesn't change reference counts.
|
||||
optimizationContext->fUsage->remove(bin.left().get());
|
||||
vectorize(b, iter, bin.left()->type(), &bin.right(), optimizationContext);
|
||||
optimizationContext->fUsage->remove(bin.leftPointer().get());
|
||||
vectorize(b, iter, bin.left().type(), &bin.rightPointer(), optimizationContext);
|
||||
}
|
||||
|
||||
// Mark that an expression which we were writing to is no longer being written to
|
||||
@ -915,8 +915,8 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
|
||||
delete_left(&b, iter, optimizationContext);
|
||||
break;
|
||||
}
|
||||
Expression& left = *bin->left();
|
||||
Expression& right = *bin->right();
|
||||
Expression& left = bin->left();
|
||||
Expression& right = bin->right();
|
||||
const Type& leftType = left.type();
|
||||
const Type& rightType = right.type();
|
||||
// collapse useless expressions like x * 1 or x + 0
|
||||
@ -1221,7 +1221,7 @@ static std::unique_ptr<Statement> block_for_case(SwitchStatement* switchStatemen
|
||||
// of action. First, find the switch-case we are interested in.
|
||||
auto iter = switchStatement->cases().begin();
|
||||
for (; iter != switchStatement->cases().end(); ++iter) {
|
||||
if (iter->get() == caseToCapture) {
|
||||
if (&*iter == caseToCapture) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1232,7 +1232,7 @@ static std::unique_ptr<Statement> block_for_case(SwitchStatement* switchStatemen
|
||||
auto startIter = iter;
|
||||
Statement* unconditionalBreakStmt = nullptr;
|
||||
for (; iter != switchStatement->cases().end(); ++iter) {
|
||||
for (std::unique_ptr<Statement>& stmt : (*iter)->statements()) {
|
||||
for (std::unique_ptr<Statement>& stmt : iter->statements()) {
|
||||
if (contains_conditional_break(*stmt)) {
|
||||
// We can't reduce switch-cases to a block when they have conditional breaks.
|
||||
return nullptr;
|
||||
@ -1257,7 +1257,7 @@ static std::unique_ptr<Statement> block_for_case(SwitchStatement* switchStatemen
|
||||
|
||||
// We can move over most of the statements as-is.
|
||||
while (startIter != iter) {
|
||||
for (std::unique_ptr<Statement>& stmt : (*startIter)->statements()) {
|
||||
for (std::unique_ptr<Statement>& stmt : startIter->statements()) {
|
||||
caseStmts.push_back(std::move(stmt));
|
||||
}
|
||||
++startIter;
|
||||
@ -1266,7 +1266,7 @@ static std::unique_ptr<Statement> block_for_case(SwitchStatement* switchStatemen
|
||||
// If we found an unconditional break at the end, we need to move what we can while avoiding
|
||||
// that break.
|
||||
if (unconditionalBreakStmt != nullptr) {
|
||||
for (std::unique_ptr<Statement>& stmt : (*startIter)->statements()) {
|
||||
for (std::unique_ptr<Statement>& stmt : startIter->statements()) {
|
||||
if (stmt.get() == unconditionalBreakStmt) {
|
||||
move_all_but_break(stmt, &caseStmts);
|
||||
unconditionalBreakStmt = nullptr;
|
||||
@ -1353,15 +1353,15 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
|
||||
// switch is constant, replace it with the case that matches
|
||||
bool found = false;
|
||||
SwitchCase* defaultCase = nullptr;
|
||||
for (const std::unique_ptr<SwitchCase>& c : s.cases()) {
|
||||
if (!c->value()) {
|
||||
defaultCase = c.get();
|
||||
for (SwitchCase& c : s.cases()) {
|
||||
if (!c.value()) {
|
||||
defaultCase = &c;
|
||||
continue;
|
||||
}
|
||||
int64_t caseValue;
|
||||
SkAssertResult(fIRGenerator->getConstantInt(*c->value(), &caseValue));
|
||||
SkAssertResult(fIRGenerator->getConstantInt(*c.value(), &caseValue));
|
||||
if (caseValue == switchValue) {
|
||||
std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get());
|
||||
std::unique_ptr<Statement> newBlock = block_for_case(&s, &c);
|
||||
if (newBlock) {
|
||||
(*iter)->setStatement(std::move(newBlock), usage);
|
||||
found = true;
|
||||
|
@ -267,9 +267,9 @@ void Dehydrator::write(const Expression* e) {
|
||||
case Expression::Kind::kBinary: {
|
||||
const BinaryExpression& b = e->as<BinaryExpression>();
|
||||
this->writeCommand(Rehydrator::kBinary_Command);
|
||||
this->write(b.left().get());
|
||||
this->write(&b.left());
|
||||
this->writeU8((int) b.getOperator());
|
||||
this->write(b.right().get());
|
||||
this->write(&b.right());
|
||||
this->write(b.type());
|
||||
break;
|
||||
}
|
||||
@ -469,11 +469,11 @@ void Dehydrator::write(const Statement* s) {
|
||||
this->writeU8(ss.isStatic());
|
||||
AutoDehydratorSymbolTable symbols(this, ss.symbols());
|
||||
this->write(ss.value().get());
|
||||
this->writeU8(ss.cases().size());
|
||||
for (const std::unique_ptr<SwitchCase>& sc : ss.cases()) {
|
||||
this->write(sc->value().get());
|
||||
this->writeU8(sc->statements().size());
|
||||
for (const std::unique_ptr<Statement>& stmt : sc->statements()) {
|
||||
this->writeU8(ss.cases().count());
|
||||
for (const SwitchCase& sc : ss.cases()) {
|
||||
this->write(sc.value().get());
|
||||
this->writeU8(sc.statements().size());
|
||||
for (const std::unique_ptr<Statement>& stmt : sc.statements()) {
|
||||
this->write(stmt.get());
|
||||
}
|
||||
}
|
||||
@ -487,9 +487,9 @@ void Dehydrator::write(const Statement* s) {
|
||||
this->writeCommand(Rehydrator::kVarDeclaration_Command);
|
||||
this->writeU16(this->symbolId(&v.var()));
|
||||
this->write(v.baseType());
|
||||
this->writeU8(v.sizes().count());
|
||||
for (const std::unique_ptr<Expression>& size : v.sizes()) {
|
||||
this->write(size.get());
|
||||
this->writeU8(v.sizeCount());
|
||||
for (int i = 0; i < v.sizeCount(); ++i) {
|
||||
this->write(v.size(i).get());
|
||||
}
|
||||
this->write(v.value().get());
|
||||
break;
|
||||
|
@ -20,7 +20,8 @@ public:
|
||||
static constexpr Kind kSymbolKind = Kind::kExternal;
|
||||
|
||||
ExternalValue(const char* name, const Type& type)
|
||||
: INHERITED(-1, kSymbolKind, name, &type) {}
|
||||
: INHERITED(-1, kSymbolKind, name)
|
||||
, fType(type) {}
|
||||
|
||||
virtual bool canRead() const {
|
||||
return false;
|
||||
@ -34,6 +35,13 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type for purposes of read and write operations.
|
||||
*/
|
||||
const Type& type() const override {
|
||||
return fType;
|
||||
}
|
||||
|
||||
virtual int callParameterCount() const {
|
||||
return -1;
|
||||
}
|
||||
@ -50,7 +58,7 @@ public:
|
||||
* Returns the return type resulting from a call operation.
|
||||
*/
|
||||
virtual const Type& callReturnType() const {
|
||||
return this->type();
|
||||
return fType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,6 +118,8 @@ public:
|
||||
|
||||
private:
|
||||
using INHERITED = Symbol;
|
||||
|
||||
const Type& fType;
|
||||
};
|
||||
|
||||
} // namespace SkSL
|
||||
|
@ -908,8 +908,8 @@ GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind
|
||||
|
||||
void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
Precedence parentPrecedence) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
const Expression& left = b.left();
|
||||
const Expression& right = b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
if (fProgram.fSettings.fCaps->unfoldShortCircuitAsTernary() &&
|
||||
(op == Token::Kind::TK_LOGICALAND || op == Token::Kind::TK_LOGICALOR)) {
|
||||
@ -952,10 +952,10 @@ void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpres
|
||||
// Transform:
|
||||
// a && b => a ? b : false
|
||||
// a || b => a ? true : b
|
||||
this->writeExpression(*b.left(), kTernary_Precedence);
|
||||
this->writeExpression(b.left(), kTernary_Precedence);
|
||||
this->write(" ? ");
|
||||
if (b.getOperator() == Token::Kind::TK_LOGICALAND) {
|
||||
this->writeExpression(*b.right(), kTernary_Precedence);
|
||||
this->writeExpression(b.right(), kTernary_Precedence);
|
||||
} else {
|
||||
BoolLiteral boolTrue(fContext, -1, true);
|
||||
this->writeBoolLiteral(boolTrue);
|
||||
@ -965,7 +965,7 @@ void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpres
|
||||
BoolLiteral boolFalse(fContext, -1, false);
|
||||
this->writeBoolLiteral(boolFalse);
|
||||
} else {
|
||||
this->writeExpression(*b.right(), kTernary_Precedence);
|
||||
this->writeExpression(b.right(), kTernary_Precedence);
|
||||
}
|
||||
if (kTernary_Precedence >= parentPrecedence) {
|
||||
this->write(")");
|
||||
@ -1251,10 +1251,10 @@ void GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool glob
|
||||
this->writeType(var.baseType());
|
||||
this->write(" ");
|
||||
this->write(var.var().name());
|
||||
for (const std::unique_ptr<Expression>& size : var.sizes()) {
|
||||
for (int i = 0; i < var.sizeCount(); ++i) {
|
||||
this->write("[");
|
||||
if (size) {
|
||||
this->writeExpression(*size, kTopLevel_Precedence);
|
||||
if (var.size(i)) {
|
||||
this->writeExpression(*var.size(i), kTopLevel_Precedence);
|
||||
}
|
||||
this->write("]");
|
||||
}
|
||||
@ -1448,16 +1448,16 @@ void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
|
||||
this->writeExpression(*s.value(), kTopLevel_Precedence);
|
||||
this->writeLine(") {");
|
||||
fIndentation++;
|
||||
for (const std::unique_ptr<SwitchCase>& c : s.cases()) {
|
||||
if (c->value()) {
|
||||
for (const SwitchCase& c : s.cases()) {
|
||||
if (c.value()) {
|
||||
this->write("case ");
|
||||
this->writeExpression(*c->value(), kTopLevel_Precedence);
|
||||
this->writeExpression(*c.value(), kTopLevel_Precedence);
|
||||
this->writeLine(":");
|
||||
} else {
|
||||
this->writeLine("default:");
|
||||
}
|
||||
fIndentation++;
|
||||
for (const auto& stmt : c->statements()) {
|
||||
for (const auto& stmt : c.statements()) {
|
||||
this->writeStatement(*stmt);
|
||||
this->writeLine();
|
||||
}
|
||||
|
@ -33,7 +33,6 @@
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
class ExternalValue;
|
||||
class FunctionCall;
|
||||
struct ParsedModule;
|
||||
struct Swizzle;
|
||||
|
@ -355,9 +355,9 @@ std::unique_ptr<Expression> Inliner::inlineExpression(int offset,
|
||||
case Expression::Kind::kBinary: {
|
||||
const BinaryExpression& b = expression.as<BinaryExpression>();
|
||||
return std::make_unique<BinaryExpression>(offset,
|
||||
expr(b.left()),
|
||||
expr(b.leftPointer()),
|
||||
b.getOperator(),
|
||||
expr(b.right()),
|
||||
expr(b.rightPointer()),
|
||||
&b.type());
|
||||
}
|
||||
case Expression::Kind::kBoolLiteral:
|
||||
@ -535,10 +535,10 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
|
||||
case Statement::Kind::kSwitch: {
|
||||
const SwitchStatement& ss = statement.as<SwitchStatement>();
|
||||
std::vector<std::unique_ptr<SwitchCase>> cases;
|
||||
cases.reserve(ss.cases().size());
|
||||
for (const std::unique_ptr<SwitchCase>& sc : ss.cases()) {
|
||||
cases.push_back(std::make_unique<SwitchCase>(offset, expr(sc->value()),
|
||||
stmts(sc->statements())));
|
||||
cases.reserve(ss.cases().count());
|
||||
for (const SwitchCase& sc : ss.cases()) {
|
||||
cases.push_back(std::make_unique<SwitchCase>(offset, expr(sc.value()),
|
||||
stmts(sc.statements())));
|
||||
}
|
||||
return std::make_unique<SwitchStatement>(offset, ss.isStatic(), expr(ss.value()),
|
||||
std::move(cases),
|
||||
@ -547,9 +547,9 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
|
||||
case Statement::Kind::kVarDeclaration: {
|
||||
const VarDeclaration& decl = statement.as<VarDeclaration>();
|
||||
ExpressionArray sizes;
|
||||
sizes.reserve_back(decl.sizes().count());
|
||||
for (const std::unique_ptr<Expression>& size : decl.sizes()) {
|
||||
sizes.push_back(expr(size));
|
||||
sizes.reserve_back(decl.sizeCount());
|
||||
for (int i = 0; i < decl.sizeCount(); ++i) {
|
||||
sizes.push_back(expr(decl.size(i)));
|
||||
}
|
||||
std::unique_ptr<Expression> initialValue = expr(decl.value());
|
||||
const Variable& old = decl.var();
|
||||
@ -940,9 +940,9 @@ public:
|
||||
}
|
||||
|
||||
this->visitExpression(&switchStmt.value());
|
||||
for (const std::unique_ptr<SwitchCase>& switchCase : switchStmt.cases()) {
|
||||
for (SwitchCase& switchCase : switchStmt.cases()) {
|
||||
// The switch-case's fValue cannot be a FunctionCall; skip it.
|
||||
for (std::unique_ptr<Statement>& caseBlock : switchCase->statements()) {
|
||||
for (std::unique_ptr<Statement>& caseBlock : switchCase.statements()) {
|
||||
this->visitStatement(&caseBlock);
|
||||
}
|
||||
}
|
||||
@ -999,7 +999,7 @@ public:
|
||||
|
||||
case Expression::Kind::kBinary: {
|
||||
BinaryExpression& binaryExpr = (*expr)->as<BinaryExpression>();
|
||||
this->visitExpression(&binaryExpr.left());
|
||||
this->visitExpression(&binaryExpr.leftPointer());
|
||||
|
||||
// Logical-and and logical-or binary expressions do not inline the right side,
|
||||
// because that would invalidate short-circuiting. That is, when evaluating
|
||||
@ -1013,7 +1013,7 @@ public:
|
||||
bool shortCircuitable = (op == Token::Kind::TK_LOGICALAND ||
|
||||
op == Token::Kind::TK_LOGICALOR);
|
||||
if (!shortCircuitable) {
|
||||
this->visitExpression(&binaryExpr.right());
|
||||
this->visitExpression(&binaryExpr.rightPointer());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -823,8 +823,8 @@ void MetalCodeGenerator::writeMatrixTimesEqualHelper(const Type& left, const Typ
|
||||
|
||||
void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
Precedence parentPrecedence) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
const Expression& left = b.left();
|
||||
const Expression& right = b.right();
|
||||
const Type& leftType = left.type();
|
||||
const Type& rightType = right.type();
|
||||
Token::Kind op = b.getOperator();
|
||||
@ -1236,10 +1236,10 @@ void MetalCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool glo
|
||||
this->writeType(var.baseType());
|
||||
this->write(" ");
|
||||
this->writeName(var.var().name());
|
||||
for (const std::unique_ptr<Expression>& size : var.sizes()) {
|
||||
for (int i = 0; i < var.sizeCount(); ++i) {
|
||||
this->write("[");
|
||||
if (size) {
|
||||
this->writeExpression(*size, kTopLevel_Precedence);
|
||||
if (var.size(i)) {
|
||||
this->writeExpression(*var.size(i), kTopLevel_Precedence);
|
||||
}
|
||||
this->write("]");
|
||||
}
|
||||
@ -1368,16 +1368,16 @@ void MetalCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
|
||||
this->writeExpression(*s.value(), kTopLevel_Precedence);
|
||||
this->writeLine(") {");
|
||||
fIndentation++;
|
||||
for (const std::unique_ptr<SwitchCase>& c : s.cases()) {
|
||||
if (c->value()) {
|
||||
for (const SwitchCase& c : s.cases()) {
|
||||
if (c.value()) {
|
||||
this->write("case ");
|
||||
this->writeExpression(*c->value(), kTopLevel_Precedence);
|
||||
this->writeExpression(*c.value(), kTopLevel_Precedence);
|
||||
this->writeLine(":");
|
||||
} else {
|
||||
this->writeLine("default:");
|
||||
}
|
||||
fIndentation++;
|
||||
for (const auto& stmt : c->statements()) {
|
||||
for (const auto& stmt : c.statements()) {
|
||||
this->writeStatement(*stmt);
|
||||
this->writeLine();
|
||||
}
|
||||
@ -1713,8 +1713,8 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
|
||||
return this->requirements(e->as<Swizzle>().base().get());
|
||||
case Expression::Kind::kBinary: {
|
||||
const BinaryExpression& bin = e->as<BinaryExpression>();
|
||||
return this->requirements(bin.left().get()) |
|
||||
this->requirements(bin.right().get());
|
||||
return this->requirements(&bin.left()) |
|
||||
this->requirements(&bin.right());
|
||||
}
|
||||
case Expression::Kind::kIndex: {
|
||||
const IndexExpression& idx = e->as<IndexExpression>();
|
||||
@ -1802,8 +1802,8 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Statemen
|
||||
case Statement::Kind::kSwitch: {
|
||||
const SwitchStatement& sw = s->as<SwitchStatement>();
|
||||
Requirements result = this->requirements(sw.value().get());
|
||||
for (const std::unique_ptr<SwitchCase>& sc : sw.cases()) {
|
||||
for (const auto& st : sc->statements()) {
|
||||
for (const SwitchCase& sc : sw.cases()) {
|
||||
for (const auto& st : sc.statements()) {
|
||||
result |= this->requirements(st.get());
|
||||
}
|
||||
}
|
||||
|
@ -2317,8 +2317,8 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, OutputStream& out) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
const Expression& left = b.left();
|
||||
const Expression& right = b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
// handle cases where we don't necessarily evaluate both LHS and RHS
|
||||
switch (op) {
|
||||
@ -2357,14 +2357,14 @@ SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStrea
|
||||
SkASSERT(a.getOperator() == Token::Kind::TK_LOGICALAND);
|
||||
BoolLiteral falseLiteral(fContext, -1, false);
|
||||
SpvId falseConstant = this->writeBoolLiteral(falseLiteral);
|
||||
SpvId lhs = this->writeExpression(*a.left(), out);
|
||||
SpvId lhs = this->writeExpression(a.left(), out);
|
||||
SpvId rhsLabel = this->nextId();
|
||||
SpvId end = this->nextId();
|
||||
SpvId lhsBlock = fCurrentBlock;
|
||||
this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out);
|
||||
this->writeInstruction(SpvOpBranchConditional, lhs, rhsLabel, end, out);
|
||||
this->writeLabel(rhsLabel, out);
|
||||
SpvId rhs = this->writeExpression(*a.right(), out);
|
||||
SpvId rhs = this->writeExpression(a.right(), out);
|
||||
SpvId rhsBlock = fCurrentBlock;
|
||||
this->writeInstruction(SpvOpBranch, end, out);
|
||||
this->writeLabel(end, out);
|
||||
@ -2378,14 +2378,14 @@ SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream
|
||||
SkASSERT(o.getOperator() == Token::Kind::TK_LOGICALOR);
|
||||
BoolLiteral trueLiteral(fContext, -1, true);
|
||||
SpvId trueConstant = this->writeBoolLiteral(trueLiteral);
|
||||
SpvId lhs = this->writeExpression(*o.left(), out);
|
||||
SpvId lhs = this->writeExpression(o.left(), out);
|
||||
SpvId rhsLabel = this->nextId();
|
||||
SpvId end = this->nextId();
|
||||
SpvId lhsBlock = fCurrentBlock;
|
||||
this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out);
|
||||
this->writeInstruction(SpvOpBranchConditional, lhs, end, rhsLabel, out);
|
||||
this->writeLabel(rhsLabel, out);
|
||||
SpvId rhs = this->writeExpression(*o.right(), out);
|
||||
SpvId rhs = this->writeExpression(o.right(), out);
|
||||
SpvId rhsBlock = fCurrentBlock;
|
||||
this->writeInstruction(SpvOpBranch, end, out);
|
||||
this->writeLabel(end, out);
|
||||
@ -3055,11 +3055,11 @@ void SPIRVCodeGenerator::writeSwitchStatement(const SwitchStatement& s, OutputSt
|
||||
SpvId defaultLabel = end;
|
||||
fBreakTarget.push(end);
|
||||
int size = 3;
|
||||
auto& cases = s.cases();
|
||||
for (const std::unique_ptr<SwitchCase>& c : cases) {
|
||||
auto cases = s.cases();
|
||||
for (const SwitchCase& c : cases) {
|
||||
SpvId label = this->nextId();
|
||||
labels.push_back(label);
|
||||
if (c->value()) {
|
||||
if (c.value()) {
|
||||
size += 2;
|
||||
} else {
|
||||
defaultLabel = label;
|
||||
@ -3070,16 +3070,16 @@ void SPIRVCodeGenerator::writeSwitchStatement(const SwitchStatement& s, OutputSt
|
||||
this->writeOpCode(SpvOpSwitch, size, out);
|
||||
this->writeWord(value, out);
|
||||
this->writeWord(defaultLabel, out);
|
||||
for (size_t i = 0; i < cases.size(); ++i) {
|
||||
if (!cases[i]->value()) {
|
||||
for (int i = 0; i < cases.count(); ++i) {
|
||||
if (!cases[i].value()) {
|
||||
continue;
|
||||
}
|
||||
this->writeWord(cases[i]->value()->as<IntLiteral>().value(), out);
|
||||
this->writeWord(cases[i].value()->as<IntLiteral>().value(), out);
|
||||
this->writeWord(labels[i], out);
|
||||
}
|
||||
for (size_t i = 0; i < cases.size(); ++i) {
|
||||
for (int i = 0; i < cases.count(); ++i) {
|
||||
this->writeLabel(labels[i], out);
|
||||
for (const auto& stmt : cases[i]->statements()) {
|
||||
for (const auto& stmt : cases[i].statements()) {
|
||||
this->writeStatement(*stmt, out);
|
||||
}
|
||||
if (fCurrentBlock) {
|
||||
|
@ -52,71 +52,79 @@ public:
|
||||
|
||||
BinaryExpression(int offset, std::unique_ptr<Expression> left, Token::Kind op,
|
||||
std::unique_ptr<Expression> right, const Type* type)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fLeft(std::move(left))
|
||||
, fOperator(op)
|
||||
, fRight(std::move(right)) {
|
||||
: INHERITED(offset, kExpressionKind, TypeTokenData{type, op}) {
|
||||
fExpressionChildren.reserve_back(2);
|
||||
fExpressionChildren.push_back(std::move(left));
|
||||
fExpressionChildren.push_back(std::move(right));
|
||||
// If we are assigning to a VariableReference, ensure that it is set to Write or ReadWrite
|
||||
SkASSERT(!Compiler::IsAssignment(op) || check_ref(*this->left()));
|
||||
SkASSERT(!Compiler::IsAssignment(op) || check_ref(this->left()));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& left() {
|
||||
return fLeft;
|
||||
const Type& type() const override {
|
||||
return *this->typeTokenData().fType;
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& left() const {
|
||||
return fLeft;
|
||||
Expression& left() const {
|
||||
return this->expressionChild(0);
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& right() {
|
||||
return fRight;
|
||||
std::unique_ptr<Expression>& leftPointer() {
|
||||
return this->expressionPointer(0);
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& right() const {
|
||||
return fRight;
|
||||
const std::unique_ptr<Expression>& leftPointer() const {
|
||||
return this->expressionPointer(0);
|
||||
}
|
||||
|
||||
Expression& right() const {
|
||||
return this->expressionChild(1);
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& rightPointer() {
|
||||
return this->expressionPointer(1);
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& rightPointer() const {
|
||||
return this->expressionPointer(1);
|
||||
}
|
||||
|
||||
Token::Kind getOperator() const {
|
||||
return fOperator;
|
||||
return this->typeTokenData().fToken;
|
||||
}
|
||||
|
||||
bool isConstantOrUniform() const override {
|
||||
return this->left()->isConstantOrUniform() && this->right()->isConstantOrUniform();
|
||||
return this->left().isConstantOrUniform() && this->right().isConstantOrUniform();
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
|
||||
const DefinitionMap& definitions) override {
|
||||
return irGenerator.constantFold(*this->left(),
|
||||
return irGenerator.constantFold(this->left(),
|
||||
this->getOperator(),
|
||||
*this->right());
|
||||
this->right());
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
if (property == Property::kSideEffects && Compiler::IsAssignment(this->getOperator())) {
|
||||
return true;
|
||||
}
|
||||
return this->left()->hasProperty(property) || this->right()->hasProperty(property);
|
||||
return this->left().hasProperty(property) || this->right().hasProperty(property);
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> clone() const override {
|
||||
return std::unique_ptr<Expression>(new BinaryExpression(fOffset,
|
||||
this->left()->clone(),
|
||||
this->left().clone(),
|
||||
this->getOperator(),
|
||||
this->right()->clone(),
|
||||
this->right().clone(),
|
||||
&this->type()));
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
return "(" + this->left()->description() + " " +
|
||||
Compiler::OperatorName(this->getOperator()) + " " + this->right()->description() +
|
||||
return "(" + this->left().description() + " " +
|
||||
Compiler::OperatorName(this->getOperator()) + " " + this->right().description() +
|
||||
")";
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fLeft;
|
||||
Token::Kind fOperator;
|
||||
std::unique_ptr<Expression> fRight;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -22,29 +22,27 @@ public:
|
||||
|
||||
Block(int offset, StatementArray statements,
|
||||
const std::shared_ptr<SymbolTable> symbols = nullptr, bool isScope = true)
|
||||
: INHERITED(offset, kStatementKind)
|
||||
, fChildren(std::move(statements))
|
||||
, fSymbolTable(std::move(symbols))
|
||||
, fIsScope(isScope) {}
|
||||
: INHERITED(offset, kStatementKind, BlockData{std::move(symbols), isScope},
|
||||
std::move(statements)) {}
|
||||
|
||||
const StatementArray& children() const {
|
||||
return fChildren;
|
||||
return fStatementChildren;
|
||||
}
|
||||
|
||||
StatementArray& children() {
|
||||
return fChildren;
|
||||
return fStatementChildren;
|
||||
}
|
||||
|
||||
bool isScope() const {
|
||||
return fIsScope;
|
||||
return this->blockData().fIsScope;
|
||||
}
|
||||
|
||||
void setIsScope(bool isScope) {
|
||||
fIsScope = isScope;
|
||||
this->blockData().fIsScope = isScope;
|
||||
}
|
||||
|
||||
std::shared_ptr<SymbolTable> symbolTable() const {
|
||||
return fSymbolTable;
|
||||
return this->blockData().fSymbolTable;
|
||||
}
|
||||
|
||||
bool isEmpty() const override {
|
||||
@ -78,13 +76,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
StatementArray fChildren;
|
||||
std::shared_ptr<SymbolTable> fSymbolTable;
|
||||
// if isScope is false, this is just a group of statements rather than an actual
|
||||
// language-level block. This allows us to pass around multiple statements as if they were a
|
||||
// single unit, with no semantic impact.
|
||||
bool fIsScope;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -21,11 +21,14 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kBoolLiteral;
|
||||
|
||||
BoolLiteral(const Context& context, int offset, bool value)
|
||||
: INHERITED(offset, kExpressionKind, context.fBool_Type.get())
|
||||
, fValue(value) {}
|
||||
: INHERITED(offset, BoolLiteralData{context.fBool_Type.get(), value}) {}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->boolLiteralData().fType;
|
||||
}
|
||||
|
||||
bool value() const {
|
||||
return fValue;
|
||||
return this->boolLiteralData().fValue;
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
@ -51,10 +54,7 @@ public:
|
||||
|
||||
private:
|
||||
BoolLiteral(int offset, bool value, const Type* type)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fValue(value) {}
|
||||
|
||||
bool fValue;
|
||||
: INHERITED(offset, BoolLiteralData{type, value}) {}
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
@ -31,15 +31,16 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kConstructor;
|
||||
|
||||
Constructor(int offset, const Type* type, ExpressionArray arguments)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fArguments(std::move(arguments)) {}
|
||||
: INHERITED(offset, kExpressionKind, type) {
|
||||
fExpressionChildren = std::move(arguments);
|
||||
}
|
||||
|
||||
ExpressionArray& arguments() {
|
||||
return fArguments;
|
||||
return fExpressionChildren;
|
||||
}
|
||||
|
||||
const ExpressionArray& arguments() const {
|
||||
return fArguments;
|
||||
return fExpressionChildren;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
|
||||
@ -113,8 +114,6 @@ public:
|
||||
SKSL_FLOAT getMatComponent(int col, int row) const override;
|
||||
|
||||
private:
|
||||
ExpressionArray fArguments;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -22,24 +22,25 @@ public:
|
||||
|
||||
DoStatement(int offset, std::unique_ptr<Statement> statement,
|
||||
std::unique_ptr<Expression> test)
|
||||
: INHERITED(offset, kStatementKind)
|
||||
, fStatement(std::move(statement))
|
||||
, fTest(std::move(test)) {}
|
||||
: INHERITED(offset, kStatementKind) {
|
||||
fStatementChildren.push_back(std::move(statement));
|
||||
fExpressionChildren.push_back(std::move(test));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& statement() {
|
||||
return fStatement;
|
||||
return fStatementChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& statement() const {
|
||||
return fStatement;
|
||||
return fStatementChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& test() {
|
||||
return fTest;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& test() const {
|
||||
return fTest;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
@ -53,9 +54,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Statement> fStatement;
|
||||
std::unique_ptr<Expression> fTest;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -58,18 +58,63 @@ public:
|
||||
kContainsRTAdjust
|
||||
};
|
||||
|
||||
Expression(int offset, Kind kind, const Type* type)
|
||||
: INHERITED(offset, (int) kind)
|
||||
, fType(type) {
|
||||
Expression(int offset, const BoolLiteralData& data)
|
||||
: INHERITED(offset, (int) Kind::kBoolLiteral, data) {
|
||||
}
|
||||
|
||||
Expression(int offset, Kind kind, const ExternalValueData& data)
|
||||
: INHERITED(offset, (int) kind, data) {
|
||||
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
|
||||
}
|
||||
|
||||
Expression(int offset, const FieldAccessData& data)
|
||||
: INHERITED(offset, (int) Kind::kFieldAccess, data) {}
|
||||
|
||||
Expression(int offset, const FloatLiteralData& data)
|
||||
: INHERITED(offset, (int) Kind::kFloatLiteral, data) {}
|
||||
|
||||
Expression(int offset, const FunctionCallData& data)
|
||||
: INHERITED(offset, (int) Kind::kFunctionCall, data) {}
|
||||
|
||||
Expression(int offset, const FunctionReferenceData& data)
|
||||
: INHERITED(offset, (int) Kind::kFunctionReference, data) {}
|
||||
|
||||
Expression(int offset, const IntLiteralData& data)
|
||||
: INHERITED(offset, (int) Kind::kIntLiteral, data) {
|
||||
}
|
||||
|
||||
Expression(int offset, const SettingData& data)
|
||||
: INHERITED(offset, (int) Kind::kSetting, data) {
|
||||
}
|
||||
|
||||
Expression(int offset, const SwizzleData& data)
|
||||
: INHERITED(offset, (int) Kind::kSwizzle, data) {
|
||||
}
|
||||
|
||||
Expression(int offset, Kind kind, const Type* type)
|
||||
: INHERITED(offset, (int) kind, type) {
|
||||
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
|
||||
}
|
||||
|
||||
Expression(int offset, const TypeReferenceData& data)
|
||||
: INHERITED(offset, (int) Kind::kTypeReference, data) {
|
||||
}
|
||||
|
||||
Expression(int offset, Kind kind, const TypeTokenData& data)
|
||||
: INHERITED(offset, (int) kind, data) {
|
||||
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
|
||||
}
|
||||
|
||||
Expression(int offset, const VariableReferenceData& data)
|
||||
: INHERITED(offset, (int) Kind::kVariableReference, data) {
|
||||
}
|
||||
|
||||
Kind kind() const {
|
||||
return (Kind) fKind;
|
||||
}
|
||||
|
||||
virtual const Type& type() const {
|
||||
return *fType;
|
||||
return *this->typeData();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,8 +240,6 @@ public:
|
||||
virtual std::unique_ptr<Expression> clone() const = 0;
|
||||
|
||||
private:
|
||||
const Type* fType;
|
||||
|
||||
using INHERITED = IRNode;
|
||||
};
|
||||
|
||||
|
@ -21,15 +21,16 @@ public:
|
||||
static constexpr Kind kStatementKind = Kind::kExpression;
|
||||
|
||||
ExpressionStatement(std::unique_ptr<Expression> expression)
|
||||
: INHERITED(expression->fOffset, kStatementKind)
|
||||
, fExpression(std::move(expression)) {}
|
||||
: INHERITED(expression->fOffset, kStatementKind) {
|
||||
fExpressionChildren.push_back(std::move(expression));
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& expression() const {
|
||||
return fExpression;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& expression() {
|
||||
return fExpression;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
@ -41,8 +42,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fExpression;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -20,11 +20,10 @@ public:
|
||||
static constexpr Kind kProgramElementKind = Kind::kExtension;
|
||||
|
||||
Extension(int offset, String name)
|
||||
: INHERITED(offset, kProgramElementKind)
|
||||
, fName(std::move(name)) {}
|
||||
: INHERITED(offset, kProgramElementKind, name) {}
|
||||
|
||||
const String& name() const {
|
||||
return fName;
|
||||
return this->stringData();
|
||||
}
|
||||
|
||||
std::unique_ptr<ProgramElement> clone() const override {
|
||||
@ -36,8 +35,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
String fName;
|
||||
|
||||
using INHERITED = ProgramElement;
|
||||
};
|
||||
|
||||
|
@ -23,20 +23,24 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kExternalFunctionCall;
|
||||
|
||||
ExternalFunctionCall(int offset, const ExternalValue* function, ExpressionArray arguments)
|
||||
: INHERITED(offset, kExpressionKind, &function->callReturnType())
|
||||
, fFunction(*function)
|
||||
, fArguments(std::move(arguments)) {}
|
||||
: INHERITED(offset, kExpressionKind, ExternalValueData{&function->callReturnType(), function}) {
|
||||
fExpressionChildren = std::move(arguments);
|
||||
}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->externalValueData().fType;
|
||||
}
|
||||
|
||||
ExpressionArray& arguments() {
|
||||
return fArguments;
|
||||
return fExpressionChildren;
|
||||
}
|
||||
|
||||
const ExpressionArray& arguments() const {
|
||||
return fArguments;
|
||||
return fExpressionChildren;
|
||||
}
|
||||
|
||||
const ExternalValue& function() const {
|
||||
return fFunction;
|
||||
return *this->externalValueData().fValue;
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -73,10 +77,6 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
const ExternalValue& fFunction;
|
||||
ExpressionArray fArguments;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -21,11 +21,14 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kExternalValue;
|
||||
|
||||
ExternalValueReference(int offset, const ExternalValue* ev)
|
||||
: INHERITED(offset, kExpressionKind, &ev->type())
|
||||
, fValue(*ev) {}
|
||||
: INHERITED(offset, kExpressionKind, ExternalValueData{&ev->type(), ev}) {}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->externalValueData().fType;
|
||||
}
|
||||
|
||||
const ExternalValue& value() const {
|
||||
return fValue;
|
||||
return *this->externalValueData().fValue;
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -41,8 +44,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const ExternalValue& fValue;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -31,25 +31,29 @@ public:
|
||||
|
||||
FieldAccess(std::unique_ptr<Expression> base, int fieldIndex,
|
||||
OwnerKind ownerKind = OwnerKind::kDefault)
|
||||
: INHERITED(base->fOffset, kExpressionKind, base->type().fields()[fieldIndex].fType)
|
||||
, fFieldIndex(fieldIndex)
|
||||
, fOwnerKind(ownerKind)
|
||||
, fBase(std::move(base)) {}
|
||||
: INHERITED(base->fOffset, FieldAccessData{base->type().fields()[fieldIndex].fType,
|
||||
fieldIndex, ownerKind}) {
|
||||
fExpressionChildren.push_back(std::move(base));
|
||||
}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->fieldAccessData().fType;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& base() {
|
||||
return fBase;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& base() const {
|
||||
return fBase;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
int fieldIndex() const {
|
||||
return fFieldIndex;
|
||||
return this->fieldAccessData().fFieldIndex;
|
||||
}
|
||||
|
||||
OwnerKind ownerKind() const {
|
||||
return fOwnerKind;
|
||||
return this->fieldAccessData().fOwnerKind;
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -68,10 +72,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
int fFieldIndex;
|
||||
FieldAccessOwnerKind fOwnerKind;
|
||||
std::unique_ptr<Expression> fBase;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -21,15 +21,17 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kFloatLiteral;
|
||||
|
||||
FloatLiteral(const Context& context, int offset, float value)
|
||||
: INHERITED(offset, kExpressionKind, context.fFloatLiteral_Type.get())
|
||||
, fValue(value) {}
|
||||
: INHERITED(offset, FloatLiteralData{context.fFloatLiteral_Type.get(), value}) {}
|
||||
|
||||
FloatLiteral(int offset, float value, const Type* type)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fValue(value) {}
|
||||
: INHERITED(offset, FloatLiteralData{type, value}) {}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->floatLiteralData().fType;
|
||||
}
|
||||
|
||||
float value() const {
|
||||
return fValue;
|
||||
return this->floatLiteralData().fValue;
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
@ -64,8 +66,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
float fValue;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -24,47 +24,49 @@ public:
|
||||
ForStatement(int offset, std::unique_ptr<Statement> initializer,
|
||||
std::unique_ptr<Expression> test, std::unique_ptr<Expression> next,
|
||||
std::unique_ptr<Statement> statement, std::shared_ptr<SymbolTable> symbols)
|
||||
: INHERITED(offset, kStatementKind)
|
||||
, fSymbolTable(std::move(symbols))
|
||||
, fInitializer(std::move(initializer))
|
||||
, fTest(std::move(test))
|
||||
, fNext(std::move(next))
|
||||
, fStatement(std::move(statement)) {}
|
||||
: INHERITED(offset, ForStatementData{std::move(symbols)}) {
|
||||
fStatementChildren.reserve_back(2);
|
||||
fStatementChildren.push_back(std::move(initializer));
|
||||
fStatementChildren.push_back(std::move(statement));
|
||||
fExpressionChildren.reserve_back(2);
|
||||
fExpressionChildren.push_back(std::move(test));
|
||||
fExpressionChildren.push_back(std::move(next));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& initializer() {
|
||||
return fInitializer;
|
||||
return fStatementChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& initializer() const {
|
||||
return fInitializer;
|
||||
return fStatementChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& test() {
|
||||
return fTest;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& test() const {
|
||||
return fTest;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& next() {
|
||||
return fNext;
|
||||
return fExpressionChildren[1];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& next() const {
|
||||
return fNext;
|
||||
return fExpressionChildren[1];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& statement() {
|
||||
return fStatement;
|
||||
return fStatementChildren[1];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& statement() const {
|
||||
return fStatement;
|
||||
return fStatementChildren[1];
|
||||
}
|
||||
|
||||
const std::shared_ptr<SymbolTable>& symbols() const {
|
||||
return fSymbolTable;
|
||||
std::shared_ptr<SymbolTable> symbols() const {
|
||||
return this->forStatementData().fSymbolTable;
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
@ -97,12 +99,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SymbolTable> fSymbolTable;
|
||||
std::unique_ptr<Statement> fInitializer;
|
||||
std::unique_ptr<Expression> fTest;
|
||||
std::unique_ptr<Expression> fNext;
|
||||
std::unique_ptr<Statement> fStatement;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -23,22 +23,26 @@ public:
|
||||
|
||||
FunctionCall(int offset, const Type* type, const FunctionDeclaration* function,
|
||||
ExpressionArray arguments)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fFunction(*function)
|
||||
, fArguments(std::move(arguments)) {}
|
||||
: INHERITED(offset, FunctionCallData{type, function}) {
|
||||
fExpressionChildren = std::move(arguments);
|
||||
}
|
||||
|
||||
~FunctionCall() override {}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->functionCallData().fType;
|
||||
}
|
||||
|
||||
const FunctionDeclaration& function() const {
|
||||
return fFunction;
|
||||
return *this->functionCallData().fFunction;
|
||||
}
|
||||
|
||||
ExpressionArray& arguments() {
|
||||
return fArguments;
|
||||
return fExpressionChildren;
|
||||
}
|
||||
|
||||
const ExpressionArray& arguments() const {
|
||||
return fArguments;
|
||||
return fExpressionChildren;
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -77,9 +81,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const FunctionDeclaration& fFunction;
|
||||
ExpressionArray fArguments;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -30,9 +30,10 @@ public:
|
||||
: INHERITED(offset, kProgramElementKind)
|
||||
, fDeclaration(declaration)
|
||||
, fBuiltin(builtin)
|
||||
, fBody(std::move(body))
|
||||
, fReferencedIntrinsics(std::move(referencedIntrinsics))
|
||||
, fSource(nullptr) {}
|
||||
, fSource(nullptr) {
|
||||
fStatementChildren.push_back(std::move(body));
|
||||
}
|
||||
|
||||
const FunctionDeclaration& declaration() const {
|
||||
return *fDeclaration;
|
||||
@ -43,11 +44,11 @@ public:
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& body() {
|
||||
return fBody;
|
||||
return this->fStatementChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& body() const {
|
||||
return fBody;
|
||||
return this->fStatementChildren[0];
|
||||
}
|
||||
|
||||
const std::unordered_set<const FunctionDeclaration*>& referencedIntrinsics() const {
|
||||
@ -75,7 +76,6 @@ public:
|
||||
private:
|
||||
const FunctionDeclaration* fDeclaration;
|
||||
bool fBuiltin;
|
||||
std::unique_ptr<Statement> fBody;
|
||||
// We track intrinsic functions we reference so that we can ensure that all of them end up
|
||||
// copied into the final output.
|
||||
std::unordered_set<const FunctionDeclaration*> fReferencedIntrinsics;
|
||||
|
@ -24,11 +24,14 @@ public:
|
||||
|
||||
FunctionReference(const Context& context, int offset,
|
||||
std::vector<const FunctionDeclaration*> functions)
|
||||
: INHERITED(offset, kExpressionKind, context.fInvalid_Type.get())
|
||||
, fFunctions(std::move(functions)) {}
|
||||
: INHERITED(offset, FunctionReferenceData{context.fInvalid_Type.get(), std::move(functions)}) {}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->functionReferenceData().fType;
|
||||
}
|
||||
|
||||
const std::vector<const FunctionDeclaration*>& functions() const {
|
||||
return fFunctions;
|
||||
return this->functionReferenceData().fFunctions;
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -47,10 +50,7 @@ public:
|
||||
private:
|
||||
FunctionReference(int offset, std::vector<const FunctionDeclaration*> functions,
|
||||
const Type* type)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fFunctions(std::move(functions)) {}
|
||||
|
||||
std::vector<const FunctionDeclaration*> fFunctions;
|
||||
: INHERITED(offset, FunctionReferenceData{type, std::move(functions)}) {}
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
137
src/sksl/ir/SkSLIRNode.cpp
Normal file
137
src/sksl/ir/SkSLIRNode.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/sksl/ir/SkSLIRNode.h"
|
||||
|
||||
#include "src/sksl/ir/SkSLExpression.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const BlockData& data, StatementArray stmts)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data)
|
||||
, fStatementChildren(std::move(stmts)) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const BoolLiteralData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const ExternalValueData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const FieldAccessData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const FloatLiteralData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const ForStatementData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const FunctionCallData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const FunctionReferenceData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const IfStatementData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const InlineMarkerData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const IntLiteralData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const ModifiersDeclarationData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const SettingData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const String& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const SwitchStatementData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const SwizzleData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const SymbolData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const SymbolAliasData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const Type* data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const TypeReferenceData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const TypeTokenData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const UnresolvedFunctionData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const VarDeclarationData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const VariableReferenceData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::~IRNode() {}
|
||||
|
||||
} // namespace SkSL
|
@ -23,6 +23,7 @@
|
||||
namespace SkSL {
|
||||
|
||||
class Expression;
|
||||
class ExternalValue;
|
||||
class FunctionDeclaration;
|
||||
class FunctionDefinition;
|
||||
class Statement;
|
||||
@ -31,6 +32,7 @@ class SymbolTable;
|
||||
class Type;
|
||||
class Variable;
|
||||
class VariableReference;
|
||||
enum class FieldAccessOwnerKind : int8_t;
|
||||
enum class VariableRefKind : int8_t;
|
||||
enum class VariableStorage : int8_t;
|
||||
|
||||
@ -43,7 +45,19 @@ using StatementArray = SkSTArray<2, std::unique_ptr<Statement>>;
|
||||
*/
|
||||
class IRNode {
|
||||
public:
|
||||
virtual ~IRNode() {}
|
||||
virtual ~IRNode();
|
||||
|
||||
IRNode& operator=(const IRNode& other) {
|
||||
// Need to have a copy assignment operator because Type requires it, but can't use the
|
||||
// default version until we finish migrating away from std::unique_ptr children. For now,
|
||||
// just assert that there are no children (we could theoretically clone them, but we never
|
||||
// actually copy nodes containing children).
|
||||
SkASSERT(other.fExpressionChildren.empty());
|
||||
fKind = other.fKind;
|
||||
fOffset = other.fOffset;
|
||||
fData = other.fData;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual String description() const = 0;
|
||||
|
||||
@ -61,11 +75,716 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
IRNode(int offset, int kind)
|
||||
: fOffset(offset)
|
||||
, fKind(kind) {}
|
||||
struct BlockData {
|
||||
std::shared_ptr<SymbolTable> fSymbolTable;
|
||||
// if isScope is false, this is just a group of statements rather than an actual
|
||||
// language-level block. This allows us to pass around multiple statements as if they were a
|
||||
// single unit, with no semantic impact.
|
||||
bool fIsScope;
|
||||
};
|
||||
|
||||
struct BoolLiteralData {
|
||||
const Type* fType;
|
||||
bool fValue;
|
||||
};
|
||||
|
||||
struct ExternalValueData {
|
||||
const Type* fType;
|
||||
const ExternalValue* fValue;
|
||||
};
|
||||
|
||||
struct FieldAccessData {
|
||||
const Type* fType;
|
||||
int fFieldIndex;
|
||||
FieldAccessOwnerKind fOwnerKind;
|
||||
};
|
||||
|
||||
struct FloatLiteralData {
|
||||
const Type* fType;
|
||||
float fValue;
|
||||
};
|
||||
|
||||
struct ForStatementData {
|
||||
std::shared_ptr<SymbolTable> fSymbolTable;
|
||||
};
|
||||
|
||||
struct FunctionCallData {
|
||||
const Type* fType;
|
||||
const FunctionDeclaration* fFunction;
|
||||
};
|
||||
|
||||
struct FunctionReferenceData {
|
||||
const Type* fType;
|
||||
std::vector<const FunctionDeclaration*> fFunctions;
|
||||
};
|
||||
|
||||
struct IfStatementData {
|
||||
bool fIsStatic;
|
||||
};
|
||||
|
||||
struct IntLiteralData {
|
||||
const Type* fType;
|
||||
int64_t fValue;
|
||||
};
|
||||
|
||||
struct InlineMarkerData {
|
||||
const FunctionDeclaration* fFunction;
|
||||
};
|
||||
|
||||
struct ModifiersDeclarationData {
|
||||
ModifiersPool::Handle fModifiersHandle;
|
||||
};
|
||||
|
||||
struct SettingData {
|
||||
String fName;
|
||||
const Type* fType;
|
||||
};
|
||||
|
||||
struct SwitchStatementData {
|
||||
bool fIsStatic;
|
||||
std::shared_ptr<SymbolTable> fSymbols;
|
||||
};
|
||||
|
||||
struct SwizzleData {
|
||||
const Type* fType;
|
||||
std::vector<int> fComponents;
|
||||
};
|
||||
|
||||
struct SymbolData {
|
||||
StringFragment fName;
|
||||
const Type* fType;
|
||||
};
|
||||
|
||||
struct SymbolAliasData {
|
||||
StringFragment fName;
|
||||
const Symbol* fOrigSymbol;
|
||||
};
|
||||
|
||||
struct TypeReferenceData {
|
||||
const Type* fType;
|
||||
const Type* fValue;
|
||||
};
|
||||
|
||||
struct TypeTokenData {
|
||||
const Type* fType;
|
||||
Token::Kind fToken;
|
||||
};
|
||||
|
||||
struct UnresolvedFunctionData {
|
||||
// FIXME move this into the child vector after killing fExpressionChildren /
|
||||
// fStatementChildren
|
||||
std::vector<const FunctionDeclaration*> fFunctions;
|
||||
};
|
||||
|
||||
struct VarDeclarationData {
|
||||
const Type* fBaseType;
|
||||
const Variable* fVar;
|
||||
};
|
||||
|
||||
struct VariableReferenceData {
|
||||
const Variable* fVariable;
|
||||
VariableRefKind fRefKind;
|
||||
};
|
||||
|
||||
struct NodeData {
|
||||
enum class Kind {
|
||||
kBlock,
|
||||
kBoolLiteral,
|
||||
kExternalValue,
|
||||
kFieldAccess,
|
||||
kFloatLiteral,
|
||||
kForStatement,
|
||||
kFunctionCall,
|
||||
kFunctionReference,
|
||||
kIfStatement,
|
||||
kInlineMarker,
|
||||
kIntLiteral,
|
||||
kModifiersDeclaration,
|
||||
kSetting,
|
||||
kString,
|
||||
kSwitchStatement,
|
||||
kSwizzle,
|
||||
kSymbol,
|
||||
kSymbolAlias,
|
||||
kType,
|
||||
kTypeReference,
|
||||
kTypeToken,
|
||||
kUnresolvedFunction,
|
||||
kVarDeclaration,
|
||||
kVariableReference,
|
||||
} fKind = Kind::kType;
|
||||
// it doesn't really matter what kind we default to, as long as it's a POD type
|
||||
|
||||
union Contents {
|
||||
BlockData fBlock;
|
||||
BoolLiteralData fBoolLiteral;
|
||||
ExternalValueData fExternalValue;
|
||||
FieldAccessData fFieldAccess;
|
||||
FloatLiteralData fFloatLiteral;
|
||||
ForStatementData fForStatement;
|
||||
FunctionCallData fFunctionCall;
|
||||
FunctionReferenceData fFunctionReference;
|
||||
IfStatementData fIfStatement;
|
||||
InlineMarkerData fInlineMarker;
|
||||
IntLiteralData fIntLiteral;
|
||||
ModifiersDeclarationData fModifiersDeclaration;
|
||||
SettingData fSetting;
|
||||
String fString;
|
||||
SwitchStatementData fSwitchStatement;
|
||||
SwizzleData fSwizzle;
|
||||
SymbolData fSymbol;
|
||||
SymbolAliasData fSymbolAlias;
|
||||
const Type* fType;
|
||||
TypeReferenceData fTypeReference;
|
||||
TypeTokenData fTypeToken;
|
||||
UnresolvedFunctionData fUnresolvedFunction;
|
||||
VarDeclarationData fVarDeclaration;
|
||||
VariableReferenceData fVariableReference;
|
||||
|
||||
Contents() {}
|
||||
|
||||
~Contents() {}
|
||||
} fContents;
|
||||
|
||||
NodeData(const BlockData& data)
|
||||
: fKind(Kind::kBlock) {
|
||||
*(new(&fContents) BlockData) = data;
|
||||
}
|
||||
|
||||
NodeData(const BoolLiteralData& data)
|
||||
: fKind(Kind::kBoolLiteral) {
|
||||
*(new(&fContents) BoolLiteralData) = data;
|
||||
}
|
||||
|
||||
NodeData(const ExternalValueData& data)
|
||||
: fKind(Kind::kExternalValue) {
|
||||
*(new(&fContents) ExternalValueData) = data;
|
||||
}
|
||||
|
||||
NodeData(const FieldAccessData& data)
|
||||
: fKind(Kind::kFieldAccess) {
|
||||
*(new(&fContents) FieldAccessData) = data;
|
||||
}
|
||||
|
||||
NodeData(const FloatLiteralData& data)
|
||||
: fKind(Kind::kFloatLiteral) {
|
||||
*(new(&fContents) FloatLiteralData) = data;
|
||||
}
|
||||
|
||||
NodeData(const ForStatementData& data)
|
||||
: fKind(Kind::kForStatement) {
|
||||
*(new(&fContents) ForStatementData) = data;
|
||||
}
|
||||
|
||||
NodeData(const FunctionCallData& data)
|
||||
: fKind(Kind::kFunctionCall) {
|
||||
*(new(&fContents) FunctionCallData) = data;
|
||||
}
|
||||
|
||||
NodeData(const FunctionReferenceData& data)
|
||||
: fKind(Kind::kFunctionReference) {
|
||||
*(new(&fContents) FunctionReferenceData) = data;
|
||||
}
|
||||
|
||||
NodeData(IfStatementData data)
|
||||
: fKind(Kind::kIfStatement) {
|
||||
*(new(&fContents) IfStatementData) = data;
|
||||
}
|
||||
|
||||
NodeData(InlineMarkerData data)
|
||||
: fKind(Kind::kInlineMarker) {
|
||||
*(new(&fContents) InlineMarkerData) = data;
|
||||
}
|
||||
|
||||
NodeData(IntLiteralData data)
|
||||
: fKind(Kind::kIntLiteral) {
|
||||
*(new(&fContents) IntLiteralData) = data;
|
||||
}
|
||||
|
||||
NodeData(ModifiersDeclarationData data)
|
||||
: fKind(Kind::kModifiersDeclaration) {
|
||||
*(new(&fContents) ModifiersDeclarationData) = data;
|
||||
}
|
||||
|
||||
NodeData(const SettingData& data)
|
||||
: fKind(Kind::kSetting) {
|
||||
*(new(&fContents) SettingData) = data;
|
||||
}
|
||||
|
||||
NodeData(const String& data)
|
||||
: fKind(Kind::kString) {
|
||||
*(new(&fContents) String) = data;
|
||||
}
|
||||
|
||||
NodeData(const SwitchStatementData& data)
|
||||
: fKind(Kind::kSwitchStatement) {
|
||||
*(new(&fContents) SwitchStatementData) = data;
|
||||
}
|
||||
|
||||
NodeData(const SwizzleData& data)
|
||||
: fKind(Kind::kSwizzle) {
|
||||
*(new(&fContents) SwizzleData) = data;
|
||||
}
|
||||
|
||||
NodeData(const SymbolData& data)
|
||||
: fKind(Kind::kSymbol) {
|
||||
*(new(&fContents) SymbolData) = data;
|
||||
}
|
||||
|
||||
NodeData(const SymbolAliasData& data)
|
||||
: fKind(Kind::kSymbolAlias) {
|
||||
*(new(&fContents) SymbolAliasData) = data;
|
||||
}
|
||||
|
||||
NodeData(const Type* data)
|
||||
: fKind(Kind::kType) {
|
||||
*(new(&fContents) const Type*) = data;
|
||||
}
|
||||
|
||||
NodeData(const TypeReferenceData& data)
|
||||
: fKind(Kind::kTypeReference) {
|
||||
*(new(&fContents) TypeReferenceData) = data;
|
||||
}
|
||||
|
||||
NodeData(const TypeTokenData& data)
|
||||
: fKind(Kind::kTypeToken) {
|
||||
*(new(&fContents) TypeTokenData) = data;
|
||||
}
|
||||
|
||||
NodeData(const UnresolvedFunctionData& data)
|
||||
: fKind(Kind::kUnresolvedFunction) {
|
||||
*(new(&fContents) UnresolvedFunctionData) = data;
|
||||
}
|
||||
|
||||
NodeData(const VarDeclarationData& data)
|
||||
: fKind(Kind::kVarDeclaration) {
|
||||
*(new(&fContents) VarDeclarationData) = data;
|
||||
}
|
||||
|
||||
NodeData(const VariableReferenceData& data)
|
||||
: fKind(Kind::kVariableReference) {
|
||||
*(new(&fContents) VariableReferenceData) = data;
|
||||
}
|
||||
|
||||
NodeData(const NodeData& other) {
|
||||
*this = other;
|
||||
}
|
||||
|
||||
NodeData& operator=(const NodeData& other) {
|
||||
this->cleanup();
|
||||
fKind = other.fKind;
|
||||
switch (fKind) {
|
||||
case Kind::kBlock:
|
||||
*(new(&fContents) BlockData) = other.fContents.fBlock;
|
||||
break;
|
||||
case Kind::kBoolLiteral:
|
||||
*(new(&fContents) BoolLiteralData) = other.fContents.fBoolLiteral;
|
||||
break;
|
||||
case Kind::kExternalValue:
|
||||
*(new(&fContents) ExternalValueData) = other.fContents.fExternalValue;
|
||||
break;
|
||||
case Kind::kFieldAccess:
|
||||
*(new(&fContents) FieldAccessData) = other.fContents.fFieldAccess;
|
||||
break;
|
||||
case Kind::kFloatLiteral:
|
||||
*(new(&fContents) FloatLiteralData) = other.fContents.fFloatLiteral;
|
||||
break;
|
||||
case Kind::kForStatement:
|
||||
*(new(&fContents) ForStatementData) = other.fContents.fForStatement;
|
||||
break;
|
||||
case Kind::kFunctionCall:
|
||||
*(new(&fContents) FunctionCallData) = other.fContents.fFunctionCall;
|
||||
break;
|
||||
case Kind::kFunctionReference:
|
||||
*(new(&fContents) FunctionReferenceData) = other.fContents.fFunctionReference;
|
||||
break;
|
||||
case Kind::kIfStatement:
|
||||
*(new(&fContents) IfStatementData) = other.fContents.fIfStatement;
|
||||
break;
|
||||
case Kind::kInlineMarker:
|
||||
*(new(&fContents) InlineMarkerData) = other.fContents.fInlineMarker;
|
||||
break;
|
||||
case Kind::kIntLiteral:
|
||||
*(new(&fContents) IntLiteralData) = other.fContents.fIntLiteral;
|
||||
break;
|
||||
case Kind::kModifiersDeclaration:
|
||||
*(new(&fContents) ModifiersDeclarationData) =
|
||||
other.fContents.fModifiersDeclaration;
|
||||
break;
|
||||
case Kind::kSetting:
|
||||
*(new(&fContents) SettingData) = other.fContents.fSetting;
|
||||
break;
|
||||
case Kind::kString:
|
||||
*(new(&fContents) String) = other.fContents.fString;
|
||||
break;
|
||||
case Kind::kSwitchStatement:
|
||||
*(new(&fContents) SwitchStatementData) = other.fContents.fSwitchStatement;
|
||||
break;
|
||||
case Kind::kSwizzle:
|
||||
*(new(&fContents) SwizzleData) = other.fContents.fSwizzle;
|
||||
break;
|
||||
case Kind::kSymbol:
|
||||
*(new(&fContents) SymbolData) = other.fContents.fSymbol;
|
||||
break;
|
||||
case Kind::kSymbolAlias:
|
||||
*(new(&fContents) SymbolAliasData) = other.fContents.fSymbolAlias;
|
||||
break;
|
||||
case Kind::kType:
|
||||
*(new(&fContents) const Type*) = other.fContents.fType;
|
||||
break;
|
||||
case Kind::kTypeReference:
|
||||
*(new(&fContents) TypeReferenceData) = other.fContents.fTypeReference;
|
||||
break;
|
||||
case Kind::kTypeToken:
|
||||
*(new(&fContents) TypeTokenData) = other.fContents.fTypeToken;
|
||||
break;
|
||||
case Kind::kUnresolvedFunction:
|
||||
*(new(&fContents) UnresolvedFunctionData) = other.fContents.fUnresolvedFunction;
|
||||
break;
|
||||
case Kind::kVarDeclaration:
|
||||
*(new(&fContents) VarDeclarationData) = other.fContents.fVarDeclaration;
|
||||
break;
|
||||
case Kind::kVariableReference:
|
||||
*(new(&fContents) VariableReferenceData) = other.fContents.fVariableReference;
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~NodeData() {
|
||||
this->cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
void cleanup() {
|
||||
switch (fKind) {
|
||||
case Kind::kBlock:
|
||||
fContents.fBlock.~BlockData();
|
||||
break;
|
||||
case Kind::kBoolLiteral:
|
||||
fContents.fBoolLiteral.~BoolLiteralData();
|
||||
break;
|
||||
case Kind::kExternalValue:
|
||||
fContents.fExternalValue.~ExternalValueData();
|
||||
break;
|
||||
case Kind::kFieldAccess:
|
||||
fContents.fFieldAccess.~FieldAccessData();
|
||||
break;
|
||||
case Kind::kFloatLiteral:
|
||||
fContents.fFloatLiteral.~FloatLiteralData();
|
||||
break;
|
||||
case Kind::kForStatement:
|
||||
fContents.fForStatement.~ForStatementData();
|
||||
break;
|
||||
case Kind::kFunctionCall:
|
||||
fContents.fFunctionCall.~FunctionCallData();
|
||||
break;
|
||||
case Kind::kFunctionReference:
|
||||
fContents.fFunctionReference.~FunctionReferenceData();
|
||||
break;
|
||||
case Kind::kIfStatement:
|
||||
fContents.fIfStatement.~IfStatementData();
|
||||
break;
|
||||
case Kind::kInlineMarker:
|
||||
fContents.fInlineMarker.~InlineMarkerData();
|
||||
break;
|
||||
case Kind::kIntLiteral:
|
||||
fContents.fIntLiteral.~IntLiteralData();
|
||||
break;
|
||||
case Kind::kModifiersDeclaration:
|
||||
fContents.fModifiersDeclaration.~ModifiersDeclarationData();
|
||||
break;
|
||||
case Kind::kSetting:
|
||||
fContents.fSetting.~SettingData();
|
||||
break;
|
||||
case Kind::kString:
|
||||
fContents.fString.~String();
|
||||
break;
|
||||
case Kind::kSwitchStatement:
|
||||
fContents.fSwitchStatement.~SwitchStatementData();
|
||||
break;
|
||||
case Kind::kSwizzle:
|
||||
fContents.fSwizzle.~SwizzleData();
|
||||
break;
|
||||
case Kind::kSymbol:
|
||||
fContents.fSymbol.~SymbolData();
|
||||
break;
|
||||
case Kind::kSymbolAlias:
|
||||
fContents.fSymbolAlias.~SymbolAliasData();
|
||||
break;
|
||||
case Kind::kType:
|
||||
break;
|
||||
case Kind::kTypeReference:
|
||||
fContents.fTypeReference.~TypeReferenceData();
|
||||
break;
|
||||
case Kind::kTypeToken:
|
||||
fContents.fTypeToken.~TypeTokenData();
|
||||
break;
|
||||
case Kind::kUnresolvedFunction:
|
||||
fContents.fUnresolvedFunction.~UnresolvedFunctionData();
|
||||
break;
|
||||
case Kind::kVarDeclaration:
|
||||
fContents.fVarDeclaration.~VarDeclarationData();
|
||||
break;
|
||||
case Kind::kVariableReference:
|
||||
fContents.fVariableReference.~VariableReferenceData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IRNode(int offset, int kind, const BlockData& data, StatementArray stmts);
|
||||
|
||||
IRNode(int offset, int kind, const BoolLiteralData& data);
|
||||
|
||||
IRNode(int offset, int kind, const ExternalValueData& data);
|
||||
|
||||
IRNode(int offset, int kind, const FieldAccessData& data);
|
||||
|
||||
IRNode(int offset, int kind, const FloatLiteralData& data);
|
||||
|
||||
IRNode(int offset, int kind, const ForStatementData& data);
|
||||
|
||||
IRNode(int offset, int kind, const FunctionCallData& data);
|
||||
|
||||
IRNode(int offset, int kind, const FunctionReferenceData& data);
|
||||
|
||||
IRNode(int offset, int kind, const IfStatementData& data);
|
||||
|
||||
IRNode(int offset, int kind, const InlineMarkerData& data);
|
||||
|
||||
IRNode(int offset, int kind, const IntLiteralData& data);
|
||||
|
||||
IRNode(int offset, int kind, const ModifiersDeclarationData& data);
|
||||
|
||||
IRNode(int offset, int kind, const SettingData& data);
|
||||
|
||||
IRNode(int offset, int kind, const String& data);
|
||||
|
||||
IRNode(int offset, int kind, const SwitchStatementData& data);
|
||||
|
||||
IRNode(int offset, int kind, const SwizzleData& data);
|
||||
|
||||
IRNode(int offset, int kind, const SymbolData& data);
|
||||
|
||||
IRNode(int offset, int kind, const SymbolAliasData& data);
|
||||
|
||||
IRNode(int offset, int kind, const Type* data = nullptr);
|
||||
|
||||
IRNode(int offset, int kind, const TypeReferenceData& data);
|
||||
|
||||
IRNode(int offset, int kind, const TypeTokenData& data);
|
||||
|
||||
IRNode(int offset, int kind, const UnresolvedFunctionData& data);
|
||||
|
||||
IRNode(int offset, int kind, const VarDeclarationData& data);
|
||||
|
||||
IRNode(int offset, int kind, const VariableReferenceData& data);
|
||||
|
||||
Expression& expressionChild(int index) const {
|
||||
SkASSERT(index >= 0 && index < (int) fExpressionChildren.size());
|
||||
return *fExpressionChildren[index];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& expressionPointer(int index) {
|
||||
SkASSERT(index >= 0 && index < (int) fExpressionChildren.size());
|
||||
return fExpressionChildren[index];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& expressionPointer(int index) const {
|
||||
SkASSERT(index >= 0 && index < (int) fExpressionChildren.size());
|
||||
return fExpressionChildren[index];
|
||||
}
|
||||
|
||||
int expressionChildCount() const {
|
||||
return fExpressionChildren.size();
|
||||
}
|
||||
|
||||
|
||||
Statement& statementChild(int index) const {
|
||||
SkASSERT(index >= 0 && index < (int) fStatementChildren.size());
|
||||
return *fStatementChildren[index];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& statementPointer(int index) {
|
||||
SkASSERT(index >= 0 && index < (int) fStatementChildren.size());
|
||||
return fStatementChildren[index];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& statementPointer(int index) const {
|
||||
SkASSERT(index >= 0 && index < (int) fStatementChildren.size());
|
||||
return fStatementChildren[index];
|
||||
}
|
||||
|
||||
int statementChildCount() const {
|
||||
return fStatementChildren.size();
|
||||
}
|
||||
|
||||
BlockData& blockData() {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kBlock);
|
||||
return fData.fContents.fBlock;
|
||||
}
|
||||
|
||||
const BlockData& blockData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kBlock);
|
||||
return fData.fContents.fBlock;
|
||||
}
|
||||
|
||||
const BoolLiteralData& boolLiteralData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kBoolLiteral);
|
||||
return fData.fContents.fBoolLiteral;
|
||||
}
|
||||
|
||||
const ExternalValueData& externalValueData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kExternalValue);
|
||||
return fData.fContents.fExternalValue;
|
||||
}
|
||||
|
||||
const FieldAccessData& fieldAccessData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kFieldAccess);
|
||||
return fData.fContents.fFieldAccess;
|
||||
}
|
||||
|
||||
const FloatLiteralData& floatLiteralData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kFloatLiteral);
|
||||
return fData.fContents.fFloatLiteral;
|
||||
}
|
||||
|
||||
const ForStatementData& forStatementData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kForStatement);
|
||||
return fData.fContents.fForStatement;
|
||||
}
|
||||
|
||||
const FunctionCallData& functionCallData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kFunctionCall);
|
||||
return fData.fContents.fFunctionCall;
|
||||
}
|
||||
|
||||
const FunctionReferenceData& functionReferenceData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kFunctionReference);
|
||||
return fData.fContents.fFunctionReference;
|
||||
}
|
||||
|
||||
const IfStatementData& ifStatementData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kIfStatement);
|
||||
return fData.fContents.fIfStatement;
|
||||
}
|
||||
|
||||
const InlineMarkerData& inlineMarkerData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kInlineMarker);
|
||||
return fData.fContents.fInlineMarker;
|
||||
}
|
||||
|
||||
const IntLiteralData& intLiteralData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kIntLiteral);
|
||||
return fData.fContents.fIntLiteral;
|
||||
}
|
||||
|
||||
const ModifiersDeclarationData& modifiersDeclarationData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kModifiersDeclaration);
|
||||
return fData.fContents.fModifiersDeclaration;
|
||||
}
|
||||
|
||||
const SettingData& settingData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kSetting);
|
||||
return fData.fContents.fSetting;
|
||||
}
|
||||
|
||||
const String& stringData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kString);
|
||||
return fData.fContents.fString;
|
||||
}
|
||||
|
||||
SwitchStatementData& switchStatementData() {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kSwitchStatement);
|
||||
return fData.fContents.fSwitchStatement;
|
||||
}
|
||||
|
||||
const SwitchStatementData& switchStatementData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kSwitchStatement);
|
||||
return fData.fContents.fSwitchStatement;
|
||||
}
|
||||
|
||||
SwizzleData& swizzleData() {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kSwizzle);
|
||||
return fData.fContents.fSwizzle;
|
||||
}
|
||||
|
||||
const SwizzleData& swizzleData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kSwizzle);
|
||||
return fData.fContents.fSwizzle;
|
||||
}
|
||||
|
||||
SymbolData& symbolData() {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kSymbol);
|
||||
return fData.fContents.fSymbol;
|
||||
}
|
||||
|
||||
const SymbolData& symbolData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kSymbol);
|
||||
return fData.fContents.fSymbol;
|
||||
}
|
||||
|
||||
const SymbolAliasData& symbolAliasData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kSymbolAlias);
|
||||
return fData.fContents.fSymbolAlias;
|
||||
}
|
||||
|
||||
const Type* typeData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kType);
|
||||
return fData.fContents.fType;
|
||||
}
|
||||
|
||||
const TypeReferenceData& typeReferenceData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kTypeReference);
|
||||
return fData.fContents.fTypeReference;
|
||||
}
|
||||
|
||||
const TypeTokenData& typeTokenData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kTypeToken);
|
||||
return fData.fContents.fTypeToken;
|
||||
}
|
||||
|
||||
const UnresolvedFunctionData& unresolvedFunctionData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kUnresolvedFunction);
|
||||
return fData.fContents.fUnresolvedFunction;
|
||||
}
|
||||
|
||||
VarDeclarationData& varDeclarationData() {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kVarDeclaration);
|
||||
return fData.fContents.fVarDeclaration;
|
||||
}
|
||||
|
||||
const VarDeclarationData& varDeclarationData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kVarDeclaration);
|
||||
return fData.fContents.fVarDeclaration;
|
||||
}
|
||||
|
||||
VariableReferenceData& variableReferenceData() {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kVariableReference);
|
||||
return fData.fContents.fVariableReference;
|
||||
}
|
||||
|
||||
const VariableReferenceData& variableReferenceData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kVariableReference);
|
||||
return fData.fContents.fVariableReference;
|
||||
}
|
||||
|
||||
int fKind;
|
||||
|
||||
NodeData fData;
|
||||
|
||||
// Needing two separate vectors is a temporary issue. Ideally, we'd just be able to use a single
|
||||
// vector of nodes, but there are various spots where we take pointers to std::unique_ptr<>,
|
||||
// and it isn't safe to pun std::unique_ptr<IRNode> to std::unique_ptr<Statement / Expression>.
|
||||
// And we can't update the call sites to expect std::unique_ptr<IRNode> while there are still
|
||||
// old-style nodes around.
|
||||
// When the transition is finished, we'll be able to drop the unique_ptrs and just handle
|
||||
// <IRNode> directly.
|
||||
ExpressionArray fExpressionChildren;
|
||||
// it's important to keep the statement array defined after (and thus destroyed before) fData,
|
||||
// because destroying statements can modify reference counts in a SymbolTable contained in fData
|
||||
StatementArray fStatementChildren;
|
||||
};
|
||||
|
||||
} // namespace SkSL
|
||||
|
@ -16,44 +16,44 @@ namespace SkSL {
|
||||
/**
|
||||
* An 'if' statement.
|
||||
*/
|
||||
class IfStatement final : public Statement {
|
||||
public:
|
||||
struct IfStatement final : public Statement {
|
||||
static constexpr Kind kStatementKind = Kind::kIf;
|
||||
|
||||
IfStatement(int offset, bool isStatic, std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Statement> ifTrue, std::unique_ptr<Statement> ifFalse)
|
||||
: INHERITED(offset, kStatementKind)
|
||||
, fTest(std::move(test))
|
||||
, fIfTrue(std::move(ifTrue))
|
||||
, fIfFalse(std::move(ifFalse))
|
||||
, fIsStatic(isStatic) {}
|
||||
: INHERITED(offset, IfStatementData{isStatic}) {
|
||||
fExpressionChildren.push_back(std::move(test));
|
||||
fStatementChildren.reserve_back(2);
|
||||
fStatementChildren.push_back(std::move(ifTrue));
|
||||
fStatementChildren.push_back(std::move(ifFalse));
|
||||
}
|
||||
|
||||
bool isStatic() const {
|
||||
return fIsStatic;
|
||||
return this->ifStatementData().fIsStatic;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& test() {
|
||||
return fTest;
|
||||
return this->fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& test() const {
|
||||
return fTest;
|
||||
return this->fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& ifTrue() {
|
||||
return fIfTrue;
|
||||
return this->fStatementChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& ifTrue() const {
|
||||
return fIfTrue;
|
||||
return this->fStatementChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& ifFalse() {
|
||||
return fIfFalse;
|
||||
return this->fStatementChildren[1];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& ifFalse() const {
|
||||
return fIfFalse;
|
||||
return this->fStatementChildren[1];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
@ -76,12 +76,6 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fTest;
|
||||
std::unique_ptr<Statement> fIfTrue;
|
||||
std::unique_ptr<Statement> fIfFalse;
|
||||
bool fIsStatic;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -46,24 +46,27 @@ struct IndexExpression final : public Expression {
|
||||
|
||||
IndexExpression(const Context& context, std::unique_ptr<Expression> base,
|
||||
std::unique_ptr<Expression> index)
|
||||
: INHERITED(base->fOffset, kExpressionKind, &index_type(context, base->type()))
|
||||
, fBase(std::move(base))
|
||||
, fIndex(std::move(index)) {}
|
||||
: INHERITED(base->fOffset, kExpressionKind, &index_type(context, base->type())) {
|
||||
SkASSERT(index->type() == *context.fInt_Type || index->type() == *context.fUInt_Type);
|
||||
fExpressionChildren.reserve_back(2);
|
||||
fExpressionChildren.push_back(std::move(base));
|
||||
fExpressionChildren.push_back(std::move(index));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& base() {
|
||||
return fBase;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& base() const {
|
||||
return fBase;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& index() {
|
||||
return fIndex;
|
||||
return fExpressionChildren[1];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& index() const {
|
||||
return fIndex;
|
||||
return fExpressionChildren[1];
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -85,13 +88,11 @@ struct IndexExpression final : public Expression {
|
||||
private:
|
||||
IndexExpression(std::unique_ptr<Expression> base, std::unique_ptr<Expression> index,
|
||||
const Type* type)
|
||||
: INHERITED(base->fOffset, Kind::kIndex, type)
|
||||
, fBase(std::move(base))
|
||||
, fIndex(std::move(index)) {}
|
||||
|
||||
|
||||
std::unique_ptr<Expression> fBase;
|
||||
std::unique_ptr<Expression> fIndex;
|
||||
: INHERITED(base->fOffset, Kind::kIndex, type) {
|
||||
fExpressionChildren.reserve_back(2);
|
||||
fExpressionChildren.push_back(std::move(base));
|
||||
fExpressionChildren.push_back(std::move(index));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace SkSL
|
||||
|
@ -23,11 +23,10 @@ public:
|
||||
static constexpr Kind kStatementKind = Kind::kInlineMarker;
|
||||
|
||||
InlineMarker(const FunctionDeclaration* function)
|
||||
: INHERITED(-1, kStatementKind)
|
||||
, fFunction(*function) {}
|
||||
: INHERITED(-1, InlineMarkerData{function}) {}
|
||||
|
||||
const FunctionDeclaration& function() const {
|
||||
return fFunction;
|
||||
return *this->inlineMarkerData().fFunction;
|
||||
}
|
||||
|
||||
bool isEmpty() const override {
|
||||
@ -43,8 +42,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const FunctionDeclaration& fFunction;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -23,15 +23,17 @@ public:
|
||||
// FIXME: we will need to revisit this if/when we add full support for both signed and unsigned
|
||||
// 64-bit integers, but for right now an int64_t will hold every value we care about
|
||||
IntLiteral(const Context& context, int offset, int64_t value)
|
||||
: INHERITED(offset, kExpressionKind, context.fInt_Type.get())
|
||||
, fValue(value) {}
|
||||
: INHERITED(offset, IntLiteralData{context.fInt_Type.get(), value}) {}
|
||||
|
||||
IntLiteral(int offset, int64_t value, const Type* type = nullptr)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fValue(value) {}
|
||||
: INHERITED(offset, IntLiteralData{type, value}) {}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->intLiteralData().fType;
|
||||
}
|
||||
|
||||
int64_t value() const {
|
||||
return fValue;
|
||||
return this->intLiteralData().fValue;
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
@ -67,8 +69,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
int64_t fValue;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -34,8 +34,9 @@ public:
|
||||
, fVariable(var)
|
||||
, fTypeName(std::move(typeName))
|
||||
, fInstanceName(std::move(instanceName))
|
||||
, fSizes(std::move(sizes))
|
||||
, fTypeOwner(std::move(typeOwner)) {}
|
||||
, fTypeOwner(std::move(typeOwner)) {
|
||||
fExpressionChildren.move_back_n(sizes.size(), sizes.data());
|
||||
}
|
||||
|
||||
const Variable& variable() const {
|
||||
return *fVariable;
|
||||
@ -58,11 +59,11 @@ public:
|
||||
}
|
||||
|
||||
ExpressionArray& sizes() {
|
||||
return fSizes;
|
||||
return fExpressionChildren;
|
||||
}
|
||||
|
||||
const ExpressionArray& sizes() const {
|
||||
return fSizes;
|
||||
return fExpressionChildren;
|
||||
}
|
||||
|
||||
std::unique_ptr<ProgramElement> clone() const override {
|
||||
@ -103,7 +104,6 @@ private:
|
||||
const Variable* fVariable;
|
||||
String fTypeName;
|
||||
String fInstanceName;
|
||||
ExpressionArray fSizes;
|
||||
std::shared_ptr<SymbolTable> fTypeOwner;
|
||||
|
||||
using INHERITED = ProgramElement;
|
||||
|
@ -23,15 +23,14 @@ public:
|
||||
static constexpr Kind kProgramElementKind = Kind::kModifiers;
|
||||
|
||||
ModifiersDeclaration(ModifiersPool::Handle modifiers)
|
||||
: INHERITED(-1, kProgramElementKind)
|
||||
, fModifiersHandle(modifiers) {}
|
||||
: INHERITED(-1, ModifiersDeclarationData{modifiers}) {}
|
||||
|
||||
const Modifiers& modifiers() const {
|
||||
return *fModifiersHandle;
|
||||
return *this->modifiersDeclarationData().fModifiersHandle;
|
||||
}
|
||||
|
||||
const ModifiersPool::Handle& modifiersHandle() const {
|
||||
return fModifiersHandle;
|
||||
return this->modifiersDeclarationData().fModifiersHandle;
|
||||
}
|
||||
|
||||
std::unique_ptr<ProgramElement> clone() const override {
|
||||
@ -43,8 +42,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
ModifiersPool::Handle fModifiersHandle;
|
||||
|
||||
using INHERITED = ProgramElement;
|
||||
};
|
||||
|
||||
|
@ -22,20 +22,24 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kPostfix;
|
||||
|
||||
PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op)
|
||||
: INHERITED(operand->fOffset, kExpressionKind, &operand->type())
|
||||
, fOperand(std::move(operand))
|
||||
, fOperator(op) {}
|
||||
: INHERITED(operand->fOffset, kExpressionKind, TypeTokenData{&operand->type(), op}) {
|
||||
fExpressionChildren.push_back(std::move(operand));
|
||||
}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->typeTokenData().fType;
|
||||
}
|
||||
|
||||
Token::Kind getOperator() const {
|
||||
return fOperator;
|
||||
return this->typeTokenData().fToken;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& operand() {
|
||||
return fOperand;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& operand() const {
|
||||
return fOperand;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -55,9 +59,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fOperand;
|
||||
Token::Kind fOperator;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -24,20 +24,24 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kPrefix;
|
||||
|
||||
PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand)
|
||||
: INHERITED(operand->fOffset, kExpressionKind, &operand->type())
|
||||
, fOperator(op)
|
||||
, fOperand(std::move(operand)) {}
|
||||
: INHERITED(operand->fOffset, kExpressionKind, TypeTokenData{&operand->type(), op}) {
|
||||
fExpressionChildren.push_back(std::move(operand));
|
||||
}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->typeTokenData().fType;
|
||||
}
|
||||
|
||||
Token::Kind getOperator() const {
|
||||
return fOperator;
|
||||
return this->typeTokenData().fToken;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& operand() {
|
||||
return fOperand;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& operand() const {
|
||||
return fOperand;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
bool isCompileTimeConstant() const override {
|
||||
@ -91,9 +95,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Token::Kind fOperator;
|
||||
std::unique_ptr<Expression> fOperand;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,15 @@ public:
|
||||
};
|
||||
|
||||
ProgramElement(int offset, Kind kind)
|
||||
: INHERITED(offset, (int) kind) {
|
||||
: INHERITED(offset, (int) kind) {
|
||||
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
|
||||
}
|
||||
|
||||
ProgramElement(int offset, const ModifiersDeclarationData& data)
|
||||
: INHERITED(offset, (int) Kind::kModifiers, data) {}
|
||||
|
||||
ProgramElement(int offset, Kind kind, const String& data)
|
||||
: INHERITED(offset, (int) kind, data) {
|
||||
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
|
||||
}
|
||||
|
||||
|
@ -21,18 +21,21 @@ public:
|
||||
static constexpr Kind kStatementKind = Kind::kReturn;
|
||||
|
||||
ReturnStatement(int offset)
|
||||
: INHERITED(offset, kStatementKind) {}
|
||||
: INHERITED(offset, kStatementKind) {
|
||||
fExpressionChildren.push_back(nullptr);
|
||||
}
|
||||
|
||||
ReturnStatement(std::unique_ptr<Expression> expression)
|
||||
: INHERITED(expression->fOffset, kStatementKind)
|
||||
, fExpression(std::move(expression)) {}
|
||||
: INHERITED(expression->fOffset, kStatementKind) {
|
||||
fExpressionChildren.push_back(std::move(expression));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& expression() {
|
||||
return fExpression;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& expression() const {
|
||||
return fExpression;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
@ -51,8 +54,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fExpression;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -22,8 +22,7 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kSetting;
|
||||
|
||||
Setting(int offset, String name, const Type* type)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fName(std::move(name)) {}
|
||||
: INHERITED(offset, SettingData{std::move(name), type}) {}
|
||||
|
||||
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
|
||||
const DefinitionMap& definitions) override;
|
||||
@ -33,7 +32,11 @@ public:
|
||||
}
|
||||
|
||||
const String& name() const {
|
||||
return fName;
|
||||
return this->settingData().fName;
|
||||
}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->settingData().fType;
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
@ -49,8 +52,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
String fName;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -44,6 +44,26 @@ public:
|
||||
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
|
||||
}
|
||||
|
||||
Statement(int offset, Kind kind, BlockData data, StatementArray stmts)
|
||||
: INHERITED(offset, (int) kind, data, std::move(stmts)) {
|
||||
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
|
||||
}
|
||||
|
||||
Statement(int offset, const ForStatementData& data)
|
||||
: INHERITED(offset, (int) Kind::kFor, data) {}
|
||||
|
||||
Statement(int offset, const IfStatementData& data)
|
||||
: INHERITED(offset, (int) Kind::kIf, data) {}
|
||||
|
||||
Statement(int offset, const InlineMarkerData& data)
|
||||
: INHERITED(offset, (int) Kind::kInlineMarker, data) {}
|
||||
|
||||
Statement(int offset, const SwitchStatementData& data)
|
||||
: INHERITED(offset, (int) Kind::kSwitch, data) {}
|
||||
|
||||
Statement(int offset, const VarDeclarationData& data)
|
||||
: INHERITED(offset, (int) Kind::kVarDeclaration, data) {}
|
||||
|
||||
Kind kind() const {
|
||||
return (Kind) fKind;
|
||||
}
|
||||
|
@ -22,24 +22,25 @@ public:
|
||||
|
||||
// null value implies "default" case
|
||||
SwitchCase(int offset, std::unique_ptr<Expression> value, StatementArray statements)
|
||||
: INHERITED(offset, kStatementKind)
|
||||
, fValue(std::move(value))
|
||||
, fStatements(std::move(statements)) {}
|
||||
: INHERITED(offset, kStatementKind) {
|
||||
fExpressionChildren.push_back(std::move(value));
|
||||
fStatementChildren = std::move(statements);
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& value() {
|
||||
return fValue;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& value() const {
|
||||
return fValue;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
StatementArray& statements() {
|
||||
return fStatements;
|
||||
return fStatementChildren;
|
||||
}
|
||||
|
||||
const StatementArray& statements() const {
|
||||
return fStatements;
|
||||
return fStatementChildren;
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
@ -67,9 +68,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fValue;
|
||||
StatementArray fStatements;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -23,43 +23,49 @@ class SwitchStatement final : public Statement {
|
||||
public:
|
||||
static constexpr Kind kStatementKind = Kind::kSwitch;
|
||||
|
||||
using CaseArray = NodeArrayWrapper<SwitchCase, Statement>;
|
||||
|
||||
using ConstCaseArray = ConstNodeArrayWrapper<SwitchCase, Statement>;
|
||||
|
||||
SwitchStatement(int offset, bool isStatic, std::unique_ptr<Expression> value,
|
||||
std::vector<std::unique_ptr<SwitchCase>> cases,
|
||||
const std::shared_ptr<SymbolTable> symbols)
|
||||
: INHERITED(offset, kStatementKind)
|
||||
, fIsStatic(isStatic)
|
||||
, fValue(std::move(value))
|
||||
, fCases(std::move(cases))
|
||||
, fSymbols(std::move(symbols)) {}
|
||||
: INHERITED(offset, SwitchStatementData{isStatic, std::move(symbols)}) {
|
||||
fExpressionChildren.push_back(std::move(value));
|
||||
fStatementChildren.reserve_back(cases.size());
|
||||
for (std::unique_ptr<SwitchCase>& c : cases) {
|
||||
fStatementChildren.push_back(std::move(c));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& value() {
|
||||
return fValue;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& value() const {
|
||||
return fValue;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<SwitchCase>>& cases() {
|
||||
return fCases;
|
||||
CaseArray cases() {
|
||||
return CaseArray(&fStatementChildren);
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<SwitchCase>>& cases() const {
|
||||
return fCases;
|
||||
ConstCaseArray cases() const {
|
||||
return ConstCaseArray(&fStatementChildren);
|
||||
}
|
||||
|
||||
bool isStatic() const {
|
||||
return fIsStatic;
|
||||
return this->switchStatementData().fIsStatic;
|
||||
}
|
||||
|
||||
const std::shared_ptr<SymbolTable>& symbols() const {
|
||||
return fSymbols;
|
||||
return this->switchStatementData().fSymbols;
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
std::vector<std::unique_ptr<SwitchCase>> cloned;
|
||||
for (const std::unique_ptr<SwitchCase>& sc : this->cases()) {
|
||||
cloned.emplace_back(&sc->clone().release()->as<SwitchCase>());
|
||||
for (const std::unique_ptr<Statement>& s : fStatementChildren) {
|
||||
cloned.emplace_back((SwitchCase*) s->as<SwitchCase>().clone().release());
|
||||
}
|
||||
return std::unique_ptr<Statement>(new SwitchStatement(
|
||||
fOffset,
|
||||
@ -76,18 +82,13 @@ public:
|
||||
}
|
||||
result += String::printf("switch (%s) {\n", this->value()->description().c_str());
|
||||
for (const auto& c : this->cases()) {
|
||||
result += c->description();
|
||||
result += c.description();
|
||||
}
|
||||
result += "}";
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
bool fIsStatic;
|
||||
std::unique_ptr<Expression> fValue;
|
||||
std::vector<std::unique_ptr<SwitchCase>> fCases;
|
||||
std::shared_ptr<SymbolTable> fSymbols;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
@ -23,23 +23,25 @@ struct Swizzle final : public Expression {
|
||||
static constexpr Kind kExpressionKind = Kind::kSwizzle;
|
||||
|
||||
Swizzle(const Context& context, std::unique_ptr<Expression> base, std::vector<int> components)
|
||||
: INHERITED(base->fOffset, kExpressionKind,
|
||||
&base->type().componentType().toCompound(context, components.size(), 1))
|
||||
, fBase(std::move(base))
|
||||
, fComponents(std::move(components)) {
|
||||
: INHERITED(base->fOffset, swizzle_data(context, *base, std::move(components))) {
|
||||
SkASSERT(this->components().size() >= 1 && this->components().size() <= 4);
|
||||
fExpressionChildren.push_back(std::move(base));
|
||||
}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->swizzleData().fType;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& base() {
|
||||
return fBase;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& base() const {
|
||||
return fBase;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::vector<int>& components() const {
|
||||
return fComponents;
|
||||
return this->swizzleData().fComponents;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
|
||||
@ -84,14 +86,18 @@ struct Swizzle final : public Expression {
|
||||
|
||||
private:
|
||||
Swizzle(const Type* type, std::unique_ptr<Expression> base, std::vector<int> components)
|
||||
: INHERITED(base->fOffset, kExpressionKind, type)
|
||||
, fBase(std::move(base))
|
||||
, fComponents(std::move(components)) {
|
||||
: INHERITED(base->fOffset, SwizzleData{type, std::move(components)}) {
|
||||
SkASSERT(this->components().size() >= 1 && this->components().size() <= 4);
|
||||
fExpressionChildren.push_back(std::move(base));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> fBase;
|
||||
std::vector<int> fComponents;
|
||||
static SwizzleData swizzle_data(const Context& context, Expression& base,
|
||||
std::vector<int> components) {
|
||||
SwizzleData result;
|
||||
result.fType = &base.type().componentType().toCompound(context, components.size(), 1);
|
||||
result.fComponents = std::move(components);
|
||||
return result;
|
||||
}
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
@ -32,27 +32,30 @@ public:
|
||||
};
|
||||
|
||||
Symbol(int offset, Kind kind, StringFragment name, const Type* type = nullptr)
|
||||
: INHERITED(offset, (int) kind)
|
||||
, fName(name)
|
||||
, fType(type) {
|
||||
: INHERITED(offset, (int) kind, SymbolData{name, type}) {
|
||||
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
|
||||
}
|
||||
|
||||
Symbol(int offset, const SymbolAliasData& data)
|
||||
: INHERITED(offset, (int) Kind::kSymbolAlias, data) {}
|
||||
|
||||
Symbol(int offset, const UnresolvedFunctionData& data)
|
||||
: INHERITED(offset, (int) Kind::kUnresolvedFunction, data) {}
|
||||
|
||||
Symbol& operator=(const Symbol&) = default;
|
||||
|
||||
~Symbol() override {}
|
||||
|
||||
const Type& type() const {
|
||||
SkASSERT(fType);
|
||||
return *fType;
|
||||
virtual const Type& type() const {
|
||||
return *this->symbolData().fType;
|
||||
}
|
||||
|
||||
Kind kind() const {
|
||||
return (Kind) fKind;
|
||||
}
|
||||
|
||||
StringFragment name() const {
|
||||
return fName;
|
||||
virtual StringFragment name() const {
|
||||
return this->symbolData().fName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,12 +83,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
StringFragment fName;
|
||||
const Type* fType;
|
||||
|
||||
using INHERITED = IRNode;
|
||||
|
||||
friend class Type;
|
||||
};
|
||||
|
||||
} // namespace SkSL
|
||||
|
@ -20,11 +20,14 @@ public:
|
||||
static constexpr Kind kSymbolKind = Kind::kSymbolAlias;
|
||||
|
||||
SymbolAlias(int offset, StringFragment name, const Symbol* origSymbol)
|
||||
: INHERITED(offset, kSymbolKind, name)
|
||||
, fOrigSymbol(origSymbol) {}
|
||||
: INHERITED(offset, SymbolAliasData{name, origSymbol}) {}
|
||||
|
||||
StringFragment name() const override {
|
||||
return this->symbolAliasData().fName;
|
||||
}
|
||||
|
||||
const Symbol* origSymbol() const {
|
||||
return fOrigSymbol;
|
||||
return this->symbolAliasData().fOrigSymbol;
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
@ -32,8 +35,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const Symbol* fOrigSymbol;
|
||||
|
||||
using INHERITED = Symbol;
|
||||
};
|
||||
|
||||
|
@ -22,35 +22,36 @@ public:
|
||||
|
||||
TernaryExpression(int offset, std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Expression> ifTrue, std::unique_ptr<Expression> ifFalse)
|
||||
: INHERITED(offset, kExpressionKind, &ifTrue->type())
|
||||
, fTest(std::move(test))
|
||||
, fIfTrue(std::move(ifTrue))
|
||||
, fIfFalse(std::move(ifFalse)) {
|
||||
SkASSERT(this->ifTrue()->type() == this->ifFalse()->type());
|
||||
: INHERITED(offset, kExpressionKind, &ifTrue->type()) {
|
||||
SkASSERT(ifTrue->type() == ifFalse->type());
|
||||
fExpressionChildren.reserve_back(3);
|
||||
fExpressionChildren.push_back(std::move(test));
|
||||
fExpressionChildren.push_back(std::move(ifTrue));
|
||||
fExpressionChildren.push_back(std::move(ifFalse));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& test() {
|
||||
return fTest;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& test() const {
|
||||
return fTest;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& ifTrue() {
|
||||
return fIfTrue;
|
||||
return fExpressionChildren[1];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& ifTrue() const {
|
||||
return fIfTrue;
|
||||
return fExpressionChildren[1];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& ifFalse() {
|
||||
return fIfFalse;
|
||||
return fExpressionChildren[2];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& ifFalse() const {
|
||||
return fIfFalse;
|
||||
return fExpressionChildren[2];
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -75,10 +76,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fTest;
|
||||
std::unique_ptr<Expression> fIfTrue;
|
||||
std::unique_ptr<Expression> fIfFalse;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -116,7 +116,7 @@ public:
|
||||
, fNameString(std::move(name))
|
||||
, fTypeKind(kind)
|
||||
, fNumberKind(NumberKind::kNonnumeric) {
|
||||
fName = StringFragment(fNameString.c_str(), fNameString.length());
|
||||
this->symbolData().fName = StringFragment(fNameString.c_str(), fNameString.length());
|
||||
}
|
||||
|
||||
// Create a generic type which maps to the listed types.
|
||||
@ -133,7 +133,7 @@ public:
|
||||
, fTypeKind(TypeKind::kStruct)
|
||||
, fNumberKind(NumberKind::kNonnumeric)
|
||||
, fFields(std::move(fields)) {
|
||||
fName = StringFragment(fNameString.c_str(), fNameString.length());
|
||||
this->symbolData().fName = StringFragment(fNameString.c_str(), fNameString.length());
|
||||
}
|
||||
|
||||
// Create a scalar type.
|
||||
@ -169,7 +169,7 @@ public:
|
||||
, fColumns(1)
|
||||
, fRows(1)
|
||||
, fDimensions(SpvDim1D) {
|
||||
fName = StringFragment(fNameString.c_str(), fNameString.length());
|
||||
this->symbolData().fName = StringFragment(fNameString.c_str(), fNameString.length());
|
||||
}
|
||||
|
||||
// Create a vector type.
|
||||
@ -189,7 +189,7 @@ public:
|
||||
, fRows(1)
|
||||
, fDimensions(SpvDim1D) {
|
||||
SkASSERT(fColumns > 0 || (fTypeKind == TypeKind::kArray && fColumns == kUnsizedArray));
|
||||
fName = StringFragment(fNameString.c_str(), fNameString.length());
|
||||
this->symbolData().fName = StringFragment(fNameString.c_str(), fNameString.length());
|
||||
}
|
||||
|
||||
// Create a matrix type.
|
||||
|
@ -22,11 +22,14 @@ public:
|
||||
static constexpr Kind kExpressionKind = Kind::kTypeReference;
|
||||
|
||||
TypeReference(const Context& context, int offset, const Type* value)
|
||||
: INHERITED(offset, kExpressionKind, context.fInvalid_Type.get())
|
||||
, fValue(*value) {}
|
||||
: INHERITED(offset, TypeReferenceData{context.fInvalid_Type.get(), value}) {}
|
||||
|
||||
const Type& type() const override {
|
||||
return *this->typeReferenceData().fType;
|
||||
}
|
||||
|
||||
const Type& value() const {
|
||||
return fValue;
|
||||
return *this->typeReferenceData().fValue;
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
@ -44,10 +47,7 @@ public:
|
||||
|
||||
private:
|
||||
TypeReference(int offset, const Type* value, const Type* type)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fValue(*value) {}
|
||||
|
||||
const Type& fValue;
|
||||
: INHERITED(offset, TypeReferenceData{type, value}) {}
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
@ -20,8 +20,7 @@ public:
|
||||
static constexpr Kind kSymbolKind = Kind::kUnresolvedFunction;
|
||||
|
||||
UnresolvedFunction(std::vector<const FunctionDeclaration*> funcs)
|
||||
: INHERITED(-1, kSymbolKind, funcs[0]->name())
|
||||
, fFunctions(std::move(funcs)) {
|
||||
: INHERITED(-1, UnresolvedFunctionData{std::move(funcs)}) {
|
||||
#ifdef SK_DEBUG
|
||||
SkASSERT(!this->functions().empty());
|
||||
for (auto func : this->functions()) {
|
||||
@ -30,8 +29,12 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
StringFragment name() const override {
|
||||
return this->functions()[0]->name();
|
||||
}
|
||||
|
||||
const std::vector<const FunctionDeclaration*>& functions() const {
|
||||
return fFunctions;
|
||||
return this->unresolvedFunctionData().fFunctions;
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
@ -39,8 +42,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<const FunctionDeclaration*> fFunctions;
|
||||
|
||||
using INHERITED = Symbol;
|
||||
};
|
||||
|
||||
|
@ -28,42 +28,47 @@ public:
|
||||
const Type* baseType,
|
||||
ExpressionArray sizes,
|
||||
std::unique_ptr<Expression> value)
|
||||
: INHERITED(var->fOffset, kStatementKind)
|
||||
, fVar(var)
|
||||
, fBaseType(*baseType)
|
||||
, fSizes(std::move(sizes))
|
||||
, fValue(std::move(value)) {}
|
||||
: INHERITED(var->fOffset, VarDeclarationData{baseType, var}) {
|
||||
fExpressionChildren.reserve_back(sizes.size() + 1);
|
||||
fExpressionChildren.move_back_n(sizes.size(), sizes.data());
|
||||
fExpressionChildren.push_back(std::move(value));
|
||||
}
|
||||
|
||||
const Type& baseType() const {
|
||||
return fBaseType;
|
||||
return *this->varDeclarationData().fBaseType;
|
||||
}
|
||||
|
||||
const Variable& var() const {
|
||||
return *fVar;
|
||||
return *this->varDeclarationData().fVar;
|
||||
}
|
||||
|
||||
void setVar(const Variable* var) {
|
||||
fVar = var;
|
||||
this->varDeclarationData().fVar = var;
|
||||
}
|
||||
|
||||
const ExpressionArray& sizes() const {
|
||||
return fSizes;
|
||||
int sizeCount() const {
|
||||
return fExpressionChildren.size() - 1;
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& size(int index) const {
|
||||
SkASSERT(index >= 0 && index < this->sizeCount());
|
||||
return fExpressionChildren[index];
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& value() {
|
||||
return fValue;
|
||||
return fExpressionChildren.back();
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& value() const {
|
||||
return fValue;
|
||||
return fExpressionChildren.back();
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
ExpressionArray sizesClone;
|
||||
sizesClone.reserve_back(this->sizes().count());
|
||||
for (const std::unique_ptr<Expression>& size : this->sizes()) {
|
||||
if (size) {
|
||||
sizesClone.push_back(size->clone());
|
||||
sizesClone.reserve_back(this->sizeCount());
|
||||
for (int i = 0; i < this->sizeCount(); ++i) {
|
||||
if (this->size(i)) {
|
||||
sizesClone.push_back(this->size(i)->clone());
|
||||
} else {
|
||||
sizesClone.push_back(nullptr);
|
||||
}
|
||||
@ -77,9 +82,9 @@ public:
|
||||
String description() const override {
|
||||
String result = this->var().modifiers().description() + this->baseType().description() +
|
||||
" " + this->var().name();
|
||||
for (const std::unique_ptr<Expression>& size : this->sizes()) {
|
||||
if (size) {
|
||||
result += "[" + size->description() + "]";
|
||||
for (int i = 0; i < this->sizeCount(); ++i) {
|
||||
if (this->size(i)) {
|
||||
result += "[" + this->size(i)->description() + "]";
|
||||
} else {
|
||||
result += "[]";
|
||||
}
|
||||
@ -91,12 +96,6 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
const Variable* fVar;
|
||||
const Type& fBaseType;
|
||||
ExpressionArray fSizes;
|
||||
std::unique_ptr<Expression> fValue;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
@ -109,17 +108,17 @@ public:
|
||||
static constexpr Kind kProgramElementKind = Kind::kGlobalVar;
|
||||
|
||||
GlobalVarDeclaration(int offset, std::unique_ptr<Statement> decl)
|
||||
: INHERITED(offset, kProgramElementKind)
|
||||
, fDeclaration(std::move(decl)) {
|
||||
SkASSERT(this->declaration()->is<VarDeclaration>());
|
||||
: INHERITED(offset, kProgramElementKind) {
|
||||
SkASSERT(decl->is<VarDeclaration>());
|
||||
fStatementChildren.push_back(std::move(decl));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& declaration() {
|
||||
return fDeclaration;
|
||||
return fStatementChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& declaration() const {
|
||||
return fDeclaration;
|
||||
return fStatementChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<ProgramElement> clone() const override {
|
||||
@ -131,8 +130,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Statement> fDeclaration;
|
||||
|
||||
using INHERITED = ProgramElement;
|
||||
};
|
||||
|
||||
|
@ -15,12 +15,14 @@
|
||||
namespace SkSL {
|
||||
|
||||
VariableReference::VariableReference(int offset, const Variable* variable, RefKind refKind)
|
||||
: INHERITED(offset, kExpressionKind, &variable->type())
|
||||
, fVariable(variable)
|
||||
, fRefKind(refKind) {
|
||||
: INHERITED(offset, VariableReferenceData{variable, refKind}) {
|
||||
SkASSERT(this->variable());
|
||||
}
|
||||
|
||||
const Type& VariableReference::type() const {
|
||||
return this->variableReferenceData().fVariable->type();
|
||||
}
|
||||
|
||||
bool VariableReference::hasProperty(Property property) const {
|
||||
switch (property) {
|
||||
case Property::kSideEffects: return false;
|
||||
@ -40,11 +42,11 @@ String VariableReference::description() const {
|
||||
}
|
||||
|
||||
void VariableReference::setRefKind(RefKind refKind) {
|
||||
fRefKind = refKind;
|
||||
this->variableReferenceData().fRefKind = refKind;
|
||||
}
|
||||
|
||||
void VariableReference::setVariable(const Variable* variable) {
|
||||
fVariable = variable;
|
||||
this->variableReferenceData().fVariable = variable;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerator& irGenerator,
|
||||
|
@ -42,12 +42,14 @@ public:
|
||||
VariableReference(const VariableReference&) = delete;
|
||||
VariableReference& operator=(const VariableReference&) = delete;
|
||||
|
||||
const Type& type() const override;
|
||||
|
||||
const Variable* variable() const {
|
||||
return fVariable;
|
||||
return this->variableReferenceData().fVariable;
|
||||
}
|
||||
|
||||
RefKind refKind() const {
|
||||
return fRefKind;
|
||||
return (RefKind) this->variableReferenceData().fRefKind;
|
||||
}
|
||||
|
||||
void setRefKind(RefKind refKind);
|
||||
@ -68,9 +70,6 @@ public:
|
||||
const DefinitionMap& definitions) override;
|
||||
|
||||
private:
|
||||
const Variable* fVariable;
|
||||
VariableRefKind fRefKind;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
@ -21,24 +21,25 @@ struct WhileStatement final : public Statement {
|
||||
|
||||
WhileStatement(int offset, std::unique_ptr<Expression> test,
|
||||
std::unique_ptr<Statement> statement)
|
||||
: INHERITED(offset, kStatementKind)
|
||||
, fTest(std::move(test))
|
||||
, fStatement(std::move(statement)) {}
|
||||
: INHERITED(offset, kStatementKind) {
|
||||
fExpressionChildren.push_back(std::move(test));
|
||||
fStatementChildren.push_back(std::move(statement));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& test() {
|
||||
return fTest;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Expression>& test() const {
|
||||
return fTest;
|
||||
return fExpressionChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement>& statement() {
|
||||
return fStatement;
|
||||
return fStatementChildren[0];
|
||||
}
|
||||
|
||||
const std::unique_ptr<Statement>& statement() const {
|
||||
return fStatement;
|
||||
return fStatementChildren[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
@ -50,10 +51,6 @@ struct WhileStatement final : public Statement {
|
||||
return "while (" + this->test()->description() + ") " + this->statement()->description();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fTest;
|
||||
std::unique_ptr<Statement> fStatement;
|
||||
|
||||
using INHERITED = Statement;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user