blob: 2871d58d1027af65f66b5d5a88d7888ff6e00293 [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLIRGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -07009
10#include "limits.h"
John Stiles44e96be2020-08-31 13:16:04 -040011#include <iterator>
John Stilesfbd050b2020-08-03 13:21:46 -040012#include <memory>
Ethan Nicholasaf197692017-02-27 13:26:45 -050013#include <unordered_set>
ethannicholasb3058bd2016-07-01 08:22:01 -070014
Ethan Nicholasdaed2592021-03-04 14:30:25 -050015#include "include/private/SkSLLayout.h"
John Stiles6bef6a72020-12-02 14:26:04 -050016#include "include/private/SkTArray.h"
Ethan Nicholasbe65cd52021-05-18 12:09:01 -040017#include "include/sksl/DSLCore.h"
John Stilesb2705a12021-02-19 10:55:14 -050018#include "src/core/SkScopeExit.h"
Ethan Nicholas6e0fa402020-08-20 14:08:23 -040019#include "src/sksl/SkSLAnalysis.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/sksl/SkSLCompiler.h"
John Stilesdc8ec312021-01-11 11:05:21 -050021#include "src/sksl/SkSLConstantFolder.h"
Ethan Nicholas58014fa2021-09-29 17:18:18 -040022#include "src/sksl/SkSLIntrinsicMap.h"
Brian Osman00185012021-02-04 16:07:11 -050023#include "src/sksl/SkSLOperators.h"
Brian Osman3000d6b2020-07-31 15:57:28 -040024#include "src/sksl/SkSLUtil.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/sksl/ir/SkSLBinaryExpression.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/sksl/ir/SkSLBreakStatement.h"
27#include "src/sksl/ir/SkSLConstructor.h"
28#include "src/sksl/ir/SkSLContinueStatement.h"
29#include "src/sksl/ir/SkSLDiscardStatement.h"
30#include "src/sksl/ir/SkSLDoStatement.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050031#include "src/sksl/ir/SkSLExpressionStatement.h"
Ethan Nicholas9e6a3932019-05-17 16:31:21 -040032#include "src/sksl/ir/SkSLExternalFunctionCall.h"
Brian Osmanbe0b3b72021-01-06 14:27:35 -050033#include "src/sksl/ir/SkSLExternalFunctionReference.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050034#include "src/sksl/ir/SkSLField.h"
35#include "src/sksl/ir/SkSLFieldAccess.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050036#include "src/sksl/ir/SkSLForStatement.h"
37#include "src/sksl/ir/SkSLFunctionCall.h"
38#include "src/sksl/ir/SkSLFunctionDeclaration.h"
39#include "src/sksl/ir/SkSLFunctionDefinition.h"
John Stiles569249b2020-11-03 12:18:22 -050040#include "src/sksl/ir/SkSLFunctionPrototype.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050041#include "src/sksl/ir/SkSLFunctionReference.h"
42#include "src/sksl/ir/SkSLIfStatement.h"
43#include "src/sksl/ir/SkSLIndexExpression.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050044#include "src/sksl/ir/SkSLInterfaceBlock.h"
John Stiles7591d4b2021-09-13 13:32:06 -040045#include "src/sksl/ir/SkSLLiteral.h"
Brian Osman3099f792021-09-01 13:12:16 -040046#include "src/sksl/ir/SkSLMethodReference.h"
Chris Daltonb0fd4b12019-10-29 13:41:22 -060047#include "src/sksl/ir/SkSLNop.h"
John Stilesff6c5bf2021-09-07 15:22:02 -040048#include "src/sksl/ir/SkSLPoison.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050049#include "src/sksl/ir/SkSLPostfixExpression.h"
50#include "src/sksl/ir/SkSLPrefixExpression.h"
51#include "src/sksl/ir/SkSLReturnStatement.h"
52#include "src/sksl/ir/SkSLSetting.h"
John Stilesdc75a972020-11-25 16:24:55 -050053#include "src/sksl/ir/SkSLStructDefinition.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050054#include "src/sksl/ir/SkSLSwitchCase.h"
55#include "src/sksl/ir/SkSLSwitchStatement.h"
56#include "src/sksl/ir/SkSLSwizzle.h"
57#include "src/sksl/ir/SkSLTernaryExpression.h"
58#include "src/sksl/ir/SkSLUnresolvedFunction.h"
59#include "src/sksl/ir/SkSLVarDeclarations.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050060#include "src/sksl/ir/SkSLVariable.h"
61#include "src/sksl/ir/SkSLVariableReference.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070062
63namespace SkSL {
64
John Stilesc1a98b82021-02-24 13:35:02 -050065IRGenerator::IRGenerator(const Context* context)
John Stiles10d39d92021-05-04 16:13:14 -040066 : fContext(*context) {}
Brian Osman0006ad02020-11-18 15:38:39 -050067
Ethan Nicholas89cfde12021-09-27 11:20:34 -040068void IRGenerator::checkVarDeclaration(int line, const Modifiers& modifiers, const Type* baseType,
Ethan Nicholas489e5522021-01-20 10:53:11 -050069 Variable::Storage storage) {
John Stilese6095982021-02-04 12:42:01 -050070 if (this->strictES2Mode() && baseType->isArray()) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -040071 this->errorReporter().error(line, "array size must appear after variable name");
John Stilese6095982021-02-04 12:42:01 -050072 }
73
John Stiles3624aba2020-12-22 16:29:53 -050074 if (baseType->componentType().isOpaque() && storage != Variable::Storage::kGlobal) {
John Stilesb30151e2021-01-11 16:13:08 -050075 this->errorReporter().error(
Ethan Nicholas89cfde12021-09-27 11:20:34 -040076 line,
John Stilesb30151e2021-01-11 16:13:08 -050077 "variables of type '" + baseType->displayName() + "' must be global");
Brian Osman82329002020-07-21 09:39:27 -040078 }
Brian Osman8c264792021-07-01 16:41:27 -040079 if ((modifiers.fFlags & Modifiers::kIn_Flag) && baseType->isMatrix()) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -040080 this->errorReporter().error(line, "'in' variables may not have matrix type");
Brian Osman8c264792021-07-01 16:41:27 -040081 }
82 if ((modifiers.fFlags & Modifiers::kIn_Flag) && (modifiers.fFlags & Modifiers::kUniform_Flag)) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -040083 this->errorReporter().error(line, "'in uniform' variables not permitted");
Brian Osman2fe83fe2019-12-16 13:17:59 -050084 }
John Stilesbb2ef922021-07-26 08:32:07 -040085 if (this->isRuntimeEffect()) {
Brian Osman5c625822021-04-06 14:28:07 -040086 if (modifiers.fFlags & Modifiers::kIn_Flag) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -040087 this->errorReporter().error(line, "'in' variables not permitted in runtime effects");
Brian Osmana4b91692020-08-10 14:26:16 -040088 }
89 }
Brian Osman5c625822021-04-06 14:28:07 -040090 if (baseType->isEffectChild() && !(modifiers.fFlags & Modifiers::kUniform_Flag)) {
91 this->errorReporter().error(
Ethan Nicholas89cfde12021-09-27 11:20:34 -040092 line, "variables of type '" + baseType->displayName() + "' must be uniform");
Brian Osman5c625822021-04-06 14:28:07 -040093 }
Brian Osmanb32d66b2020-04-30 17:12:03 -040094 if (modifiers.fLayout.fFlags & Layout::kSRGBUnpremul_Flag) {
John Stilesbb2ef922021-07-26 08:32:07 -040095 if (!this->isRuntimeEffect()) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -040096 this->errorReporter().error(line,
John Stilesb30151e2021-01-11 16:13:08 -050097 "'srgb_unpremul' is only permitted in runtime effects");
Brian Osmanb32d66b2020-04-30 17:12:03 -040098 }
99 if (!(modifiers.fFlags & Modifiers::kUniform_Flag)) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400100 this->errorReporter().error(line,
John Stilesb30151e2021-01-11 16:13:08 -0500101 "'srgb_unpremul' is only permitted on 'uniform' variables");
Brian Osmanb32d66b2020-04-30 17:12:03 -0400102 }
103 auto validColorXformType = [](const Type& t) {
John Stiles9aeed132020-11-24 17:36:06 -0500104 return t.isVector() && t.componentType().isFloat() &&
Brian Osmanb32d66b2020-04-30 17:12:03 -0400105 (t.columns() == 3 || t.columns() == 4);
106 };
John Stilesc0c51062020-12-03 17:16:29 -0500107 if (!validColorXformType(*baseType) && !(baseType->isArray() &&
Brian Osmanb32d66b2020-04-30 17:12:03 -0400108 validColorXformType(baseType->componentType()))) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400109 this->errorReporter().error(line,
John Stilesb30151e2021-01-11 16:13:08 -0500110 "'srgb_unpremul' is only permitted on half3, half4, "
111 "float3, or float4 variables");
Brian Osmanb32d66b2020-04-30 17:12:03 -0400112 }
113 }
John Stilesb806da42021-08-04 16:26:47 -0400114 int permitted = Modifiers::kConst_Flag | Modifiers::kHighp_Flag | Modifiers::kMediump_Flag |
115 Modifiers::kLowp_Flag;
Ethan Nicholas453f67f2020-10-09 10:43:45 -0400116 if (storage == Variable::Storage::kGlobal) {
Brian Osman9ca38ff2021-02-18 12:58:54 -0500117 permitted |= Modifiers::kIn_Flag | Modifiers::kOut_Flag | Modifiers::kUniform_Flag |
Brian Osmane49703f2021-04-19 11:15:24 -0400118 Modifiers::kFlat_Flag | Modifiers::kNoPerspective_Flag;
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400119 }
Brian Osmana654faa2021-02-26 11:52:59 -0500120 // TODO(skbug.com/11301): Migrate above checks into building a mask of permitted layout flags
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400121 CheckModifiers(fContext, line, modifiers, permitted, /*permittedLayoutFlags=*/~0);
Ethan Nicholas489e5522021-01-20 10:53:11 -0500122}
123
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400124std::unique_ptr<Variable> IRGenerator::convertVar(int line, const Modifiers& modifiers,
Ethan Nicholas962dec42021-06-10 13:06:39 -0400125 const Type* baseType, skstd::string_view name,
Ethan Nicholasbd974002021-02-22 16:20:06 -0500126 bool isArray,
127 std::unique_ptr<Expression> arraySize,
128 Variable::Storage storage) {
Ethan Nicholas489e5522021-01-20 10:53:11 -0500129 if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
John Stilesd1204642021-02-17 16:30:02 -0500130 (modifiers.fFlags & Modifiers::kOut_Flag) &&
John Stilese67bd132021-03-19 18:39:25 -0400131 this->programKind() == ProgramKind::kFragment && name != Compiler::FRAGCOLOR_NAME) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400132 this->errorReporter().error(line,
Ethan Nicholas489e5522021-01-20 10:53:11 -0500133 "out location=0, index=0 is reserved for sk_FragColor");
134 }
135 const Type* type = baseType;
136 int arraySizeValue = 0;
137 if (isArray) {
Ethan Nicholas489e5522021-01-20 10:53:11 -0500138 SkASSERT(arraySize);
John Stiles7253a202021-08-23 09:24:33 -0400139 arraySizeValue = type->convertArraySize(fContext, std::move(arraySize));
John Stiles80b02af2021-02-12 17:07:51 -0500140 if (!arraySizeValue) {
141 return {};
142 }
Ethan Nicholas489e5522021-01-20 10:53:11 -0500143 type = fSymbolTable->addArrayDimension(type, arraySizeValue);
144 }
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400145 return std::make_unique<Variable>(line, this->modifiersPool().add(modifiers), name,
John Stilesc8764892021-10-04 11:56:30 -0400146 type, fContext.fConfig->fIsBuiltinCode, storage);
Ethan Nicholasbd974002021-02-22 16:20:06 -0500147}
148
149std::unique_ptr<Statement> IRGenerator::convertVarDeclaration(std::unique_ptr<Variable> var,
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400150 std::unique_ptr<Expression> value,
151 bool addToSymbolTable) {
John Stilese67bd132021-03-19 18:39:25 -0400152 std::unique_ptr<Statement> varDecl = VarDeclaration::Convert(fContext, var.get(),
153 std::move(value));
154 if (!varDecl) {
155 return nullptr;
156 }
157
158 // Detect the declaration of magical variables.
159 if ((var->storage() == Variable::Storage::kGlobal) && var->name() == Compiler::FRAGCOLOR_NAME) {
160 // Silently ignore duplicate definitions of `sk_FragColor`.
161 const Symbol* symbol = (*fSymbolTable)[var->name()];
162 if (symbol) {
Brian Osman7b361492021-02-25 11:25:30 -0500163 return nullptr;
164 }
John Stilese67bd132021-03-19 18:39:25 -0400165 } else if ((var->storage() == Variable::Storage::kGlobal ||
166 var->storage() == Variable::Storage::kInterfaceBlock) &&
167 var->name() == Compiler::RTADJUST_NAME) {
168 // `sk_RTAdjust` is special, and makes the IR generator emit position-fixup expressions.
169 if (fRTAdjust) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400170 this->errorReporter().error(var->fLine, "duplicate definition of 'sk_RTAdjust'");
Brian Osman7b361492021-02-25 11:25:30 -0500171 return nullptr;
172 }
John Stilese67bd132021-03-19 18:39:25 -0400173 if (var->type() != *fContext.fTypes.fFloat4) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400174 this->errorReporter().error(var->fLine, "sk_RTAdjust must have type 'float4'");
Brian Osmanfc4b9912021-03-05 16:45:06 -0500175 return nullptr;
176 }
Ethan Nicholas489e5522021-01-20 10:53:11 -0500177 fRTAdjust = var.get();
178 }
John Stilese67bd132021-03-19 18:39:25 -0400179
Ethan Nicholasdd2fdea2021-07-20 15:23:04 -0400180 if (addToSymbolTable) {
181 fSymbolTable->add(std::move(var));
182 } else {
183 fSymbolTable->takeOwnershipOfSymbol(std::move(var));
184 }
John Stilese67bd132021-03-19 18:39:25 -0400185 return varDecl;
Ethan Nicholasbd974002021-02-22 16:20:06 -0500186}
187
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400188std::unique_ptr<Statement> IRGenerator::convertVarDeclaration(int line,
Ethan Nicholasbd974002021-02-22 16:20:06 -0500189 const Modifiers& modifiers,
190 const Type* baseType,
Ethan Nicholas962dec42021-06-10 13:06:39 -0400191 skstd::string_view name,
Ethan Nicholasbd974002021-02-22 16:20:06 -0500192 bool isArray,
193 std::unique_ptr<Expression> arraySize,
194 std::unique_ptr<Expression> value,
195 Variable::Storage storage) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400196 std::unique_ptr<Variable> var = this->convertVar(line, modifiers, baseType, name, isArray,
Ethan Nicholasbd974002021-02-22 16:20:06 -0500197 std::move(arraySize), storage);
198 if (!var) {
199 return nullptr;
200 }
201 return this->convertVarDeclaration(std::move(var), std::move(value));
Ethan Nicholas489e5522021-01-20 10:53:11 -0500202}
203
John Stiles3b204892021-08-27 17:35:35 -0400204void IRGenerator::appendRTAdjustFixupToVertexMain(const FunctionDeclaration& decl, Block* body) {
John Stilesd45ebbc2021-05-18 16:54:36 -0400205 using namespace SkSL::dsl;
206 using SkSL::dsl::Swizzle; // disambiguate from SkSL::Swizzle
John Stiles3b204892021-08-27 17:35:35 -0400207 using OwnerKind = SkSL::FieldAccess::OwnerKind;
John Stilesd45ebbc2021-05-18 16:54:36 -0400208
John Stiles3b204892021-08-27 17:35:35 -0400209 // If this is a vertex program that uses RTAdjust, and this is main()...
Ethan Nicholasa97ad0f2021-09-02 09:54:04 -0400210 if ((fRTAdjust || fRTAdjustInterfaceBlock) && decl.isMain() &&
211 ProgramKind::kVertex == this->programKind()) {
John Stiles3b204892021-08-27 17:35:35 -0400212 // ... append a line to the end of the function body which fixes up sk_Position.
213 const Variable* skPerVertex = nullptr;
Ethan Nicholas58014fa2021-09-29 17:18:18 -0400214 if (const ProgramElement* perVertexDecl =
215 fContext.fIntrinsics->find(Compiler::PERVERTEX_NAME)) {
John Stiles3b204892021-08-27 17:35:35 -0400216 SkASSERT(perVertexDecl->is<SkSL::InterfaceBlock>());
217 skPerVertex = &perVertexDecl->as<SkSL::InterfaceBlock>().variable();
218 }
219
220 SkASSERT(skPerVertex);
221 auto Ref = [](const Variable* var) -> std::unique_ptr<Expression> {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400222 return VariableReference::Make(/*line=*/-1, var);
John Stiles3b204892021-08-27 17:35:35 -0400223 };
224 auto Field = [&](const Variable* var, int idx) -> std::unique_ptr<Expression> {
225 return FieldAccess::Make(fContext, Ref(var), idx, OwnerKind::kAnonymousInterfaceBlock);
226 };
227 auto Pos = [&]() -> DSLExpression {
228 return DSLExpression(FieldAccess::Make(fContext, Ref(skPerVertex), /*fieldIndex=*/0,
229 OwnerKind::kAnonymousInterfaceBlock));
230 };
231 auto Adjust = [&]() -> DSLExpression {
232 return DSLExpression(fRTAdjustInterfaceBlock
233 ? Field(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex)
234 : Ref(fRTAdjust));
235 };
236
237 auto fixupStmt = DSLStatement(
238 Pos() = Float4(Swizzle(Pos(), X, Y) * Swizzle(Adjust(), X, Z) +
239 Swizzle(Pos(), W, W) * Swizzle(Adjust(), Y, W),
240 0,
241 Pos().w())
242 );
243
244 body->children().push_back(fixupStmt.release());
Brian Osman88cda172020-10-09 12:05:16 -0400245 }
Robert Phillipsfe8da172018-01-24 14:52:02 +0000246}
247
Ethan Nicholas371f6e12021-05-04 14:30:02 -0400248void IRGenerator::CheckModifiers(const Context& context,
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400249 int line,
Brian Osmana654faa2021-02-26 11:52:59 -0500250 const Modifiers& modifiers,
251 int permittedModifierFlags,
252 int permittedLayoutFlags) {
Brian Osmanb5de6be2021-08-10 15:16:34 -0400253 static constexpr struct { Modifiers::Flag flag; const char* name; } kModifierFlags[] = {
254 { Modifiers::kConst_Flag, "const" },
255 { Modifiers::kIn_Flag, "in" },
256 { Modifiers::kOut_Flag, "out" },
257 { Modifiers::kUniform_Flag, "uniform" },
258 { Modifiers::kFlat_Flag, "flat" },
259 { Modifiers::kNoPerspective_Flag, "noperspective" },
260 { Modifiers::kHasSideEffects_Flag, "sk_has_side_effects" },
261 { Modifiers::kInline_Flag, "inline" },
262 { Modifiers::kNoInline_Flag, "noinline" },
263 { Modifiers::kHighp_Flag, "highp" },
264 { Modifiers::kMediump_Flag, "mediump" },
265 { Modifiers::kLowp_Flag, "lowp" },
John Stilesefde90d2021-08-12 23:06:24 -0400266 { Modifiers::kES3_Flag, "$es3" },
Brian Osmana654faa2021-02-26 11:52:59 -0500267 };
268
Brian Osmanb5de6be2021-08-10 15:16:34 -0400269 int modifierFlags = modifiers.fFlags;
270 for (const auto& f : kModifierFlags) {
271 if (modifierFlags & f.flag) {
272 if (!(permittedModifierFlags & f.flag)) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400273 context.fErrors->error(line, "'" + String(f.name) + "' is not permitted here");
Brian Osmanb5de6be2021-08-10 15:16:34 -0400274 }
275 modifierFlags &= ~f.flag;
276 }
277 }
278 SkASSERT(modifierFlags == 0);
279
280 static constexpr struct { Layout::Flag flag; const char* name; } kLayoutFlags[] = {
281 { Layout::kOriginUpperLeft_Flag, "origin_upper_left"},
282 { Layout::kPushConstant_Flag, "push_constant"},
283 { Layout::kBlendSupportAllEquations_Flag, "blend_support_all_equations"},
284 { Layout::kSRGBUnpremul_Flag, "srgb_unpremul"},
285 { Layout::kLocation_Flag, "location"},
286 { Layout::kOffset_Flag, "offset"},
287 { Layout::kBinding_Flag, "binding"},
288 { Layout::kIndex_Flag, "index"},
289 { Layout::kSet_Flag, "set"},
290 { Layout::kBuiltin_Flag, "builtin"},
291 { Layout::kInputAttachmentIndex_Flag, "input_attachment_index"},
Brian Osmanb5de6be2021-08-10 15:16:34 -0400292 };
Brian Osmana654faa2021-02-26 11:52:59 -0500293
294 int layoutFlags = modifiers.fLayout.fFlags;
Brian Osmanb5de6be2021-08-10 15:16:34 -0400295 for (const auto& lf : kLayoutFlags) {
296 if (layoutFlags & lf.flag) {
297 if (!(permittedLayoutFlags & lf.flag)) {
Ethan Nicholas39f6da42021-08-23 13:10:07 -0400298 context.fErrors->error(
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400299 line, "layout qualifier '" + String(lf.name) + "' is not permitted here");
Brian Osmana654faa2021-02-26 11:52:59 -0500300 }
Brian Osmanb5de6be2021-08-10 15:16:34 -0400301 layoutFlags &= ~lf.flag;
Brian Osmana654faa2021-02-26 11:52:59 -0500302 }
Brian Osmanb5de6be2021-08-10 15:16:34 -0400303 }
Brian Osmana654faa2021-02-26 11:52:59 -0500304 SkASSERT(layoutFlags == 0);
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400305}
306
Ethan Nicholas494eb3e2021-08-27 19:17:01 -0400307void IRGenerator::scanInterfaceBlock(SkSL::InterfaceBlock& intf) {
308 const std::vector<Type::Field>& fields = intf.variable().type().componentType().fields();
309 for (size_t i = 0; i < fields.size(); ++i) {
310 const Type::Field& f = fields[i];
311 if (f.fName == Compiler::RTADJUST_NAME) {
312 if (*f.fType == *fContext.fTypes.fFloat4) {
313 fRTAdjustInterfaceBlock = &intf.variable();
314 fRTAdjustFieldIndex = i;
315 } else {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400316 this->errorReporter().error(intf.fLine, "sk_RTAdjust must have type 'float4'");
Ethan Nicholas494eb3e2021-08-27 19:17:01 -0400317 }
318 }
319 }
320}
321
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400322std::unique_ptr<Expression> IRGenerator::convertIdentifier(int line, skstd::string_view name) {
Ethan Nicholas9ead3df2021-01-06 12:10:48 -0500323 const Symbol* result = (*fSymbolTable)[name];
ethannicholasb3058bd2016-07-01 08:22:01 -0700324 if (!result) {
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400325 this->errorReporter().error(line, "unknown identifier '" + name + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700326 return nullptr;
327 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400328 switch (result->kind()) {
329 case Symbol::Kind::kFunctionDeclaration: {
ethannicholasd598f792016-07-25 10:08:54 -0700330 std::vector<const FunctionDeclaration*> f = {
John Stiles17c5b702020-08-18 10:40:03 -0400331 &result->as<FunctionDeclaration>()
ethannicholasb3058bd2016-07-01 08:22:01 -0700332 };
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400333 return std::make_unique<FunctionReference>(fContext, line, f);
ethannicholasb3058bd2016-07-01 08:22:01 -0700334 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400335 case Symbol::Kind::kUnresolvedFunction: {
John Stiles17c5b702020-08-18 10:40:03 -0400336 const UnresolvedFunction* f = &result->as<UnresolvedFunction>();
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400337 return std::make_unique<FunctionReference>(fContext, line, f->functions());
ethannicholasb3058bd2016-07-01 08:22:01 -0700338 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400339 case Symbol::Kind::kVariable: {
John Stiles17c5b702020-08-18 10:40:03 -0400340 const Variable* var = &result->as<Variable>();
Ethan Nicholas041fd0a2020-10-07 16:42:04 -0400341 const Modifiers& modifiers = var->modifiers();
342 switch (modifiers.fLayout.fBuiltin) {
Ethan Nicholascd700e92018-08-24 16:43:57 -0400343 case SK_FRAGCOORD_BUILTIN:
Brian Salomond8d85b92021-07-07 09:41:17 -0400344 if (caps().canUseFragCoord()) {
345 fInputs.fUseFlipRTUniform = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -0400346 }
Brian Salomond8d85b92021-07-07 09:41:17 -0400347 break;
348 case SK_CLOCKWISE_BUILTIN:
349 fInputs.fUseFlipRTUniform = true;
350 break;
Ethan Nicholascd700e92018-08-24 16:43:57 -0400351 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500352 // default to kRead_RefKind; this will be corrected later if the variable is written to
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400353 return VariableReference::Make(line, var, VariableReference::RefKind::kRead);
ethannicholasb3058bd2016-07-01 08:22:01 -0700354 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400355 case Symbol::Kind::kField: {
John Stiles17c5b702020-08-18 10:40:03 -0400356 const Field* field = &result->as<Field>();
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400357 auto base = VariableReference::Make(line, &field->owner(),
John Stilesa94e0262021-04-27 17:29:59 -0400358 VariableReference::RefKind::kRead);
John Stiles06d600f2021-03-08 09:18:21 -0500359 return FieldAccess::Make(fContext, std::move(base), field->fieldIndex(),
360 FieldAccess::OwnerKind::kAnonymousInterfaceBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -0700361 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400362 case Symbol::Kind::kType: {
John Stilesa1064722021-10-04 12:43:39 -0400363 return TypeReference::Convert(fContext, line, &result->as<Type>());
ethannicholasb3058bd2016-07-01 08:22:01 -0700364 }
Ethan Nicholase6592142020-09-08 10:22:09 -0400365 case Symbol::Kind::kExternal: {
Brian Osmanbe0b3b72021-01-06 14:27:35 -0500366 const ExternalFunction* r = &result->as<ExternalFunction>();
Ethan Nicholas89cfde12021-09-27 11:20:34 -0400367 return std::make_unique<ExternalFunctionReference>(line, r);
Ethan Nicholas91164d12019-05-15 15:29:54 -0400368 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700369 default:
John Stilesf57207b2021-02-02 17:50:34 -0500370 SK_ABORT("unsupported symbol type %d\n", (int) result->kind());
ethannicholasb3058bd2016-07-01 08:22:01 -0700371 }
Ethan Nicholasc0709392017-06-27 11:20:22 -0400372}
373
Ethan Nicholas8b3dd342021-03-23 12:32:56 -0400374void IRGenerator::start(const ParsedModule& base,
Ethan Nicholas8b3dd342021-03-23 12:32:56 -0400375 std::vector<std::unique_ptr<ProgramElement>>* elements,
376 std::vector<const ProgramElement*>* sharedElements) {
Ethan Nicholas624a5292021-04-16 14:54:43 -0400377 fProgramElements = elements;
378 fSharedElements = sharedElements;
Brian Osman88cda172020-10-09 12:05:16 -0400379 fSymbolTable = base.fSymbols;
Brian Osman88cda172020-10-09 12:05:16 -0400380
Brian Salomond8d85b92021-07-07 09:41:17 -0400381 fInputs = {};
Brian Osman88cda172020-10-09 12:05:16 -0400382 fRTAdjust = nullptr;
383 fRTAdjustInterfaceBlock = nullptr;
Brian Osman02bc5222021-01-28 11:00:20 -0500384 fDefinedStructs.clear();
John Stilesc8764892021-10-04 11:56:30 -0400385 SymbolTable::Push(&fSymbolTable, fContext.fConfig->fIsBuiltinCode);
Brian Osman88cda172020-10-09 12:05:16 -0400386
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400387 if (this->settings().fExternalFunctions) {
John Stilesaecf8d52021-05-14 12:15:01 -0400388 // Add any external values to the new symbol table, so they're only visible to this Program.
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400389 for (const std::unique_ptr<ExternalFunction>& ef : *this->settings().fExternalFunctions) {
Brian Osmanbe0b3b72021-01-06 14:27:35 -0500390 fSymbolTable->addWithoutOwnership(ef.get());
Brian Osman88cda172020-10-09 12:05:16 -0400391 }
392 }
John Stilesaecf8d52021-05-14 12:15:01 -0400393
John Stilesbb2ef922021-07-26 08:32:07 -0400394 if (this->isRuntimeEffect() && !fContext.fConfig->fSettings.fEnforceES2Restrictions) {
John Stiles325c8082021-05-17 14:49:05 -0400395 // We're compiling a runtime effect, but we're not enforcing ES2 restrictions. Add various
John Stiles12eb0ee2021-06-01 14:14:50 -0400396 // non-ES2 types to our symbol table to allow them to be tested.
John Stilesaecf8d52021-05-14 12:15:01 -0400397 fSymbolTable->addAlias("mat2x2", fContext.fTypes.fFloat2x2.get());
398 fSymbolTable->addAlias("mat2x3", fContext.fTypes.fFloat2x3.get());
399 fSymbolTable->addAlias("mat2x4", fContext.fTypes.fFloat2x4.get());
400 fSymbolTable->addAlias("mat3x2", fContext.fTypes.fFloat3x2.get());
401 fSymbolTable->addAlias("mat3x3", fContext.fTypes.fFloat3x3.get());
402 fSymbolTable->addAlias("mat3x4", fContext.fTypes.fFloat3x4.get());
403 fSymbolTable->addAlias("mat4x2", fContext.fTypes.fFloat4x2.get());
404 fSymbolTable->addAlias("mat4x3", fContext.fTypes.fFloat4x3.get());
405 fSymbolTable->addAlias("mat4x4", fContext.fTypes.fFloat4x4.get());
406
407 fSymbolTable->addAlias("float2x3", fContext.fTypes.fFloat2x3.get());
408 fSymbolTable->addAlias("float2x4", fContext.fTypes.fFloat2x4.get());
409 fSymbolTable->addAlias("float3x2", fContext.fTypes.fFloat3x2.get());
410 fSymbolTable->addAlias("float3x4", fContext.fTypes.fFloat3x4.get());
411 fSymbolTable->addAlias("float4x2", fContext.fTypes.fFloat4x2.get());
412 fSymbolTable->addAlias("float4x3", fContext.fTypes.fFloat4x3.get());
413
414 fSymbolTable->addAlias("half2x3", fContext.fTypes.fHalf2x3.get());
415 fSymbolTable->addAlias("half2x4", fContext.fTypes.fHalf2x4.get());
416 fSymbolTable->addAlias("half3x2", fContext.fTypes.fHalf3x2.get());
417 fSymbolTable->addAlias("half3x4", fContext.fTypes.fHalf3x4.get());
418 fSymbolTable->addAlias("half4x2", fContext.fTypes.fHalf4x2.get());
419 fSymbolTable->addAlias("half4x3", fContext.fTypes.fHalf4x3.get());
John Stiles325c8082021-05-17 14:49:05 -0400420
421 fSymbolTable->addAlias("uint", fContext.fTypes.fUInt.get());
422 fSymbolTable->addAlias("uint2", fContext.fTypes.fUInt2.get());
423 fSymbolTable->addAlias("uint3", fContext.fTypes.fUInt3.get());
424 fSymbolTable->addAlias("uint4", fContext.fTypes.fUInt4.get());
John Stiles26487162021-08-10 16:03:44 -0400425
426 fSymbolTable->addAlias("short", fContext.fTypes.fShort.get());
427 fSymbolTable->addAlias("short2", fContext.fTypes.fShort2.get());
428 fSymbolTable->addAlias("short3", fContext.fTypes.fShort3.get());
429 fSymbolTable->addAlias("short4", fContext.fTypes.fShort4.get());
430
431 fSymbolTable->addAlias("ushort", fContext.fTypes.fUShort.get());
432 fSymbolTable->addAlias("ushort2", fContext.fTypes.fUShort2.get());
433 fSymbolTable->addAlias("ushort3", fContext.fTypes.fUShort3.get());
434 fSymbolTable->addAlias("ushort4", fContext.fTypes.fUShort4.get());
John Stilesaecf8d52021-05-14 12:15:01 -0400435 }
Ethan Nicholas8b3dd342021-03-23 12:32:56 -0400436}
Brian Osman88cda172020-10-09 12:05:16 -0400437
Ethan Nicholas8b3dd342021-03-23 12:32:56 -0400438IRGenerator::IRBundle IRGenerator::finish() {
John Stilesf2872e62021-05-04 11:38:43 -0400439 return IRBundle{std::move(*fProgramElements),
440 std::move(*fSharedElements),
John Stilesf2872e62021-05-04 11:38:43 -0400441 std::move(fSymbolTable),
442 fInputs};
Ethan Nicholas8b3dd342021-03-23 12:32:56 -0400443}
444
John Stilesa6841be2020-08-06 14:11:56 -0400445} // namespace SkSL