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