chromium/third_party/skia/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp

/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/sksl/codegen/SkSLSPIRVCodeGenerator.h"

#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkEnumBitMask.h"
#include "src/core/SkChecksum.h"
#include "src/core/SkTHash.h"
#include "src/core/SkTraceEvent.h"
#include "src/sksl/GLSL.std.450.h"
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLBuiltinTypes.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLDefines.h"
#include "src/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLIntrinsicList.h"
#include "src/sksl/SkSLMemoryLayout.h"
#include "src/sksl/SkSLOperator.h"
#include "src/sksl/SkSLOutputStream.h"
#include "src/sksl/SkSLPool.h"
#include "src/sksl/SkSLPosition.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/SkSLStringStream.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/analysis/SkSLSpecialization.h"
#include "src/sksl/codegen/SkSLCodeGenerator.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLConstructorArrayCast.h"
#include "src/sksl/ir/SkSLConstructorCompound.h"
#include "src/sksl/ir/SkSLConstructorCompoundCast.h"
#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
#include "src/sksl/ir/SkSLConstructorMatrixResize.h"
#include "src/sksl/ir/SkSLConstructorScalarCast.h"
#include "src/sksl/ir/SkSLConstructorSplat.h"
#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLExtension.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLFieldSymbol.h"
#include "src/sksl/ir/SkSLForStatement.h"
#include "src/sksl/ir/SkSLFunctionCall.h"
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
#include "src/sksl/ir/SkSLFunctionDefinition.h"
#include "src/sksl/ir/SkSLIRNode.h"
#include "src/sksl/ir/SkSLIfStatement.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
#include "src/sksl/ir/SkSLInterfaceBlock.h"
#include "src/sksl/ir/SkSLLayout.h"
#include "src/sksl/ir/SkSLLiteral.h"
#include "src/sksl/ir/SkSLModifierFlags.h"
#include "src/sksl/ir/SkSLModifiersDeclaration.h"
#include "src/sksl/ir/SkSLPoison.h"
#include "src/sksl/ir/SkSLPostfixExpression.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
#include "src/sksl/ir/SkSLProgram.h"
#include "src/sksl/ir/SkSLProgramElement.h"
#include "src/sksl/ir/SkSLReturnStatement.h"
#include "src/sksl/ir/SkSLSetting.h"
#include "src/sksl/ir/SkSLStatement.h"
#include "src/sksl/ir/SkSLSwitchCase.h"
#include "src/sksl/ir/SkSLSwitchStatement.h"
#include "src/sksl/ir/SkSLSwizzle.h"
#include "src/sksl/ir/SkSLSymbol.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#include "src/sksl/ir/SkSLTernaryExpression.h"
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
#include "src/sksl/ir/SkSLVariable.h"
#include "src/sksl/ir/SkSLVariableReference.h"
#include "src/sksl/spirv.h"
#include "src/sksl/transform/SkSLTransform.h"
#include "src/utils/SkBitSet.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <ctype.h>
#include <functional>
#include <memory>
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

usingnamespaceskia_private;

#define kLast_Capability

constexpr int DEVICE_FRAGCOORDS_BUILTIN =;
constexpr int DEVICE_CLOCKWISE_BUILTIN  =;
static constexpr SkSL::Layout kDefaultTypeLayout;

