/src/skia/src/sksl/ir/SkSLConstructorArrayCast.cpp
Line | Count | Source (jump to first uncovered line) |
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/SkSLConstructorArrayCast.h" |
9 | | |
10 | | #include "src/sksl/SkSLConstantFolder.h" |
11 | | #include "src/sksl/ir/SkSLConstructorArray.h" |
12 | | #include "src/sksl/ir/SkSLConstructorCompoundCast.h" |
13 | | #include "src/sksl/ir/SkSLConstructorScalarCast.h" |
14 | | |
15 | | namespace SkSL { |
16 | | |
17 | | static std::unique_ptr<Expression> cast_constant_array(const Context& context, |
18 | | const Type& destType, |
19 | 0 | std::unique_ptr<Expression> constCtor) { |
20 | 0 | const Type& scalarType = destType.componentType(); |
21 | | |
22 | | // Create a ConstructorArray(...) which typecasts each argument inside. |
23 | 0 | auto inputArgs = constCtor->as<ConstructorArray>().argumentSpan(); |
24 | 0 | ExpressionArray typecastArgs; |
25 | 0 | typecastArgs.reserve_back(inputArgs.size()); |
26 | 0 | for (std::unique_ptr<Expression>& arg : inputArgs) { |
27 | 0 | int offset = arg->fOffset; |
28 | 0 | if (arg->type().isScalar()) { |
29 | 0 | typecastArgs.push_back(ConstructorScalarCast::Make(context, offset, scalarType, |
30 | 0 | std::move(arg))); |
31 | 0 | } else { |
32 | 0 | typecastArgs.push_back(ConstructorCompoundCast::Make(context, offset, scalarType, |
33 | 0 | std::move(arg))); |
34 | 0 | } |
35 | 0 | } |
36 | |
|
37 | 0 | return ConstructorArray::Make(context, constCtor->fOffset, destType, std::move(typecastArgs)); |
38 | 0 | } |
39 | | |
40 | | std::unique_ptr<Expression> ConstructorArrayCast::Make(const Context& context, |
41 | | int offset, |
42 | | const Type& type, |
43 | 558 | std::unique_ptr<Expression> arg) { |
44 | | // Only arrays of the same size are allowed. |
45 | 558 | SkASSERT(type.isArray()); |
46 | 558 | SkASSERT(arg->type().isArray()); |
47 | 558 | SkASSERT(type.columns() == arg->type().columns()); |
48 | | |
49 | | // If this is a no-op cast, return the expression as-is. |
50 | 558 | if (type == arg->type()) { |
51 | 0 | return arg; |
52 | 0 | } |
53 | | |
54 | | // When optimization is on, look up the value of constant variables. This allows expressions |
55 | | // like `myArray` to be replaced with the compile-time constant `int[2](0, 1)`. |
56 | 558 | if (context.fConfig->fSettings.fOptimize) { |
57 | 558 | arg = ConstantFolder::MakeConstantValueForVariable(std::move(arg)); |
58 | 558 | } |
59 | | // We can cast a vector of compile-time constants at compile-time. |
60 | 558 | if (arg->isCompileTimeConstant()) { |
61 | 0 | return cast_constant_array(context, type, std::move(arg)); |
62 | 0 | } |
63 | 558 | return std::make_unique<ConstructorArrayCast>(offset, type, std::move(arg)); |
64 | 558 | } |
65 | | |
66 | | } // namespace SkSL |