chromium/third_party/glslang/src/SPIRV/SpvBuilder.cpp

//
// Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//    Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
//    Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

//
// Helper for making SPIR-V IR.  Generally, this is documented in the header
// SpvBuilder.h.
//

#include <cassert>
#include <cstdlib>

#include <unordered_set>
#include <algorithm>

#include "SpvBuilder.h"
#include "hex_float.h"

#ifndef _WIN32
    #include <cstdio>
#endif

namespace spv {

Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) :{}

Builder::~Builder()
{}

Id Builder::import(const char* name)
{}

// For creating new groupedTypes (will return old type if the requested one was already made).
Id Builder::makeVoidType()
{}

Id Builder::makeBoolType()
{}

Id Builder::makeSamplerType()
{}

Id Builder::makePointer(StorageClass storageClass, Id pointee)
{}

Id Builder::makeForwardPointer(StorageClass storageClass)
{}

Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee)
{}

Id Builder::makeIntegerType(int width, bool hasSign)
{}

Id Builder::makeFloatType(int width)
{}

// Make a struct without checking for duplication.
// See makeStructResultType() for non-decorated structs
// needed as the result of some instructions, which does
// check for duplicates.
Id Builder::makeStructType(const std::vector<Id>& members, const char* name, bool const compilerGenerated)
{}

// Make a struct for the simple results of several instructions,
// checking for duplication.
Id Builder::makeStructResultType(Id type0, Id type1)
{}

Id Builder::makeVectorType(Id component, int size)
{}

Id Builder::makeMatrixType(Id component, int cols, int rows)
{}

Id Builder::makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id cols, Id use)
{}

Id Builder::makeCooperativeMatrixTypeNV(Id component, Id scope, Id rows, Id cols)
{}

Id Builder::makeCooperativeMatrixTypeWithSameShape(Id component, Id otherType)
{}

Id Builder::makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands)
{}

// TODO: performance: track arrays per stride
// If a stride is supplied (non-zero) make an array.
// If no stride (0), reuse previous array types.
// 'size' is an Id of a constant or specialization constant of the array size
Id Builder::makeArrayType(Id element, Id sizeId, int stride)
{}

Id Builder::makeRuntimeArray(Id element)
{}

Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
{}

Id Builder::makeDebugFunctionType(Id returnType, const std::vector<Id>& paramTypes)
{}

Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
    ImageFormat format)
{}

Id Builder::makeSampledImageType(Id imageType)
{}

Id Builder::makeDebugInfoNone()
{}

Id Builder::makeBoolDebugType(int const size)
{}

Id Builder::makeIntegerDebugType(int const width, bool const hasSign)
{}

Id Builder::makeFloatDebugType(int const width)
{}

Id Builder::makeSequentialDebugType(Id const baseType, Id const componentCount, NonSemanticShaderDebugInfo100Instructions const sequenceType)
{}

Id Builder::makeArrayDebugType(Id const baseType, Id const componentCount)
{}

Id Builder::makeVectorDebugType(Id const baseType, int const componentCount)
{}

Id Builder::makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor)
{}

Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc)
{}

// Note: To represent a source language opaque type, this instruction must have no Members operands, Size operand must be
// DebugInfoNone, and Name must start with @ to avoid clashes with user defined names.
Id Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char const*const name,
    NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType)
{}

Id Builder::makePointerDebugType(StorageClass storageClass, Id const baseType)
{}

// Emit a OpExtInstWithForwardRefsKHR nonsemantic instruction for a pointer debug type
// where we don't have the pointee yet. Since we don't have the pointee yet, it just
// points to itself and we rely on patching it later.
Id Builder::makeForwardPointerDebugType(StorageClass storageClass)
{}

Id Builder::makeDebugSource(const Id fileName) {}

Id Builder::makeDebugCompilationUnit() {}

Id Builder::createDebugGlobalVariable(Id const type, char const*const name, Id const variable)
{}

Id Builder::createDebugLocalVariable(Id type, char const*const name, size_t const argNumber)
{}

Id Builder::makeDebugExpression()
{}

Id Builder::makeDebugDeclare(Id const debugLocalVariable, Id const pointer)
{}

Id Builder::makeDebugValue(Id const debugLocalVariable, Id const value)
{}

Id Builder::makeAccelerationStructureType()
{}

Id Builder::makeRayQueryType()
{}

Id Builder::makeHitObjectNVType()
{}

Id Builder::getDerefTypeId(Id resultId) const
{}

Op Builder::getMostBasicTypeClass(Id typeId) const
{}

unsigned int Builder::getNumTypeConstituents(Id typeId) const
{}

// Return the lowest-level type of scalar that an homogeneous composite is made out of.
// Typically, this is just to find out if something is made out of ints or floats.
// However, it includes returning a structure, if say, it is an array of structure.
Id Builder::getScalarTypeId(Id typeId) const
{}

