| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SKSL_IRNODE |
| #define SKSL_IRNODE |
| |
| #include "src/sksl/SkSLASTNode.h" |
| #include "src/sksl/SkSLLexer.h" |
| #include "src/sksl/SkSLString.h" |
| |
| #include <vector> |
| |
| namespace SkSL { |
| |
| struct Expression; |
| class Type; |
| |
| /** |
| * Represents a node in the intermediate representation (IR) tree. The IR is a fully-resolved |
| * version of the program (all types determined, everything validated), ready for code generation. |
| */ |
| class IRNode { |
| public: |
| 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; |
| |
| // character offset of this element within the program being compiled, for error reporting |
| // purposes |
| int fOffset; |
| |
| const Type& type() const { |
| switch (fData.fKind) { |
| case NodeData::Kind::kType: |
| return *this->typeData(); |
| case NodeData::Kind::kTypeToken: |
| return *this->typeTokenData().fType; |
| default: |
| SkUNREACHABLE; |
| } |
| } |
| |
| protected: |
| struct TypeTokenData { |
| const Type* fType; |
| Token::Kind fToken; |
| }; |
| |
| struct NodeData { |
| char fBytes[std::max(sizeof(Type*), |
| sizeof(TypeTokenData))]; |
| |
| enum class Kind { |
| kType, |
| kTypeToken, |
| } fKind; |
| |
| NodeData() = default; |
| |
| NodeData(const Type* data) |
| : fKind(Kind::kType) { |
| memcpy(fBytes, &data, sizeof(data)); |
| } |
| |
| NodeData(TypeTokenData data) |
| : fKind(Kind::kTypeToken) { |
| memcpy(fBytes, &data, sizeof(data)); |
| } |
| }; |
| |
| IRNode(int offset, int kind, const Type* data = nullptr); |
| |
| IRNode(int offset, int kind, TypeTokenData data); |
| |
| IRNode(const IRNode& other); |
| |
| Expression& expressionChild(int index) const { |
| return *fExpressionChildren[index]; |
| } |
| |
| std::unique_ptr<Expression>& expressionPointer(int index) { |
| return fExpressionChildren[index]; |
| } |
| |
| const std::unique_ptr<Expression>& expressionPointer(int index) const { |
| return fExpressionChildren[index]; |
| } |
| |
| Type* typeData() const { |
| SkASSERT(fData.fKind == NodeData::Kind::kType); |
| Type* result; |
| memcpy(&result, fData.fBytes, sizeof(result)); |
| return result; |
| } |
| |
| TypeTokenData typeTokenData() const { |
| SkASSERT(fData.fKind == NodeData::Kind::kTypeToken); |
| TypeTokenData result; |
| memcpy(&result, fData.fBytes, sizeof(result)); |
| return result; |
| } |
| |
| int fKind; |
| std::vector<std::unique_ptr<Expression>> fExpressionChildren; |
| |
| private: |
| NodeData fData; |
| }; |
| |
| } // namespace SkSL |
| |
| #endif |