• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 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/dsl/priv/DSLWriter.h"
9 
10 #include "include/core/SkTypes.h"
11 #include "include/private/SkSLDefines.h"
12 #include "include/private/SkSLProgramElement.h"
13 #include "include/private/SkSLStatement.h"
14 #include "include/sksl/DSLCore.h"
15 #include "include/sksl/DSLExpression.h"
16 #include "include/sksl/DSLModifiers.h"
17 #include "include/sksl/DSLStatement.h"
18 #include "include/sksl/DSLType.h"
19 #include "include/sksl/DSLVar.h"
20 #include "include/sksl/SkSLPosition.h"
21 #include "src/sksl/SkSLModifiersPool.h"
22 #include "src/sksl/SkSLThreadContext.h"
23 #include "src/sksl/ir/SkSLBlock.h"
24 #include "src/sksl/ir/SkSLExpression.h"
25 #include "src/sksl/ir/SkSLNop.h"
26 #include "src/sksl/ir/SkSLSymbolTable.h"
27 #include "src/sksl/ir/SkSLType.h"
28 #include "src/sksl/ir/SkSLVarDeclarations.h"
29 #include "src/sksl/ir/SkSLVariable.h"
30 
31 #include <utility>
32 #include <vector>
33 
34 namespace SkSL {
35 
36 namespace dsl {
37 
Var(DSLVarBase & var)38 SkSL::Variable* DSLWriter::Var(DSLVarBase& var) {
39     // fInitialized is true if we have attempted to create a var, whether or not we actually
40     // succeeded. If it's true, we don't want to try again, to avoid reporting the same error
41     // multiple times.
42     if (!var.fInitialized) {
43         // We haven't even attempted to create a var yet, so fVar ought to be null
44         SkASSERT(!var.fVar);
45         var.fInitialized = true;
46         if (var.storage() != SkSL::VariableStorage::kParameter) {
47             const SkSL::Type* baseType = &var.fType.skslType();
48             if (baseType->isArray()) {
49                 baseType = &baseType->componentType();
50             }
51         }
52         std::unique_ptr<SkSL::Variable> skslvar = SkSL::Variable::Convert(ThreadContext::Context(),
53                                                                           var.fPosition,
54                                                                           var.fModifiers.fPosition,
55                                                                           var.fModifiers.fModifiers,
56                                                                           &var.fType.skslType(),
57                                                                           var.fNamePosition,
58                                                                           var.fName,
59                                                                           /*isArray=*/false,
60                                                                           /*arraySize=*/nullptr,
61                                                                           var.storage());
62         SkSL::Variable* varPtr = skslvar.get();
63         if (var.storage() != SkSL::VariableStorage::kParameter) {
64             var.fDeclaration = VarDeclaration::Convert(ThreadContext::Context(),
65                                                        std::move(skslvar),
66                                                        var.fInitialValue.releaseIfPossible(),
67                                                        /*addToSymbolTable=*/false);
68             if (var.fDeclaration) {
69                 var.fVar = varPtr;
70                 var.fInitialized = true;
71             }
72         }
73     }
74     return var.fVar;
75 }
76 
CreateParameterVar(DSLParameter & var)77 std::unique_ptr<SkSL::Variable> DSLWriter::CreateParameterVar(DSLParameter& var) {
78     // This should only be called on undeclared parameter variables, but we allow the creation to go
79     // ahead regardless so we don't have to worry about null pointers potentially sneaking in and
80     // breaking things. DSLFunction is responsible for reporting errors for invalid parameters.
81     return SkSL::Variable::Convert(ThreadContext::Context(),
82                                    var.fPosition,
83                                    var.fModifiers.fPosition,
84                                    var.fModifiers.fModifiers,
85                                    &var.fType.skslType(),
86                                    var.fNamePosition,
87                                    var.fName,
88                                    /*isArray=*/false,
89                                    /*arraySize=*/nullptr,
90                                    var.storage());
91 }
92 
Declaration(DSLVarBase & var)93 std::unique_ptr<SkSL::Statement> DSLWriter::Declaration(DSLVarBase& var) {
94     Var(var);
95     if (!var.fDeclaration) {
96         // We should have already reported an error before ending up here, just clean up the
97         // initial value so it doesn't assert and return a nop.
98         var.fInitialValue.releaseIfPossible();
99         return SkSL::Nop::Make();
100     }
101     return std::move(var.fDeclaration);
102 }
103 
AddVarDeclaration(DSLStatement & existing,DSLVar & additional)104 void DSLWriter::AddVarDeclaration(DSLStatement& existing, DSLVar& additional) {
105     if (existing.fStatement->is<Block>()) {
106         SkSL::Block& block = existing.fStatement->as<Block>();
107         SkASSERT(!block.isScope());
108         block.children().push_back(Declare(additional).release());
109     } else if (existing.fStatement->is<VarDeclaration>()) {
110         Position pos = existing.fStatement->fPosition;
111         StatementArray stmts;
112         stmts.reserve_back(2);
113         stmts.push_back(std::move(existing.fStatement));
114         stmts.push_back(Declare(additional).release());
115         existing.fStatement = SkSL::Block::Make(pos, std::move(stmts),
116                                                 Block::Kind::kCompoundStatement);
117     } else if (existing.fStatement->isEmpty()) {
118         // If the variable declaration generated an error, we can end up with a Nop statement here.
119         existing.fStatement = Declare(additional).release();
120     }
121 }
122 
Reset()123 void DSLWriter::Reset() {
124     SymbolTable::Pop(&ThreadContext::SymbolTable());
125     SymbolTable::Push(&ThreadContext::SymbolTable());
126     ThreadContext::ProgramElements().clear();
127     ThreadContext::GetModifiersPool()->clear();
128 }
129 
130 } // namespace dsl
131 
132 } // namespace SkSL
133