// Return the type of 'member' of a composite.
Id Builder::getContainedTypeId(Id typeId, int member) const
{}

// Figure out the final resulting type of the access chain.
Id Builder::getResultingAccessChainType() const
{}

// Return the immediately contained type of a given composite type.
Id Builder::getContainedTypeId(Id typeId) const
{}

// Returns true if 'typeId' is or contains a scalar type declared with 'typeOp'
// of width 'width'. The 'width' is only consumed for int and float types.
// Returns false otherwise.
bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const
{}

// return true if the type is a pointer to PhysicalStorageBufferEXT or an
// contains such a pointer. These require restrict/aliased decorations.
bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const
{}

// See if a scalar constant of this type has already been created, so it
// can be reused rather than duplicated.  (Required by the specification).
Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value)
{}

// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64').
Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2)
{}

// Return true if consuming 'opcode' means consuming a constant.
// "constant" here means after final transform to executable code,
// the value consumed will be a constant, so includes specialization.
bool Builder::isConstantOpCode(Op opcode) const
{}

// Return true if consuming 'opcode' means consuming a specialization constant.
bool Builder::isSpecConstantOpCode(Op opcode) const
{}

Id Builder::makeNullConstant(Id typeId)
{}

Id Builder::makeBoolConstant(bool b, bool specConstant)
{}

Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant)
{}

Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant)
{}

Id Builder::makeFloatConstant(float f, bool specConstant)
{}

Id Builder::makeDoubleConstant(double d, bool specConstant)
{}

Id Builder::makeFloat16Constant(float f16, bool specConstant)
{}

Id Builder::makeFpConstant(Id type, double d, bool specConstant)
{}

Id Builder::importNonSemanticShaderDebugInfoInstructions()
{}

Id Builder::findCompositeConstant(Op typeClass, Id typeId, const std::vector<Id>& comps)
{}

Id Builder::findStructConstant(Id typeId, const std::vector<Id>& comps)
{}

// Comments in header
Id Builder::makeCompositeConstant(Id typeId, const std::vector<Id>& members, bool specConstant)
{}

Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name)
{}

// Currently relying on the fact that all 'value' of interest are small non-negative values.
void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3)
{}

void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector<unsigned>& literals)
{}

void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector<Id>& operandIds)
{}

void Builder::addName(Id id, const char* string)
{}

void Builder::addMemberName(Id id, int memberNumber, const char* string)
{}

void Builder::addDecoration(Id id, Decoration decoration, int num)
{}

void Builder::addDecoration(Id id, Decoration decoration, const char* s)
{}

void Builder::addDecoration(Id id, Decoration decoration, const std::vector<unsigned>& literals)
{}

void Builder::addDecoration(Id id, Decoration decoration, const std::vector<const char*>& strings)
{}

void Builder::addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType) {}

void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
{}

void Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id>& operandIds)
{}

void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
{}

void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s)
{}

void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<unsigned>& literals)
{}

void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<const char*>& strings)
{}

void Builder::addInstruction(std::unique_ptr<Instruction> inst) {}

// Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint)
{}

// Comments in header
Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType,
                                     const std::vector<Id>& paramTypes,
                                     const std::vector<std::vector<Decoration>>& decorations, Block** entry)
{}

void Builder::setupFunctionDebugInfo(Function* function, const char* name, const std::vector<Id>& paramTypes,
                                     const std::vector<char const*>& paramNames)
{}

Id Builder::makeDebugFunction([[maybe_unused]] Function* function, Id nameId, Id funcTypeId)
{}

Id Builder::makeDebugLexicalBlock(uint32_t line) {}

std::string Builder::unmangleFunctionName(std::string const& name) const
{}

// Comments in header
void Builder::makeReturn(bool implicit, Id retVal)
{}

// Comments in header
void Builder::enterLexicalBlock(uint32_t line)
{}

// Comments in header
void Builder::leaveLexicalBlock()
{}

// Comments in header
void Builder::enterFunction(Function const* function)
{}

// Comments in header
void Builder::leaveFunction()
{}

// Comments in header
void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
{}

// Comments in header
void Builder::makeStatementTerminator(spv::Op opcode, const std::vector<Id>& operands, const char* name)
{}

// Comments in header
Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer,
    bool const compilerGenerated)
{}

// Comments in header
Id Builder::createUndefined(Id type)
{}

// av/vis/nonprivate are unnecessary and illegal for some storage classes.
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
    const
{}

// Comments in header
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
    unsigned int alignment)
{}

// Comments in header
Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess,
    spv::Scope scope, unsigned int alignment)
{}

// Comments in header
Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets)
{}

Id Builder::createArrayLength(Id base, unsigned int member)
{}

