diff options
Diffstat (limited to 'gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.h')
-rw-r--r-- | gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.h | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.h b/gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.h new file mode 100644 index 0000000000..47f619c82a --- /dev/null +++ b/gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.h @@ -0,0 +1,214 @@ +/* + * 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_SYMBOLTABLE +#define SKSL_SYMBOLTABLE + +#include "include/core/SkTypes.h" +#include "include/private/SkOpts_spi.h" +#include "include/private/SkSLSymbol.h" +#include "src/core/SkTHash.h" + +#include <cstddef> +#include <cstdint> +#include <forward_list> +#include <memory> +#include <string> +#include <string_view> +#include <type_traits> +#include <utility> +#include <vector> + +namespace SkSL { + +class Type; + +/** + * Maps identifiers to symbols. + */ +class SymbolTable { +public: + explicit SymbolTable(bool builtin) + : fBuiltin(builtin) {} + + explicit SymbolTable(std::shared_ptr<SymbolTable> parent, bool builtin) + : fParent(parent) + , fBuiltin(builtin) {} + + /** Replaces the passed-in SymbolTable with a newly-created child symbol table. */ + static void Push(std::shared_ptr<SymbolTable>* table) { + Push(table, (*table)->isBuiltin()); + } + static void Push(std::shared_ptr<SymbolTable>* table, bool isBuiltin) { + *table = std::make_shared<SymbolTable>(*table, isBuiltin); + } + + /** + * Replaces the passed-in SymbolTable with its parent. If the child symbol table is otherwise + * unreferenced, it will be deleted. + */ + static void Pop(std::shared_ptr<SymbolTable>* table) { + *table = (*table)->fParent; + } + + /** + * If the input is a built-in symbol table, returns a new empty symbol table as a child of the + * input table. If the input is not a built-in symbol table, returns it as-is. Built-in symbol + * tables must not be mutated after creation, so they must be wrapped if mutation is necessary. + */ + static std::shared_ptr<SymbolTable> WrapIfBuiltin(std::shared_ptr<SymbolTable> symbolTable) { + if (!symbolTable) { + return nullptr; + } + if (!symbolTable->isBuiltin()) { + return symbolTable; + } + return std::make_shared<SymbolTable>(std::move(symbolTable), /*builtin=*/false); + } + + /** + * Looks up the requested symbol and returns a const pointer. + */ + const Symbol* find(std::string_view name) const { + return this->lookup(MakeSymbolKey(name)); + } + + /** + * Looks up the requested symbol, only searching the built-in symbol tables. Always const. + */ + const Symbol* findBuiltinSymbol(std::string_view name) const; + + /** + * Looks up the requested symbol and returns a mutable pointer. Use caution--mutating a symbol + * will have program-wide impact, and built-in symbol tables must never be mutated. + */ + Symbol* findMutable(std::string_view name) const { + return this->lookup(MakeSymbolKey(name)); + } + + /** + * Assigns a new name to the passed-in symbol. The old name will continue to exist in the symbol + * table and point to the symbol. + */ + void renameSymbol(Symbol* symbol, std::string_view newName); + + /** + * Returns true if the name refers to a type (user or built-in) in the current symbol table. + */ + bool isType(std::string_view name) const; + + /** + * Returns true if the name refers to a builtin type. + */ + bool isBuiltinType(std::string_view name) const; + + /** + * Adds a symbol to this symbol table, without conferring ownership. The caller is responsible + * for keeping the Symbol alive throughout the lifetime of the program/module. + */ + void addWithoutOwnership(Symbol* symbol); + + /** + * Adds a symbol to this symbol table, conferring ownership. + */ + template <typename T> + T* add(std::unique_ptr<T> symbol) { + T* ptr = symbol.get(); + this->addWithoutOwnership(this->takeOwnershipOfSymbol(std::move(symbol))); + return ptr; + } + + /** + * Forces a symbol into this symbol table, without conferring ownership. Replaces any existing + * symbol with the same name, if one exists. + */ + void injectWithoutOwnership(Symbol* symbol); + + /** + * Forces a symbol into this symbol table, conferring ownership. Replaces any existing symbol + * with the same name, if one exists. + */ + template <typename T> + T* inject(std::unique_ptr<T> symbol) { + T* ptr = symbol.get(); + this->injectWithoutOwnership(this->takeOwnershipOfSymbol(std::move(symbol))); + return ptr; + } + + /** + * Confers ownership of a symbol without adding its name to the lookup table. + */ + template <typename T> + T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) { + T* ptr = symbol.get(); + fOwnedSymbols.push_back(std::move(symbol)); + return ptr; + } + + /** + * Given type = `float` and arraySize = 5, creates the array type `float[5]` in the symbol + * table. The created array type is returned. If zero is passed, the base type is returned + * unchanged. + */ + const Type* addArrayDimension(const Type* type, int arraySize); + + // Call fn for every symbol in the table. You may not mutate anything. + template <typename Fn> + void foreach(Fn&& fn) const { + fSymbols.foreach( + [&fn](const SymbolKey& key, const Symbol* symbol) { fn(key.fName, symbol); }); + } + + size_t count() { + return fSymbols.count(); + } + + /** Returns true if this is a built-in SymbolTable. */ + bool isBuiltin() const { + return fBuiltin; + } + + const std::string* takeOwnershipOfString(std::string n); + + /** + * Indicates that this symbol table's parent is in a different module than this one. + */ + void markModuleBoundary() { + fAtModuleBoundary = true; + } + + std::shared_ptr<SymbolTable> fParent; + + std::vector<std::unique_ptr<const Symbol>> fOwnedSymbols; + +private: + struct SymbolKey { + std::string_view fName; + uint32_t fHash; + + bool operator==(const SymbolKey& that) const { return fName == that.fName; } + bool operator!=(const SymbolKey& that) const { return fName != that.fName; } + struct Hash { + uint32_t operator()(const SymbolKey& key) const { return key.fHash; } + }; + }; + + static SymbolKey MakeSymbolKey(std::string_view name) { + return SymbolKey{name, SkOpts::hash_fn(name.data(), name.size(), 0)}; + } + + Symbol* lookup(const SymbolKey& key) const; + + bool fBuiltin = false; + bool fAtModuleBoundary = false; + std::forward_list<std::string> fOwnedStrings; + SkTHashMap<SymbolKey, Symbol*, SymbolKey::Hash> fSymbols; +}; + +} // namespace SkSL + +#endif |