SkSL enum changes

Changed a couple of SkSL enums to enum classes and rearranged things to
make their storage within IRNode type safe.

Change-Id: I6509d027d79161c1a09473e90943aae061583f20
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/324624
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2020-10-09 10:43:45 -04:00 committed by Skia Commit-Bot
parent e70a30d46f
commit 453f67ff0a
14 changed files with 93 additions and 82 deletions

View File

@ -193,9 +193,10 @@ public:
bool visitExpression(const Expression& e) override {
if (e.is<VariableReference>()) {
const VariableReference& ref = e.as<VariableReference>();
if (ref.variable() == fVar && (ref.refKind() == VariableReference::kWrite_RefKind ||
ref.refKind() == VariableReference::kReadWrite_RefKind ||
ref.refKind() == VariableReference::kPointer_RefKind)) {
if (ref.variable() == fVar &&
(ref.refKind() == VariableReference::RefKind::kWrite ||
ref.refKind() == VariableReference::RefKind::kReadWrite ||
ref.refKind() == VariableReference::RefKind::kPointer)) {
return true;
}
}

View File

@ -218,7 +218,7 @@ std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const Functio
static int expression_as_builtin(const Expression& e) {
if (e.is<VariableReference>()) {
const Variable& var(*e.as<VariableReference>().variable());
if (var.storage() == Variable::kGlobal_Storage) {
if (var.storage() == Variable::Storage::kGlobal) {
return var.modifiers().fLayout.fBuiltin;
}
}
@ -424,7 +424,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
// given that we seldom have more than a couple of variables, linear search is probably the most
// efficient way to handle lookups
switch (var.storage()) {
case Variable::kLocal_Storage: {
case Variable::Storage::kLocal: {
for (int i = fLocals.size() - 1; i >= 0; --i) {
if (fLocals[i] == &var) {
SkASSERT(fParameterCount + i <= 255);
@ -439,7 +439,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
SkASSERT(result <= 255);
return { result, Storage::kLocal };
}
case Variable::kParameter_Storage: {
case Variable::Storage::kParameter: {
int offset = 0;
for (const auto& p : fFunction->fDeclaration.parameters()) {
if (p == &var) {
@ -451,7 +451,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
SkASSERT(false);
return Location::MakeInvalid();
}
case Variable::kGlobal_Storage: {
case Variable::Storage::kGlobal: {
if (var.type() == *fContext.fFragmentProcessor_Type) {
int offset = 0;
for (const auto& e : fProgram.elements()) {

View File

@ -138,7 +138,7 @@ static bool is_private(const Variable& var) {
const Modifiers& modifiers = var.modifiers();
return !(modifiers.fFlags & Modifiers::kUniform_Flag) &&
!(modifiers.fFlags & Modifiers::kIn_Flag) &&
var.storage() == Variable::kGlobal_Storage &&
var.storage() == Variable::Storage::kGlobal &&
modifiers.fLayout.fBuiltin == -1;
}

View File

@ -207,8 +207,10 @@ Compiler::Compiler(Flags flags)
StringFragment skCapsName("sk_Caps");
fRootSymbolTable->add(std::make_unique<Variable>(/*offset=*/-1,
fIRGenerator->fModifiers->handle(Modifiers()),
skCapsName, fContext->fSkCaps_Type.get(),
/*builtin=*/false, Variable::kGlobal_Storage));
skCapsName,
fContext->fSkCaps_Type.get(),
/*builtin=*/false,
Variable::Storage::kGlobal));
fRootModule = {fRootSymbolTable, /*fIntrinsics=*/nullptr};
@ -350,7 +352,7 @@ void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expressio
switch (lvalue->kind()) {
case Expression::Kind::kVariableReference: {
const Variable& var = *lvalue->as<VariableReference>().variable();
if (var.storage() == Variable::kLocal_Storage) {
if (var.storage() == Variable::Storage::kLocal) {
definitions->set(&var, expr);
}
break;
@ -452,7 +454,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node, DefinitionMap* defin
}
case Expression::Kind::kVariableReference: {
const VariableReference* v = &expr->as<VariableReference>();
if (v->refKind() != VariableReference::kRead_RefKind) {
if (v->refKind() != VariableReference::RefKind::kRead) {
this->addDefinition(
v,
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
@ -785,7 +787,7 @@ static void vectorize_right(BasicBlock* b,
static void clear_write(Expression& expr) {
switch (expr.kind()) {
case Expression::Kind::kVariableReference: {
expr.as<VariableReference>().setRefKind(VariableReference::kRead_RefKind);
expr.as<VariableReference>().setRefKind(VariableReference::RefKind::kRead);
break;
}
case Expression::Kind::kFieldAccess:
@ -829,9 +831,9 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
case Expression::Kind::kVariableReference: {
const VariableReference& ref = expr->as<VariableReference>();
const Variable* var = ref.variable();
if (ref.refKind() != VariableReference::kWrite_RefKind &&
ref.refKind() != VariableReference::kPointer_RefKind &&
var->storage() == Variable::kLocal_Storage && !definitions[var] &&
if (ref.refKind() != VariableReference::RefKind::kWrite &&
ref.refKind() != VariableReference::RefKind::kPointer &&
var->storage() == Variable::Storage::kLocal && !definitions[var] &&
(*undefinedVariables).find(var) == (*undefinedVariables).end()) {
(*undefinedVariables).insert(var);
this->error(expr->fOffset,

View File

@ -220,7 +220,7 @@ void Dehydrator::write(const Symbol& s) {
this->write(v.modifiers());
this->write(v.name());
this->write(v.type());
this->writeU8(v.storage());
this->writeU8((int8_t) v.storage());
break;
}
case Symbol::Kind::kField: {
@ -379,7 +379,7 @@ void Dehydrator::write(const Expression* e) {
const VariableReference& v = e->as<VariableReference>();
this->writeCommand(Rehydrator::kVariableReference_Command);
this->writeId(v.variable());
this->writeU8(v.refKind());
this->writeU8((int8_t) v.refKind());
break;
}
case Expression::Kind::kFunctionReference:

View File

@ -296,7 +296,7 @@ std::unique_ptr<Block> IRGenerator::convertBlock(const ASTNode& block) {
std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(const ASTNode& s) {
SkASSERT(s.fKind == ASTNode::Kind::kVarDeclarations);
auto decls = this->convertVarDeclarations(s, Variable::kLocal_Storage);
auto decls = this->convertVarDeclarations(s, Variable::Storage::kLocal);
if (decls.empty()) {
return nullptr;
}
@ -320,7 +320,7 @@ std::vector<std::unique_ptr<Statement>> IRGenerator::convertVarDeclarations(
return {};
}
if (baseType->nonnullable() == *fContext.fFragmentProcessor_Type &&
storage != Variable::kGlobal_Storage) {
storage != Variable::Storage::kGlobal) {
fErrors.error(decls.fOffset,
"variables of type '" + baseType->displayName() + "' must be global");
}
@ -397,7 +397,7 @@ std::vector<std::unique_ptr<Statement>> IRGenerator::convertVarDeclarations(
}
}
int permitted = Modifiers::kConst_Flag;
if (storage == Variable::kGlobal_Storage) {
if (storage == Variable::Storage::kGlobal) {
permitted |= Modifiers::kIn_Flag | Modifiers::kOut_Flag | Modifiers::kUniform_Flag |
Modifiers::kFlat_Flag | Modifiers::kVarying_Flag |
Modifiers::kNoPerspective_Flag | Modifiers::kPLS_Flag |
@ -468,9 +468,9 @@ std::vector<std::unique_ptr<Statement>> IRGenerator::convertVarDeclarations(
var->setInitialValue(value.get());
}
Symbol* symbol = (*fSymbolTable)[var->name()];
if (symbol && storage == Variable::kGlobal_Storage && var->name() == "sk_FragColor") {
if (symbol && storage == Variable::Storage::kGlobal && var->name() == "sk_FragColor") {
// Already defined, ignore.
} else if (symbol && storage == Variable::kGlobal_Storage &&
} else if (symbol && storage == Variable::Storage::kGlobal &&
symbol->kind() == Symbol::Kind::kVariable &&
symbol->as<Variable>().modifiers().fLayout.fBuiltin >= 0) {
// Already defined, just update the modifiers.
@ -789,9 +789,9 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
fContext.fBool_Type.get()));
std::unique_ptr<Expression> next(new PostfixExpression(
std::unique_ptr<Expression>(
new VariableReference(-1,
loopIdx,
VariableReference::kReadWrite_RefKind)),
new VariableReference(-1,
loopIdx,
VariableReference::RefKind::kReadWrite)),
Token::Kind::TK_PLUSPLUS));
ASTNode endPrimitiveID(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier, "EndPrimitive");
std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
@ -809,7 +809,7 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
std::vector<std::unique_ptr<Expression>>()))));
std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
std::unique_ptr<Expression>(new VariableReference(-1, loopIdx,
VariableReference::kWrite_RefKind)),
VariableReference::RefKind::kWrite)),
Token::Kind::TK_EQ,
std::make_unique<IntLiteral>(fContext, -1, 0),
fContext.fInt_Type.get()));
@ -832,9 +832,9 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
// sk_Position.w);
SkASSERT(fSkPerVertex && fRTAdjust);
#define REF(var) std::unique_ptr<Expression>(\
new VariableReference(-1, var, VariableReference::kRead_RefKind))
new VariableReference(-1, var, VariableReference::RefKind::kRead))
#define WREF(var) std::unique_ptr<Expression>(\
new VariableReference(-1, var, VariableReference::kWrite_RefKind))
new VariableReference(-1, var, VariableReference::RefKind::kWrite))
#define FIELD(var, idx) std::unique_ptr<Expression>(\
new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
#define POS std::unique_ptr<Expression>(new FieldAccess(WREF(fSkPerVertex), 0, \
@ -964,7 +964,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
Variable* var = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Variable>(param.fOffset, fModifiers->handle(pd.fModifiers),
name, type, fIsBuiltinCode,
Variable::kParameter_Storage));
Variable::Storage::kParameter));
parameters.push_back(var);
}
@ -1137,7 +1137,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
auto iter = intf.begin();
for (size_t i = 0; i < id.fDeclarationCount; ++i) {
std::vector<std::unique_ptr<Statement>> decls =
this->convertVarDeclarations(*(iter++), Variable::kInterfaceBlock_Storage);
this->convertVarDeclarations(*(iter++), Variable::Storage::kInterfaceBlock);
if (decls.empty()) {
return nullptr;
}
@ -1205,7 +1205,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
type,
fIsBuiltinCode,
Variable::kGlobal_Storage));
Variable::Storage::kGlobal));
if (foundRTAdjust) {
fRTAdjustInterfaceBlock = var;
}
@ -1274,7 +1274,7 @@ void IRGenerator::convertEnum(const ASTNode& e) {
++currentValue;
fSymbolTable->add(std::make_unique<Variable>(e.fOffset, fModifiers->handle(modifiers),
child.getString(), type, fIsBuiltinCode,
Variable::kGlobal_Storage, value.get()));
Variable::Storage::kGlobal, value.get()));
fSymbolTable->takeOwnershipOfIRNode(std::move(value));
}
// Now we orphanize the Enum's symbol table, so that future lookups in it are strict
@ -1431,12 +1431,12 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
// default to kRead_RefKind; this will be corrected later if the variable is written to
return std::make_unique<VariableReference>(identifier.fOffset,
var,
VariableReference::kRead_RefKind);
VariableReference::RefKind::kRead);
}
case Symbol::Kind::kField: {
const Field* field = &result->as<Field>();
auto base = std::make_unique<VariableReference>(identifier.fOffset, &field->owner(),
VariableReference::kRead_RefKind);
VariableReference::RefKind::kRead);
return std::make_unique<FieldAccess>(std::move(base),
field->fieldIndex(),
FieldAccess::kAnonymousInterfaceBlock_OwnerKind);
@ -1967,8 +1967,8 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode&
}
if (Compiler::IsAssignment(op)) {
if (!this->setRefKind(*left, op != Token::Kind::TK_EQ
? VariableReference::kReadWrite_RefKind
: VariableReference::kWrite_RefKind)) {
? VariableReference::RefKind::kReadWrite
: VariableReference::RefKind::kWrite)) {
return nullptr;
}
}
@ -2122,8 +2122,8 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
const Modifiers& paramModifiers = function.parameters()[i]->modifiers();
if (paramModifiers.fFlags & Modifiers::kOut_Flag) {
if (!this->setRefKind(*arguments[i], paramModifiers.fFlags & Modifiers::kIn_Flag
? VariableReference::kReadWrite_RefKind
: VariableReference::kPointer_RefKind)) {
? VariableReference::RefKind::kReadWrite
: VariableReference::RefKind::kPointer)) {
return nullptr;
}
}
@ -2407,7 +2407,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
if (!this->setRefKind(*base, VariableReference::kReadWrite_RefKind)) {
if (!this->setRefKind(*base, VariableReference::RefKind::kReadWrite)) {
return nullptr;
}
break;
@ -2418,7 +2418,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
if (!this->setRefKind(*base, VariableReference::kReadWrite_RefKind)) {
if (!this->setRefKind(*base, VariableReference::RefKind::kReadWrite)) {
return nullptr;
}
break;
@ -2832,7 +2832,7 @@ std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode&
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
if (!this->setRefKind(*base, VariableReference::kReadWrite_RefKind)) {
if (!this->setRefKind(*base, VariableReference::RefKind::kReadWrite)) {
return nullptr;
}
return std::make_unique<PostfixExpression>(std::move(base), expression.getToken().fKind);
@ -2975,7 +2975,7 @@ void IRGenerator::convertProgram(Program::Kind kind,
switch (decl.fKind) {
case ASTNode::Kind::kVarDeclarations: {
std::vector<std::unique_ptr<Statement>> decls =
this->convertVarDeclarations(decl, Variable::kGlobal_Storage);
this->convertVarDeclarations(decl, Variable::Storage::kGlobal);
for (auto& varDecl : decls) {
fProgramElements->push_back(std::make_unique<GlobalVarDeclaration>(
decl.fOffset, std::move(varDecl)));

View File

@ -503,7 +503,8 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
auto assignment =
std::make_unique<ExpressionStatement>(std::make_unique<BinaryExpression>(
offset,
clone_with_ref_kind(*resultExpr, VariableReference::kWrite_RefKind),
clone_with_ref_kind(*resultExpr,
VariableReference::RefKind::kWrite),
Token::Kind::TK_EQ,
expr(r.expression()),
&resultExpr->type()));
@ -633,7 +634,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
const Variable* variableSymbol = symbolTableForCall->add(std::make_unique<Variable>(
/*offset=*/-1, fModifiers->handle(Modifiers()),
nameFrag, type, caller->isBuiltin(),
Variable::kLocal_Storage, initialValue->get()));
Variable::Storage::kLocal, initialValue->get()));
// Prepare the variable declaration (taking extra care with `out` params to not clobber any
// initial value).
@ -719,7 +720,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
inlinedBody.children().push_back(
std::make_unique<ExpressionStatement>(std::make_unique<BinaryExpression>(
offset,
clone_with_ref_kind(*arguments[i], VariableReference::kWrite_RefKind),
clone_with_ref_kind(*arguments[i], VariableReference::RefKind::kWrite),
Token::Kind::TK_EQ,
std::move(varMap[p]),
&arguments[i]->type())));
@ -727,7 +728,8 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
if (resultExpr != nullptr) {
// Return our result variable as our replacement expression.
SkASSERT(resultExpr->as<VariableReference>().refKind() == VariableReference::kRead_RefKind);
SkASSERT(resultExpr->as<VariableReference>().refKind() ==
VariableReference::RefKind::kRead);
inlinedCall.fReplacementExpr = std::move(resultExpr);
} else {
// It's a void function, so it doesn't actually result in anything, but we have to return

View File

@ -702,7 +702,7 @@ void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) {
break;
default:
const Variable& var = *ref.variable();
if (var.storage() == Variable::kGlobal_Storage) {
if (var.storage() == Variable::Storage::kGlobal) {
if (var.modifiers().fFlags & Modifiers::kIn_Flag) {
this->write("_in.");
} else if (var.modifiers().fFlags & Modifiers::kOut_Flag) {
@ -839,7 +839,7 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
this->write("(");
}
if (Compiler::IsAssignment(op) && left.is<VariableReference>() &&
left.as<VariableReference>().variable()->storage() == Variable::kParameter_Storage &&
left.as<VariableReference>().variable()->storage() == Variable::Storage::kParameter &&
left.as<VariableReference>().variable()->modifiers().fFlags & Modifiers::kOut_Flag) {
// writing to an out parameter. Since we have to turn those into pointers, we have to
// dereference it here.
@ -1723,7 +1723,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
Requirements result = kNo_Requirements;
if (modifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
result = kGlobals_Requirement | kFragCoord_Requirement;
} else if (Variable::kGlobal_Storage == v.variable()->storage()) {
} else if (Variable::Storage::kGlobal == v.variable()->storage()) {
if (modifiers.fFlags & Modifiers::kIn_Flag) {
result = kInputs_Requirement;
} else if (modifiers.fFlags & Modifiers::kOut_Flag) {

View File

@ -1565,7 +1565,7 @@ SpvStorageClass_ get_storage_class(const Expression& expr) {
switch (expr.kind()) {
case Expression::Kind::kVariableReference: {
const Variable& var = *expr.as<VariableReference>().variable();
if (var.storage() != Variable::kGlobal_Storage) {
if (var.storage() != Variable::Storage::kGlobal) {
return SpvStorageClassFunction;
}
SpvStorageClass_ result = get_storage_class(var.modifiers());
@ -1883,7 +1883,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
name,
&intfStruct,
/*builtin=*/false,
Variable::kGlobal_Storage));
Variable::Storage::kGlobal));
InterfaceBlock intf(-1, intfVar, name, String(""),
std::vector<std::unique_ptr<Expression>>(), st);
@ -3232,7 +3232,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
}
for (auto entry : fVariableMap) {
const Variable* var = entry.first;
if (var->storage() == Variable::kGlobal_Storage &&
if (var->storage() == Variable::Storage::kGlobal &&
((var->modifiers().fFlags & Modifiers::kIn_Flag) ||
(var->modifiers().fFlags & Modifiers::kOut_Flag)) && !is_dead(*var)) {
interfaceVars.insert(entry.second);

View File

@ -35,8 +35,8 @@ static inline bool check_ref(const Expression& expr) {
}
case Expression::Kind::kVariableReference: {
const VariableReference& ref = expr.as<VariableReference>();
return ref.refKind() == VariableReference::kWrite_RefKind ||
ref.refKind() == VariableReference::kReadWrite_RefKind;
return ref.refKind() == VariableReference::RefKind::kWrite ||
ref.refKind() == VariableReference::RefKind::kReadWrite;
}
default:
return false;

View File

@ -29,6 +29,8 @@ class SymbolTable;
class Type;
class Variable;
class VariableReference;
enum class VariableRefKind : int8_t;
enum class VariableStorage : int8_t;
/**
* Represents a node in the intermediate representation (IR) tree. The IR is a fully-resolved
@ -165,13 +167,13 @@ protected:
// Tracks how many sites write to the variable. If this is zero, the variable is dead and
// may be eliminated.
mutable int16_t fWriteCount;
/*Variable::Storage*/int8_t fStorage;
VariableStorage fStorage;
bool fBuiltin;
};
struct VariableReferenceData {
const Variable* fVariable;
/*VariableReference::RefKind*/int8_t fRefKind;
VariableRefKind fRefKind;
};
struct NodeData {

View File

@ -18,6 +18,13 @@ namespace SkSL {
class Expression;
enum class VariableStorage : int8_t {
kGlobal,
kInterfaceBlock,
kLocal,
kParameter
};
/**
* Represents a variable, whether local, global, or a function parameter. This represents the
* variable itself (the storage location), which is shared between all VariableReferences which
@ -25,20 +32,15 @@ class Expression;
*/
class Variable : public Symbol {
public:
static constexpr Kind kSymbolKind = Kind::kVariable;
using Storage = VariableStorage;
enum Storage {
kGlobal_Storage,
kInterfaceBlock_Storage,
kLocal_Storage,
kParameter_Storage
};
static constexpr Kind kSymbolKind = Kind::kVariable;
Variable(int offset, ModifiersPool::Handle modifiers, StringFragment name, const Type* type,
bool builtin, Storage storage, const Expression* initialValue = nullptr)
: INHERITED(offset, VariableData{name, type, initialValue, modifiers, /*readCount=*/0,
/*writeCount=*/(int16_t) (initialValue ? 1 : 0),
(int8_t) storage, builtin}) {}
storage, builtin}) {}
~Variable() override {
// can't destroy a variable while there are remaining references to it
@ -102,7 +104,7 @@ public:
bool dead() const {
const VariableData& data = this->variableData();
const Modifiers& modifiers = this->modifiers();
if ((data.fStorage != kLocal_Storage && this->variableData().fReadCount) ||
if ((data.fStorage != Storage::kLocal && this->variableData().fReadCount) ||
(modifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag |
Modifiers::kUniform_Flag | Modifiers::kVarying_Flag))) {
return false;
@ -114,19 +116,19 @@ public:
private:
void referenceCreated(VariableReference::RefKind refKind) const {
if (refKind != VariableReference::kRead_RefKind) {
if (refKind != VariableReference::RefKind::kRead) {
++this->variableData().fWriteCount;
}
if (refKind != VariableReference::kWrite_RefKind) {
if (refKind != VariableReference::RefKind::kWrite) {
++this->variableData().fReadCount;
}
}
void referenceDestroyed(VariableReference::RefKind refKind) const {
if (refKind != VariableReference::kRead_RefKind) {
if (refKind != VariableReference::RefKind::kRead) {
--this->variableData().fWriteCount;
}
if (refKind != VariableReference::kWrite_RefKind) {
if (refKind != VariableReference::RefKind::kWrite) {
--this->variableData().fReadCount;
}
}

View File

@ -15,7 +15,7 @@
namespace SkSL {
VariableReference::VariableReference(int offset, const Variable* variable, RefKind refKind)
: INHERITED(offset, VariableReferenceData{variable, (int8_t)refKind}) {
: INHERITED(offset, VariableReferenceData{variable, refKind}) {
SkASSERT(this->variable());
this->variable()->referenceCreated(refKind);
}
@ -60,7 +60,7 @@ void VariableReference::setVariable(const Variable* variable) {
std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) {
if (this->refKind() != kRead_RefKind) {
if (this->refKind() != RefKind::kRead) {
return nullptr;
}
const Expression* initialValue = this->variable()->initialValue();

View File

@ -15,6 +15,15 @@ namespace SkSL {
class IRGenerator;
class Variable;
enum class VariableRefKind : int8_t {
kRead,
kWrite,
kReadWrite,
// taking the address of a variable - we consider this a read & write but don't complain if
// the variable was not previously assigned
kPointer
};
/**
* A reference to a variable, through which it can be read or written. In the statement:
*
@ -24,18 +33,11 @@ class Variable;
*/
class VariableReference : public Expression {
public:
using RefKind = VariableRefKind;
static constexpr Kind kExpressionKind = Kind::kVariableReference;
enum RefKind {
kRead_RefKind,
kWrite_RefKind,
kReadWrite_RefKind,
// taking the address of a variable - we consider this a read & write but don't complain if
// the variable was not previously assigned
kPointer_RefKind
};
VariableReference(int offset, const Variable* variable, RefKind refKind = kRead_RefKind);
VariableReference(int offset, const Variable* variable, RefKind refKind = RefKind::kRead);
~VariableReference() override;