Id Builder::createCooperativeMatrixLengthKHR(Id type)
{}

Id Builder::createCooperativeMatrixLengthNV(Id type)
{}

Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
{}

Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector<unsigned>& indexes)
{}

Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index)
{}

Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector<unsigned>& indexes)
{}

Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
{}

Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex)
{}

// An opcode that has no operands, no result id, and no type
void Builder::createNoResultOp(Op opCode)
{}

// An opcode that has one id operand, no result id, and no type
void Builder::createNoResultOp(Op opCode, Id operand)
{}

// An opcode that has one or more operands, no result id, and no type
void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
{}

// An opcode that has multiple operands, no result id, and no type
void Builder::createNoResultOp(Op opCode, const std::vector<IdImmediate>& operands)
{}

void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
{}

void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
{}

// An opcode that has one operands, a result id, and a type
Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
{}

Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
{}

Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
{}

Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
{}

Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& operands)
{}

Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands,
    const std::vector<unsigned>& literals)
{}

Id Builder::createFunctionCall(spv::Function* function, const std::vector<spv::Id>& args)
{}

// Comments in header
Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector<unsigned>& channels)
{}

// Comments in header
Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector<unsigned>& channels)
{}

// Comments in header
void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
{}

// Comments in header
Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
{}

// Comments in header
Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector<Id>& args)
{}

// Accept all parameters needed to create a texture instruction.
// Create the correct instruction based on the inputs, and make the call.
Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
    bool noImplicitLod, const TextureParameters& parameters, ImageOperandsMask signExtensionMask)
{}

// Comments in header
Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult)
{}

// External comments in header.
// Operates recursively to visit the composite's hierarchy.
Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal)
{}

// OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
{}

// Vector or scalar constructor
Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
{}

// Comments in header
Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
{}

// Comments in header
Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) :{}

// Comments in header
void Builder::If::makeBeginElse()
{}

// Comments in header
void Builder::If::makeEndIf()
{}

// Comments in header
void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector<int>& caseValues,
                         const std::vector<int>& valueIndexToSegment, int defaultSegment,
                         std::vector<Block*>& segmentBlocks)
{}

// Comments in header
void Builder::addSwitchBreak()
{}

// Comments in header
void Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegment)
{}

// Comments in header
void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/)
{}

Block& Builder::makeNewBlock()
{}

Builder::LoopBlocks& Builder::makeNewLoop()
{}

void Builder::createLoopContinue()
{}

void Builder::createLoopExit()
{}

void Builder::closeLoop()
{}

void Builder::clearAccessChain()
{}

// Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
    AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{}

// Comments in header
void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{}

// Comments in header
Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform,
    Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess,
    spv::Scope scope, unsigned int alignment)
{}

Id Builder::accessChainGetLValue()
{}

// comment in header
Id Builder::accessChainGetInferredType()
{}

void Builder::dump(std::vector<unsigned int>& out) const
{}

//
// Protected methods.
//

// Turn the described access chain in 'accessChain' into an instruction(s)
// computing its address.  This *cannot* include complex swizzles, which must
// be handled after this is called.
//
// Can generate code.
Id Builder::collapseAccessChain()
{}

// For a dynamic component selection of a swizzle.
//
// Turn the swizzle and dynamic component into just a dynamic component.
//
// Generates code.
void Builder::remapDynamicSwizzle()
{}

// clear out swizzle if it is redundant, that is reselecting the same components
// that would be present without the swizzle.
void Builder::simplifyAccessChainSwizzle()
{}

// To the extent any swizzling can become part of the chain
// of accesses instead of a post operation, make it so.
// If 'dynamic' is true, include transferring the dynamic component,
// otherwise, leave it pending.
//
// Does not generate code. just updates the access chain.
void Builder::transferAccessChainSwizzle(bool dynamic)
{}

// Utility method for creating a new block and setting the insert point to
// be in it. This is useful for flow-control operations that need a "dummy"
// block proceeding them (e.g. instructions after a discard, etc).
void Builder::createAndSetNoPredecessorBlock(const char* /*name*/)
{}

// Comments in header
void Builder::createBranch(Block* block)
{}

void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
{}

void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
                              const std::vector<unsigned int>& operands)
{}

void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
{}

// OpSource
// [OpSourceContinued]
// ...
void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& text,
                                     std::vector<unsigned int>& out) const
{}

// Dump an OpSource[Continued] sequence for the source and every include file
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
{}

template <class Range> void Builder::dumpInstructions(std::vector<unsigned int>& out, const Range& instructions) const
{}

void Builder::dumpModuleProcesses(std::vector<unsigned int>& out) const
{}

bool Builder::DecorationInstructionLessThan::operator()(const std::unique_ptr<Instruction>& lhs,
                                                        const std::unique_ptr<Instruction>& rhs) const
{}
} // end spv namespace