2 * Copyright 2020 Google LLC
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "src/sksl/dsl/priv/DSLWriter.h"
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/DSLSymbols.h"
19 #include "include/sksl/DSLType.h"
20 #include "include/sksl/DSLVar.h"
21 #include "include/sksl/SkSLPosition.h"
22 #include "src/sksl/SkSLModifiersPool.h"
23 #include "src/sksl/SkSLThreadContext.h"
24 #include "src/sksl/ir/SkSLBlock.h"
25 #include "src/sksl/ir/SkSLExpression.h"
26 #include "src/sksl/ir/SkSLNop.h"
27 #include "src/sksl/ir/SkSLType.h"
28 #include "src/sksl/ir/SkSLVarDeclarations.h"
29 #include "src/sksl/ir/SkSLVariable.h"
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
42 if (!var.fInitialized) {
43 // We haven't even attempted to create a var yet, so fVar ought to be null
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();
52 std::unique_ptr<SkSL::Variable> skslvar = SkSL::Variable::Convert(ThreadContext::Context(),
53 var.fPosition, var.fModifiers.fPosition, var.fModifiers.fModifiers,
54 &var.fType.skslType(), var.fNamePosition, var.fName, /*isArray=*/false,
55 /*arraySize=*/nullptr, var.storage());
56 SkSL::Variable* varPtr = skslvar.get();
57 if (var.storage() != SkSL::VariableStorage::kParameter) {
58 var.fDeclaration = VarDeclaration::Convert(ThreadContext::Context(), std::move(skslvar),
59 var.fInitialValue.releaseIfPossible(), /*addToSymbolTable=*/false);
60 if (var.fDeclaration) {
62 var.fInitialized = true;
65 ThreadContext::ReportErrors(var.fPosition);
70 std::unique_ptr<SkSL::Variable> DSLWriter::CreateParameterVar(DSLParameter& var) {
71 // This should only be called on undeclared parameter variables, but we allow the creation to go
72 // ahead regardless so we don't have to worry about null pointers potentially sneaking in and
73 // breaking things. DSLFunction is responsible for reporting errors for invalid parameters.
74 return SkSL::Variable::Convert(ThreadContext::Context(), var.fPosition,
75 var.fModifiers.fPosition, var.fModifiers.fModifiers, &var.fType.skslType(),
76 var.fNamePosition, var.fName, /*isArray=*/false, /*arraySize=*/nullptr, var.storage());
79 std::unique_ptr<SkSL::Statement> DSLWriter::Declaration(DSLVarBase& var) {
81 if (!var.fDeclaration) {
82 // We should have already reported an error before ending up here, just clean up the
83 // initial value so it doesn't assert and return a nop.
84 var.fInitialValue.releaseIfPossible();
85 return SkSL::Nop::Make();
87 return std::move(var.fDeclaration);
90 void DSLWriter::AddVarDeclaration(DSLStatement& existing, DSLVar& additional) {
91 if (existing.fStatement->is<Block>()) {
92 SkSL::Block& block = existing.fStatement->as<Block>();
93 SkASSERT(!block.isScope());
94 block.children().push_back(Declare(additional).release());
95 } else if (existing.fStatement->is<VarDeclaration>()) {
96 Position pos = existing.fStatement->fPosition;
98 stmts.reserve_back(2);
99 stmts.push_back(std::move(existing.fStatement));
100 stmts.push_back(Declare(additional).release());
101 existing.fStatement = SkSL::Block::Make(pos, std::move(stmts),
102 Block::Kind::kCompoundStatement);
103 } else if (existing.fStatement->isEmpty()) {
104 // If the variable declaration generated an error, we can end up with a Nop statement here.
105 existing.fStatement = Declare(additional).release();
109 void DSLWriter::Reset() {
110 dsl::PopSymbolTable();
111 dsl::PushSymbolTable();
112 ThreadContext::ProgramElements().clear();
113 ThreadContext::GetModifiersPool()->clear();