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