summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.cpp')
-rw-r--r--gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.cpp b/gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.cpp
new file mode 100644
index 0000000000..e8771c9560
--- /dev/null
+++ b/gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/sksl/ir/SkSLSymbolTable.h"
+
+#include "src/sksl/SkSLThreadContext.h"
+#include "src/sksl/ir/SkSLFunctionDeclaration.h"
+#include "src/sksl/ir/SkSLType.h"
+
+namespace SkSL {
+
+bool SymbolTable::isType(std::string_view name) const {
+ const Symbol* symbol = this->find(name);
+ return symbol && symbol->is<Type>();
+}
+
+bool SymbolTable::isBuiltinType(std::string_view name) const {
+ if (!this->isBuiltin()) {
+ return fParent && fParent->isBuiltinType(name);
+ }
+ return this->isType(name);
+}
+
+const Symbol* SymbolTable::findBuiltinSymbol(std::string_view name) const {
+ if (!this->isBuiltin()) {
+ return fParent ? fParent->findBuiltinSymbol(name) : nullptr;
+ }
+ return this->find(name);
+}
+
+Symbol* SymbolTable::lookup(const SymbolKey& key) const {
+ Symbol** symbolPPtr = fSymbols.find(key);
+ if (symbolPPtr) {
+ return *symbolPPtr;
+ }
+
+ // The symbol wasn't found; recurse into the parent symbol table.
+ return fParent ? fParent->lookup(key) : nullptr;
+}
+
+void SymbolTable::renameSymbol(Symbol* symbol, std::string_view newName) {
+ if (symbol->is<FunctionDeclaration>()) {
+ // This is a function declaration, so we need to rename the entire overload set.
+ for (FunctionDeclaration* fn = &symbol->as<FunctionDeclaration>(); fn != nullptr;
+ fn = fn->mutableNextOverload()) {
+ fn->setName(newName);
+ }
+ } else {
+ // Other types of symbols don't allow multiple symbols with the same name.
+ symbol->setName(newName);
+ }
+
+ this->addWithoutOwnership(symbol);
+}
+
+const std::string* SymbolTable::takeOwnershipOfString(std::string str) {
+ fOwnedStrings.push_front(std::move(str));
+ // Because fOwnedStrings is a linked list, pointers to elements are stable.
+ return &fOwnedStrings.front();
+}
+
+void SymbolTable::addWithoutOwnership(Symbol* symbol) {
+ auto key = MakeSymbolKey(symbol->name());
+
+ // If this is a function declaration, we need to keep the overload chain in sync.
+ if (symbol->is<FunctionDeclaration>()) {
+ // If we have a function with the same name...
+ Symbol* existingSymbol = this->lookup(key);
+ if (existingSymbol && existingSymbol->is<FunctionDeclaration>()) {
+ // ... add the existing function as the next overload in the chain.
+ FunctionDeclaration* existingDecl = &existingSymbol->as<FunctionDeclaration>();
+ symbol->as<FunctionDeclaration>().setNextOverload(existingDecl);
+ fSymbols[key] = symbol;
+ return;
+ }
+ }
+
+ if (fAtModuleBoundary && fParent && fParent->lookup(key)) {
+ // We are attempting to declare a symbol at global scope that already exists in a parent
+ // module. This is a duplicate symbol and should be rejected.
+ } else {
+ Symbol*& refInSymbolTable = fSymbols[key];
+
+ if (refInSymbolTable == nullptr) {
+ refInSymbolTable = symbol;
+ return;
+ }
+ }
+
+ ThreadContext::ReportError("symbol '" + std::string(symbol->name()) + "' was already defined",
+ symbol->fPosition);
+}
+
+void SymbolTable::injectWithoutOwnership(Symbol* symbol) {
+ auto key = MakeSymbolKey(symbol->name());
+ fSymbols[key] = symbol;
+}
+
+const Type* SymbolTable::addArrayDimension(const Type* type, int arraySize) {
+ if (arraySize == 0) {
+ return type;
+ }
+ // If this is a builtin type, we add it as high as possible in the symbol table tree (at the
+ // module boundary), to enable additional reuse of the array-type.
+ if (type->isInBuiltinTypes() && fParent && !fAtModuleBoundary) {
+ return fParent->addArrayDimension(type, arraySize);
+ }
+ // Reuse an existing array type with this name if one already exists in our symbol table.
+ std::string arrayName = type->getArrayName(arraySize);
+ if (const Symbol* existingType = this->find(arrayName)) {
+ return &existingType->as<Type>();
+ }
+ // Add a new array type to the symbol table.
+ const std::string* arrayNamePtr = this->takeOwnershipOfString(std::move(arrayName));
+ return this->add(Type::MakeArrayType(*arrayNamePtr, *type, arraySize));
+}
+
+} // namespace SkSL