namespace SkSL {

enum class ProgramKind : int8_t;

enum class StorageClass {};

static SpvStorageClass get_storage_class_spv_id(StorageClass storageClass) {}

class SPIRVCodeGenerator : public CodeGenerator {};

// Equality and hash operators for Instructions.
bool SPIRVCodeGenerator::Instruction::operator==(const SPIRVCodeGenerator::Instruction& that) const {}

struct SPIRVCodeGenerator::Instruction::Hash {};

// This class is used to pass values and result placeholder slots to writeInstruction.
struct SPIRVCodeGenerator::Word {};

// Skia's magic number is 31 and goes in the top 16 bits. We can use the lower bits to version the
// sksl generator if we want.
// https://github.com/KhronosGroup/SPIRV-Headers/blob/master/include/spirv/spir-v.xml#L84
static const int32_t SKSL_MAGIC  =;

SPIRVCodeGenerator::Intrinsic SPIRVCodeGenerator::getIntrinsic(IntrinsicKind ik) const {}

void SPIRVCodeGenerator::writeWord(int32_t word, OutputStream& out) {}

static bool is_float(const Type& type) {}

static bool is_signed(const Type& type) {}

static bool is_unsigned(const Type& type) {}

static bool is_bool(const Type& type) {}

template <typename T>
static T pick_by_type(const Type& type, T ifFloat, T ifInt, T ifUInt, T ifBool) {}

static bool is_out(ModifierFlags f) {}

static bool is_in(ModifierFlags f) {}

static bool is_control_flow_op(SpvOp_ op) {}

static bool is_globally_reachable_op(SpvOp_ op) {}

void SPIRVCodeGenerator::writeOpCode(SpvOp_ opCode, int length, OutputStream& out) {}

void SPIRVCodeGenerator::writeLabel(SpvId label, StraightLineLabelType, OutputStream& out) {}

void SPIRVCodeGenerator::writeLabel(SpvId label, BranchingLabelType type,
                                    ConditionalOpCounts ops, OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, OutputStream& out) {}

void SPIRVCodeGenerator::writeString(std::string_view s, OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, std::string_view string,
                                          OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, std::string_view string,
                                          OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
                                          std::string_view string, OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
                                          OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
                                          int32_t word3, OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
                                          int32_t word3, int32_t word4, OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
                                          int32_t word3, int32_t word4, int32_t word5,
                                          OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
                                          int32_t word3, int32_t word4, int32_t word5,
                                          int32_t word6, OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
                                          int32_t word3, int32_t word4, int32_t word5,
                                          int32_t word6, int32_t word7, OutputStream& out) {}

void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
                                          int32_t word3, int32_t word4, int32_t word5,
                                          int32_t word6, int32_t word7, int32_t word8,
                                          OutputStream& out) {}

SPIRVCodeGenerator::Instruction SPIRVCodeGenerator::BuildInstructionKey(SpvOp_ opCode,
                                                                        const TArray<Word>& words) {}

SpvId SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode,
                                           const TArray<Word>& words,
                                           OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeOpLoad(SpvId type,
                                      Precision precision,
                                      SpvId pointer,
                                      OutputStream& out) {}

void SPIRVCodeGenerator::writeOpStore(StorageClass storageClass,
                                      SpvId pointer,
                                      SpvId value,
                                      OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeOpConstantTrue(const Type& type) {}

SpvId SPIRVCodeGenerator::writeOpConstantFalse(const Type& type) {}

SpvId SPIRVCodeGenerator::writeOpConstant(const Type& type, int32_t valueBits) {}

SpvId SPIRVCodeGenerator::writeOpConstantComposite(const Type& type,
                                                   const TArray<SpvId>& values) {}

bool SPIRVCodeGenerator::toConstants(SpvId value, TArray<SpvId>* constants) {}

bool SPIRVCodeGenerator::toConstants(SkSpan<const SpvId> values, TArray<SpvId>* constants) {}

SpvId SPIRVCodeGenerator::writeOpCompositeConstruct(const Type& type,
                                                    const TArray<SpvId>& values,
                                                    OutputStream& out) {}

SPIRVCodeGenerator::Instruction* SPIRVCodeGenerator::resultTypeForInstruction(
        const Instruction& instr) {}

int SPIRVCodeGenerator::numComponentsForVecInstruction(const Instruction& instr) {}

SpvId SPIRVCodeGenerator::toComponent(SpvId id, int component) {}

SpvId SPIRVCodeGenerator::writeOpCompositeExtract(const Type& type,
                                                  SpvId base,
                                                  int component,
                                                  OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeOpCompositeExtract(const Type& type,
                                                  SpvId base,
                                                  int componentA,
                                                  int componentB,
                                                  OutputStream& out) {}

void SPIRVCodeGenerator::writeCapabilities(OutputStream& out) {}

SpvId SPIRVCodeGenerator::nextId(const Type* type) {}

SpvId SPIRVCodeGenerator::nextId(Precision precision) {}

SpvId SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memoryLayout) {}

SpvId SPIRVCodeGenerator::getType(const Type& type) {}

static SpvImageFormat layout_flags_to_image_format(LayoutFlags flags) {}

SpvId SPIRVCodeGenerator::getType(const Type& rawType,
                                  const Layout& typeLayout,
                                  const MemoryLayout& memoryLayout) {}

SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) {}

