diff options
Diffstat (limited to 'gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.cpp')
-rw-r--r-- | gfx/skia/skia/src/sksl/ir/SkSLSymbolTable.cpp | 122 |
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 |