1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC. 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/SkSLVariable.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/sksl/SkSLCompiler.h" 11cb93a386Sopenharmony_ci#include "src/sksl/SkSLContext.h" 12cb93a386Sopenharmony_ci#include "src/sksl/SkSLMangler.h" 13cb93a386Sopenharmony_ci#include "src/sksl/SkSLProgramSettings.h" 14cb93a386Sopenharmony_ci#include "src/sksl/SkSLThreadContext.h" 15cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSymbolTable.h" 16cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLVarDeclarations.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_cinamespace SkSL { 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ciVariable::~Variable() { 21cb93a386Sopenharmony_ci // Unhook this Variable from its associated VarDeclaration, since we're being deleted. 22cb93a386Sopenharmony_ci if (fDeclaration) { 23cb93a386Sopenharmony_ci fDeclaration->setVar(nullptr); 24cb93a386Sopenharmony_ci } 25cb93a386Sopenharmony_ci} 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ciconst Expression* Variable::initialValue() const { 28cb93a386Sopenharmony_ci return fDeclaration ? fDeclaration->value().get() : nullptr; 29cb93a386Sopenharmony_ci} 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_cistd::unique_ptr<Variable> Variable::Convert(const Context& context, int line, 32cb93a386Sopenharmony_ci const Modifiers& modifiers, const Type* baseType, skstd::string_view name, bool isArray, 33cb93a386Sopenharmony_ci std::unique_ptr<Expression> arraySize, Variable::Storage storage) { 34cb93a386Sopenharmony_ci if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 && 35cb93a386Sopenharmony_ci (modifiers.fFlags & Modifiers::kOut_Flag) && 36cb93a386Sopenharmony_ci context.fConfig->fKind == ProgramKind::kFragment && name != Compiler::FRAGCOLOR_NAME) { 37cb93a386Sopenharmony_ci context.fErrors->error(line, "out location=0, index=0 is reserved for sk_FragColor"); 38cb93a386Sopenharmony_ci } 39cb93a386Sopenharmony_ci return Make(context, line, modifiers, baseType, name, isArray, std::move(arraySize), storage); 40cb93a386Sopenharmony_ci} 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_cistd::unique_ptr<Variable> Variable::Make(const Context& context, int line, 43cb93a386Sopenharmony_ci const Modifiers& modifiers, const Type* baseType, skstd::string_view name, bool isArray, 44cb93a386Sopenharmony_ci std::unique_ptr<Expression> arraySize, Variable::Storage storage) { 45cb93a386Sopenharmony_ci const Type* type = baseType; 46cb93a386Sopenharmony_ci int arraySizeValue = 0; 47cb93a386Sopenharmony_ci if (isArray) { 48cb93a386Sopenharmony_ci SkASSERT(arraySize); 49cb93a386Sopenharmony_ci arraySizeValue = type->convertArraySize(context, std::move(arraySize)); 50cb93a386Sopenharmony_ci if (!arraySizeValue) { 51cb93a386Sopenharmony_ci return nullptr; 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci type = ThreadContext::SymbolTable()->addArrayDimension(type, arraySizeValue); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci return std::make_unique<Variable>(line, context.fModifiersPool->add(modifiers), name, type, 56cb93a386Sopenharmony_ci context.fConfig->fIsBuiltinCode, storage); 57cb93a386Sopenharmony_ci} 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ciVariable::ScratchVariable Variable::MakeScratchVariable(const Context& context, 60cb93a386Sopenharmony_ci skstd::string_view baseName, 61cb93a386Sopenharmony_ci const Type* type, 62cb93a386Sopenharmony_ci const Modifiers& modifiers, 63cb93a386Sopenharmony_ci SymbolTable* symbolTable, 64cb93a386Sopenharmony_ci std::unique_ptr<Expression> initialValue) { 65cb93a386Sopenharmony_ci // $floatLiteral or $intLiteral aren't real types that we can use for scratch variables, so 66cb93a386Sopenharmony_ci // replace them if they ever appear here. If this happens, we likely forgot to coerce a type 67cb93a386Sopenharmony_ci // somewhere during compilation. 68cb93a386Sopenharmony_ci if (type->isLiteral()) { 69cb93a386Sopenharmony_ci SkDEBUGFAIL("found a $literal type in MakeScratchVariable"); 70cb93a386Sopenharmony_ci type = &type->scalarTypeForLiteral(); 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci // Out-parameters aren't supported. 74cb93a386Sopenharmony_ci SkASSERT(!(modifiers.fFlags & Modifiers::kOut_Flag)); 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci // Provide our new variable with a unique name, and add it to our symbol table. 77cb93a386Sopenharmony_ci const String* name = 78cb93a386Sopenharmony_ci symbolTable->takeOwnershipOfString(context.fMangler->uniqueName(baseName, symbolTable)); 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci // Create our new variable and add it to the symbol table. 81cb93a386Sopenharmony_ci ScratchVariable result; 82cb93a386Sopenharmony_ci auto var = std::make_unique<Variable>(initialValue ? initialValue->fLine : -1, 83cb93a386Sopenharmony_ci context.fModifiersPool->add(Modifiers{}), 84cb93a386Sopenharmony_ci name->c_str(), 85cb93a386Sopenharmony_ci type, 86cb93a386Sopenharmony_ci symbolTable->isBuiltin(), 87cb93a386Sopenharmony_ci Variable::Storage::kLocal); 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci // If we are creating an array type, reduce it to base type plus array-size. 90cb93a386Sopenharmony_ci int arraySize = 0; 91cb93a386Sopenharmony_ci if (type->isArray()) { 92cb93a386Sopenharmony_ci arraySize = type->columns(); 93cb93a386Sopenharmony_ci type = &type->componentType(); 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci // Create our variable declaration. 96cb93a386Sopenharmony_ci result.fVarDecl = VarDeclaration::Make(context, var.get(), type, arraySize, 97cb93a386Sopenharmony_ci std::move(initialValue)); 98cb93a386Sopenharmony_ci result.fVarSymbol = symbolTable->add(std::move(var)); 99cb93a386Sopenharmony_ci return result; 100cb93a386Sopenharmony_ci} 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci} // namespace SkSL 103