SpvId SPIRVCodeGenerator::getFunctionParameterType(const Type& parameterType,
                                                   const Layout& parameterLayout) {}

SpvId SPIRVCodeGenerator::getPointerType(const Type& type, StorageClass storageClass) {}

SpvId SPIRVCodeGenerator::getPointerType(const Type& type,
                                         const Layout& typeLayout,
                                         const MemoryLayout& memoryLayout,
                                         StorageClass storageClass) {}

SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream& out) {}

SpvId SPIRVCodeGenerator::vectorize(const Expression& arg, int vectorSize, OutputStream& out) {}

TArray<SpvId> SPIRVCodeGenerator::vectorize(const ExpressionArray& args, OutputStream& out) {}

void SPIRVCodeGenerator::writeGLSLExtendedInstruction(const Type& type, SpvId id, SpvId floatInst,
                                                      SpvId signedInst, SpvId unsignedInst,
                                                      const TArray<SpvId>& args,
                                                      OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind,
                                                OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeAtomicIntrinsic(const FunctionCall& c,
                                               SpecialIntrinsic kind,
                                               SpvId resultId,
                                               OutputStream& out) {}

void SPIRVCodeGenerator::writeFunctionCallArgument(TArray<SpvId>& argumentList,
                                                   const FunctionCall& call,
                                                   int argIndex,
                                                   std::vector<TempVar>* tempVars,
                                                   const SkBitSet* specializedParams,
                                                   OutputStream& out) {}

void SPIRVCodeGenerator::copyBackTempVars(const std::vector<TempVar>& tempVars, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, OutputStream& out) {}

SpvId SPIRVCodeGenerator::castScalarToType(SpvId inputExprId,
                                           const Type& inputType,
                                           const Type& outputType,
                                           OutputStream& out) {}

SpvId SPIRVCodeGenerator::castScalarToFloat(SpvId inputId, const Type& inputType,
                                            const Type& outputType, OutputStream& out) {}

SpvId SPIRVCodeGenerator::castScalarToSignedInt(SpvId inputId, const Type& inputType,
                                                const Type& outputType, OutputStream& out) {}

SpvId SPIRVCodeGenerator::castScalarToUnsignedInt(SpvId inputId, const Type& inputType,
                                                  const Type& outputType, OutputStream& out) {}

SpvId SPIRVCodeGenerator::castScalarToBoolean(SpvId inputId, const Type& inputType,
                                              const Type& outputType, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeMatrixCopy(SpvId src, const Type& srcType, const Type& dstType,
                                          OutputStream& out) {}

void SPIRVCodeGenerator::addColumnEntry(const Type& columnType,
                                        TArray<SpvId>* currentColumn,
                                        TArray<SpvId>* columnIds,
                                        int rows,
                                        SpvId entry,
                                        OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeMatrixConstructor(const ConstructorCompound& c, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeConstructorCompound(const ConstructorCompound& c,
                                                   OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeVectorConstructor(const ConstructorCompound& c, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeConstructorSplat(const ConstructorSplat& c, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeCompositeConstructor(const AnyConstructor& c, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeConstructorScalarCast(const ConstructorScalarCast& c,
                                                     OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeConstructorCompoundCast(const ConstructorCompoundCast& c,
                                                       OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeConstructorDiagonalMatrix(const ConstructorDiagonalMatrix& c,
                                                         OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeConstructorMatrixResize(const ConstructorMatrixResize& c,
                                                       OutputStream& out) {}

static StorageClass get_storage_class_for_global_variable(
        const Variable& var, StorageClass fallbackStorageClass) {}

StorageClass SPIRVCodeGenerator::getStorageClass(const Expression& expr) {}

TArray<SpvId> SPIRVCodeGenerator::getAccessChain(const Expression& expr, OutputStream& out) {}

class PointerLValue : public SPIRVCodeGenerator::LValue {};

class SwizzleLValue : public SPIRVCodeGenerator::LValue {};

int SPIRVCodeGenerator::findUniformFieldIndex(const Variable& var) const {}

std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const Expression& expr,
                                                                          OutputStream& out) {}

std::unique_ptr<Expression> SPIRVCodeGenerator::identifier(std::string_view name) {}

SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeIndexExpression(const IndexExpression& expr, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeFieldAccess(const FieldAccess& f, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeSwizzle(const Expression& baseExpr,
                                       const ComponentArray& components,
                                       OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeSwizzle(const Swizzle& swizzle, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType, const Type& operandType,
                                               SpvId lhs, SpvId rhs,
                                               bool writeComponentwiseIfMatrix,
                                               SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
                                               SpvOp_ ifBool, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeBinaryOperationComponentwiseIfMatrix(const Type& resultType,
                                                                    const Type& operandType,
                                                                    SpvId lhs, SpvId rhs,
                                                                    SpvOp_ ifFloat, SpvOp_ ifInt,
                                                                    SpvOp_ ifUInt, SpvOp_ ifBool,
                                                                    OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType, const Type& operandType,
                                               SpvId lhs, SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt,
                                               SpvOp_ ifUInt, SpvOp_ ifBool, OutputStream& out) {}

SpvId SPIRVCodeGenerator::foldToBool(SpvId id, const Type& operandType, SpvOp op,
                                     OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeMatrixComparison(const Type& operandType, SpvId lhs, SpvId rhs,
                                                SpvOp_ floatOperator, SpvOp_ intOperator,
                                                SpvOp_ vectorMergeOperator, SpvOp_ mergeOperator,
                                                OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeComponentwiseMatrixUnary(const Type& operandType,
                                                        SpvId operand,
                                                        SpvOp_ op,
                                                        OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeComponentwiseMatrixBinary(const Type& operandType, SpvId lhs,
                                                         SpvId rhs, SpvOp_ op, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeReciprocal(const Type& type, SpvId value, OutputStream& out) {}

SpvId SPIRVCodeGenerator::splat(const Type& type, SpvId id, OutputStream& out) {}

static bool types_match(const Type& a, const Type& b) {}

SpvId SPIRVCodeGenerator::writeDecomposedMatrixVectorMultiply(const Type& leftType,
                                                              SpvId lhs,
                                                              const Type& rightType,
                                                              SpvId rhs,
                                                              const Type& resultType,
                                                              OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs, Operator op,
                                                const Type& rightType, SpvId rhs,
                                                const Type& resultType, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeArrayComparison(const Type& arrayType, SpvId lhs, Operator op,
                                               SpvId rhs, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeStructComparison(const Type& structType, SpvId lhs, Operator op,
                                                SpvId rhs, OutputStream& out) {}

SpvId SPIRVCodeGenerator::mergeComparisons(SpvId comparison, SpvId allComparisons, Operator op,
                                           OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeLogicalAnd(const Expression& left, const Expression& right,
                                          OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeLogicalOr(const Expression& left, const Expression& right,
                                         OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writePostfixExpression(const PostfixExpression& p, OutputStream& out) {}

SpvId SPIRVCodeGenerator::writeLiteral(const Literal& l) {}

SpvId SPIRVCodeGenerator::writeLiteral(double value, const Type& type) {}

void SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, OutputStream& out) {}

void SPIRVCodeGenerator::writeFunction(const FunctionDefinition& f, OutputStream& out) {}

void SPIRVCodeGenerator::writeFunctionInstantiation(
        const FunctionDefinition& f,
        Analysis::SpecializationIndex specializationIndex,
        const Analysis::SpecializedParameters* specializedParams,
        OutputStream& out) {}

void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target, Position pos) {}

void SPIRVCodeGenerator::writeFieldLayout(const Layout& layout, SpvId target, int member) {}

MemoryLayout SPIRVCodeGenerator::memoryLayoutForStorageClass(StorageClass storageClass) {}

MemoryLayout SPIRVCodeGenerator::memoryLayoutForVariable(const Variable& v) const {}

SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTFlip) {}

// This function determines whether to skip an OpVariable (of pointer type) declaration for
// compile-time constant scalars and vectors which we turn into OpConstant/OpConstantComposite and
// always reference by value.
//
// Accessing a matrix or array member with a dynamic index requires the use of OpAccessChain which
// requires a base operand of pointer type. However, a vector can always be accessed by value using
// OpVectorExtractDynamic (see writeIndexExpression).
//
// This is why we always emit an OpVariable for all non-scalar and non-vector types in case they get
// accessed via a dynamic index.
static bool is_vardecl_compile_time_constant(const VarDeclaration& varDecl) {}

bool SPIRVCodeGenerator::writeGlobalVarDeclaration(ProgramKind kind,
                                                   const VarDeclaration& varDecl) {}

SpvId SPIRVCodeGenerator::writeGlobalVar(ProgramKind kind,
                                         StorageClass storageClass,
                                         const Variable& var) {}

void SPIRVCodeGenerator::writeVarDeclaration(const VarDeclaration& varDecl, OutputStream& out) {}

void SPIRVCodeGenerator::writeStatement(const Statement& s, OutputStream& out) {}

void SPIRVCodeGenerator::writeBlock(const Block& b, OutputStream& out) {}

SPIRVCodeGenerator::ConditionalOpCounts SPIRVCodeGenerator::getConditionalOpCounts() {}

void SPIRVCodeGenerator::pruneConditionalOps(ConditionalOpCounts ops) {}

void SPIRVCodeGenerator::writeIfStatement(const IfStatement& stmt, OutputStream& out) {}

void SPIRVCodeGenerator::writeForStatement(const ForStatement& f, OutputStream& out) {}

void SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, OutputStream& out) {}

void SPIRVCodeGenerator::writeSwitchStatement(const SwitchStatement& s, OutputStream& out) {}

void SPIRVCodeGenerator::writeReturnStatement(const ReturnStatement& r, OutputStream& out) {}

// Given any function, returns the top-level symbol table (OUTSIDE of the function's scope).
static SymbolTable* get_top_level_symbol_table(const FunctionDeclaration& anyFunc) {}

SPIRVCodeGenerator::EntrypointAdapter SPIRVCodeGenerator::writeEntrypointAdapter(
        const FunctionDeclaration& main) {}

void SPIRVCodeGenerator::writeUniformBuffer(SymbolTable* topLevelSymbolTable) {}

void SPIRVCodeGenerator::addRTFlipUniform(Position pos) {}

std::tuple<const Variable*, const Variable*> SPIRVCodeGenerator::synthesizeTextureAndSampler(
        const Variable& combinedSampler) {}

void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& out) {}

bool SPIRVCodeGenerator::generateCode() {}

bool ToSPIRV(Program& program,
             const ShaderCaps* caps,
             OutputStream& out,
             ValidateSPIRVProc validateSPIRV) {}

bool ToSPIRV(Program& program,
             const ShaderCaps* caps,
             std::string* out,
             ValidateSPIRVProc validateSPIRV) {}

}  // namespace SkSL