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/sksl/DSLCore.h"
11 #include "include/sksl/DSLStatement.h"
12 #include "include/sksl/DSLSymbols.h"
13 #include "include/sksl/DSLVar.h"
14 #include "src/sksl/SkSLThreadContext.h"
15 #include "src/sksl/ir/SkSLBlock.h"
16 #include "src/sksl/ir/SkSLNop.h"
17 #include "src/sksl/ir/SkSLVarDeclarations.h"
18 #include "src/sksl/ir/SkSLVariable.h"
19
20 namespace SkSL {
21
22 namespace dsl {
23
ManglingEnabled()24 bool DSLWriter::ManglingEnabled() {
25 return ThreadContext::Instance().fSettings.fDSLMangling;
26 }
27
Name(skstd::string_view name)28 skstd::string_view DSLWriter::Name(skstd::string_view name) {
29 if (ManglingEnabled()) {
30 const String* s = ThreadContext::SymbolTable()->takeOwnershipOfString(
31 ThreadContext::Instance().fMangler.uniqueName(name,
32 ThreadContext::SymbolTable().get()));
33 return s->c_str();
34 }
35 return name;
36 }
37
Var(DSLVarBase & var)38 const 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.line(), var.fModifiers.fModifiers, &var.fType.skslType(), var.fName,
54 /*isArray=*/false, /*arraySize=*/nullptr, var.storage());
55 SkSL::Variable* varPtr = skslvar.get();
56 if (var.storage() != SkSL::VariableStorage::kParameter) {
57 var.fDeclaration = VarDeclaration::Convert(ThreadContext::Context(), std::move(skslvar),
58 var.fInitialValue.releaseIfPossible(), /*addToSymbolTable=*/false);
59 if (var.fDeclaration) {
60 var.fVar = varPtr;
61 var.fInitialized = true;
62 }
63 }
64 ThreadContext::ReportErrors(var.fPosition);
65 }
66 return var.fVar;
67 }
68
CreateParameterVar(DSLParameter & var)69 std::unique_ptr<SkSL::Variable> DSLWriter::CreateParameterVar(DSLParameter& var) {
70 // This should only be called on undeclared parameter variables, but we allow the creation to go
71 // ahead regardless so we don't have to worry about null pointers potentially sneaking in and
72 // breaking things. DSLFunction is responsible for reporting errors for invalid parameters.
73 return SkSL::Variable::Convert(ThreadContext::Context(), var.fPosition.line(),
74 var.fModifiers.fModifiers, &var.fType.skslType(), var.fName, /*isArray=*/false,
75 /*arraySize=*/nullptr, var.storage());
76 }
77
Declaration(DSLVarBase & var)78 std::unique_ptr<SkSL::Statement> DSLWriter::Declaration(DSLVarBase& var) {
79 Var(var);
80 if (!var.fDeclaration) {
81 // We should have already reported an error before ending up here, just clean up the
82 // initial value so it doesn't assert and return a nop.
83 var.fInitialValue.releaseIfPossible();
84 return SkSL::Nop::Make();
85 }
86 return std::move(var.fDeclaration);
87 }
88
MarkDeclared(DSLVarBase & var)89 void DSLWriter::MarkDeclared(DSLVarBase& var) {
90 SkASSERT(!var.fDeclared);
91 var.fDeclared = true;
92 }
93
MarkVarsDeclared()94 bool DSLWriter::MarkVarsDeclared() {
95 return ThreadContext::Instance().fSettings.fDSLMarkVarsDeclared;
96 }
97
AddVarDeclaration(DSLStatement & existing,DSLVar & additional)98 void DSLWriter::AddVarDeclaration(DSLStatement& existing, DSLVar& additional) {
99 if (existing.fStatement->is<Block>()) {
100 SkSL::Block& block = existing.fStatement->as<Block>();
101 SkASSERT(!block.isScope());
102 block.children().push_back(Declare(additional).release());
103 } else if (existing.fStatement->is<VarDeclaration>()) {
104 StatementArray stmts;
105 stmts.reserve_back(2);
106 stmts.push_back(std::move(existing.fStatement));
107 stmts.push_back(Declare(additional).release());
108 existing.fStatement = SkSL::Block::MakeUnscoped(/*line=*/-1, std::move(stmts));
109 } else if (existing.fStatement->isEmpty()) {
110 // If the variable declaration generated an error, we can end up with a Nop statement here.
111 existing.fStatement = Declare(additional).release();
112 }
113 }
114
115 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
VarUniformHandle(const DSLGlobalVar & var)116 GrGLSLUniformHandler::UniformHandle DSLWriter::VarUniformHandle(const DSLGlobalVar& var) {
117 return GrGLSLUniformHandler::UniformHandle(var.fUniformHandle);
118 }
119 #endif
120
Reset()121 void DSLWriter::Reset() {
122 dsl::PopSymbolTable();
123 dsl::PushSymbolTable();
124 ThreadContext::ProgramElements().clear();
125 ThreadContext::GetModifiersPool()->clear();
126 }
127
128 } // namespace dsl
129
130 } // namespace SkSL
131