1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSymbolTable.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/sksl/SkSLContext.h" 11cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSymbolAlias.h" 12cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLType.h" 13cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLUnresolvedFunction.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_cinamespace SkSL { 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_cistd::vector<const FunctionDeclaration*> SymbolTable::GetFunctions(const Symbol& s) { 18cb93a386Sopenharmony_ci switch (s.kind()) { 19cb93a386Sopenharmony_ci case Symbol::Kind::kFunctionDeclaration: 20cb93a386Sopenharmony_ci return { &s.as<FunctionDeclaration>() }; 21cb93a386Sopenharmony_ci case Symbol::Kind::kUnresolvedFunction: 22cb93a386Sopenharmony_ci return s.as<UnresolvedFunction>().functions(); 23cb93a386Sopenharmony_ci default: 24cb93a386Sopenharmony_ci return std::vector<const FunctionDeclaration*>(); 25cb93a386Sopenharmony_ci } 26cb93a386Sopenharmony_ci} 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ciconst Symbol* SymbolTable::operator[](skstd::string_view name) { 29cb93a386Sopenharmony_ci return this->lookup(fBuiltin ? nullptr : this, MakeSymbolKey(name)); 30cb93a386Sopenharmony_ci} 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ciconst Symbol* SymbolTable::lookup(SymbolTable* writableSymbolTable, const SymbolKey& key) { 33cb93a386Sopenharmony_ci // Symbol-table lookup can cause new UnresolvedFunction nodes to be created; however, we don't 34cb93a386Sopenharmony_ci // want these to end up in built-in root symbol tables (where they will outlive the Program 35cb93a386Sopenharmony_ci // associated with those UnresolvedFunction nodes). `writableSymbolTable` tracks the closest 36cb93a386Sopenharmony_ci // symbol table to the root which is not a built-in. 37cb93a386Sopenharmony_ci if (!fBuiltin) { 38cb93a386Sopenharmony_ci writableSymbolTable = this; 39cb93a386Sopenharmony_ci } 40cb93a386Sopenharmony_ci const Symbol** symbolPPtr = fSymbols.find(key); 41cb93a386Sopenharmony_ci if (!symbolPPtr) { 42cb93a386Sopenharmony_ci if (fParent) { 43cb93a386Sopenharmony_ci return fParent->lookup(writableSymbolTable, key); 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci return nullptr; 46cb93a386Sopenharmony_ci } 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci const Symbol* symbol = *symbolPPtr; 49cb93a386Sopenharmony_ci if (fParent) { 50cb93a386Sopenharmony_ci auto functions = GetFunctions(*symbol); 51cb93a386Sopenharmony_ci if (functions.size() > 0) { 52cb93a386Sopenharmony_ci bool modified = false; 53cb93a386Sopenharmony_ci const Symbol* previous = fParent->lookup(writableSymbolTable, key); 54cb93a386Sopenharmony_ci if (previous) { 55cb93a386Sopenharmony_ci auto previousFunctions = GetFunctions(*previous); 56cb93a386Sopenharmony_ci for (const FunctionDeclaration* prev : previousFunctions) { 57cb93a386Sopenharmony_ci bool found = false; 58cb93a386Sopenharmony_ci for (const FunctionDeclaration* current : functions) { 59cb93a386Sopenharmony_ci if (current->matches(*prev)) { 60cb93a386Sopenharmony_ci found = true; 61cb93a386Sopenharmony_ci break; 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci if (!found) { 65cb93a386Sopenharmony_ci functions.push_back(prev); 66cb93a386Sopenharmony_ci modified = true; 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci if (modified) { 70cb93a386Sopenharmony_ci SkASSERT(functions.size() > 1); 71cb93a386Sopenharmony_ci return writableSymbolTable 72cb93a386Sopenharmony_ci ? writableSymbolTable->takeOwnershipOfSymbol( 73cb93a386Sopenharmony_ci std::make_unique<UnresolvedFunction>(functions)) 74cb93a386Sopenharmony_ci : nullptr; 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci while (symbol && symbol->is<SymbolAlias>()) { 80cb93a386Sopenharmony_ci symbol = symbol->as<SymbolAlias>().origSymbol(); 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci return symbol; 83cb93a386Sopenharmony_ci} 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ciconst String* SymbolTable::takeOwnershipOfString(String str) { 86cb93a386Sopenharmony_ci fOwnedStrings.push_front(std::move(str)); 87cb93a386Sopenharmony_ci // Because fOwnedStrings is a linked list, pointers to elements are stable. 88cb93a386Sopenharmony_ci return &fOwnedStrings.front(); 89cb93a386Sopenharmony_ci} 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_civoid SymbolTable::addAlias(skstd::string_view name, const Symbol* symbol) { 92cb93a386Sopenharmony_ci this->add(std::make_unique<SymbolAlias>(symbol->fLine, name, symbol)); 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_civoid SymbolTable::addWithoutOwnership(const Symbol* symbol) { 96cb93a386Sopenharmony_ci const skstd::string_view& name = symbol->name(); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci const Symbol*& refInSymbolTable = fSymbols[MakeSymbolKey(name)]; 99cb93a386Sopenharmony_ci if (refInSymbolTable == nullptr) { 100cb93a386Sopenharmony_ci refInSymbolTable = symbol; 101cb93a386Sopenharmony_ci return; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci if (!symbol->is<FunctionDeclaration>()) { 105cb93a386Sopenharmony_ci fContext.fErrors->error(symbol->fLine, "symbol '" + name + "' was already defined"); 106cb93a386Sopenharmony_ci return; 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci std::vector<const FunctionDeclaration*> functions; 110cb93a386Sopenharmony_ci if (refInSymbolTable->is<FunctionDeclaration>()) { 111cb93a386Sopenharmony_ci functions = {&refInSymbolTable->as<FunctionDeclaration>(), 112cb93a386Sopenharmony_ci &symbol->as<FunctionDeclaration>()}; 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci refInSymbolTable = this->takeOwnershipOfSymbol( 115cb93a386Sopenharmony_ci std::make_unique<UnresolvedFunction>(std::move(functions))); 116cb93a386Sopenharmony_ci } else if (refInSymbolTable->is<UnresolvedFunction>()) { 117cb93a386Sopenharmony_ci functions = refInSymbolTable->as<UnresolvedFunction>().functions(); 118cb93a386Sopenharmony_ci functions.push_back(&symbol->as<FunctionDeclaration>()); 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci refInSymbolTable = this->takeOwnershipOfSymbol( 121cb93a386Sopenharmony_ci std::make_unique<UnresolvedFunction>(std::move(functions))); 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ciconst Type* SymbolTable::addArrayDimension(const Type* type, int arraySize) { 126cb93a386Sopenharmony_ci if (arraySize != 0) { 127cb93a386Sopenharmony_ci const String* arrayName = this->takeOwnershipOfString(type->getArrayName(arraySize)); 128cb93a386Sopenharmony_ci type = this->takeOwnershipOfSymbol(Type::MakeArrayType(*arrayName, *type, arraySize)); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci return type; 131cb93a386Sopenharmony_ci} 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci} // namespace SkSL 134