| /* |
| * Copyright 2020 Google LLC. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SKSL_REHYDRATOR |
| #define SKSL_REHYDRATOR |
| |
| #include "src/sksl/SkSLDefines.h" |
| |
| #include "src/sksl/ir/SkSLModifiers.h" |
| #include "src/sksl/ir/SkSLSymbol.h" |
| |
| #include <vector> |
| |
| namespace SkSL { |
| |
| class Context; |
| class ErrorReporter; |
| struct Expression; |
| struct ProgramElement; |
| struct Statement; |
| class SymbolTable; |
| class Type; |
| |
| union FloatIntUnion { |
| float fFloat; |
| int32_t fInt; |
| }; |
| |
| /** |
| * Interprets a simple bytecode format that encodes the structure of an SkSL IR tree. This is used |
| * to process the .sksl files representing SkSL's core include files, so that they can be quickly |
| * reconstituted at runtime. |
| */ |
| class Rehydrator { |
| public: |
| enum Command { |
| // uint16 id, Type componentType, uint8 count |
| kArrayType_Command, |
| // Expression left, uint8 op, Expression right, Type type |
| kBinary_Command, |
| // SymbolTable symbolTable, uint8 statementCount, Statement[] statements, bool isScope |
| kBlock_Command, |
| // bool value |
| kBoolLiteral_Command, |
| kBreak_Command, |
| // int16 builtin |
| kBuiltinLayout_Command, |
| // Type type, uint8 argCount, Expression[] arguments |
| kConstructor_Command, |
| kContinue_Command, |
| kDefaultLayout_Command, |
| kDefaultModifiers_Command, |
| kDiscard_Command, |
| // Statement stmt, Expression test |
| kDo_Command, |
| // uint8 count, uint8 index |
| kElements_Command, |
| // String typeName, SymbolTable symbols, int32[] values |
| kEnum_Command, |
| // uint16 id, String name |
| kEnumType_Command, |
| // Expression expression |
| kExpressionStatement_Command, |
| // uint16 ownerId, uint8 index |
| kField_Command, |
| // Expression base, uint8 index, uint8 ownerKind |
| kFieldAccess_Command, |
| // float value |
| kFloatLiteral_Command, |
| // Statement initializer, Expression test, Expression next, Statement body, |
| // SymbolTable symbols |
| kFor_Command, |
| // Type type, uint16 function, uint8 argCount, Expression[] arguments |
| kFunctionCall_Command, |
| // uint16 declaration, Statement body, uint8 refCount, uint16[] referencedIntrinsics |
| kFunctionDefinition_Command, |
| // uint16 id, Modifiers modifiers, String name, uint8 parameterCount, uint16[] parameterIds, |
| // Type returnType |
| kFunctionDeclaration_Command, |
| // bool isStatic, Expression test, Statement ifTrue, Statement ifFalse |
| kIf_Command, |
| // Expression base, Expression index |
| kIndex_Command, |
| // FunctionDeclaration function |
| kInlineMarker_Command, |
| // Variable* var, String typeName, String instanceName, uint8 sizeCount, Expression[] sizes |
| kInterfaceBlock_Command, |
| // int32 value |
| kIntLiteral_Command, |
| // int32 flags, int8 location, int8 offset, int8 binding, int8 index, int8 set, |
| // int16 builtin, int8 inputAttachmentIndex, int8 format, int8 primitive, int8 maxVertices, |
| // int8 invocations, String marker, String when, int8 key, int8 ctype |
| kLayout_Command, |
| // Layout layout, uint8 flags |
| kModifiers8Bit_Command, |
| // Layout layout, uint32 flags |
| kModifiers_Command, |
| // uint16 id, Type baseType |
| kNullableType_Command, |
| kNullLiteral_Command, |
| // uint8 op, Expression operand |
| kPostfix_Command, |
| // uint8 op, Expression operand |
| kPrefix_Command, |
| // Expression value |
| kReturn_Command, |
| // String name, Expression value |
| kSetting_Command, |
| // uint16 id, String name, uint8 fieldCount, (Modifiers, String, Type)[] fields |
| kStructType_Command, |
| // bool isStatic, SymbolTable symbols, Expression value, uint8 caseCount, |
| // (Expression value, uint8 statementCount, Statement[] statements)[] cases |
| kSwitch_Command, |
| // Expression base, uint8 componentCount, uint8[] components |
| kSwizzle_Command, |
| // uint16 id |
| kSymbolRef_Command, |
| // uint16 owned symbol count, Symbol[] ownedSymbols, uint16 symbol count, |
| // (String, uint16/*index*/)[]. |
| kSymbolTable_Command, |
| // uint16 id, String name |
| kSystemType_Command, |
| // Expression test, Expression ifTrue, Expression ifFalse |
| kTernary_Command, |
| // uint16 id, FunctionDeclaration[] functions |
| kUnresolvedFunction_Command, |
| // uint16 id, Modifiers modifiers, String name, Type type, uint8 storage |
| kVariable_Command, |
| // uint16 varId, uint8 sizeCount, Expression[] sizes, Expression? value |
| kVarDeclaration_Command, |
| // Type baseType, uint8 varCount, VarDeclaration vars |
| kVarDeclarations_Command, |
| // uint16 varId, uint8 refKind |
| kVariableReference_Command, |
| kVoid_Command, |
| // Expression test, Statement body |
| kWhile_Command, |
| }; |
| |
| // src must remain in memory as long as the objects created from it do |
| Rehydrator(Context* context, std::shared_ptr<SymbolTable> symbolTable, |
| ErrorReporter* errorReporter, const uint8_t* src, size_t length) |
| : fContext(*context) |
| , fErrors(errorReporter) |
| , fSymbolTable(std::move(symbolTable)) |
| , fStart(src) |
| SkDEBUGCODE(, fEnd(fStart + length)) { |
| SkASSERT(fSymbolTable); |
| // skip past string data |
| fIP = fStart; |
| fIP += this->readU16(); |
| } |
| |
| std::vector<std::unique_ptr<ProgramElement>> elements(); |
| |
| std::shared_ptr<SymbolTable> symbolTable(bool inherit = true); |
| |
| private: |
| int8_t readS8() { |
| SkASSERT(fIP < fEnd); |
| return *(fIP++); |
| } |
| |
| uint8_t readU8() { |
| return this->readS8(); |
| } |
| |
| int16_t readS16() { |
| uint8_t b1 = this->readU8(); |
| uint8_t b2 = this->readU8(); |
| return (b2 << 8) + b1; |
| } |
| |
| uint16_t readU16() { |
| return this->readS16(); |
| } |
| |
| int32_t readS32() { |
| uint8_t b1 = this->readU8(); |
| uint8_t b2 = this->readU8(); |
| uint8_t b3 = this->readU8(); |
| uint8_t b4 = this->readU8(); |
| return (b4 << 24) + (b3 << 16) + (b2 << 8) + b1; |
| } |
| |
| uint32_t readU32() { |
| return this->readS32(); |
| } |
| |
| StringFragment readString() { |
| uint16_t offset = this->readU16(); |
| uint8_t length = *(uint8_t*) (fStart + offset); |
| const char* chars = (const char*) fStart + offset + 1; |
| return StringFragment(chars, length); |
| } |
| |
| void addSymbol(int id, const Symbol* symbol) { |
| while ((size_t) id >= fSymbols.size()) { |
| fSymbols.push_back(nullptr); |
| } |
| fSymbols[id] = symbol; |
| } |
| |
| template<typename T> |
| T* symbolRef(Symbol::Kind kind) { |
| uint16_t result = this->readU16(); |
| SkASSERT(fSymbols.size() > result); |
| return (T*) fSymbols[result]; |
| } |
| |
| Layout layout(); |
| |
| Modifiers modifiers(); |
| |
| const Symbol* symbol(); |
| |
| std::unique_ptr<ProgramElement> element(); |
| |
| std::unique_ptr<Statement> statement(); |
| |
| std::unique_ptr<Expression> expression(); |
| |
| const Type* type(); |
| |
| Context& fContext; |
| ErrorReporter* fErrors; |
| std::shared_ptr<SymbolTable> fSymbolTable; |
| std::vector<const Symbol*> fSymbols; |
| |
| const uint8_t* fStart; |
| const uint8_t* fIP; |
| SkDEBUGCODE(const uint8_t* fEnd;) |
| |
| friend class AutoRehydratorSymbolTable; |
| }; |
| |
| } // namespace SkSL |
| |
| #endif |