• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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