mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
Code drop of the Codeplay spirv-tools source.
This commit contains the source for the SPIRV static library, spirv-as, spirv-dis, and spirv-val tools.
This commit is contained in:
commit
83e5a29b06
65
.clang-format
Normal file
65
.clang-format
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: true
|
||||
AlignEscapedNewlinesLeft: true
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AlwaysBreakAfterDefinitionReturnType: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BinPackParameters: true
|
||||
BinPackArguments: true
|
||||
ColumnLimit: 80
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
DerivePointerAlignment: true
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
IndentCaseLabels: true
|
||||
IndentWrappedFunctionNames: false
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
SpacesBeforeTrailingComments: 2
|
||||
Cpp11BracedListStyle: true
|
||||
Standard: Auto
|
||||
IndentWidth: 2
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
BreakBeforeBraces: Attach
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpacesInAngles: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
ContinuationIndentWidth: 4
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
SpaceBeforeParens: ControlStatements
|
||||
DisableFormat: false
|
||||
...
|
||||
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build*
|
||||
.ycm_extra_conf.py*
|
188
CMakeLists.txt
Normal file
188
CMakeLists.txt
Normal file
@ -0,0 +1,188 @@
|
||||
# Copyright (c) 2015 The Khronos Group Inc.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and/or associated documentation files (the
|
||||
# "Materials"), to deal in the Materials without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
# permit persons to whom the Materials are furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Materials.
|
||||
#
|
||||
# MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
# KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
# SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
# https://www.khronos.org/registry/
|
||||
#
|
||||
# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(SPIRV)
|
||||
|
||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
add_definitions(-DSPIRV_LINUX)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
||||
add_definitions(-DSPIRV_WINDOWS)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||
add_definitions(-DSPIRV_MAC)
|
||||
else()
|
||||
message(FATAL_ERROR "Your platform '${CMAKE_SYSTEM_NAME}' is not supported!")
|
||||
endif()
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
if (UNIX)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
elseif(WIN32)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
endif()
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "No build type selected, default to Debug")
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-exceptions -fno-rtti")
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
|
||||
set(SPIRV_USE_SANITIZER "" CACHE STRING
|
||||
"Use the clang sanitizer [address|memory|thread|...]")
|
||||
if(NOT "${SPIRV_USE_SANITIZER}" STREQUAL "")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${SPIRV_USE_SANITIZER}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=${SPIRV_USE_SANITIZER}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
option(SPIRV_COLOR_TERMINAL "Enable color terminal output" ON)
|
||||
if(${SPIRV_COLOR_TERMINAL})
|
||||
add_definitions(-DSPV_COLOR_TERMINAL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
set(SPIRV_WARNINGS "-Wall -Wextra -Wno-missing-field-initializers")
|
||||
option(SPIRV_WARN_EVERYTHING "Enable -Weverything for SPIRV library" OFF)
|
||||
if(${SPIRV_WARN_EVERYTHING})
|
||||
set(SPIRV_WARNINGS
|
||||
"${SPIRV_WARNINGS} -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded")
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(SPIRV_WARNINGS "-D_CRT_SECURE_NO_WARNINGS /wd4800")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
option(SPIRV_WERROR "Enable error on warning" OFF)
|
||||
if(${SPIRV_WERROR})
|
||||
set(SPIRV_WARNINGS "${SPIRV_WARNINGS} -Werror")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/external/include)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
set(SPIRV_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/binary.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/opcode.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/operand.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/print.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/text.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/validate.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/ext_inst.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/opcode.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/operand.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/print.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/text.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/validate.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/validate_id.cpp)
|
||||
|
||||
add_library(SPIRV ${SPIRV_SOURCES})
|
||||
target_link_libraries(SPIRV ${SPIRV_LIBS})
|
||||
set_target_properties(SPIRV PROPERTIES COMPILE_FLAGS ${SPIRV_WARNINGS})
|
||||
|
||||
add_executable(spirv-as
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/as/as.cpp)
|
||||
set_target_properties(spirv-as PROPERTIES COMPILE_FLAGS ${SPIRV_WARNINGS})
|
||||
target_link_libraries(spirv-as SPIRV)
|
||||
|
||||
add_executable(spirv-dis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/dis/dis.cpp)
|
||||
set_target_properties(spirv-dis PROPERTIES COMPILE_FLAGS ${SPIRV_WARNINGS})
|
||||
target_link_libraries(spirv-dis SPIRV)
|
||||
|
||||
add_executable(spirv-val
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/val/val.cpp)
|
||||
set_target_properties(spirv-val PROPERTIES COMPILE_FLAGS ${SPIRV_WARNINGS})
|
||||
target_link_libraries(spirv-val SPIRV)
|
||||
|
||||
set(GTEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/googletest)
|
||||
if(EXISTS ${GTEST_DIR})
|
||||
if(WIN32)
|
||||
option(gtest_force_shared_crt
|
||||
"Use shared (DLL) run-time lib even when Google Test is built as static lib."
|
||||
ON)
|
||||
endif()
|
||||
|
||||
message(STATUS "Found googletest, building tests.")
|
||||
|
||||
include_directories(SYSTEM
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/external/googletest
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/external/googletest/include)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/googletest)
|
||||
|
||||
add_executable(UnitSPIRV
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/UnitSPIRV.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryEndianness.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/FixWord.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryHeaderGet.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/BinaryToText.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/NamedId.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeTableGet.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeIsVariable.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeRequiresCapabilities.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeMake.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/OpcodeSplit.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/OperandTableGet.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/TextAdvance.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/TextWordGet.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/TextToBinary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/TextDestroy.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/DiagnosticPrint.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/Validate.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/ValidateID.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/main.cpp)
|
||||
target_link_libraries(UnitSPIRV SPIRV gtest)
|
||||
else()
|
||||
message(STATUS "Did not find googletest, tests will not be built."
|
||||
"To enable tests place googletest in '<spirv-dir>/external/googletest'.")
|
||||
endif()
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)
|
||||
install(TARGETS SPIRV spirv-as spirv-dis spirv-val
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
|
||||
DESTINATION include/libspirv/)
|
213
external/include/headers/GLSL450Lib.h
vendored
Normal file
213
external/include/headers/GLSL450Lib.h
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
** Copyright (c) 2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
//
|
||||
// Author: John Kessenich, LunarG
|
||||
//
|
||||
|
||||
namespace GLSL_STD_450 {
|
||||
|
||||
enum Entrypoints {
|
||||
Round = 0,
|
||||
RoundEven = 1,
|
||||
Trunc = 2,
|
||||
Abs = 3,
|
||||
Sign = 4,
|
||||
Floor = 5,
|
||||
Ceil = 6,
|
||||
Fract = 7,
|
||||
|
||||
Radians = 8,
|
||||
Degrees = 9,
|
||||
Sin = 10,
|
||||
Cos = 11,
|
||||
Tan = 12,
|
||||
Asin = 13,
|
||||
Acos = 14,
|
||||
Atan = 15,
|
||||
Sinh = 16,
|
||||
Cosh = 17,
|
||||
Tanh = 18,
|
||||
Asinh = 19,
|
||||
Acosh = 20,
|
||||
Atanh = 21,
|
||||
Atan2 = 22,
|
||||
|
||||
Pow = 23,
|
||||
Exp = 24,
|
||||
Log = 25,
|
||||
Exp2 = 26,
|
||||
Log2 = 27,
|
||||
Sqrt = 28,
|
||||
InverseSqrt = 29,
|
||||
|
||||
Determinant = 30,
|
||||
MatrixInverse = 31,
|
||||
|
||||
Modf = 32, // second argument needs the OpVariable = , not an OpLoad
|
||||
Min = 33,
|
||||
Max = 34,
|
||||
Clamp = 35,
|
||||
Mix = 36,
|
||||
Step = 37,
|
||||
SmoothStep = 38,
|
||||
|
||||
FloatBitsToInt = 39,
|
||||
FloatBitsToUint = 40,
|
||||
IntBitsToFloat = 41,
|
||||
UintBitsToFloat = 42,
|
||||
|
||||
Fma = 43,
|
||||
Frexp = 44,
|
||||
Ldexp = 45,
|
||||
|
||||
PackSnorm4x8 = 46,
|
||||
PackUnorm4x8 = 47,
|
||||
PackSnorm2x16 = 48,
|
||||
PackUnorm2x16 = 49,
|
||||
PackHalf2x16 = 50,
|
||||
PackDouble2x32 = 51,
|
||||
UnpackSnorm2x16 = 52,
|
||||
UnpackUnorm2x16 = 53,
|
||||
UnpackHalf2x16 = 54,
|
||||
UnpackSnorm4x8 = 55,
|
||||
UnpackUnorm4x8 = 56,
|
||||
UnpackDouble2x32 = 57,
|
||||
|
||||
Length = 58,
|
||||
Distance = 59,
|
||||
Cross = 60,
|
||||
Normalize = 61,
|
||||
Ftransform = 62,
|
||||
FaceForward = 63,
|
||||
Reflect = 64,
|
||||
Refract = 65,
|
||||
|
||||
UaddCarry = 66,
|
||||
UsubBorrow = 67,
|
||||
UmulExtended = 68,
|
||||
ImulExtended = 69,
|
||||
BitfieldExtract = 70,
|
||||
BitfieldInsert = 71,
|
||||
BitfieldReverse = 72,
|
||||
BitCount = 73,
|
||||
FindLSB = 74,
|
||||
FindMSB = 75,
|
||||
|
||||
InterpolateAtCentroid = 76,
|
||||
InterpolateAtSample = 77,
|
||||
InterpolateAtOffset = 78,
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
inline void GetDebugNames(const char** names)
|
||||
{
|
||||
for (int i = 0; i < Count; ++i)
|
||||
names[i] = "Unknown";
|
||||
|
||||
names[Round] = "round";
|
||||
names[RoundEven] = "roundEven";
|
||||
names[Trunc] = "trunc";
|
||||
names[Abs] = "abs";
|
||||
names[Sign] = "sign";
|
||||
names[Floor] = "floor";
|
||||
names[Ceil] = "ceil";
|
||||
names[Fract] = "fract";
|
||||
names[Radians] = "radians";
|
||||
names[Degrees] = "degrees";
|
||||
names[Sin] = "sin";
|
||||
names[Cos] = "cos";
|
||||
names[Tan] = "tan";
|
||||
names[Asin] = "asin";
|
||||
names[Acos] = "acos";
|
||||
names[Atan] = "atan";
|
||||
names[Sinh] = "sinh";
|
||||
names[Cosh] = "cosh";
|
||||
names[Tanh] = "tanh";
|
||||
names[Asinh] = "asinh";
|
||||
names[Acosh] = "acosh";
|
||||
names[Atanh] = "atanh";
|
||||
names[Atan2] = "atan2";
|
||||
names[Pow] = "pow";
|
||||
names[Exp] = "exp";
|
||||
names[Log] = "log";
|
||||
names[Exp2] = "exp2";
|
||||
names[Log2] = "log2";
|
||||
names[Sqrt] = "sqrt";
|
||||
names[InverseSqrt] = "inversesqrt";
|
||||
names[Determinant] = "determinant";
|
||||
names[MatrixInverse] = "inverse";
|
||||
names[Modf] = "modf";
|
||||
names[Min] = "min";
|
||||
names[Max] = "max";
|
||||
names[Clamp] = "clamp";
|
||||
names[Mix] = "mix";
|
||||
names[Step] = "step";
|
||||
names[SmoothStep] = "smoothstep";
|
||||
names[FloatBitsToInt] = "floatBitsToInt";
|
||||
names[FloatBitsToUint] = "floatBitsToUint";
|
||||
names[IntBitsToFloat] = "intBitsToFloat";
|
||||
names[UintBitsToFloat] = "uintBitsToFloat";
|
||||
names[Fma] = "fma";
|
||||
names[Frexp] = "frexp";
|
||||
names[Ldexp] = "ldexp";
|
||||
names[PackSnorm4x8] = "packSnorm4x8";
|
||||
names[PackUnorm4x8] = "packUnorm4x8";
|
||||
names[PackSnorm2x16] = "packSnorm2x16";
|
||||
names[PackUnorm2x16] = "packUnorm2x16";
|
||||
names[PackHalf2x16] = "packHalf2x16";
|
||||
names[PackDouble2x32] = "packDouble2x32";
|
||||
names[UnpackSnorm2x16] = "unpackSnorm2x16";
|
||||
names[UnpackUnorm2x16] = "unpackUnorm2x16";
|
||||
names[UnpackHalf2x16] = "unpackHalf2x16";
|
||||
names[UnpackSnorm4x8] = "unpackSnorm4x8";
|
||||
names[UnpackUnorm4x8] = "unpackUnorm4x8";
|
||||
names[UnpackDouble2x32] = "unpackDouble2x32";
|
||||
names[Length] = "length";
|
||||
names[Distance] = "distance";
|
||||
names[Cross] = "cross";
|
||||
names[Normalize] = "normalize";
|
||||
names[Ftransform] = "ftransform";
|
||||
names[FaceForward] = "faceforward";
|
||||
names[Reflect] = "reflect";
|
||||
names[Refract] = "refract";
|
||||
names[UaddCarry] = "uaddCarry";
|
||||
names[UsubBorrow] = "usubBorrow";
|
||||
names[UmulExtended] = "umulExtended";
|
||||
names[ImulExtended] = "imulExtended";
|
||||
names[BitfieldExtract] = "bitfieldExtract";
|
||||
names[BitfieldInsert] = "bitfieldInsert";
|
||||
names[BitfieldReverse] = "bitfieldReverse";
|
||||
names[BitCount] = "bitCount";
|
||||
names[FindLSB] = "findLSB";
|
||||
names[FindMSB] = "findMSB";
|
||||
names[InterpolateAtCentroid] = "interpolateAtCentroid";
|
||||
names[InterpolateAtSample] = "interpolateAtSample";
|
||||
names[InterpolateAtOffset] = "interpolateAtOffset";
|
||||
}
|
||||
|
||||
}; // end namespace GLSL_STD_450
|
307
external/include/headers/OpenCLLib.h
vendored
Normal file
307
external/include/headers/OpenCLLib.h
vendored
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
** Copyright (c) 2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
//
|
||||
// Author: Boaz Ouriel, Intel
|
||||
//
|
||||
|
||||
namespace OpenCLLIB {
|
||||
|
||||
enum Entrypoints {
|
||||
|
||||
// math functions
|
||||
Acos = 0,
|
||||
Acosh = 1,
|
||||
Acospi = 2,
|
||||
Asin = 3,
|
||||
Asinh = 4,
|
||||
Asinpi = 5,
|
||||
Atan = 6,
|
||||
Atan2 = 7,
|
||||
Atanh = 8,
|
||||
Atanpi = 9,
|
||||
Atan2pi = 10,
|
||||
Cbrt = 11,
|
||||
Ceil = 12,
|
||||
Copysign = 13,
|
||||
Cos = 14,
|
||||
Cosh = 15,
|
||||
Cospi = 16,
|
||||
Erfc = 17,
|
||||
Erf = 18,
|
||||
Exp = 19,
|
||||
Exp2 = 20,
|
||||
Exp10 = 21,
|
||||
Expm1 = 22,
|
||||
Fabs = 23,
|
||||
Fdim = 24,
|
||||
Floor = 25,
|
||||
Fma = 26,
|
||||
Fmax = 27,
|
||||
Fmin = 28,
|
||||
Fmod = 29,
|
||||
Fract = 30,
|
||||
Frexp = 31,
|
||||
Hypot = 32,
|
||||
Ilogb = 33,
|
||||
Ldexp = 34,
|
||||
Lgamma = 35,
|
||||
Lgamma_r = 36,
|
||||
Log = 37,
|
||||
Log2 = 38,
|
||||
Log10 = 39,
|
||||
Log1p = 40,
|
||||
Logb = 41,
|
||||
Mad = 42,
|
||||
Maxmag = 43,
|
||||
Minmag = 44,
|
||||
Modf = 45,
|
||||
Nan = 46,
|
||||
Nextafter = 47,
|
||||
Pow = 48,
|
||||
Pown = 49,
|
||||
Powr = 50,
|
||||
Remainder = 51,
|
||||
Remquo = 52,
|
||||
Rint = 53,
|
||||
Rootn = 54,
|
||||
Round = 55,
|
||||
Rsqrt = 56,
|
||||
Sin = 57,
|
||||
Sincos = 58,
|
||||
Sinh = 59,
|
||||
Sinpi = 60,
|
||||
Sqrt = 61,
|
||||
Tan = 62,
|
||||
Tanh = 63,
|
||||
Tanpi = 64,
|
||||
Tgamma = 65,
|
||||
Trunc = 66,
|
||||
Half_cos = 67,
|
||||
Half_divide = 68,
|
||||
Half_exp = 69,
|
||||
Half_exp2 = 70,
|
||||
Half_exp10 = 71,
|
||||
Half_log = 72,
|
||||
Half_log2 = 73,
|
||||
Half_log10 = 74,
|
||||
Half_powr = 75,
|
||||
Half_recip = 76,
|
||||
Half_rsqrt = 77,
|
||||
Half_sin = 78,
|
||||
Half_sqrt = 79,
|
||||
Half_tan = 80,
|
||||
Native_cos = 81,
|
||||
Native_divide = 82,
|
||||
Native_exp = 83,
|
||||
Native_exp2 = 84,
|
||||
Native_exp10 = 85,
|
||||
Native_log = 86,
|
||||
Native_log2 = 87,
|
||||
Native_log10 = 88,
|
||||
Native_powr = 89,
|
||||
Native_recip = 90,
|
||||
Native_rsqrt = 91,
|
||||
Native_sin = 92,
|
||||
Native_sqrt = 93,
|
||||
Native_tan = 94,
|
||||
|
||||
// Common
|
||||
FClamp = 95,
|
||||
Degrees = 96,
|
||||
FMax_common = 97,
|
||||
FMin_common = 98,
|
||||
Mix = 99,
|
||||
Radians = 100,
|
||||
Step = 101,
|
||||
Smoothstep = 102,
|
||||
Sign = 103,
|
||||
|
||||
// Geometrics
|
||||
Cross = 104,
|
||||
Distance = 105,
|
||||
Length = 106,
|
||||
Normalize = 107,
|
||||
Fast_distance = 108,
|
||||
Fast_length = 109,
|
||||
Fast_normalize = 110,
|
||||
|
||||
// Images
|
||||
Read_imagef = 111,
|
||||
Read_imagei = 112,
|
||||
Read_imageui = 113,
|
||||
Read_imageh = 114,
|
||||
|
||||
Read_imagef_samplerless = 115,
|
||||
Read_imagei_samplerless = 116,
|
||||
Read_imageui_samplerless = 117,
|
||||
Read_imageh_samplerless = 118,
|
||||
|
||||
Write_imagef = 119,
|
||||
Write_imagei = 120,
|
||||
Write_imageui = 121,
|
||||
Write_imageh = 122,
|
||||
Read_imagef_mipmap_lod = 123,
|
||||
Read_imagei_mipmap_lod = 124,
|
||||
Read_imageui_mipmap_lod = 125,
|
||||
Read_imagef_mipmap_grad = 126,
|
||||
Read_imagei_mipmap_grad = 127,
|
||||
Read_imageui_mipmap_grad = 128,
|
||||
Write_imagef_mipmap_lod = 129,
|
||||
Write_imagei_mipmap_lod = 130,
|
||||
Write_imageui_mipmap_lod = 131,
|
||||
Get_image_width = 132,
|
||||
Get_image_height = 133,
|
||||
Get_image_depth = 134,
|
||||
Get_image_channel_data_type = 135,
|
||||
Get_image_channel_order = 136,
|
||||
Get_image_dim = 137,
|
||||
Get_image_array_size = 138,
|
||||
Get_image_num_samples = 139,
|
||||
Get_image_num_mip_levels = 140,
|
||||
|
||||
// Integers
|
||||
SAbs = 141,
|
||||
SAbs_diff = 142,
|
||||
SAdd_sat = 143,
|
||||
UAdd_sat = 144,
|
||||
SHadd = 145,
|
||||
UHadd = 146,
|
||||
SRhadd = 147,
|
||||
URhadd = 148,
|
||||
SClamp = 149,
|
||||
UClamp = 150,
|
||||
Clz = 151,
|
||||
Ctz = 152,
|
||||
SMad_hi = 153,
|
||||
UMad_sat = 154,
|
||||
SMad_sat = 155,
|
||||
SMax = 156,
|
||||
UMax = 157,
|
||||
SMin = 158,
|
||||
UMin = 159,
|
||||
SMul_hi = 160,
|
||||
Rotate = 161,
|
||||
SSub_sat = 162,
|
||||
USub_sat = 163,
|
||||
U_Upsample = 164,
|
||||
S_Upsample = 165,
|
||||
Popcount = 166,
|
||||
SMad24 = 167,
|
||||
UMad24 = 168,
|
||||
SMul24 = 169,
|
||||
UMul24 = 170,
|
||||
|
||||
// Vector Loads/Stores
|
||||
Vloadn = 171,
|
||||
Vstoren = 172,
|
||||
Vload_half = 173,
|
||||
Vload_halfn = 174,
|
||||
Vstore_half = 175,
|
||||
Vstore_half_r = 176,
|
||||
Vstore_halfn = 177,
|
||||
Vstore_halfn_r = 178,
|
||||
Vloada_halfn = 179,
|
||||
Vstorea_halfn = 180,
|
||||
Vstorea_halfn_r = 181,
|
||||
|
||||
// Vector Misc
|
||||
Shuffle = 182,
|
||||
Shuffle2 = 183,
|
||||
|
||||
//
|
||||
Printf = 184,
|
||||
Prefetch = 185,
|
||||
|
||||
// Relationals
|
||||
Bitselect = 186,
|
||||
Select = 187,
|
||||
|
||||
// pipes
|
||||
Read_pipe = 188,
|
||||
Write_pipe = 189,
|
||||
Reserve_read_pipe = 190,
|
||||
Reserve_write_pipe = 191,
|
||||
Commit_read_pipe = 192,
|
||||
Commit_write_pipe = 193,
|
||||
Is_valid_reserve_id = 194,
|
||||
Work_group_reserve_read_pipe = 195,
|
||||
Work_group_reserve_write_pipe = 196,
|
||||
Work_group_commit_read_pipe = 197,
|
||||
Work_group_commit_write_pipe = 198,
|
||||
Get_pipe_num_packets = 199,
|
||||
Get_pipe_max_packets = 200,
|
||||
|
||||
// more integers
|
||||
UAbs = 201,
|
||||
UAbs_diff = 202,
|
||||
UMul_hi = 203,
|
||||
UMad_hi = 204,
|
||||
};
|
||||
|
||||
enum ImageChannelOrder {
|
||||
R_ChannelOrder = 0x10B0,
|
||||
A_ChannelOrder = 0x10B1,
|
||||
RG_ChannelOrder = 0x10B2,
|
||||
RA_ChannelOrder = 0x10B3,
|
||||
RGB_ChannelOrder = 0x10B4,
|
||||
RGBA_ChannelOrder = 0x10B5,
|
||||
BGRA_ChannelOrder = 0x10B6,
|
||||
ARGB_ChannelOrder = 0x10B7,
|
||||
INTENSITY_ChannelOrder = 0x10B8,
|
||||
LUMINANCE_ChannelOrder = 0x10B9,
|
||||
Rx_ChannelOrder = 0x10BA,
|
||||
RGx_ChannelOrder = 0x10BB,
|
||||
RGBx_ChannelOrder = 0x10BC,
|
||||
DEPTH_ChannelOrder = 0x10BD,
|
||||
DEPTH_STENCIL_ChannelOrder = 0x10BE,
|
||||
sRGB_ChannelOrder = 0x10BF,
|
||||
sRGBx_ChannelOrder = 0x10C0,
|
||||
sRGBA_ChannelOrder = 0x10C1,
|
||||
sBGRA_ChannelOrder = 0x10C2,
|
||||
};
|
||||
|
||||
enum ImageChannelType {
|
||||
SNORM_INT8_ChannelType = 0x10D0,
|
||||
SNORM_INT16_ChannelType = 0x10D1,
|
||||
UNORM_INT8_ChannelType = 0x10D2,
|
||||
UNORM_INT16_ChannelType = 0x10D3,
|
||||
UNORM_SHORT_565_ChannelType = 0x10D4,
|
||||
UNORM_SHORT_555_ChannelType = 0x10D5,
|
||||
UNORM_INT_101010_ChannelType = 0x10D6,
|
||||
SIGNED_INT8_ChannelType = 0x10D7,
|
||||
SIGNED_INT16_ChannelType = 0x10D8,
|
||||
SIGNED_INT32_ChannelType = 0x10D9,
|
||||
UNSIGNED_INT8_ChannelType = 0x10DA,
|
||||
UNSIGNED_INT16_ChannelType = 0x10DB,
|
||||
UNSIGNED_INT32_ChannelType = 0x10DC,
|
||||
HALF_FLOAT_ChannelType = 0x10DD,
|
||||
FLOAT_ChannelType = 0x10DE,
|
||||
UNORM_INT24_ChannelType = 0x10DF,
|
||||
};
|
||||
|
||||
}; // end namespace OpenCL20
|
||||
|
1354
external/include/headers/spirv.h
vendored
Normal file
1354
external/include/headers/spirv.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
423
include/libspirv/libspirv.h
Normal file
423
include/libspirv/libspirv.h
Normal file
@ -0,0 +1,423 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _CODEPLAY_SPIRV_SPIRV_H_
|
||||
#define _CODEPLAY_SPIRV_SPIRV_H_
|
||||
|
||||
#include <headers/spirv.h>
|
||||
#include <headers/GLSL450Lib.h>
|
||||
#include <headers/OpenCLLib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
using namespace spv;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Magic numbers
|
||||
|
||||
#define SPV_MAGIC_NUMBER 0x07230203
|
||||
#define SPV_VERSION_NUMBER 99u
|
||||
|
||||
// Header indices
|
||||
|
||||
#define SPV_INDEX_MAGIC_NUMBER 0u
|
||||
#define SPV_INDEX_VERSION_NUMBER 1u
|
||||
#define SPV_INDEX_GENERATOR_NUMBER 2u
|
||||
#define SPV_INDEX_BOUND 3u
|
||||
#define SPV_INDEX_SCHEMA 4u
|
||||
#define SPV_INDEX_INSTRUCTION 5u
|
||||
|
||||
// Universal limits
|
||||
|
||||
// NOTE: These are set to the minimum maximum values
|
||||
#define SPV_LIMIT_LITERAL_NAME_MAX 0x00000400
|
||||
#define SPV_LIMIT_LITERAL_STRING_MAX 0x00010000
|
||||
#define SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX 0x00000108
|
||||
#define SPV_LIMIT_RESULT_ID_BOUND 0x00400000
|
||||
#define SPV_LIMIT_CONTROL_FLOW_NEST_DEPTH 0x00000400
|
||||
#define SPV_LIMIT_GLOBAL_VARIABLES_MAX 0x00010000
|
||||
#define SPV_LIMIT_LOCAL_VARIABLES_MAX 0x00080000
|
||||
// TODO: Decorations per target ID max, depends on decoration table size
|
||||
#define SPV_LIMIT_EXECUTION_MODE_PER_ENTRY_POINT_MAX 0x00000100
|
||||
#define SPV_LIMIT_INDICIES_MAX_ACCESS_CHAIN_COMPOSITE_MAX 0x00000100
|
||||
#define SPV_LIMIT_FUNCTION_PARAMETERS_PER_FUNCTION_DECL 0x00000100
|
||||
#define SPV_LIMIT_FUNCTION_CALL_ARGUMENTS_MAX 0x00000100
|
||||
#define SPV_LIMIT_EXT_FUNCTION_CALL_ARGUMENTS_MAX 0x00000100
|
||||
#define SPV_LIMIT_SWITCH_LITERAL_LABEL_PAIRS_MAX 0x00004000
|
||||
#define SPV_LIMIT_STRUCT_MEMBERS_MAX 0x0000400
|
||||
#define SPV_LIMIT_STRUCT_NESTING_DEPTH_MAX 0x00000100
|
||||
|
||||
// Helpers
|
||||
|
||||
#define spvCheck(condition, action) \
|
||||
if (condition) { \
|
||||
action; \
|
||||
}
|
||||
|
||||
#define spvCheckReturn(expression) \
|
||||
{ \
|
||||
spv_result_t error = (expression); \
|
||||
if (error) { \
|
||||
return error; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define spvIsInBitfield(value, bitfield) (value == (value & bitfield))
|
||||
|
||||
#define SPV_BIT(shift) 1 << shift
|
||||
|
||||
#define SPV_FORCE_16_BIT_ENUM(name) _##name = 0x7fff
|
||||
#define SPV_FORCE_32_BIT_ENUM(name) _##name = 0x7fffffff
|
||||
|
||||
// Enumerations
|
||||
|
||||
typedef enum spv_generator_t {
|
||||
SPV_GENERATOR_KHRONOS = 0,
|
||||
SPV_GENERATOR_VALVE = 1,
|
||||
SPV_GENERATOR_LUNARG = 2,
|
||||
SPV_GENERATOR_CODEPLAY = 3,
|
||||
SPV_FORCE_32_BIT_ENUM(spv_generator_t)
|
||||
} spv_generator_t;
|
||||
|
||||
typedef enum spv_result_t {
|
||||
SPV_SUCCESS = 0,
|
||||
SPV_UNSUPPORTED = 1,
|
||||
SPV_END_OF_STREAM = 2,
|
||||
SPV_WARNING = 3,
|
||||
SPV_ERROR_INTERNAL = -1,
|
||||
SPV_ERROR_OUT_OF_MEMORY = -2,
|
||||
SPV_ERROR_INVALID_POINTER = -3,
|
||||
SPV_ERROR_INVALID_BINARY = -4,
|
||||
SPV_ERROR_INVALID_TEXT = -5,
|
||||
SPV_ERROR_INVALID_TABLE = -6,
|
||||
SPV_ERROR_INVALID_VALUE = -7,
|
||||
SPV_ERROR_INVALID_DIAGNOSTIC = -8,
|
||||
SPV_ERROR_INVALID_LOOKUP = -9,
|
||||
SPV_ERROR_INVALID_ID = -10,
|
||||
SPV_FORCE_32_BIT_ENUM(spv_result_t)
|
||||
} spv_result_t;
|
||||
|
||||
typedef enum spv_endianness_t {
|
||||
SPV_ENDIANNESS_LITTLE,
|
||||
SPV_ENDIANNESS_BIG,
|
||||
SPV_FORCE_32_BIT_ENUM(spv_endianness_t)
|
||||
} spv_endianness_t;
|
||||
|
||||
typedef enum spv_opcode_flags_t {
|
||||
SPV_OPCODE_FLAGS_NONE = 0,
|
||||
SPV_OPCODE_FLAGS_VARIABLE = 1,
|
||||
SPV_OPCODE_FLAGS_CAPABILITIES = 2,
|
||||
SPV_FORCE_32_BIT_ENUM(spv_opcode_flags_t)
|
||||
} spv_opcode_flags_t;
|
||||
|
||||
typedef enum spv_operand_type_t {
|
||||
SPV_OPERAND_TYPE_NONE,
|
||||
SPV_OPERAND_TYPE_ID,
|
||||
SPV_OPERAND_TYPE_RESULT_ID,
|
||||
SPV_OPERAND_TYPE_LITERAL,
|
||||
SPV_OPERAND_TYPE_LITERAL_NUMBER,
|
||||
SPV_OPERAND_TYPE_LITERAL_STRING,
|
||||
SPV_OPERAND_TYPE_SOURCE_LANGUAGE,
|
||||
SPV_OPERAND_TYPE_EXECUTION_MODEL,
|
||||
SPV_OPERAND_TYPE_ADDRESSING_MODEL,
|
||||
SPV_OPERAND_TYPE_MEMORY_MODEL,
|
||||
SPV_OPERAND_TYPE_EXECUTION_MODE,
|
||||
SPV_OPERAND_TYPE_STORAGE_CLASS,
|
||||
SPV_OPERAND_TYPE_DIMENSIONALITY,
|
||||
SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE,
|
||||
SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE,
|
||||
SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,
|
||||
SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
|
||||
SPV_OPERAND_TYPE_LINKAGE_TYPE,
|
||||
SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
|
||||
SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
|
||||
SPV_OPERAND_TYPE_DECORATION,
|
||||
SPV_OPERAND_TYPE_BUILT_IN,
|
||||
SPV_OPERAND_TYPE_SELECTION_CONTROL,
|
||||
SPV_OPERAND_TYPE_LOOP_CONTROL,
|
||||
SPV_OPERAND_TYPE_FUNCTION_CONTROL,
|
||||
SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
|
||||
SPV_OPERAND_TYPE_MEMORY_ACCESS,
|
||||
SPV_OPERAND_TYPE_EXECUTION_SCOPE,
|
||||
SPV_OPERAND_TYPE_GROUP_OPERATION,
|
||||
SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS,
|
||||
SPV_OPERAND_TYPE_KERENL_PROFILING_INFO,
|
||||
SPV_OPERAND_TYPE_CAPABILITY,
|
||||
|
||||
SPV_OPERAND_TYPE_ELLIPSIS, // NOTE: Unspecified variable operands
|
||||
SPV_FORCE_32_BIT_ENUM(spv_operand_type_t)
|
||||
} spv_operand_type_t;
|
||||
|
||||
typedef enum spv_ext_inst_type_t {
|
||||
SPV_EXT_INST_TYPE_NONE,
|
||||
SPV_EXT_INST_TYPE_GLSL_STD_450,
|
||||
SPV_EXT_INST_TYPE_OPENCL_STD_12,
|
||||
SPV_EXT_INST_TYPE_OPENCL_STD_20,
|
||||
SPV_EXT_INST_TYPE_OPENCL_STD_21,
|
||||
|
||||
SPV_FORCE_32_BIT_ENUM(spv_ext_inst_type_t)
|
||||
} spv_ext_inst_type_t;
|
||||
|
||||
typedef enum spv_binary_to_text_options_t {
|
||||
SPV_BINARY_TO_TEXT_OPTION_NONE = SPV_BIT(0),
|
||||
SPV_BINARY_TO_TEXT_OPTION_PRINT = SPV_BIT(1),
|
||||
SPV_BINARY_TO_TEXT_OPTION_COLOR = SPV_BIT(2),
|
||||
SPV_FORCE_32_BIT_ENUM(spv_binary_to_text_options_t)
|
||||
} spv_binary_to_text_options_t;
|
||||
|
||||
typedef enum spv_validate_options_t {
|
||||
SPV_VALIDATE_BASIC_BIT = SPV_BIT(0),
|
||||
SPV_VALIDATE_LAYOUT_BIT = SPV_BIT(1),
|
||||
SPV_VALIDATE_ID_BIT = SPV_BIT(2),
|
||||
SPV_VALIDATE_RULES_BIT = SPV_BIT(3),
|
||||
SPV_VALIDATE_ALL = SPV_VALIDATE_BASIC_BIT | SPV_VALIDATE_LAYOUT_BIT |
|
||||
SPV_VALIDATE_ID_BIT | SPV_VALIDATE_RULES_BIT,
|
||||
SPV_FORCE_32_BIT_ENUM(spv_validation_options_t)
|
||||
} spv_validate_options_t;
|
||||
|
||||
// Structures
|
||||
|
||||
typedef struct spv_header_t {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
uint32_t generator;
|
||||
uint32_t bound;
|
||||
uint32_t schema; // NOTE: Reserved
|
||||
const uint32_t *instructions; // NOTE: Unfixed pointer to instruciton stream
|
||||
} spv_header_t;
|
||||
|
||||
typedef struct spv_opcode_desc_t {
|
||||
const char *name;
|
||||
const uint16_t wordCount;
|
||||
const Op opcode;
|
||||
const uint32_t flags; // Bitfield of spv_opcode_flags_t
|
||||
const uint32_t capabilities; // spv_language_capabilities_t
|
||||
const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
|
||||
} spv_opcode_desc_t;
|
||||
|
||||
typedef struct spv_opcode_table_t {
|
||||
const uint32_t count;
|
||||
const spv_opcode_desc_t *entries;
|
||||
} spv_opcode_table_t;
|
||||
|
||||
typedef struct spv_operand_desc_t {
|
||||
const char *name;
|
||||
const uint32_t value;
|
||||
const uint32_t flags; // Bitfield of spv_opcode_flags_t
|
||||
const uint32_t capabilities; // spv_language_capabilities_t
|
||||
const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
|
||||
} spv_operand_desc_t;
|
||||
|
||||
typedef struct spv_operand_desc_group_t {
|
||||
const spv_operand_type_t type;
|
||||
const uint32_t count;
|
||||
const spv_operand_desc_t *entries;
|
||||
} spv_operand_desc_group_t;
|
||||
|
||||
typedef struct spv_operand_table_t {
|
||||
const uint32_t count;
|
||||
const spv_operand_desc_group_t *types;
|
||||
} spv_operand_table_t;
|
||||
|
||||
typedef struct spv_ext_inst_desc_t {
|
||||
const char *name;
|
||||
const uint32_t ext_inst;
|
||||
const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
|
||||
} spv_ext_inst_desc_t;
|
||||
|
||||
typedef struct spv_ext_inst_group_t {
|
||||
const spv_ext_inst_type_t type;
|
||||
const uint32_t count;
|
||||
const spv_ext_inst_desc_t *entries;
|
||||
} spv_ext_inst_group_t;
|
||||
|
||||
typedef struct spv_ext_inst_table_t {
|
||||
const uint32_t count;
|
||||
const spv_ext_inst_group_t *groups;
|
||||
} spv_ext_inst_table_t;
|
||||
|
||||
typedef struct spv_binary_t {
|
||||
uint32_t *code;
|
||||
uint64_t wordCount;
|
||||
} spv_binary_t;
|
||||
|
||||
typedef struct spv_text_t {
|
||||
const char *str;
|
||||
uint64_t length;
|
||||
} spv_text_t;
|
||||
|
||||
typedef struct spv_instruction_t {
|
||||
uint16_t wordCount;
|
||||
Op opcode;
|
||||
spv_ext_inst_type_t extInstType;
|
||||
uint32_t words[SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX];
|
||||
} spv_instruction_t;
|
||||
|
||||
typedef struct spv_position_t {
|
||||
uint64_t line;
|
||||
uint64_t column;
|
||||
uint64_t index;
|
||||
} spv_position_t;
|
||||
|
||||
typedef struct spv_diagnostic_t {
|
||||
spv_position_t position;
|
||||
char *error;
|
||||
} spv_diagnostic_t;
|
||||
|
||||
// Type Definitions
|
||||
|
||||
typedef const spv_opcode_desc_t *spv_opcode_desc;
|
||||
typedef const spv_opcode_table_t *spv_opcode_table;
|
||||
typedef const spv_operand_desc_t *spv_operand_desc;
|
||||
typedef const spv_operand_table_t *spv_operand_table;
|
||||
typedef const spv_ext_inst_desc_t *spv_ext_inst_desc;
|
||||
typedef const spv_ext_inst_table_t *spv_ext_inst_table;
|
||||
typedef spv_binary_t *spv_binary;
|
||||
typedef spv_text_t *spv_text;
|
||||
typedef spv_position_t *spv_position;
|
||||
typedef spv_diagnostic_t *spv_diagnostic;
|
||||
|
||||
// Platform API
|
||||
|
||||
// Opcode API
|
||||
|
||||
/// @brief Populate the Opcode table
|
||||
///
|
||||
/// @param[out] pOpcodeTable table to be populated
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvOpcodeTableGet(spv_opcode_table *pOpcodeTable);
|
||||
|
||||
/// @brief Populate the operand table
|
||||
///
|
||||
/// @param[in] pOperandTable table to be populated
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvOperandTableGet(spv_operand_table *pOperandTable);
|
||||
|
||||
/// @brief Populate the extended instruction table
|
||||
///
|
||||
/// @param pTable table to be populated
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvExtInstTableGet(spv_ext_inst_table *pTable);
|
||||
|
||||
// Text API
|
||||
|
||||
/// @brief Entry point to covert text form to binary form
|
||||
///
|
||||
/// @param[in] text input text
|
||||
/// @param[in] opcodeTable of specified Opcodes
|
||||
/// @param[in] operandTable of specified operands
|
||||
/// @param[in] extInstTable of specified extended instructions
|
||||
/// @param[out] pBinary the binary module
|
||||
/// @param[out] pDiagnostic contains diagnostic on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextToBinary(const spv_text text,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable,
|
||||
spv_binary *pBinary, spv_diagnostic *pDiagnostic);
|
||||
|
||||
/// @brief Free an allocated text stream
|
||||
///
|
||||
/// @param text the text object to be destored
|
||||
void spvTextDestroy(spv_text text);
|
||||
|
||||
// Binary API
|
||||
|
||||
/// @brief Entry point to convert binary to text form
|
||||
///
|
||||
/// @param[in] binary the input binary stream
|
||||
/// @param[in] options bitfield of spv_binary_to_text_options_t values
|
||||
/// @param[in] opcodeTable table of specified Opcodes
|
||||
/// @param[in] operandTable table of specified operands
|
||||
/// @param[in] extInstTable of specified extended instructions
|
||||
/// @param[out] pText the textual form
|
||||
/// @param[out] pDiagnostic contains diagnostic on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryToText(const spv_binary binary, const uint32_t options,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable,
|
||||
spv_text *pText, spv_diagnostic *pDiagnostic);
|
||||
|
||||
/// @brief Free a binary stream from memory
|
||||
///
|
||||
/// @param binary stream to destroy
|
||||
void spvBinaryDestroy(spv_binary binary);
|
||||
|
||||
// Validation API
|
||||
|
||||
/// @brief Validate a SPIR-V binary for correctness
|
||||
///
|
||||
/// @param[in] binary the input binary stream
|
||||
/// @param[in] opcodeTable table of specified Opcodes
|
||||
/// @param[in] operandTable table of specified operands
|
||||
/// @param[in] extInstTable of specified extended instructions
|
||||
/// @param[in] options bitfield of spv_validation_options_t
|
||||
/// @param[out] pDiagnostic contains diagnostic on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvValidate(const spv_binary binary,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable,
|
||||
const uint32_t options, spv_diagnostic *pDiagnostic);
|
||||
|
||||
// Diagnostic API
|
||||
|
||||
/// @brief Create a diagnostic object
|
||||
///
|
||||
/// @param position position in the text or binary stream
|
||||
/// @param message error message to display, is copied
|
||||
///
|
||||
/// @return the diagnostic object
|
||||
spv_diagnostic spvDiagnosticCreate(const spv_position position,
|
||||
const char *message);
|
||||
|
||||
/// @brief Destroy a diagnostic object
|
||||
///
|
||||
/// @param diagnostic object to destory
|
||||
void spvDiagnosticDestroy(spv_diagnostic diagnostic);
|
||||
|
||||
/// @brief Print the diagnostic to stderr
|
||||
///
|
||||
/// @param[in] diagnostic to print
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
25
licence.txt
Normal file
25
licence.txt
Normal file
@ -0,0 +1,25 @@
|
||||
Copyright (c) 2015 The Khronos Group Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and/or associated documentation files (the
|
||||
"Materials"), to deal in the Materials without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
permit persons to whom the Materials are furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Materials.
|
||||
|
||||
MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
https://www.khronos.org/registry/
|
||||
|
||||
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
242
readme.md
Normal file
242
readme.md
Normal file
@ -0,0 +1,242 @@
|
||||
# SPIR-V Tools
|
||||
|
||||
## Overview
|
||||
|
||||
The project includes an assembler, disassembler, and validator for SPIR-V, all
|
||||
based on a common static library. The library contains all of the implementation
|
||||
details and is used in the standalone tools whilst also enabling integration
|
||||
into other code bases directly.
|
||||
|
||||
Currently, the assembler and disassembler only support the core SPIR-V
|
||||
specification (i.e. nothing Vulkan or OpenCL-specific) and the validator is a
|
||||
work in progress. See the Future Work section for more information.
|
||||
|
||||
## Build
|
||||
|
||||
The project uses CMake to generate platform-specific build configurations. To
|
||||
generate these build files issue the following commands.
|
||||
|
||||
```
|
||||
mkdir <spirv-dir>/build
|
||||
cd <spirv-dir>/build
|
||||
cmake [-G<platform-generator>] ..
|
||||
```
|
||||
|
||||
Once the build files have been generated, build using your preferred
|
||||
development environment.
|
||||
|
||||
### CMake Options
|
||||
|
||||
* `SPIRV_USE_SANITIZER=<sanitizer>` - on UNIX platforms with an appropriate
|
||||
version of `clang` this option enables the use of the sanitizers documented
|
||||
[here](http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation),
|
||||
this should only be used with a debug build, disabled by default
|
||||
* `SPIRV_COLOR_TERMINAL=ON` - enables color console output, enabled by default
|
||||
* `SPIRV_WARN_EVERYTHING=OFF` - on UNIX platforms enable the `-Weverything`
|
||||
compiler front end option, disabled by default
|
||||
* `SPIRV_WERROR=OFF` - on UNIX platforms enable the `-Werror` compiler front end
|
||||
option, disabled by default
|
||||
|
||||
## Library
|
||||
|
||||
### Usage
|
||||
|
||||
In order to use the library from an application, the include path should point to
|
||||
`<spirv-dir>/include`, which will enable the application to include the header
|
||||
`<spirv-dir>/include/libspirv/libspirv.h` then linking against the static
|
||||
library in `<spirv-build-dir>/bin/libSPIRV.a` or
|
||||
`<spirv-build-dir>/bin/SPIRV.lib`. The intention is for this to be a C API,
|
||||
however currently it relies on the generated header `spirv.h` meaning this is
|
||||
currently a C++ API.
|
||||
|
||||
* `SPIRV` - the static library CMake target outputs `<spirv-dir>/lib/libSPIRV.a`
|
||||
on Linux/Mac or `<spirv-dir>/lib/SPIRV.lib` on Windows.
|
||||
|
||||
#### Entry Points
|
||||
|
||||
There are three main entry points into the library.
|
||||
|
||||
* `spvTextToBinary` implements the assembler functionality.
|
||||
* `spvBinaryToText` implements the disassembler functionality.
|
||||
* `spvValidate` implements the validator functionality.
|
||||
|
||||
### Source
|
||||
|
||||
In addition to the interface header `<spirv-dir>/include/libspirv/libspirv.h`
|
||||
the implementation source files reside in `<spirv-dir>/source/*`.
|
||||
|
||||
## Tools
|
||||
|
||||
### Assembler
|
||||
|
||||
The standalone assembler is the binary called `spirv-as` and is located in
|
||||
`<spirv-build-dir>/bin/spirv-as`. The functionality of the assembler is
|
||||
implemented by the `spvTextToBinary` library function.
|
||||
|
||||
The assembler operates on the textual form.
|
||||
|
||||
* `spirv-as` - the standalone assembler
|
||||
* `<spirv-dir>/bin/spirv-as`
|
||||
|
||||
#### Options
|
||||
|
||||
* `-o <filename>` is used to specify the output file, otherwise this is set to
|
||||
`out.spv`.
|
||||
|
||||
#### Format
|
||||
|
||||
The assembly attempts to adhere to the binary form as closely as possible using
|
||||
text names from that specification. Here is an example.
|
||||
|
||||
```
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical Simple
|
||||
OpEntryPoint GLCompute $3 "main"
|
||||
OpExecutionMode $3 LocalSize 64 64 1
|
||||
OpTypeVoid %1
|
||||
OpTypeFunction %2 $1
|
||||
OpFunction $1 %3 None $2
|
||||
OpLabel %4
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
```
|
||||
|
||||
Each line encapsulates one and only one instruction, or an OpCode and all of its
|
||||
operands. OpCodes use the names provided in section 3.28 Instructions of the
|
||||
SPIR-V specification, immediate values such as Addressing Model, Memory Model,
|
||||
etc. use the names provided in sections 3.2 Source Language through 3.27
|
||||
Capability of the SPIR-V specification. Literals strings are enclosed in quotes
|
||||
`"<string>"` while literal numbers have no special formatting.
|
||||
|
||||
##### ID Definitions & Usage
|
||||
|
||||
An ID definition pertains to the `Result <id>` of an OpCode, and ID usage is any
|
||||
input to an OpCode. To differentiate between definitions and uses, all ID
|
||||
definitions are prefixed with `%` and take the form `%<id>`, meanwhile all ID
|
||||
uses are prefixed with `$` and take the form `$<id>`. See the above example to
|
||||
see this in action.
|
||||
|
||||
##### Named IDs
|
||||
|
||||
The assembler also supports named IDs, or virtual IDs, which greatly improves
|
||||
the readability of the assembly. The same ID definition and usage prefixes
|
||||
apply. Names must begin with an character in the range `[a-z|A-Z]`. The
|
||||
following example will result in identical SPIR-V binary as the example above.
|
||||
|
||||
```
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical Simple
|
||||
OpEntryPoint GLCompute $main "main"
|
||||
OpExecutionMode $main LocalSize 64 64 1
|
||||
OpTypeVoid %void
|
||||
OpTypeFunction %fnMain $void
|
||||
OpFunction $void %main None $fnMain
|
||||
OpLabel %lbMain
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
```
|
||||
|
||||
##### Arbitrary Integers
|
||||
|
||||
When writing tests it can be useful to emit an invalid 32 bit word into the
|
||||
binary stream at arbitrary positions within the assembly. To specify an
|
||||
arbitrary word into the stream the prefix `!` is used, this takes the form
|
||||
`!<integer>`. Here is an example.
|
||||
|
||||
```
|
||||
OpCapability !0x0000FF000
|
||||
```
|
||||
|
||||
### Disassembler
|
||||
|
||||
The standalone disassembler is the binary called `spirv-dis` and is located in
|
||||
`<spirv-build-dir>/bin/spirv-dis`. The functionality of the disassembler is
|
||||
implemented by the `spvBinaryToText` library function.
|
||||
|
||||
The disassembler operates on the binary form.
|
||||
|
||||
* `spirv-dis` - the standalone disassembler
|
||||
* `<spirv-dir>/bin/spirv-dis`
|
||||
|
||||
#### Options
|
||||
|
||||
* `-o <filename>` is used to specify the output file, otherwise this is set to
|
||||
`out.spvasm`.
|
||||
* `-p` prints the assembly to the console on stdout, this includes colored
|
||||
output on Linux, Windows, and Mac.
|
||||
|
||||
### Validator
|
||||
|
||||
The standalone validator is the binary called `spirv-val` and is located in
|
||||
`<spirv-build-dir>/bin/spirv-val`. The functionality of the validator is
|
||||
implemented by the `spvValidate` library function.
|
||||
|
||||
The validator operates on the binary form.
|
||||
|
||||
* `spirv-val` - the standalone validator
|
||||
* `<spirv-dir>/bin/spirv-val`
|
||||
|
||||
#### Options
|
||||
|
||||
* `-basic` performs basic stream validation, currently not implemented.
|
||||
* `-layout` performs logical layout validation as described in section 2.16
|
||||
Validation Rules, currently not implemented.
|
||||
* `-id` performs ID validation according to the instruction rules in sections
|
||||
3.28.1 through 3.28.22, enabled but is a work in progress.
|
||||
* `-capability` performs capability validation and or reporting, currently not
|
||||
implemented.
|
||||
|
||||
## Tests
|
||||
|
||||
The project contains a number of tests, implemented in the `UnitSPIRV`
|
||||
executable, used to drive the development and correctness of the tools, these
|
||||
use the [googletest](https://code.google.com/p/googletest/) framework. The
|
||||
[googletest](https://code.google.com/p/googletest/) source is not provided with
|
||||
this project, to enable the tests place the
|
||||
[googletest](https://code.google.com/p/googletest/) source in the
|
||||
`<spirv-dir>/external/googletest` directory, rerun CMake if you have already
|
||||
done so previously, CMake will detect the existence of
|
||||
`<spirv-dir>/external/googletest` then build as normal.
|
||||
|
||||
## Future Work
|
||||
|
||||
* Support extension libraries in `spirv-as`, `spirv-dis`, and `spirv-val`.
|
||||
* Complete implementation of ID validation rules in `spirv-val`.
|
||||
* Implement section 2.16 Validation Rules in `spirv-val`.
|
||||
* Implement Capability validation and or report in `spirv-val`.
|
||||
* Improve assembly output from `spirv-dis`.
|
||||
* Improve diagnostic reports.
|
||||
|
||||
## Known Issues
|
||||
|
||||
* Improve literal parsing in the assembler, currently only decimal integers and
|
||||
floating-point numbers are supported as literal operands and the parser is not
|
||||
contextually aware of the desired width of the operand.
|
||||
|
||||
## Licence
|
||||
|
||||
Copyright (c) 2015 The Khronos Group Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and/or associated documentation files (the
|
||||
"Materials"), to deal in the Materials without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
permit persons to whom the Materials are furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Materials.
|
||||
|
||||
MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
https://www.khronos.org/registry/
|
||||
|
||||
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
469
source/binary.cpp
Normal file
469
source/binary.cpp
Normal file
@ -0,0 +1,469 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
#include "binary.h"
|
||||
#include "diagnostic.h"
|
||||
#include "ext_inst.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
// Binary API
|
||||
|
||||
enum {
|
||||
I32_ENDIAN_LITTLE = 0x03020100ul,
|
||||
I32_ENDIAN_BIG = 0x00010203ul,
|
||||
};
|
||||
|
||||
static const union {
|
||||
unsigned char bytes[4];
|
||||
uint32_t value;
|
||||
} o32_host_order = {{0, 1, 2, 3}};
|
||||
|
||||
#define I32_ENDIAN_HOST (o32_host_order.value)
|
||||
|
||||
spv_result_t spvBinaryEndianness(const spv_binary binary,
|
||||
spv_endianness_t *pEndian) {
|
||||
spvCheck(!binary->code || !binary->wordCount,
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
spvCheck(!pEndian, return SPV_ERROR_INVALID_POINTER);
|
||||
|
||||
uint8_t bytes[4];
|
||||
memcpy(bytes, binary->code, sizeof(uint32_t));
|
||||
|
||||
if (0x03 == bytes[0] && 0x02 == bytes[1] && 0x23 == bytes[2] &&
|
||||
0x07 == bytes[3]) {
|
||||
*pEndian = SPV_ENDIANNESS_LITTLE;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
if (0x07 == bytes[0] && 0x23 == bytes[1] && 0x02 == bytes[2] &&
|
||||
0x03 == bytes[3]) {
|
||||
*pEndian = SPV_ENDIANNESS_BIG;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_BINARY;
|
||||
}
|
||||
|
||||
uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian) {
|
||||
if ((SPV_ENDIANNESS_LITTLE == endian && I32_ENDIAN_HOST == I32_ENDIAN_BIG) ||
|
||||
(SPV_ENDIANNESS_BIG == endian && I32_ENDIAN_HOST == I32_ENDIAN_LITTLE)) {
|
||||
return (word & 0x000000ff) << 24 | (word & 0x0000ff00) << 8 |
|
||||
(word & 0x00ff0000) >> 8 | (word & 0xff000000) >> 24;
|
||||
}
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
spv_result_t spvBinaryHeaderGet(const spv_binary binary,
|
||||
const spv_endianness_t endian,
|
||||
spv_header_t *pHeader) {
|
||||
spvCheck(!binary->code || !binary->wordCount,
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
spvCheck(!pHeader, return SPV_ERROR_INVALID_POINTER);
|
||||
|
||||
// TODO: Validation checking?
|
||||
pHeader->magic = spvFixWord(binary->code[SPV_INDEX_MAGIC_NUMBER], endian);
|
||||
pHeader->version = spvFixWord(binary->code[SPV_INDEX_VERSION_NUMBER], endian);
|
||||
pHeader->generator =
|
||||
spvFixWord(binary->code[SPV_INDEX_GENERATOR_NUMBER], endian);
|
||||
pHeader->bound = spvFixWord(binary->code[SPV_INDEX_BOUND], endian);
|
||||
pHeader->schema = spvFixWord(binary->code[SPV_INDEX_SCHEMA], endian);
|
||||
pHeader->instructions = &binary->code[SPV_INDEX_INSTRUCTION];
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvBinaryHeaderSet(spv_binary_t *binary, const uint32_t bound) {
|
||||
spvCheck(!binary, return SPV_ERROR_INVALID_BINARY);
|
||||
spvCheck(!binary->code || !binary->wordCount,
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
binary->code[SPV_INDEX_MAGIC_NUMBER] = SPV_MAGIC_NUMBER;
|
||||
binary->code[SPV_INDEX_VERSION_NUMBER] = SPV_VERSION_NUMBER;
|
||||
binary->code[SPV_INDEX_GENERATOR_NUMBER] = SPV_GENERATOR_CODEPLAY;
|
||||
binary->code[SPV_INDEX_BOUND] = bound;
|
||||
binary->code[SPV_INDEX_SCHEMA] = 0; // NOTE: Reserved
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvBinaryEncodeU32(const uint32_t value, spv_instruction_t *pInst,
|
||||
const spv_position position,
|
||||
spv_diagnostic *pDiagnostic) {
|
||||
spvCheck(pInst->wordCount + 1 > SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX,
|
||||
DIAGNOSTIC << "Instruction word count '"
|
||||
<< SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX << "' exceeded.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
|
||||
pInst->words[pInst->wordCount++] = (uint32_t)value;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvBinaryEncodeU64(const uint64_t value, spv_instruction_t *pInst,
|
||||
const spv_position position,
|
||||
spv_diagnostic *pDiagnostic) {
|
||||
spvCheck(pInst->wordCount + 2 > SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX,
|
||||
DIAGNOSTIC << "Instruction word count '"
|
||||
<< SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX << "' exceeded.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
|
||||
uint32_t low = (uint32_t)(0x00000000ffffffff & value);
|
||||
uint32_t high = (uint32_t)((0xffffffff00000000 & value) >> 32);
|
||||
pInst->words[pInst->wordCount++] = low;
|
||||
pInst->words[pInst->wordCount++] = high;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvBinaryEncodeString(const char *str, spv_instruction_t *pInst,
|
||||
const spv_position position,
|
||||
spv_diagnostic *pDiagnostic) {
|
||||
size_t length = strlen(str);
|
||||
size_t wordCount = (length / 4) + 1;
|
||||
spvCheck((sizeof(uint32_t) * pInst->wordCount) + length >
|
||||
sizeof(uint32_t) * SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX,
|
||||
DIAGNOSTIC << "Instruction word count '"
|
||||
<< SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX << "'exceeded.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
|
||||
char *dest = (char *)&pInst->words[pInst->wordCount];
|
||||
strncpy(dest, str, length);
|
||||
pInst->wordCount += (uint16_t)wordCount;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_operand_type_t spvBinaryOperandInfo(const uint32_t word,
|
||||
const uint16_t operandIndex,
|
||||
const spv_opcode_desc opcodeEntry,
|
||||
const spv_operand_table operandTable,
|
||||
spv_operand_desc *pOperandEntry) {
|
||||
spv_operand_type_t type;
|
||||
if (operandIndex < opcodeEntry->wordCount) {
|
||||
// NOTE: Do operand table lookup to set operandEntry if successful
|
||||
uint16_t index = operandIndex - 1;
|
||||
type = opcodeEntry->operandTypes[index];
|
||||
spv_operand_desc entry = nullptr;
|
||||
if (!spvOperandTableValueLookup(operandTable, type, word, &entry)) {
|
||||
if (SPV_OPERAND_TYPE_NONE != entry->operandTypes[0]) {
|
||||
*pOperandEntry = entry;
|
||||
}
|
||||
}
|
||||
} else if (*pOperandEntry) {
|
||||
// NOTE: Use specified operand entry operand type for this word
|
||||
uint16_t index = operandIndex - opcodeEntry->wordCount;
|
||||
type = (*pOperandEntry)->operandTypes[index];
|
||||
} else if (OpSwitch == opcodeEntry->opcode) {
|
||||
// NOTE: OpSwitch is a special case which expects a list of paired extra
|
||||
// operands
|
||||
assert(0 &&
|
||||
"This case is previously untested, remove this assert and ensure it "
|
||||
"is behaving correctly!");
|
||||
uint16_t lastIndex = opcodeEntry->wordCount - 1;
|
||||
uint16_t index = lastIndex + ((operandIndex - lastIndex) % 2);
|
||||
type = opcodeEntry->operandTypes[index];
|
||||
} else {
|
||||
// NOTE: Default to last operand type in opcode entry
|
||||
uint16_t index = opcodeEntry->wordCount - 1;
|
||||
type = opcodeEntry->operandTypes[index];
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
spv_result_t spvBinaryDecodeOperand(
|
||||
const Op opcode, const spv_operand_type_t type, const uint32_t *words,
|
||||
const spv_endianness_t endian, const uint32_t options,
|
||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||
spv_ext_inst_type_t *pExtInstType, out_stream &stream,
|
||||
spv_position position, spv_diagnostic *pDiagnostic) {
|
||||
spvCheck(!words || !position, return SPV_ERROR_INVALID_POINTER);
|
||||
spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
|
||||
|
||||
bool print = spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options);
|
||||
bool color =
|
||||
print && spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COLOR, options);
|
||||
|
||||
uint64_t index = 0;
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_ID: {
|
||||
stream.get() << ((color) ? clr::yellow() : "");
|
||||
stream.get() << "$" << spvFixWord(words[index], endian);
|
||||
stream.get() << ((color) ? clr::reset() : "");
|
||||
index++;
|
||||
position->index++;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_RESULT_ID: {
|
||||
stream.get() << (color ? clr::blue() : "");
|
||||
stream.get() << "%" << spvFixWord(words[index], endian);
|
||||
stream.get() << (color ? clr::reset() : "");
|
||||
index++;
|
||||
position->index++;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL: {
|
||||
// TODO: Need to support multiple word literals
|
||||
stream.get() << (color ? clr::red() : "");
|
||||
stream.get() << spvFixWord(words[index], endian);
|
||||
stream.get() << (color ? clr::reset() : "");
|
||||
index++;
|
||||
position->index++;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
|
||||
// NOTE: Special case for extended instruction use
|
||||
if (OpExtInst == opcode) {
|
||||
spv_ext_inst_desc extInst;
|
||||
spvCheck(spvExtInstTableValueLookup(extInstTable, *pExtInstType,
|
||||
words[0], &extInst),
|
||||
DIAGNOSTIC << "Invalid extended instruction '" << words[0]
|
||||
<< "'.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
}
|
||||
|
||||
stream.get() << (color ? clr::red() : "");
|
||||
stream.get() << spvFixWord(words[index], endian);
|
||||
stream.get() << (color ? clr::reset() : "");
|
||||
index++;
|
||||
position->index++;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING: {
|
||||
const char *string = (const char *)&words[index];
|
||||
uint64_t stringOperandCount = (strlen(string) / 4) + 1;
|
||||
|
||||
// NOTE: Special case for extended instruction import
|
||||
if (OpExtInstImport == opcode) {
|
||||
*pExtInstType = spvExtInstImportTypeGet(string);
|
||||
spvCheck(SPV_EXT_INST_TYPE_NONE == *pExtInstType,
|
||||
DIAGNOSTIC << "Invalid extended instruction import'" << string
|
||||
<< "'.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
}
|
||||
|
||||
stream.get() << "\"";
|
||||
stream.get() << (color ? clr::green() : "");
|
||||
stream.get() << string;
|
||||
stream.get() << (color ? clr::reset() : "");
|
||||
stream.get() << "\"";
|
||||
index += stringOperandCount;
|
||||
position->index += stringOperandCount;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_CAPABILITY:
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODE:
|
||||
case SPV_OPERAND_TYPE_STORAGE_CLASS:
|
||||
case SPV_OPERAND_TYPE_DIMENSIONALITY:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
|
||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
|
||||
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
|
||||
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
|
||||
case SPV_OPERAND_TYPE_DECORATION:
|
||||
case SPV_OPERAND_TYPE_BUILT_IN:
|
||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS:
|
||||
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_SCOPE:
|
||||
case SPV_OPERAND_TYPE_GROUP_OPERATION:
|
||||
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
|
||||
case SPV_OPERAND_TYPE_KERENL_PROFILING_INFO: {
|
||||
spv_operand_desc entry;
|
||||
spvCheck(
|
||||
spvOperandTableValueLookup(operandTable, type,
|
||||
spvFixWord(words[index], endian), &entry),
|
||||
DIAGNOSTIC << "Invalid " << spvOperandTypeStr(type) << " operand '"
|
||||
<< words[index] << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
stream.get() << entry->name;
|
||||
index++;
|
||||
position->index++;
|
||||
} break;
|
||||
default: {
|
||||
DIAGNOSTIC << "Invalid binary operand '" << type << "'";
|
||||
return SPV_ERROR_INVALID_BINARY;
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvBinaryDecodeOpcode(
|
||||
spv_instruction_t *pInst, const spv_endianness_t endian,
|
||||
const uint32_t options, const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||
out_stream &stream, spv_position position, spv_diagnostic *pDiagnostic) {
|
||||
spvCheck(!pInst || !position, return SPV_ERROR_INVALID_POINTER);
|
||||
spvCheck(!opcodeTable || !operandTable || !extInstTable,
|
||||
return SPV_ERROR_INVALID_TABLE);
|
||||
spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
|
||||
|
||||
uint16_t wordCount;
|
||||
Op opcode;
|
||||
spvOpcodeSplit(spvFixWord(pInst->words[0], endian), &wordCount, &opcode);
|
||||
|
||||
spv_opcode_desc opcodeEntry;
|
||||
spvCheck(spvOpcodeTableValueLookup(opcodeTable, opcode, &opcodeEntry),
|
||||
DIAGNOSTIC << "Invalid Opcode '" << opcode << "'.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
spvCheck(opcodeEntry->wordCount > wordCount,
|
||||
DIAGNOSTIC << "Invalid instruction word count '" << wordCount
|
||||
<< "', expected at least '" << opcodeEntry->wordCount
|
||||
<< "'.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
stream.get() << "Op" << opcodeEntry->name;
|
||||
|
||||
position->index++;
|
||||
|
||||
spv_operand_desc operandEntry = nullptr;
|
||||
for (uint16_t index = 1; index < wordCount; ++index) {
|
||||
const uint32_t word = spvFixWord(pInst->words[index], endian);
|
||||
const uint64_t currentPosIndex = position->index;
|
||||
|
||||
stream.get() << " ";
|
||||
spv_operand_type_t type = spvBinaryOperandInfo(word, index, opcodeEntry,
|
||||
operandTable, &operandEntry);
|
||||
spvCheck(spvBinaryDecodeOperand(
|
||||
opcodeEntry->opcode, type, pInst->words + index, endian,
|
||||
options, operandTable, extInstTable, &pInst->extInstType,
|
||||
stream, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
index += (uint16_t)(position->index - currentPosIndex - 1);
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvBinaryToText(const spv_binary binary, const uint32_t options,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable,
|
||||
spv_text *pText, spv_diagnostic *pDiagnostic) {
|
||||
spvCheck(!binary->code || !binary->wordCount,
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
spvCheck(!opcodeTable || !operandTable || !extInstTable,
|
||||
return SPV_ERROR_INVALID_TABLE);
|
||||
spvCheck(pText && spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options),
|
||||
return SPV_ERROR_INVALID_POINTER);
|
||||
spvCheck(!pText && !spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options),
|
||||
return SPV_ERROR_INVALID_POINTER);
|
||||
spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
|
||||
|
||||
spv_endianness_t endian;
|
||||
spv_position_t position = {};
|
||||
spvCheck(spvBinaryEndianness(binary, &endian),
|
||||
DIAGNOSTIC << "Invalid SPIR-V magic number '" << std::hex
|
||||
<< binary->code[0] << "'.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
spv_header_t header;
|
||||
spvCheck(spvBinaryHeaderGet(binary, endian, &header),
|
||||
DIAGNOSTIC << "Invalid SPIR-V header.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
bool print = spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options);
|
||||
bool color =
|
||||
print && spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COLOR, options);
|
||||
|
||||
std::stringstream sstream;
|
||||
out_stream stream(sstream);
|
||||
if (print) {
|
||||
stream = out_stream();
|
||||
}
|
||||
|
||||
if (color) {
|
||||
stream.get() << clr::grey();
|
||||
}
|
||||
stream.get() << "; SPIR-V\n"
|
||||
<< "; Version: " << header.version << "\n"
|
||||
<< "; Generator: " << spvGeneratorStr(header.generator) << "\n"
|
||||
<< "; Bound: " << header.bound << "\n"
|
||||
<< "; Schema: " << header.schema << "\n";
|
||||
if (color) {
|
||||
stream.get() << clr::reset();
|
||||
}
|
||||
|
||||
const uint32_t *words = binary->code;
|
||||
position.index = SPV_INDEX_INSTRUCTION;
|
||||
spv_ext_inst_type_t extInstType = SPV_EXT_INST_TYPE_NONE;
|
||||
while (position.index < binary->wordCount) {
|
||||
uint64_t index = position.index;
|
||||
uint16_t wordCount;
|
||||
Op opcode;
|
||||
spvOpcodeSplit(spvFixWord(words[position.index], endian), &wordCount,
|
||||
&opcode);
|
||||
|
||||
spv_instruction_t inst = {};
|
||||
inst.extInstType = extInstType;
|
||||
spvInstructionCopy(&words[position.index], opcode, wordCount, endian,
|
||||
&inst);
|
||||
|
||||
spvCheck(
|
||||
spvBinaryDecodeOpcode(&inst, endian, options, opcodeTable, operandTable,
|
||||
extInstTable, stream, &position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
extInstType = inst.extInstType;
|
||||
|
||||
spvCheck((index + wordCount) != position.index,
|
||||
DIAGNOSTIC << "Invalid word count.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
stream.get() << "\n";
|
||||
}
|
||||
|
||||
if (!print) {
|
||||
size_t length = sstream.str().size();
|
||||
char *str = new char[length + 1];
|
||||
spvCheck(!str, return SPV_ERROR_OUT_OF_MEMORY);
|
||||
strncpy(str, sstream.str().c_str(), length + 1);
|
||||
spv_text text = new spv_text_t();
|
||||
spvCheck(!text, return SPV_ERROR_OUT_OF_MEMORY);
|
||||
text->str = str;
|
||||
text->length = length;
|
||||
*pText = text;
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
void spvBinaryDestroy(spv_binary binary) {
|
||||
spvCheck(!binary, return );
|
||||
if (binary->code) {
|
||||
delete[] binary->code;
|
||||
}
|
||||
delete binary;
|
||||
}
|
166
source/binary.h
Normal file
166
source/binary.h
Normal file
@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _LIBSPIRV_UTIL_BINARY_H_
|
||||
#define _LIBSPIRV_UTIL_BINARY_H_
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
#include "print.h"
|
||||
|
||||
// Functions
|
||||
|
||||
/// @brief Fix the endianness of a word
|
||||
///
|
||||
/// @param[in] word whos endianness should be fixed
|
||||
/// @param[in] endian the desired endianness
|
||||
///
|
||||
/// @return word with host endianness correction
|
||||
uint32_t spvFixWord(const uint32_t word, const spv_endianness_t endian);
|
||||
|
||||
/// @brief Determine the endianness of the SPV binary
|
||||
///
|
||||
/// Gets the endianness of the SPV source. Returns SPV_ENDIANNESS_UNKNOWN if
|
||||
/// the
|
||||
/// SPV magic number is invalid, otherwise the determined endianness.
|
||||
///
|
||||
/// @param[in] binary the binary module
|
||||
/// @param[out] pEndian return the endianness of the SPV module
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryEndianness(const spv_binary binary,
|
||||
spv_endianness_t *pEndian);
|
||||
|
||||
/// @brief Grab the header from the SPV module
|
||||
///
|
||||
/// @param[in] binary the binary module
|
||||
/// @param[in] endian the endianness of the module
|
||||
/// @param[out] pHeader the returned header
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryHeaderGet(const spv_binary binary,
|
||||
const spv_endianness_t endian,
|
||||
spv_header_t *pHeader);
|
||||
|
||||
/// @brief Populate a binary stream with this generators header
|
||||
///
|
||||
/// @param[in,out] binary the binary stream
|
||||
/// @param[in] bound the upper ID bound
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryHeaderSet(spv_binary binary, const uint32_t bound);
|
||||
|
||||
/// @brief Append a single word into a binary stream
|
||||
///
|
||||
/// @param[in] value the word to encode
|
||||
/// @param[in] pInst the stream to append to
|
||||
/// @param[in,out] position position in the binary
|
||||
/// @param[out] pDiagnostic contains diagnostic on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryEncodeU32(const uint32_t value, spv_instruction_t *pInst,
|
||||
const spv_position position,
|
||||
spv_diagnostic *pDiagnostic);
|
||||
|
||||
/// @brief Append two related words into the binary stream
|
||||
///
|
||||
/// @param[in] value the two words to encode
|
||||
/// @param[in] pInst the stream to append to
|
||||
/// @param[in,out] position position in the binary
|
||||
/// @param[out] pDiagnostic contains diagnostic on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryEncodeU64(const uint64_t value, spv_instruction_t *pInst,
|
||||
const spv_position position,
|
||||
spv_diagnostic *pDiagnostic);
|
||||
|
||||
/// @brief Append a string literal in the binary stream
|
||||
///
|
||||
/// @param[in] str the string to encode
|
||||
/// @param[in] pInst the stream to append to
|
||||
/// @param[in,out] position position in the binary
|
||||
/// @param[out] pDiagnostic contains diagnostic on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryEncodeString(const char *str, spv_instruction_t *pInst,
|
||||
const spv_position position,
|
||||
spv_diagnostic *pDiagnostic);
|
||||
|
||||
/// @brief Determine the type of the desired operand
|
||||
///
|
||||
/// @param[in] word the operand value
|
||||
/// @param[in] index the word index in the instruction
|
||||
/// @param[in] opcodeEntry table of specified Opcodes
|
||||
/// @param[in] operandTable table of specified operands
|
||||
/// @param[in,out] pOperandEntry the entry in the operand table
|
||||
///
|
||||
/// @return type returned
|
||||
spv_operand_type_t spvBinaryOperandInfo(const uint32_t word,
|
||||
const uint16_t index,
|
||||
const spv_opcode_desc opcodeEntry,
|
||||
const spv_operand_table operandTable,
|
||||
spv_operand_desc *pOperandEntry);
|
||||
|
||||
/// @brief Translate a binary operand to the textual form
|
||||
///
|
||||
/// @param[in] opcode of the current instruction
|
||||
/// @param[in] type type of the operand to decode
|
||||
/// @param[in] words the binary stream of words
|
||||
/// @param[in] endian the endianness of the stream
|
||||
/// @param[in] options bitfield of spv_binary_to_text_options_t values
|
||||
/// @param[in] operandTable table of specified operands
|
||||
/// @param[in,out] pExtInstType type of extended instruction library
|
||||
/// @param[in,out] stream the text output stream
|
||||
/// @param[in,out] position position in the binary stream
|
||||
/// @param[out] pDiag return diagnostic on error
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryDecodeOperand(
|
||||
const Op opcode, const spv_operand_type_t type, const uint32_t *words,
|
||||
const spv_endianness_t endian, const uint32_t options,
|
||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||
spv_ext_inst_type_t *pExtInstType, out_stream &stream,
|
||||
spv_position position, spv_diagnostic *pDiag);
|
||||
|
||||
/// @brief Translate binary Opcode stream to textual form
|
||||
///
|
||||
/// @param[in] pInst the Opcode instruction stream
|
||||
/// @param[in] endian the endianness of the stream
|
||||
/// @param[in] options bitfield of spv_binary_to_text_options_t values
|
||||
/// @param[in] opcodeTable table of specified Opcodes
|
||||
/// @param[in] operandTable table of specified operands
|
||||
/// @param[out] stream output text stream
|
||||
/// @param[in,out] position position in the stream
|
||||
/// @param[out] pDiag return diagnostic on error
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvBinaryDecodeOpcode(
|
||||
spv_instruction_t *pInst, const spv_endianness_t endian,
|
||||
const uint32_t options, const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||
out_stream &stream, spv_position position, spv_diagnostic *pDiag);
|
||||
|
||||
#endif
|
||||
|
81
source/diagnostic.cpp
Normal file
81
source/diagnostic.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
#include "diagnostic.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// Diagnostic API
|
||||
|
||||
spv_diagnostic spvDiagnosticCreate(const spv_position position,
|
||||
const char *message) {
|
||||
spv_diagnostic diagnostic = new spv_diagnostic_t;
|
||||
spvCheck(!diagnostic, return nullptr);
|
||||
size_t length = strlen(message) + 1;
|
||||
diagnostic->error = new char[length];
|
||||
spvCheck(!diagnostic->error, delete diagnostic; return nullptr);
|
||||
diagnostic->position = *position;
|
||||
memset(diagnostic->error, 0, length);
|
||||
strncpy(diagnostic->error, message, length);
|
||||
return diagnostic;
|
||||
}
|
||||
|
||||
void spvDiagnosticDestroy(spv_diagnostic diagnostic) {
|
||||
spvCheck(!diagnostic, return );
|
||||
if (diagnostic->error) {
|
||||
delete[] diagnostic->error;
|
||||
}
|
||||
delete diagnostic;
|
||||
}
|
||||
|
||||
spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic) {
|
||||
spvCheck(!diagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
|
||||
|
||||
// TODO: Check that the logic choosing between a text or binary diagnostic is
|
||||
// corrent.
|
||||
if ((diagnostic->position.line || diagnostic->position.column) &&
|
||||
diagnostic->position.index) {
|
||||
// NOTE: This is a text position
|
||||
// NOTE: add 1 to the line as editors start at line 1, we are counting new
|
||||
// line characters to start at line 0
|
||||
std::cerr << "error: " << diagnostic->position.line + 1 << ": "
|
||||
<< diagnostic->position.column + 1 << ": " << diagnostic->error
|
||||
<< "\n";
|
||||
return SPV_SUCCESS;
|
||||
} else if (!diagnostic->position.line && !diagnostic->position.column &&
|
||||
diagnostic->position.index) {
|
||||
// NOTE: This is a binary position
|
||||
std::cerr << "error: " << diagnostic->position.index << ": "
|
||||
<< diagnostic->error << "\n";
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_VALUE;
|
||||
}
|
59
source/diagnostic.h
Normal file
59
source/diagnostic.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _LIBSPIRV_UTIL_DIAGNOSTIC_H_
|
||||
#define _LIBSPIRV_UTIL_DIAGNOSTIC_H_
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
class diagnostic_helper {
|
||||
public:
|
||||
diagnostic_helper(spv_position_t &position, spv_diagnostic *pDiagnostic)
|
||||
: position(&position), pDiagnostic(pDiagnostic) {}
|
||||
|
||||
diagnostic_helper(spv_position position, spv_diagnostic *pDiagnostic)
|
||||
: position(position), pDiagnostic(pDiagnostic) {}
|
||||
|
||||
~diagnostic_helper() {
|
||||
*pDiagnostic = spvDiagnosticCreate(position, stream.str().c_str());
|
||||
}
|
||||
|
||||
std::stringstream stream;
|
||||
|
||||
private:
|
||||
spv_position position;
|
||||
spv_diagnostic *pDiagnostic;
|
||||
};
|
||||
|
||||
#define DIAGNOSTIC \
|
||||
diagnostic_helper helper(position, pDiagnostic); \
|
||||
helper.stream
|
||||
|
||||
#endif
|
113
source/ext_inst.cpp
Normal file
113
source/ext_inst.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const spv_ext_inst_desc_t glslStd450Entries[] = {
|
||||
{
|
||||
"round", GLSL_STD_450::Round, {SPV_OPERAND_TYPE_ID},
|
||||
},
|
||||
// TODO: Add remaining GLSL.std.450 instructions
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t openclStd12Entries[] = {
|
||||
{"placeholder", 0, {}},
|
||||
// TODO: Add remaining OpenCL.std.12 instructions
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t openclStd20Entries[] = {
|
||||
{"placeholder", 0, {}},
|
||||
// TODO: Add remaining OpenCL.std.20 instructions
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t openclStd21Entries[] = {
|
||||
{"placeholder", 0, {}},
|
||||
// TODO: Add remaining OpenCL.std.21 instructions
|
||||
};
|
||||
|
||||
spv_result_t spvExtInstTableGet(spv_ext_inst_table *pExtInstTable) {
|
||||
spvCheck(!pExtInstTable, return SPV_ERROR_INVALID_POINTER);
|
||||
|
||||
static const spv_ext_inst_group_t groups[] = {
|
||||
{SPV_EXT_INST_TYPE_GLSL_STD_450,
|
||||
sizeof(glslStd450Entries) / sizeof(spv_ext_inst_desc_t),
|
||||
glslStd450Entries},
|
||||
{SPV_EXT_INST_TYPE_OPENCL_STD_12,
|
||||
sizeof(openclStd12Entries) / sizeof(spv_ext_inst_desc_t),
|
||||
openclStd12Entries},
|
||||
{SPV_EXT_INST_TYPE_OPENCL_STD_20,
|
||||
sizeof(openclStd20Entries) / sizeof(spv_ext_inst_desc_t),
|
||||
openclStd20Entries},
|
||||
{SPV_EXT_INST_TYPE_OPENCL_STD_21,
|
||||
sizeof(openclStd21Entries) / sizeof(spv_ext_inst_desc_t),
|
||||
openclStd21Entries},
|
||||
};
|
||||
|
||||
static const spv_ext_inst_table_t table = {
|
||||
sizeof(groups) / sizeof(spv_ext_inst_group_t), groups};
|
||||
|
||||
*pExtInstTable = &table;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_ext_inst_type_t spvExtInstImportTypeGet(const char *name) {
|
||||
if (!strcmp("GLSL.std.450", name)) {
|
||||
return SPV_EXT_INST_TYPE_GLSL_STD_450;
|
||||
}
|
||||
if (!strcmp("OpenCL.std.12", name)) {
|
||||
return SPV_EXT_INST_TYPE_OPENCL_STD_12;
|
||||
}
|
||||
if (!strcmp("OpenCL.std.20", name)) {
|
||||
return SPV_EXT_INST_TYPE_OPENCL_STD_20;
|
||||
}
|
||||
if (!strcmp("OpenCL.std.21", name)) {
|
||||
return SPV_EXT_INST_TYPE_OPENCL_STD_21;
|
||||
}
|
||||
return SPV_EXT_INST_TYPE_NONE;
|
||||
}
|
||||
|
||||
spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const char *name,
|
||||
spv_ext_inst_desc *pEntry) {
|
||||
spvCheck(!table, return SPV_ERROR_INVALID_TABLE);
|
||||
spvCheck(!pEntry, return SPV_ERROR_INVALID_POINTER);
|
||||
|
||||
for (uint32_t groupIndex = 0; groupIndex < table->count; groupIndex++) {
|
||||
auto &group = table->groups[groupIndex];
|
||||
if (type == group.type) {
|
||||
for (uint32_t index = 0; index < group.count; index++) {
|
||||
auto &entry = group.entries[index];
|
||||
if (!strcmp(name, entry.name)) {
|
||||
*pEntry = &table->groups[groupIndex].entries[index];
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
spv_result_t spvExtInstTableValueLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const uint32_t value,
|
||||
spv_ext_inst_desc *pEntry) {
|
||||
spvCheck(!table, return SPV_ERROR_INVALID_TABLE);
|
||||
spvCheck(!pEntry, return SPV_ERROR_INVALID_POINTER);
|
||||
|
||||
for (uint32_t groupIndex = 0; groupIndex < table->count; groupIndex++) {
|
||||
auto &group = table->groups[groupIndex];
|
||||
if (type == group.type) {
|
||||
for (uint32_t index = 0; index < group.count; index++) {
|
||||
auto &entry = group.entries[index];
|
||||
if (value == entry.ext_inst) {
|
||||
*pEntry = &table->groups[groupIndex].entries[index];
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
65
source/ext_inst.h
Normal file
65
source/ext_inst.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _CODEPLAY_SPIRV_EXT_INST_H_
|
||||
#define _CODEPLAY_SPIRV_EXT_INST_H_
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
/// @brief Get the type from the extended instruction library string
|
||||
///
|
||||
/// @param name of the library
|
||||
///
|
||||
/// @return type of the extended instruction library
|
||||
spv_ext_inst_type_t spvExtInstImportTypeGet(const char *name);
|
||||
|
||||
/// @brief Find the extented instruction with value in the table
|
||||
///
|
||||
/// @param table to lookup
|
||||
/// @param type of the extended instruction import
|
||||
/// @param name of the extended instruction to find
|
||||
/// @param pEntry return the extended instruction entry
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const char *name,
|
||||
spv_ext_inst_desc *pEntry);
|
||||
|
||||
/// @brief Find the extented instruction with value in the table
|
||||
///
|
||||
/// @param table to lookup
|
||||
/// @param type of the extended instruction import
|
||||
/// @param value of the extended instruction to find
|
||||
/// @param pEntry return the extended instruction entry
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvExtInstTableValueLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const uint32_t value,
|
||||
spv_ext_inst_desc *pEntry);
|
||||
|
||||
#endif
|
2476
source/opcode.cpp
Normal file
2476
source/opcode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
186
source/opcode.h
Normal file
186
source/opcode.h
Normal file
@ -0,0 +1,186 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _LIBSPIRV_UTIL_OPCODE_H_
|
||||
#define _LIBSPIRV_UTIL_OPCODE_H_
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
// Functions
|
||||
|
||||
/// @brief Get the name of the SPIR-V generator
|
||||
///
|
||||
/// @param[in] generator Khronos SPIR-V generator ID
|
||||
///
|
||||
/// @return string name
|
||||
const char *spvGeneratorStr(uint32_t generator);
|
||||
|
||||
/// @brief Combine word count and Opcode enumerant in single word
|
||||
///
|
||||
/// @param[in] wordCount Opcode consumes
|
||||
/// @param[in] opcode enumerant value
|
||||
///
|
||||
/// @return Opcode word
|
||||
uint32_t spvOpcodeMake(uint16_t wordCount, Op opcode);
|
||||
|
||||
/// @brief Split the binary opcode into its constituent parts
|
||||
///
|
||||
/// @param[in] word binary opcode to split
|
||||
/// @param[out] wordCount the returned number of words (optional)
|
||||
/// @param[out] opcode the returned opcode enumerant (optional)
|
||||
void spvOpcodeSplit(const uint32_t word, uint16_t *wordCount, Op *opcode);
|
||||
|
||||
/// @brief Find the named Opcode in the table
|
||||
///
|
||||
/// @param[in] table to lookup
|
||||
/// @param[in] name name of Opcode to find
|
||||
/// @param[out] pEntry returned Opcode table entry
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
|
||||
const char *name, spv_opcode_desc *pEntry);
|
||||
|
||||
/// @brief Find the opcode ID in the table
|
||||
///
|
||||
/// @param[out] table to lookup
|
||||
/// @param[in] opcode value of Opcode to fine
|
||||
/// @param[out] pEntry return Opcode table entry
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
|
||||
const Op opcode, spv_opcode_desc *pEntry);
|
||||
|
||||
/// @brief Determine if the Opcode has variable word count
|
||||
///
|
||||
/// This function does not check if @a entry is valid.
|
||||
///
|
||||
/// @param[in] entry the Opcode entry
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsVariable(spv_opcode_desc entry);
|
||||
|
||||
/// @brief Determine if the Opcode has capaspvity requirements
|
||||
///
|
||||
/// This function does not check if @a entry is valid.
|
||||
///
|
||||
/// @param[in] entry the Opcode entry
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry);
|
||||
|
||||
/// @brief Copy an instructions word and fix the endianness
|
||||
///
|
||||
/// @param[in] words the input instruction stream
|
||||
/// @param[in] opcode the instructions Opcode
|
||||
/// @param[in] wordCount the number of words to copy
|
||||
/// @param[in] endian the endianness of the stream
|
||||
/// @param[out] pInst the returned instruction
|
||||
void spvInstructionCopy(const uint32_t *words, const Op opcode,
|
||||
const uint16_t wordCount, const spv_endianness_t endian,
|
||||
spv_instruction_t *pInst);
|
||||
|
||||
/// @brief Get the string of an OpCode
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return the opcode string
|
||||
const char *spvOpcodeString(const Op opcode);
|
||||
|
||||
/// @brief Determine if the Opcode is a type
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsType(const Op opcode);
|
||||
|
||||
/// @brief Determine if the OpCode is a scalar type
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsScalarType(const Op opcode);
|
||||
|
||||
/// @brief Determine if the Opcode is a constant
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsConstant(const Op opcode);
|
||||
|
||||
/// @brief Determine if the Opcode is a composite type
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsComposite(const Op opcode);
|
||||
|
||||
/// @brief Deep comparison of type declaration instructions
|
||||
///
|
||||
/// @param[in] pTypeInst0 type definition zero
|
||||
/// @param[in] pTypeInst1 type definition one
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeAreTypesEqual(const spv_instruction_t *pTypeInst0,
|
||||
const spv_instruction_t *pTypeInst1);
|
||||
|
||||
/// @brief Determine if the Opcode results in a pointer
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsPointer(const Op opcode);
|
||||
|
||||
/// @brief Determine if the Opcode results in a instantation of a non-void type
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsObject(const Op opcode);
|
||||
|
||||
/// @brief Determine if the scalar type Opcode is nullable
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsBasicTypeNullable(Op opcode);
|
||||
|
||||
/// @brief Determine if instruction is in a basic block
|
||||
///
|
||||
/// @param[in] pFirstInst first instruction in the stream
|
||||
/// @param[in] pInst current instruction
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvInstructionIsInBasicBlock(const spv_instruction_t *pFirstInst,
|
||||
const spv_instruction_t *pInst);
|
||||
|
||||
/// @brief Determine if the Opcode contains a value
|
||||
///
|
||||
/// @param[in] opcode the opcode
|
||||
///
|
||||
/// @return zero if false, non-zero otherwise
|
||||
int32_t spvOpcodeIsValue(Op opcode);
|
||||
|
||||
#endif
|
1519
source/operand.cpp
Normal file
1519
source/operand.cpp
Normal file
File diff suppressed because it is too large
Load Diff
65
source/operand.h
Normal file
65
source/operand.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _CODEPLAY_SPIRV_OPERAND_H_
|
||||
#define _CODEPLAY_SPIRV_OPERAND_H_
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
/// @brief Find the named operand in the table
|
||||
///
|
||||
/// @param[in] table to lookup
|
||||
/// @param[in] type the operand group's type
|
||||
/// @param[in] name of the operand to find
|
||||
/// @param[out] pEntry returned operand table entry
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvOperandTableNameLookup(const spv_operand_table table,
|
||||
const spv_operand_type_t type,
|
||||
const char *name,
|
||||
spv_operand_desc *pEntry);
|
||||
|
||||
/// @brief Find the operand with value in the table
|
||||
///
|
||||
/// @param[in] table to lookup
|
||||
/// @param[in] type the operand group's type
|
||||
/// @param[in] value of the operand to find
|
||||
/// @param[out] pEntry return operand table entry
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvOperandTableValueLookup(const spv_operand_table table,
|
||||
const spv_operand_type_t type,
|
||||
const uint32_t value,
|
||||
spv_operand_desc *pEntry);
|
||||
|
||||
/// @brief Get the name string of the operand type
|
||||
///
|
||||
/// @param type the type of the operand
|
||||
///
|
||||
/// @return the string name of the operand
|
||||
const char *spvOperandTypeStr(spv_operand_type_t type);
|
||||
|
||||
#endif
|
103
source/print.cpp
Normal file
103
source/print.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "print.h"
|
||||
|
||||
#if defined(SPIRV_LINUX) || defined(SPIRV_MAC)
|
||||
clr::reset::operator const char *() { return "\e[0m"; }
|
||||
|
||||
clr::grey::operator const char *() { return "\e[1;30m"; }
|
||||
|
||||
clr::red::operator const char *() { return "\e[31m"; }
|
||||
|
||||
clr::green::operator const char *() { return "\e[32m"; }
|
||||
|
||||
clr::yellow::operator const char *() { return "\e[33m"; }
|
||||
|
||||
clr::blue::operator const char *() { return "\e[34m"; }
|
||||
#elif defined(SPIRV_WINDOWS)
|
||||
#include <Windows.h>
|
||||
|
||||
clr::reset::operator const char *() {
|
||||
const DWORD color = 0Xf;
|
||||
HANDLE hConsole;
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
hConsole = GetStdHandle(STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
return "";
|
||||
}
|
||||
|
||||
clr::grey::operator const char *() {
|
||||
const DWORD color = 0x8;
|
||||
HANDLE hConsole;
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
hConsole = GetStdHandle(STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
return "";
|
||||
}
|
||||
|
||||
clr::red::operator const char *() {
|
||||
const DWORD color = 0x4;
|
||||
HANDLE hConsole;
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
hConsole = GetStdHandle(STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
return "";
|
||||
}
|
||||
|
||||
clr::green::operator const char *() {
|
||||
const DWORD color = 0x2;
|
||||
HANDLE hConsole;
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
hConsole = GetStdHandle(STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
return "";
|
||||
}
|
||||
|
||||
clr::yellow::operator const char *() {
|
||||
const DWORD color = 0x6;
|
||||
HANDLE hConsole;
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
hConsole = GetStdHandle(STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
return "";
|
||||
}
|
||||
|
||||
clr::blue::operator const char *() {
|
||||
const DWORD color = 0x1;
|
||||
HANDLE hConsole;
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
hConsole = GetStdHandle(STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
return "";
|
||||
}
|
||||
#endif
|
77
source/print.h
Normal file
77
source/print.h
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _LIBSPIRV_PRINT_H_
|
||||
#define _LIBSPIRV_PRINT_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
/// @brief Wrapper for out stream selection
|
||||
class out_stream {
|
||||
public:
|
||||
out_stream() : pStream(nullptr) {}
|
||||
out_stream(std::stringstream &stream) : pStream(&stream) {}
|
||||
|
||||
std::ostream &get() {
|
||||
if (pStream) {
|
||||
return *pStream;
|
||||
}
|
||||
return std::cout;
|
||||
}
|
||||
|
||||
private:
|
||||
std::stringstream *pStream;
|
||||
};
|
||||
|
||||
namespace clr {
|
||||
/// @brief Reset console color
|
||||
struct reset {
|
||||
operator const char *();
|
||||
};
|
||||
/// @brief Set console color to grey
|
||||
struct grey {
|
||||
operator const char *();
|
||||
};
|
||||
/// @brief Set console color to red
|
||||
struct red {
|
||||
operator const char *();
|
||||
};
|
||||
/// @brief Set console color to green
|
||||
struct green {
|
||||
operator const char *();
|
||||
};
|
||||
/// @brief Set console color to yellow
|
||||
struct yellow {
|
||||
operator const char *();
|
||||
};
|
||||
/// @brief Set console color to blue
|
||||
struct blue {
|
||||
operator const char *();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
667
source/text.cpp
Normal file
667
source/text.cpp
Normal file
@ -0,0 +1,667 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
#include "binary.h"
|
||||
#include "diagnostic.h"
|
||||
#include "ext_inst.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
#include "text.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
// Structures
|
||||
|
||||
struct spv_named_id_table_t {
|
||||
std::unordered_map<std::string, uint32_t> namedIds;
|
||||
};
|
||||
|
||||
// Text API
|
||||
|
||||
std::string getWord(const char *str) {
|
||||
size_t index = 0;
|
||||
while (true) {
|
||||
switch (str[index]) {
|
||||
case '\0':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return std::string(str, str + index);
|
||||
}
|
||||
|
||||
spv_named_id_table spvNamedIdTableCreate() {
|
||||
return new spv_named_id_table_t();
|
||||
}
|
||||
|
||||
void spvNamedIdTableDestory(spv_named_id_table table) { delete table; }
|
||||
|
||||
uint32_t spvNamedIdAssignOrGet(spv_named_id_table table, const char *textValue,
|
||||
uint32_t *pBound) {
|
||||
if (table->namedIds.end() == table->namedIds.find(textValue)) {
|
||||
table->namedIds[textValue] = *pBound;
|
||||
}
|
||||
return table->namedIds[textValue];
|
||||
}
|
||||
|
||||
int32_t spvTextIsNamedId(const char *textValue) {
|
||||
// TODO: Strengthen the parsing of textValue to only include allow names that
|
||||
// match: ([a-z]|[A-Z])(_|[a-z]|[A-Z]|[0-9])*
|
||||
switch (textValue[0]) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
spv_result_t spvTextAdvanceLine(const spv_text text, spv_position position) {
|
||||
while (true) {
|
||||
switch (text->str[position->index]) {
|
||||
case '\0':
|
||||
return SPV_END_OF_STREAM;
|
||||
case '\n':
|
||||
position->column = 0;
|
||||
position->line++;
|
||||
position->index++;
|
||||
return SPV_SUCCESS;
|
||||
default:
|
||||
position->line++;
|
||||
position->index++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spv_result_t spvTextAdvance(const spv_text text, spv_position position) {
|
||||
// NOTE: Consume white space, otherwise don't advance.
|
||||
switch (text->str[position->index]) {
|
||||
case '\0':
|
||||
return SPV_END_OF_STREAM;
|
||||
case ';':
|
||||
return spvTextAdvanceLine(text, position);
|
||||
case ' ':
|
||||
case '\t':
|
||||
position->column++;
|
||||
position->index++;
|
||||
return spvTextAdvance(text, position);
|
||||
case '\n':
|
||||
position->column = 0;
|
||||
position->line++;
|
||||
position->index++;
|
||||
return spvTextAdvance(text, position);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvTextWordGet(const spv_text text,
|
||||
const spv_position startPosition, std::string &word,
|
||||
spv_position endPosition) {
|
||||
spvCheck(!text->str || !text->length, return SPV_ERROR_INVALID_TEXT);
|
||||
spvCheck(!startPosition || !endPosition, return SPV_ERROR_INVALID_POINTER);
|
||||
|
||||
*endPosition = *startPosition;
|
||||
|
||||
// NOTE: Assumes first character is not white space!
|
||||
while (true) {
|
||||
switch (text->str[endPosition->index]) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\0': { // NOTE: End of word found!
|
||||
word.assign(text->str + startPosition->index,
|
||||
(size_t)(endPosition->index - startPosition->index));
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
endPosition->column++;
|
||||
endPosition->index++;
|
||||
}
|
||||
}
|
||||
|
||||
spv_result_t spvTextStringGet(const spv_text text,
|
||||
const spv_position startPosition,
|
||||
std::string &string, spv_position endPosition) {
|
||||
spvCheck(!text->str || !text->length, return SPV_ERROR_INVALID_TEXT);
|
||||
spvCheck(!startPosition || !endPosition, return SPV_ERROR_INVALID_POINTER);
|
||||
|
||||
spvCheck('"' != text->str[startPosition->index],
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
|
||||
*endPosition = *startPosition;
|
||||
|
||||
// NOTE: Assumes first character is not white space
|
||||
while (true) {
|
||||
endPosition->column++;
|
||||
endPosition->index++;
|
||||
|
||||
switch (text->str[endPosition->index]) {
|
||||
case '"': {
|
||||
endPosition->column++;
|
||||
endPosition->index++;
|
||||
|
||||
string.assign(text->str + startPosition->index,
|
||||
(size_t)(endPosition->index - startPosition->index));
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
case '\n':
|
||||
case '\0':
|
||||
return SPV_ERROR_INVALID_TEXT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spv_result_t spvTextToUInt32(const char *textValue, uint32_t *pValue) {
|
||||
char *endPtr = nullptr;
|
||||
*pValue = strtoul(textValue, &endPtr, 0);
|
||||
if (0 == *pValue && textValue == endPtr) {
|
||||
return SPV_ERROR_INVALID_TEXT;
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvTextToLiteral(const char *textValue, spv_literal_t *pLiteral) {
|
||||
bool isSigned = false;
|
||||
bool isFloat = false;
|
||||
bool isString = false;
|
||||
|
||||
if ('-' == textValue[0]) {
|
||||
isSigned = true;
|
||||
}
|
||||
|
||||
for (uint64_t index = 0; index < strlen(textValue); ++index) {
|
||||
switch (textValue[index]) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
break;
|
||||
case '.':
|
||||
isFloat = true;
|
||||
break;
|
||||
default:
|
||||
isString = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isString) {
|
||||
pLiteral->type = SPV_LITERAL_TYPE_STRING;
|
||||
strncpy(pLiteral->value.str, textValue, strlen(textValue));
|
||||
} else if (isFloat) {
|
||||
double d = strtod(textValue, nullptr);
|
||||
float f = (float)d;
|
||||
if (d == (double)f) {
|
||||
pLiteral->type = SPV_LITERAL_TYPE_FLOAT_32;
|
||||
pLiteral->value.f = f;
|
||||
} else {
|
||||
pLiteral->type = SPV_LITERAL_TYPE_FLOAT_64;
|
||||
pLiteral->value.d = d;
|
||||
}
|
||||
} else if (isSigned) {
|
||||
int64_t i64 = strtoll(textValue, nullptr, 10);
|
||||
int32_t i32 = (int32_t)i64;
|
||||
if (i64 == (int64_t)i32) {
|
||||
pLiteral->type = SPV_LITERAL_TYPE_INT_32;
|
||||
pLiteral->value.i32 = i32;
|
||||
} else {
|
||||
pLiteral->type = SPV_LITERAL_TYPE_INT_64;
|
||||
pLiteral->value.i64 = i64;
|
||||
}
|
||||
} else {
|
||||
uint64_t u64 = strtoull(textValue, nullptr, 10);
|
||||
uint32_t u32 = (uint32_t)u64;
|
||||
if (u64 == (uint64_t)u32) {
|
||||
pLiteral->type = SPV_LITERAL_TYPE_UINT_32;
|
||||
pLiteral->value.u32 = u32;
|
||||
} else {
|
||||
pLiteral->type = SPV_LITERAL_TYPE_UINT_64;
|
||||
pLiteral->value.u64 = u64;
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvTextEncodeOperand(
|
||||
const spv_operand_type_t type, const char *textValue,
|
||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||
spv_named_id_table namedIdTable, spv_instruction_t *pInst,
|
||||
const spv_operand_type_t **ppExtraOperands, uint32_t *pBound,
|
||||
const spv_position position, spv_diagnostic *pDiagnostic) {
|
||||
// NOTE: Handle immediate int in the stream
|
||||
if ('!' == textValue[0]) {
|
||||
const char *begin = textValue + 1;
|
||||
char *end = nullptr;
|
||||
uint32_t immediateInt = strtoul(begin, &end, 0);
|
||||
size_t size = strlen(textValue);
|
||||
size_t length = (end - begin);
|
||||
spvCheck(size - 1 != length, DIAGNOSTIC << "Invalid immediate integer '"
|
||||
<< textValue << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
position->column += size;
|
||||
position->index += size;
|
||||
pInst->words[pInst->wordCount] = immediateInt;
|
||||
pInst->wordCount += 1;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_ID: {
|
||||
if ('$' == textValue[0]) {
|
||||
textValue++;
|
||||
}
|
||||
// TODO: Force all ID's to be prefixed with '$'.
|
||||
uint32_t id = 0;
|
||||
if (spvTextIsNamedId(textValue)) {
|
||||
id = spvNamedIdAssignOrGet(namedIdTable, textValue, pBound);
|
||||
} else {
|
||||
spvCheck(spvTextToUInt32(textValue, &id),
|
||||
DIAGNOSTIC << "Invalid ID '" << textValue << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
}
|
||||
pInst->words[pInst->wordCount++] = id;
|
||||
if (*pBound <= id) {
|
||||
*pBound = id + 1;
|
||||
}
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_RESULT_ID: {
|
||||
if ('%' == textValue[0]) {
|
||||
textValue++;
|
||||
}
|
||||
// TODO: Force all Result ID's to be prefixed with '%'.
|
||||
uint32_t id = 0;
|
||||
if (spvTextIsNamedId(textValue)) {
|
||||
id = spvNamedIdAssignOrGet(namedIdTable, textValue, pBound);
|
||||
} else {
|
||||
spvCheck(spvTextToUInt32(textValue, &id),
|
||||
DIAGNOSTIC << "Invalid result ID '" << textValue << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
}
|
||||
pInst->words[pInst->wordCount++] = id;
|
||||
if (*pBound <= id) {
|
||||
*pBound = id + 1;
|
||||
}
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
|
||||
// NOTE: Special case for extension instruction lookup
|
||||
if (OpExtInst == pInst->opcode) {
|
||||
spv_ext_inst_desc extInst;
|
||||
spvCheck(spvExtInstTableNameLookup(extInstTable, pInst->extInstType,
|
||||
textValue, &extInst),
|
||||
DIAGNOSTIC << "Invalid extended instruction name '"
|
||||
<< textValue << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
pInst->words[pInst->wordCount++] = extInst->ext_inst;
|
||||
*ppExtraOperands = extInst->operandTypes;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// TODO: Literal numbers can be any number up to 64 bits wide. This
|
||||
// includes integers and floating point numbers.
|
||||
spvCheck(spvTextToUInt32(textValue, &pInst->words[pInst->wordCount++]),
|
||||
DIAGNOSTIC << "Invalid literal number '" << textValue << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL: {
|
||||
spv_literal_t literal = {};
|
||||
spvCheck(spvTextToLiteral(textValue, &literal),
|
||||
DIAGNOSTIC << "Invalid literal '" << textValue << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
switch (literal.type) {
|
||||
case SPV_LITERAL_TYPE_INT_32:
|
||||
spvCheck(spvBinaryEncodeU32((uint32_t)literal.value.i32, pInst,
|
||||
position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
break;
|
||||
case SPV_LITERAL_TYPE_INT_64: {
|
||||
spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.i64, pInst,
|
||||
position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_UINT_32: {
|
||||
spvCheck(spvBinaryEncodeU32(literal.value.u32, pInst, position,
|
||||
pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_UINT_64: {
|
||||
spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.u64, pInst,
|
||||
position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_FLOAT_32: {
|
||||
spvCheck(spvBinaryEncodeU32((uint32_t)literal.value.f, pInst,
|
||||
position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_FLOAT_64: {
|
||||
spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.d, pInst,
|
||||
position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_STRING: {
|
||||
spvCheck(spvBinaryEncodeString(literal.value.str, pInst, position,
|
||||
pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
default:
|
||||
DIAGNOSTIC << "Invalid literal '" << textValue << "'";
|
||||
return SPV_ERROR_INVALID_TEXT;
|
||||
}
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING: {
|
||||
size_t len = strlen(textValue);
|
||||
spvCheck('"' != textValue[0] && '"' != textValue[len - 1],
|
||||
DIAGNOSTIC << "Invalid literal string '" << textValue
|
||||
<< "', expected quotes.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
// NOTE: Strip quotes
|
||||
std::string text(textValue + 1, len - 2);
|
||||
|
||||
// NOTE: Special case for extended instruction library import
|
||||
if (OpExtInstImport == pInst->opcode) {
|
||||
pInst->extInstType = spvExtInstImportTypeGet(text.c_str());
|
||||
}
|
||||
|
||||
spvCheck(
|
||||
spvBinaryEncodeString(text.c_str(), pInst, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
default: {
|
||||
// NOTE: All non literal operands are handled here using the operand
|
||||
// table.
|
||||
spv_operand_desc entry;
|
||||
spvCheck(spvOperandTableNameLookup(operandTable, type, textValue, &entry),
|
||||
DIAGNOSTIC << "Invalid " << spvOperandTypeStr(type) << " '"
|
||||
<< textValue << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT;);
|
||||
spvCheck(spvBinaryEncodeU32(entry->value, pInst, position, pDiagnostic),
|
||||
DIAGNOSTIC << "Invalid " << spvOperandTypeStr(type) << " '"
|
||||
<< textValue << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT;);
|
||||
if (ppExtraOperands && entry->operandTypes[0] != SPV_OPERAND_TYPE_NONE) {
|
||||
*ppExtraOperands = entry->operandTypes;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvTextEncodeOpcode(
|
||||
const spv_text text, const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||
spv_named_id_table namedIdTable, uint32_t *pBound, spv_instruction_t *pInst,
|
||||
spv_position position, spv_diagnostic *pDiagnostic) {
|
||||
std::string opcodeName;
|
||||
spv_position_t nextPosition = {};
|
||||
spvCheck(spvTextWordGet(text, position, opcodeName, &nextPosition),
|
||||
return SPV_ERROR_INTERNAL);
|
||||
|
||||
bool immediate = false;
|
||||
spvCheck('!' == text->str[position->index], immediate = true);
|
||||
if (!immediate) {
|
||||
spvCheck('O' != opcodeName[0] || 'p' != opcodeName[1],
|
||||
DIAGNOSTIC << "Invalid Opcode prefix '" << opcodeName << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
}
|
||||
|
||||
// NOTE: Handle insertion of an immediate integer into the binary stream
|
||||
if (immediate) {
|
||||
const char *begin = opcodeName.data() + 1;
|
||||
char *end = nullptr;
|
||||
uint32_t immediateInt = strtoul(begin, &end, 0);
|
||||
size_t size = opcodeName.size() - 1;
|
||||
spvCheck(size != (size_t)(end - begin),
|
||||
DIAGNOSTIC << "Invalid immediate integer '" << opcodeName << "'.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
position->column += opcodeName.size();
|
||||
position->index += opcodeName.size();
|
||||
pInst->words[0] = immediateInt;
|
||||
pInst->wordCount = 1;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// NOTE: The table contains Opcode names without the "Op" prefix.
|
||||
const char *pInstName = opcodeName.data() + 2;
|
||||
|
||||
spv_opcode_desc opcodeEntry;
|
||||
spv_result_t error =
|
||||
spvOpcodeTableNameLookup(opcodeTable, pInstName, &opcodeEntry);
|
||||
spvCheck(error, DIAGNOSTIC << "Invalid Opcode name '"
|
||||
<< getWord(text->str + position->index) << "'";
|
||||
return error);
|
||||
pInst->opcode = opcodeEntry->opcode;
|
||||
*position = nextPosition;
|
||||
pInst->wordCount++;
|
||||
|
||||
// NOTE: Process the fixed size operands
|
||||
const spv_operand_type_t *extraOperandTypes = nullptr;
|
||||
for (int32_t operandIndex = 0; operandIndex < (opcodeEntry->wordCount - 1);
|
||||
++operandIndex) {
|
||||
spvCheck(spvTextAdvance(text, position),
|
||||
DIAGNOSTIC << "Expected operand, found end of stream.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
|
||||
std::string operandValue;
|
||||
error = spvTextWordGet(text, position, operandValue, &nextPosition);
|
||||
spvCheck(error, return error);
|
||||
|
||||
error = spvTextEncodeOperand(
|
||||
opcodeEntry->operandTypes[operandIndex], operandValue.c_str(),
|
||||
operandTable, extInstTable, namedIdTable, pInst, &extraOperandTypes,
|
||||
pBound, position, pDiagnostic);
|
||||
spvCheck(error, return error);
|
||||
|
||||
*position = nextPosition;
|
||||
}
|
||||
|
||||
if (spvOpcodeIsVariable(opcodeEntry)) {
|
||||
if (!extraOperandTypes) {
|
||||
// NOTE: Handle variable length not defined by an immediate previously
|
||||
// encountered in the Opcode.
|
||||
spv_operand_type_t type =
|
||||
opcodeEntry->operandTypes[opcodeEntry->wordCount - 1];
|
||||
|
||||
while (!spvTextAdvance(text, position)) {
|
||||
std::string textValue;
|
||||
spvTextWordGet(text, position, textValue, &nextPosition);
|
||||
|
||||
// NOTE: Check if the next text word is an Opcode
|
||||
if ('O' == textValue[0] && 'p' == textValue[1]) {
|
||||
// NOTE: This is the end of the current instruction stream and we
|
||||
// break out of this loop
|
||||
break;
|
||||
} else {
|
||||
if (SPV_OPERAND_TYPE_LITERAL_STRING == type) {
|
||||
spvCheck(spvTextAdvance(text, position),
|
||||
DIAGNOSTIC << "Invalid string, found end of stream.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
|
||||
std::string string;
|
||||
spvCheck(spvTextStringGet(text, position, string, &nextPosition),
|
||||
DIAGNOSTIC << "Invalid string, new line or end of stream.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
spvCheck(
|
||||
spvTextEncodeOperand(type, string.c_str(), operandTable,
|
||||
extInstTable, namedIdTable, pInst, nullptr,
|
||||
pBound, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} else {
|
||||
spvCheck(
|
||||
spvTextEncodeOperand(type, textValue.c_str(), operandTable,
|
||||
extInstTable, namedIdTable, pInst, nullptr,
|
||||
pBound, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
}
|
||||
*position = nextPosition;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// NOTE: Process the variable size operands defined by an immediate
|
||||
// previously encountered in the Opcode.
|
||||
uint64_t extraOperandsIndex = 0;
|
||||
while (extraOperandTypes[extraOperandsIndex]) {
|
||||
spvCheck(spvTextAdvance(text, position),
|
||||
DIAGNOSTIC << "Expected operand, found end of stream.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
|
||||
std::string operandValue;
|
||||
error = spvTextWordGet(text, position, operandValue, &nextPosition);
|
||||
|
||||
error = spvTextEncodeOperand(extraOperandTypes[extraOperandsIndex],
|
||||
operandValue.c_str(), operandTable,
|
||||
extInstTable, namedIdTable, pInst, nullptr,
|
||||
pBound, position, pDiagnostic);
|
||||
spvCheck(error, return error);
|
||||
|
||||
*position = nextPosition;
|
||||
|
||||
extraOperandsIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pInst->words[0] = spvOpcodeMake(pInst->wordCount, opcodeEntry->opcode);
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvTextToBinary(const spv_text text,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable,
|
||||
spv_binary *pBinary, spv_diagnostic *pDiagnostic) {
|
||||
spv_position_t position = {};
|
||||
spvCheck(!text->str || !text->length, DIAGNOSTIC << "Text stream is empty.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
spvCheck(!opcodeTable || !operandTable || !extInstTable,
|
||||
return SPV_ERROR_INVALID_TABLE);
|
||||
spvCheck(!pBinary, return SPV_ERROR_INVALID_POINTER);
|
||||
spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
|
||||
|
||||
// NOTE: Ensure diagnostic is zero initialised
|
||||
*pDiagnostic = {};
|
||||
|
||||
uint32_t bound = 1;
|
||||
|
||||
std::vector<spv_instruction_t> instructions;
|
||||
|
||||
spvCheck(spvTextAdvance(text, &position), DIAGNOSTIC
|
||||
<< "Text stream is empty.";
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
|
||||
spv_named_id_table namedIdTable = spvNamedIdTableCreate();
|
||||
spvCheck(!namedIdTable, return SPV_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
spv_ext_inst_type_t extInstType = SPV_EXT_INST_TYPE_NONE;
|
||||
while (text->length > position.index) {
|
||||
spv_instruction_t inst = {};
|
||||
inst.extInstType = extInstType;
|
||||
|
||||
spvCheck(spvTextEncodeOpcode(text, opcodeTable, operandTable, extInstTable,
|
||||
namedIdTable, &bound, &inst, &position,
|
||||
pDiagnostic),
|
||||
spvNamedIdTableDestory(namedIdTable);
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
extInstType = inst.extInstType;
|
||||
|
||||
instructions.push_back(inst);
|
||||
|
||||
spvCheck(spvTextAdvance(text, &position), break);
|
||||
}
|
||||
|
||||
spvNamedIdTableDestory(namedIdTable);
|
||||
|
||||
size_t totalSize = SPV_INDEX_INSTRUCTION;
|
||||
for (auto &inst : instructions) {
|
||||
totalSize += inst.wordCount;
|
||||
}
|
||||
|
||||
uint32_t *data = new uint32_t[totalSize];
|
||||
spvCheck(!data, return SPV_ERROR_OUT_OF_MEMORY);
|
||||
uint64_t currentIndex = SPV_INDEX_INSTRUCTION;
|
||||
for (auto &inst : instructions) {
|
||||
memcpy(data + currentIndex, inst.words, sizeof(uint32_t) * inst.wordCount);
|
||||
currentIndex += inst.wordCount;
|
||||
}
|
||||
|
||||
spv_binary binary = new spv_binary_t();
|
||||
spvCheck(!binary, delete[] data; return SPV_ERROR_OUT_OF_MEMORY);
|
||||
binary->code = data;
|
||||
binary->wordCount = totalSize;
|
||||
|
||||
spv_result_t error = spvBinaryHeaderSet(binary, bound);
|
||||
spvCheck(error, spvBinaryDestroy(binary); return error);
|
||||
|
||||
*pBinary = binary;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
void spvTextDestroy(spv_text text) {
|
||||
spvCheck(!text, return );
|
||||
if (text->str) {
|
||||
delete[] text->str;
|
||||
}
|
||||
delete text;
|
||||
}
|
193
source/text.h
Normal file
193
source/text.h
Normal file
@ -0,0 +1,193 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _LIBSPIRV_UTIL_TEXT_H_
|
||||
#define _LIBSPIRV_UTIL_TEXT_H_
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
// Structures
|
||||
|
||||
typedef enum spv_literal_type_t {
|
||||
SPV_LITERAL_TYPE_INT_32,
|
||||
SPV_LITERAL_TYPE_INT_64,
|
||||
SPV_LITERAL_TYPE_UINT_32,
|
||||
SPV_LITERAL_TYPE_UINT_64,
|
||||
SPV_LITERAL_TYPE_FLOAT_32,
|
||||
SPV_LITERAL_TYPE_FLOAT_64,
|
||||
SPV_LITERAL_TYPE_STRING,
|
||||
SPV_FORCE_32_BIT_ENUM(spv_literal_type_t)
|
||||
} spv_literal_type_t;
|
||||
|
||||
typedef struct spv_literal_t {
|
||||
spv_literal_type_t type;
|
||||
union value_t {
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
float f;
|
||||
double d;
|
||||
char str[SPV_LIMIT_LITERAL_STRING_MAX];
|
||||
} value;
|
||||
} spv_literal_t;
|
||||
|
||||
struct spv_named_id_table_t;
|
||||
|
||||
// Types
|
||||
|
||||
typedef spv_named_id_table_t *spv_named_id_table;
|
||||
|
||||
// Functions
|
||||
|
||||
/// @brief Advance text to the start of the next line
|
||||
///
|
||||
/// @param[in] text to be parsed
|
||||
/// @param[in,out] pPosition position text has been advanced to
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextAdvanceLine(const spv_text text, spv_position_t *pPosition);
|
||||
|
||||
/// @brief Advance text to first non white space character
|
||||
///
|
||||
/// If a null terminator is found during the text advance SPV_END_OF_STREAM is
|
||||
/// returned, SPV_SUCCESS otherwise. No error checking is performed on the
|
||||
/// parameters, its the users responsispvity to ensure these are non null.
|
||||
///
|
||||
/// @param[in] text to be parsed
|
||||
/// @param[in,out] pPosition position text has been advanced to
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextAdvance(const spv_text text, spv_position_t *pPosition);
|
||||
|
||||
/// @brief Fetch the next word from the text stream
|
||||
///
|
||||
/// @param[in] text stream to read from
|
||||
/// @param[in] startPosition current position in text stream
|
||||
/// @param[out] word returned word
|
||||
/// @param[out] endPosition one past the end of the returned word
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextWordGet(const spv_text text,
|
||||
const spv_position startPosition, std::string &word,
|
||||
spv_position endPosition);
|
||||
|
||||
/// @brief Fetch a string, including quotes, from the text stream
|
||||
///
|
||||
/// @param[in] text stream to read from
|
||||
/// @param[in] startPosition current position in text stream
|
||||
/// @param[out] string returned string
|
||||
/// @param[out] endPosition one past the end of the return string
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextStringGet(const spv_text text,
|
||||
const spv_position startPosition,
|
||||
std::string &string, spv_position endPosition);
|
||||
|
||||
/// @brief Convert the input text to a unsigned 32 bit integer
|
||||
///
|
||||
/// @param[in] textValue input text to parse
|
||||
/// @param[out] pValue the returned integer
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextToUInt32(const char *textValue, uint32_t *pValue);
|
||||
|
||||
/// @brief Convert the input text to one of the number types
|
||||
///
|
||||
/// @param[in] textValue input text to parse
|
||||
/// @param[out] pLiteral the returned literal number
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextToLiteral(const char *textValue, spv_literal_t *pLiteral);
|
||||
|
||||
/// @brief Create a named ID table
|
||||
///
|
||||
/// @return named ID table
|
||||
spv_named_id_table spvNamedIdTableCreate();
|
||||
|
||||
/// @brief Free a named ID table
|
||||
///
|
||||
/// @param table named ID table
|
||||
void spvNamedIdTableDestory(spv_named_id_table table);
|
||||
|
||||
/// @brief Lookup or assign a named ID
|
||||
///
|
||||
/// @param table named ID table
|
||||
/// @param textValue name value
|
||||
/// @param pBound upper ID bound, used for assigning new ID's
|
||||
///
|
||||
/// @return the new ID assossiated with the named ID
|
||||
uint32_t spvNamedIdAssignOrGet(spv_named_id_table table, const char *textValue,
|
||||
uint32_t *pBound);
|
||||
|
||||
/// @brief Determine if a name has an assossiated ID
|
||||
///
|
||||
/// @param textValue name value
|
||||
///
|
||||
/// @return zero on failure, non-zero otherwise
|
||||
int32_t spvTextIsNamedId(const char *textValue);
|
||||
|
||||
/// @brief Translate an Opcode operand to binary form
|
||||
///
|
||||
/// @param[in] type of the operand
|
||||
/// @param[in] textValue word of text to be parsed
|
||||
/// @param[in] operandTable operand lookup table
|
||||
/// @param[in,out] namedIdTable table of named ID's
|
||||
/// @param[out] pInst return binary Opcode
|
||||
/// @param[out] ppExtraOperands list of extra variable operands, if any
|
||||
/// @param[in,out] pBound current highest defined ID value
|
||||
/// @param[in] pPosition used in diagnostic on error
|
||||
/// @param[out] pDiagnostic populated on error
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextEncodeOperand(
|
||||
const spv_operand_type_t type, const char *textValue,
|
||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||
spv_named_id_table namedIdTable, spv_instruction_t *pInst,
|
||||
const spv_operand_type_t **ppExtraOperands, uint32_t *pBound,
|
||||
const spv_position_t *pPosition, spv_diagnostic *pDiagnostic);
|
||||
|
||||
/// @brief Translate single Opcode and operands to binary form
|
||||
///
|
||||
/// @param[in] text stream to translate
|
||||
/// @param[in] opcodeTable Opcode lookup table
|
||||
/// @param[in] operandTable operand lookup table
|
||||
/// @param[in,out] namedIdTable table of named ID's
|
||||
/// @param[in,out] pBound current highest defined ID value
|
||||
/// @param[out] pInst returned binary Opcode
|
||||
/// @param[in,out] pPosition in the text stream
|
||||
/// @param[out] pDiagnostic populated on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextEncodeOpcode(
|
||||
const spv_text text, const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable, const spv_ext_inst_table extInstTable,
|
||||
spv_named_id_table namedIdTable, uint32_t *pBound, spv_instruction_t *pInst,
|
||||
spv_position_t *pPosition, spv_diagnostic *pDiagnostic);
|
||||
|
||||
#endif
|
300
source/validate.cpp
Normal file
300
source/validate.cpp
Normal file
@ -0,0 +1,300 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
#include "binary.h"
|
||||
#include "diagnostic.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
#include "validate.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
spv_result_t spvValidateOperandsString(const uint32_t *words,
|
||||
const uint16_t wordCount,
|
||||
spv_position position,
|
||||
spv_diagnostic *pDiagnostic) {
|
||||
const char *str = (const char *)words;
|
||||
uint64_t strWordCount = strlen(str) / sizeof(uint32_t) + 1;
|
||||
spvCheck(strWordCount < wordCount, DIAGNOSTIC << "Instruction word count is "
|
||||
"too short, string extends "
|
||||
"past end of instruction.";
|
||||
return SPV_WARNING);
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvValidateOperandsLiteral(const uint32_t *words,
|
||||
const uint32_t length,
|
||||
const uint16_t maxLength,
|
||||
spv_position position,
|
||||
spv_diagnostic *pDiagnostic) {
|
||||
// NOTE: A literal could either be a number consuming up to 2 words or a
|
||||
// null terminated string.
|
||||
(void)words;
|
||||
(void)length;
|
||||
(void)maxLength;
|
||||
(void)position;
|
||||
(void)pDiagnostic;
|
||||
return SPV_UNSUPPORTED;
|
||||
}
|
||||
|
||||
spv_result_t spvValidateOperandValue(const spv_operand_type_t type,
|
||||
const uint32_t word,
|
||||
const spv_operand_table operandTable,
|
||||
spv_position position,
|
||||
spv_diagnostic *pDiagnostic) {
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_RESULT_ID: {
|
||||
// NOTE: ID's are validated in SPV_VALIDATION_LEVEL_1, this is
|
||||
// SPV_VALIDATION_LEVEL_0
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
|
||||
// NOTE: Implicitly valid as they are encoded as 32 bit value
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODE:
|
||||
case SPV_OPERAND_TYPE_STORAGE_CLASS:
|
||||
case SPV_OPERAND_TYPE_DIMENSIONALITY:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
|
||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
|
||||
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
|
||||
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
|
||||
case SPV_OPERAND_TYPE_DECORATION:
|
||||
case SPV_OPERAND_TYPE_BUILT_IN:
|
||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS:
|
||||
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_SCOPE:
|
||||
case SPV_OPERAND_TYPE_GROUP_OPERATION:
|
||||
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
|
||||
case SPV_OPERAND_TYPE_KERENL_PROFILING_INFO: {
|
||||
spv_operand_desc operandEntry = nullptr;
|
||||
spv_result_t error =
|
||||
spvOperandTableValueLookup(operandTable, type, word, &operandEntry);
|
||||
spvCheck(error, DIAGNOSTIC << "Invalid '" << spvOperandTypeStr(type)
|
||||
<< "' operand '" << word << "'.";
|
||||
return error);
|
||||
} break;
|
||||
default:
|
||||
assert(0 && "Invalid operand types should already have been caught!");
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvValidateBasic(const spv_instruction_t *pInsts,
|
||||
const uint64_t instCount,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
spv_position position,
|
||||
spv_diagnostic *pDiagnostic) {
|
||||
for (uint64_t instIndex = 0; instIndex < instCount; ++instIndex) {
|
||||
const uint32_t *words = pInsts[instIndex].words;
|
||||
uint16_t wordCount;
|
||||
Op opcode;
|
||||
spvOpcodeSplit(words[0], &wordCount, &opcode);
|
||||
|
||||
spv_opcode_desc opcodeEntry = nullptr;
|
||||
spvCheck(spvOpcodeTableValueLookup(opcodeTable, opcode, &opcodeEntry),
|
||||
DIAGNOSTIC << "Invalid Opcode '" << opcode << "'.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
position->index++;
|
||||
|
||||
spvCheck(opcodeEntry->wordCount > wordCount,
|
||||
DIAGNOSTIC << "Instruction word count '" << wordCount
|
||||
<< "' is not small, expected at least '"
|
||||
<< opcodeEntry->wordCount << "'.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
spv_operand_desc operandEntry = nullptr;
|
||||
for (uint16_t index = 1; index < pInsts[instIndex].wordCount;
|
||||
++index, position->index++) {
|
||||
const uint32_t word = words[index];
|
||||
spv_operand_type_t type = spvBinaryOperandInfo(
|
||||
word, index, opcodeEntry, operandTable, &operandEntry);
|
||||
if (SPV_OPERAND_TYPE_LITERAL_STRING == type) {
|
||||
spvCheckReturn(spvValidateOperandsString(
|
||||
words + index, wordCount - index, position, pDiagnostic));
|
||||
// NOTE: String literals are always at the end of Opcodes
|
||||
break;
|
||||
} else if (SPV_OPERAND_TYPE_LITERAL == type) {
|
||||
spvCheckReturn(spvValidateOperandsLiteral(
|
||||
words + index, wordCount - index, 2, position, pDiagnostic));
|
||||
} else {
|
||||
spvCheckReturn(spvValidateOperandValue(type, word, operandTable,
|
||||
position, pDiagnostic));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvValidateIDs(const spv_instruction_t *pInsts,
|
||||
const uint64_t count, const uint32_t bound,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable,
|
||||
spv_position position,
|
||||
spv_diagnostic *pDiagnostic) {
|
||||
std::vector<spv_id_info_t> idUses;
|
||||
std::vector<spv_id_info_t> idDefs;
|
||||
|
||||
for (uint64_t instIndex = 0; instIndex < count; ++instIndex) {
|
||||
const uint32_t *words = pInsts[instIndex].words;
|
||||
Op opcode;
|
||||
spvOpcodeSplit(words[0], nullptr, &opcode);
|
||||
|
||||
spv_opcode_desc opcodeEntry = nullptr;
|
||||
spvCheck(spvOpcodeTableValueLookup(opcodeTable, opcode, &opcodeEntry),
|
||||
DIAGNOSTIC << "Invalid Opcode '" << opcode << "'.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
spv_operand_desc operandEntry = nullptr;
|
||||
position->index++; // NOTE: Account for Opcode word
|
||||
for (uint16_t index = 1; index < pInsts[instIndex].wordCount;
|
||||
++index, position->index++) {
|
||||
const uint32_t word = words[index];
|
||||
|
||||
spv_operand_type_t type = spvBinaryOperandInfo(
|
||||
word, index, opcodeEntry, operandTable, &operandEntry);
|
||||
|
||||
if (SPV_OPERAND_TYPE_RESULT_ID == type || SPV_OPERAND_TYPE_ID == type) {
|
||||
spvCheck(0 == word, DIAGNOSTIC << "Invalid ID of '0' is not allowed.";
|
||||
return SPV_ERROR_INVALID_ID);
|
||||
spvCheck(bound < word, DIAGNOSTIC << "Invalid ID '" << word
|
||||
<< "' exceeds the bound '" << bound
|
||||
<< "'.";
|
||||
return SPV_ERROR_INVALID_ID);
|
||||
}
|
||||
|
||||
if (SPV_OPERAND_TYPE_RESULT_ID == type) {
|
||||
idDefs.push_back(
|
||||
{word, opcodeEntry->opcode, &pInsts[instIndex], *position});
|
||||
}
|
||||
|
||||
if (SPV_OPERAND_TYPE_ID == type) {
|
||||
idUses.push_back({word, opcodeEntry->opcode, nullptr, *position});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Error on redefined ID
|
||||
for (size_t outerIndex = 0; outerIndex < idDefs.size(); ++outerIndex) {
|
||||
for (size_t innerIndex = 0; innerIndex < idDefs.size(); ++innerIndex) {
|
||||
if (outerIndex == innerIndex) {
|
||||
continue;
|
||||
}
|
||||
if (idDefs[outerIndex].id == idDefs[innerIndex].id) {
|
||||
DIAGNOSTIC << "Multiply defined ID '" << idDefs[outerIndex].id << "'.";
|
||||
return SPV_ERROR_INVALID_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Validate ID usage, including use of undefined ID's
|
||||
position->index = SPV_INDEX_INSTRUCTION;
|
||||
spvCheck(spvValidateInstructionIDs(pInsts, count, idUses.data(),
|
||||
idUses.size(), idDefs.data(),
|
||||
idDefs.size(), opcodeTable, operandTable,
|
||||
extInstTable, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_ID);
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvValidate(const spv_binary binary,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable,
|
||||
const uint32_t options, spv_diagnostic *pDiagnostic) {
|
||||
spvCheck(!opcodeTable || !operandTable, return SPV_ERROR_INVALID_TABLE);
|
||||
spvCheck(!pDiagnostic, return SPV_ERROR_INVALID_DIAGNOSTIC);
|
||||
|
||||
spv_endianness_t endian;
|
||||
spv_position_t position = {};
|
||||
spvCheck(spvBinaryEndianness(binary, &endian),
|
||||
DIAGNOSTIC << "Invalid SPIR-V magic number.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
spv_header_t header;
|
||||
spvCheck(spvBinaryHeaderGet(binary, endian, &header),
|
||||
DIAGNOSTIC << "Invalid SPIR-V header.";
|
||||
return SPV_ERROR_INVALID_BINARY);
|
||||
|
||||
// NOTE: Copy each instruction for easier processing
|
||||
std::vector<spv_instruction_t> instructions;
|
||||
uint64_t index = SPV_INDEX_INSTRUCTION;
|
||||
while (index < binary->wordCount) {
|
||||
uint16_t wordCount;
|
||||
Op opcode;
|
||||
spvOpcodeSplit(spvFixWord(binary->code[index], endian), &wordCount,
|
||||
&opcode);
|
||||
spv_instruction_t inst;
|
||||
spvInstructionCopy(&binary->code[index], opcode, wordCount, endian, &inst);
|
||||
instructions.push_back(inst);
|
||||
index += wordCount;
|
||||
}
|
||||
|
||||
if (spvIsInBitfield(SPV_VALIDATE_BASIC_BIT, options)) {
|
||||
position.index = SPV_INDEX_INSTRUCTION;
|
||||
// TODO: Imcomplete implementation
|
||||
spvCheckReturn(spvValidateBasic(instructions.data(), instructions.size(),
|
||||
opcodeTable, operandTable, &position,
|
||||
pDiagnostic));
|
||||
}
|
||||
|
||||
if (spvIsInBitfield(SPV_VALIDATE_LAYOUT_BIT, options)) {
|
||||
position.index = SPV_INDEX_INSTRUCTION;
|
||||
// TODO: spvBinaryValidateLayout
|
||||
}
|
||||
|
||||
if (spvIsInBitfield(SPV_VALIDATE_ID_BIT, options)) {
|
||||
position.index = SPV_INDEX_INSTRUCTION;
|
||||
spvCheckReturn(spvValidateIDs(instructions.data(), instructions.size(),
|
||||
header.bound, opcodeTable, operandTable,
|
||||
extInstTable, &position, pDiagnostic));
|
||||
}
|
||||
|
||||
if (spvIsInBitfield(SPV_VALIDATE_RULES_BIT, options)) {
|
||||
position.index = SPV_INDEX_INSTRUCTION;
|
||||
// TODO: Specified validation rules...
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
83
source/validate.h
Normal file
83
source/validate.h
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _LIBSPIRV_UTIL_VALIDATE_H_
|
||||
#define _LIBSPIRV_UTIL_VALIDATE_H_
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
// Structures
|
||||
|
||||
typedef struct spv_id_info_t {
|
||||
uint32_t id;
|
||||
Op opcode;
|
||||
const spv_instruction_t *inst;
|
||||
spv_position_t position;
|
||||
} spv_id_info_t;
|
||||
|
||||
// Functions
|
||||
|
||||
/// @brief Validate the ID usage of the instruction stream
|
||||
///
|
||||
/// @param[in] pInsts stream of instructions
|
||||
/// @param[in] instCount number of instructions
|
||||
/// @param[in] pIdUses stream of ID uses
|
||||
/// @param[in] idUsesCount number of ID uses
|
||||
/// @param[in] pIdDefs stream of ID uses
|
||||
/// @param[in] idDefsCount number of ID uses
|
||||
/// @param[in] opcodeTable table of specified Opcodes
|
||||
/// @param[in] operandTable table of specified operands
|
||||
/// @param[in,out] position current position in the stream
|
||||
/// @param[out] pDiag contains diagnostic on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvValidateInstructionIDs(
|
||||
const spv_instruction_t *pInsts, const uint64_t instCount,
|
||||
const spv_id_info_t *pIdUses, const uint64_t idUsesCount,
|
||||
const spv_id_info_t *pIdDefs, const uint64_t idDefsCount,
|
||||
const spv_opcode_table opcodeTable, const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable, spv_position position,
|
||||
spv_diagnostic *pDiag);
|
||||
|
||||
/// @brief Validate the ID's within a SPIR-V binary
|
||||
///
|
||||
/// @param[in] pInstructions array of instructions
|
||||
/// @param[in] count number of elements in instruction array
|
||||
/// @param[in] bound the binary header
|
||||
/// @param[in] opcodeTable table of specified Opcodes
|
||||
/// @param[in] operandTable table of specified operands
|
||||
/// @param[in,out] position current word in the binary
|
||||
/// @param[out] pDiagnostic contains diagnostic on failure
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvValidateIDs(const spv_instruction_t *pInstructions,
|
||||
const uint64_t count, const uint32_t bound,
|
||||
const spv_opcode_table opcodeTable,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_ext_inst_table extInstTable,
|
||||
spv_position position, spv_diagnostic *pDiagnostic);
|
||||
|
||||
#endif
|
2808
source/validate_id.cpp
Normal file
2808
source/validate_id.cpp
Normal file
File diff suppressed because it is too large
Load Diff
60
test/BinaryEndianness.cpp
Normal file
60
test/BinaryEndianness.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(BinaryEndianness, InvalidCode) {
|
||||
uint32_t invalidMagicNumber[] = {0};
|
||||
spv_binary_t binary = {invalidMagicNumber, 1};
|
||||
spv_endianness_t endian;
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_BINARY, spvBinaryEndianness(&binary, &endian));
|
||||
}
|
||||
|
||||
TEST(BinaryEndianness, Little) {
|
||||
uint32_t magicNumber;
|
||||
if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) {
|
||||
magicNumber = 0x07230203;
|
||||
} else {
|
||||
magicNumber = 0x03022307;
|
||||
}
|
||||
spv_binary_t binary = {&magicNumber, 1};
|
||||
spv_endianness_t endian;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&binary, &endian));
|
||||
ASSERT_EQ(SPV_ENDIANNESS_LITTLE, endian);
|
||||
}
|
||||
|
||||
TEST(BinaryEndianness, Big) {
|
||||
uint32_t magicNumber;
|
||||
if (I32_ENDIAN_HOST == I32_ENDIAN_BIG) {
|
||||
magicNumber = 0x07230203;
|
||||
} else {
|
||||
magicNumber = 0x03022307;
|
||||
}
|
||||
spv_binary_t binary = {&magicNumber, 1};
|
||||
spv_endianness_t endian;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&binary, &endian));
|
||||
ASSERT_EQ(SPV_ENDIANNESS_BIG, endian);
|
||||
}
|
76
test/BinaryHeaderGet.cpp
Normal file
76
test/BinaryHeaderGet.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
class BinaryHeaderGet : public ::testing::Test {
|
||||
public:
|
||||
BinaryHeaderGet() { memset(code, 0, sizeof(code)); }
|
||||
|
||||
virtual void SetUp() {
|
||||
code[0] = SPV_MAGIC_NUMBER;
|
||||
code[1] = SPV_VERSION_NUMBER;
|
||||
code[2] = SPV_GENERATOR_CODEPLAY;
|
||||
code[3] = 1; // NOTE: Bound
|
||||
code[4] = 0; // NOTE: Schema; reserved
|
||||
code[5] = 0; // NOTE: Instructions
|
||||
|
||||
binary.code = code;
|
||||
binary.wordCount = 6;
|
||||
}
|
||||
|
||||
virtual void TearDown() {}
|
||||
|
||||
uint32_t code[6];
|
||||
spv_binary_t binary;
|
||||
};
|
||||
|
||||
TEST_F(BinaryHeaderGet, Default) {
|
||||
spv_endianness_t endian;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvBinaryEndianness(&binary, &endian));
|
||||
|
||||
spv_header_t header;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvBinaryHeaderGet(&binary, endian, &header));
|
||||
|
||||
ASSERT_EQ((uint32_t)SPV_MAGIC_NUMBER, header.magic);
|
||||
ASSERT_EQ(99u, header.version);
|
||||
ASSERT_EQ((uint32_t)SPV_GENERATOR_CODEPLAY, header.generator);
|
||||
ASSERT_EQ(1u, header.bound);
|
||||
ASSERT_EQ(0u, header.schema);
|
||||
ASSERT_EQ(&code[5], header.instructions);
|
||||
}
|
||||
|
||||
TEST_F(BinaryHeaderGet, InvalidCode) {
|
||||
spv_binary_t binary = {nullptr, 0};
|
||||
spv_header_t header;
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_BINARY,
|
||||
spvBinaryHeaderGet(&binary, SPV_ENDIANNESS_LITTLE, &header));
|
||||
}
|
||||
|
||||
TEST_F(BinaryHeaderGet, InvalidPointerHeader) {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_POINTER,
|
||||
spvBinaryHeaderGet(&binary, SPV_ENDIANNESS_LITTLE, nullptr));
|
||||
}
|
169
test/BinaryToText.cpp
Normal file
169
test/BinaryToText.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
class BinaryToText : public ::testing::Test {
|
||||
public:
|
||||
BinaryToText() : binary(), opcodeTable(nullptr), operandTable(nullptr) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||
|
||||
const char *textStr = R"(
|
||||
OpSource OpenCL 12
|
||||
OpMemoryModel Physical64 OpenCL1.2
|
||||
OpSourceExtension "PlaceholderExtensionName"
|
||||
OpEntryPoint Kernel $1
|
||||
OpExecutionMode $1 LocalSizeHint 1 1 1
|
||||
OpTypeVoid %2
|
||||
OpTypeBool %3
|
||||
OpTypeInt %4 8 0
|
||||
OpTypeInt %5 8 1
|
||||
OpTypeInt %6 16 0
|
||||
OpTypeInt %7 16 1
|
||||
OpTypeInt %8 32 0
|
||||
OpTypeInt %9 32 1
|
||||
OpTypeInt %10 64 0
|
||||
OpTypeInt %11 64 1
|
||||
OpTypeFloat %12 16
|
||||
OpTypeFloat %13 32
|
||||
OpTypeFloat %14 64
|
||||
OpTypeVector %15 4 2
|
||||
)";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic);
|
||||
if (error) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
ASSERT_EQ(SPV_SUCCESS, error);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown() { spvBinaryDestroy(binary); }
|
||||
|
||||
spv_binary binary;
|
||||
spv_opcode_table opcodeTable;
|
||||
spv_operand_table operandTable;
|
||||
spv_ext_inst_table extInstTable;
|
||||
};
|
||||
|
||||
TEST_F(BinaryToText, Default) {
|
||||
spv_text text = nullptr;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
|
||||
operandTable, extInstTable, &text, &diagnostic));
|
||||
printf("%s", text->str);
|
||||
spvTextDestroy(text);
|
||||
}
|
||||
|
||||
TEST_F(BinaryToText, InvalidCode) {
|
||||
spv_binary_t binary = {nullptr, 42};
|
||||
spv_text text;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
ASSERT_EQ(
|
||||
SPV_ERROR_INVALID_BINARY,
|
||||
spvBinaryToText(&binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
|
||||
operandTable, extInstTable, &text, &diagnostic));
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(BinaryToText, InvalidTable) {
|
||||
spv_text text;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
|
||||
spvBinaryToText(binary, 0, nullptr, operandTable, extInstTable,
|
||||
&text, &diagnostic));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
|
||||
spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
|
||||
nullptr, extInstTable, &text, &diagnostic));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
|
||||
spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
|
||||
operandTable, nullptr, &text, &diagnostic));
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(BinaryToText, InvalidDiagnostic) {
|
||||
spv_text text;
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC,
|
||||
spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
|
||||
operandTable, extInstTable, &text, nullptr));
|
||||
}
|
||||
|
||||
TEST(BinaryToTextExtInst, Default) {
|
||||
spv_opcode_table opcodeTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||
spv_operand_table operandTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||
spv_ext_inst_table extInstTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||
const char *spirv = R"(
|
||||
OpCapability Shader
|
||||
OpExtInstImport %glsl450 "GLSL.std.450"
|
||||
OpMemoryModel Logical Simple
|
||||
OpEntryPoint Vertex $main "main"
|
||||
OpTypeVoid %void
|
||||
OpTypeFloat %float 32
|
||||
OpConstant $float %const1.5 1.5
|
||||
OpTypeFunction %fnMain %void
|
||||
OpFunction $void %main None $fnMain
|
||||
OpLabel %lbMain
|
||||
OpExtInst $float %result $glsl450 round $const1.5
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
spv_text_t text = {spirv, strlen(spirv)};
|
||||
spv_binary binary;
|
||||
spv_diagnostic diagnostic;
|
||||
spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic);
|
||||
if (error) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
ASSERT_EQ(SPV_SUCCESS, error);
|
||||
}
|
||||
|
||||
error = spvBinaryToText(
|
||||
binary, SPV_BINARY_TO_TEXT_OPTION_COLOR | SPV_BINARY_TO_TEXT_OPTION_PRINT,
|
||||
opcodeTable, operandTable, extInstTable, nullptr, &diagnostic);
|
||||
|
||||
if (error) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
ASSERT_EQ(SPV_SUCCESS, error);
|
||||
}
|
||||
}
|
40
test/DiagnosticPrint.cpp
Normal file
40
test/DiagnosticPrint.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(DiagnosticPrint, Default) {
|
||||
char message[] = "Test Diagnostic!";
|
||||
spv_diagnostic_t diagnostic = {{2, 3, 5}, message};
|
||||
// TODO: Redirect stderr
|
||||
ASSERT_EQ(SPV_SUCCESS, spvDiagnosticPrint(&diagnostic));
|
||||
// TODO: Validate the output of spvDiagnosticPrint()
|
||||
// TODO: Remove the redirection of stderr
|
||||
}
|
||||
|
||||
TEST(DiagnosticPrint, InvalidDiagnostic) {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC, spvDiagnosticPrint(nullptr));
|
||||
}
|
50
test/FixWord.cpp
Normal file
50
test/FixWord.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(FixWord, Default) {
|
||||
spv_endianness_t endian;
|
||||
if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) {
|
||||
endian = SPV_ENDIANNESS_LITTLE;
|
||||
} else {
|
||||
endian = SPV_ENDIANNESS_BIG;
|
||||
}
|
||||
uint32_t word = 0x53780921;
|
||||
ASSERT_EQ(word, spvFixWord(word, endian));
|
||||
}
|
||||
|
||||
TEST(FixWord, Reorder) {
|
||||
spv_endianness_t endian;
|
||||
if (I32_ENDIAN_HOST == I32_ENDIAN_LITTLE) {
|
||||
endian = SPV_ENDIANNESS_BIG;
|
||||
} else {
|
||||
endian = SPV_ENDIANNESS_LITTLE;
|
||||
}
|
||||
uint32_t word = 0x53780921;
|
||||
uint32_t result = 0x21097853;
|
||||
ASSERT_EQ(result, spvFixWord(word, endian));
|
||||
}
|
69
test/NamedId.cpp
Normal file
69
test/NamedId.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(NamedId, Default) {
|
||||
const char *spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical Simple
|
||||
OpEntryPoint Vertex $main
|
||||
OpTypeVoid %void
|
||||
OpTypeFunction %fnMain $void
|
||||
OpFunction $void %main None $fnMain
|
||||
OpLabel %lbMain
|
||||
OpReturn
|
||||
OpFunctionEnd)";
|
||||
spv_text_t text;
|
||||
text.str = spirv;
|
||||
text.length = strlen(spirv);
|
||||
spv_opcode_table opcodeTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||
spv_operand_table operandTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||
spv_ext_inst_table extInstTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||
spv_binary binary;
|
||||
spv_diagnostic diagnostic;
|
||||
spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic);
|
||||
if (error) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
spvBinaryDestroy(binary);
|
||||
ASSERT_EQ(SPV_SUCCESS, error);
|
||||
}
|
||||
error = spvBinaryToText(
|
||||
binary, SPV_BINARY_TO_TEXT_OPTION_PRINT | SPV_BINARY_TO_TEXT_OPTION_COLOR,
|
||||
opcodeTable, operandTable, extInstTable, nullptr, &diagnostic);
|
||||
if (error) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
spvBinaryDestroy(binary);
|
||||
ASSERT_EQ(SPV_SUCCESS, error);
|
||||
}
|
||||
spvBinaryDestroy(binary);
|
||||
}
|
33
test/OpcodeIsVariable.cpp
Normal file
33
test/OpcodeIsVariable.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(OpcodeIsVariable, Default) {
|
||||
spv_opcode_desc_t entry = {
|
||||
nullptr, 0, (Op)0, SPV_OPCODE_FLAGS_VARIABLE, 0, {}};
|
||||
ASSERT_NE(0, spvOpcodeIsVariable(&entry));
|
||||
}
|
42
test/OpcodeMake.cpp
Normal file
42
test/OpcodeMake.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
TEST(OpcodeMake, DISABLED_Default) {
|
||||
for (uint16_t wordCount = 0; wordCount < std::numeric_limits<uint16_t>::max();
|
||||
++wordCount) {
|
||||
for (uint16_t code = 0; code < std::numeric_limits<uint16_t>::max();
|
||||
++code) {
|
||||
uint32_t opcode = 0;
|
||||
opcode |= (uint32_t)code;
|
||||
opcode |= (uint32_t)wordCount << 16;
|
||||
ASSERT_EQ(opcode, spvOpcodeMake(wordCount, (Op)code));
|
||||
}
|
||||
}
|
||||
}
|
60
test/OpcodeRequiresCapabilities.cpp
Normal file
60
test/OpcodeRequiresCapabilities.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
class Requires : public ::testing::TestWithParam<Capability> {
|
||||
public:
|
||||
Requires()
|
||||
: entry({nullptr,
|
||||
0,
|
||||
(Op)0,
|
||||
SPV_OPCODE_FLAGS_CAPABILITIES,
|
||||
GetParam(),
|
||||
{}}) {}
|
||||
|
||||
virtual void SetUp() {}
|
||||
|
||||
virtual void TearDown() {}
|
||||
|
||||
spv_opcode_desc_t entry;
|
||||
};
|
||||
|
||||
TEST_P(Requires, Capabilityabilities) {
|
||||
ASSERT_NE(0, spvOpcodeRequiresCapabilities(&entry));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Op, Requires,
|
||||
::testing::Values(CapabilityMatrix, CapabilityShader,
|
||||
CapabilityGeometry,
|
||||
CapabilityTessellation,
|
||||
CapabilityAddresses,
|
||||
CapabilityLinkage, CapabilityKernel));
|
||||
|
||||
TEST(OpcodeRequiresCapabilityaspvities, None) {
|
||||
spv_opcode_desc_t entry = {nullptr, 0, (Op)0, SPV_OPCODE_FLAGS_NONE, 0, {}};
|
||||
ASSERT_EQ(0, spvOpcodeRequiresCapabilities(&entry));
|
||||
}
|
36
test/OpcodeSplit.cpp
Normal file
36
test/OpcodeSplit.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(OpcodeSplit, Default) {
|
||||
uint32_t word = spvOpcodeMake(42, (Op)23);
|
||||
uint16_t wordCount = 0;
|
||||
Op opcode;
|
||||
spvOpcodeSplit(word, &wordCount, &opcode);
|
||||
ASSERT_EQ(42, wordCount);
|
||||
ASSERT_EQ(23, opcode);
|
||||
}
|
38
test/OpcodeTableGet.cpp
Normal file
38
test/OpcodeTableGet.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(OpcodeTableGet, Default) {
|
||||
spv_opcode_table table;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&table));
|
||||
ASSERT_NE(0, table->count);
|
||||
ASSERT_NE(nullptr, table->entries);
|
||||
}
|
||||
|
||||
TEST(OpcodeTableGet, InvalidPointerTable) {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_POINTER, spvOpcodeTableGet(nullptr));
|
||||
}
|
38
test/OperandTableGet.cpp
Normal file
38
test/OperandTableGet.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(OperandTableGet, Default) {
|
||||
spv_operand_table table;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&table));
|
||||
ASSERT_NE(0, table->count);
|
||||
ASSERT_NE(nullptr, table->types);
|
||||
}
|
||||
|
||||
TEST(OperandTableGet, InvalidPointerTable) {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_POINTER, spvOperandTableGet(nullptr));
|
||||
}
|
74
test/TextAdvance.cpp
Normal file
74
test/TextAdvance.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(TextAdvance, LeadingNewLines) {
|
||||
char textStr[] = "\n\nWord";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_position_t position = {};
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &position));
|
||||
ASSERT_EQ(0, position.column);
|
||||
ASSERT_EQ(2, position.line);
|
||||
ASSERT_EQ(2, position.index);
|
||||
}
|
||||
|
||||
TEST(TextAdvance, LeadingSpaces) {
|
||||
char textStr[] = " Word";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_position_t position = {};
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &position));
|
||||
ASSERT_EQ(4, position.column);
|
||||
ASSERT_EQ(0, position.line);
|
||||
ASSERT_EQ(4, position.index);
|
||||
}
|
||||
|
||||
TEST(TextAdvance, LeadingTabs) {
|
||||
char textStr[] = "\t\t\tWord";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_position_t position = {};
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &position));
|
||||
ASSERT_EQ(3, position.column);
|
||||
ASSERT_EQ(0, position.line);
|
||||
ASSERT_EQ(3, position.index);
|
||||
}
|
||||
|
||||
TEST(TextAdvance, LeadingNewLinesSpacesAndTabs) {
|
||||
char textStr[] = "\n\n\t Word";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_position_t position = {};
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &position));
|
||||
ASSERT_EQ(3, position.column);
|
||||
ASSERT_EQ(2, position.line);
|
||||
ASSERT_EQ(5, position.index);
|
||||
}
|
||||
|
||||
TEST(TextAdvance, NullTerminator) {
|
||||
char textStr[] = "";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_position_t position = {};
|
||||
ASSERT_EQ(SPV_END_OF_STREAM, spvTextAdvance(&text, &position));
|
||||
}
|
85
test/TextDestroy.cpp
Normal file
85
test/TextDestroy.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(TextDestroy, Default) {
|
||||
spv_opcode_table opcodeTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||
|
||||
spv_operand_table operandTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||
|
||||
spv_ext_inst_table extInstTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||
|
||||
char textStr[] =
|
||||
"OpSource OpenCL 12\n"
|
||||
"OpMemoryModel Physical64 OpenCL1.2\n"
|
||||
"OpSourceExtension \"PlaceholderExtensionName\"\n"
|
||||
"OpEntryPoint Kernel 0\n"
|
||||
"OpExecutionMode 0 LocalSizeHint 1 1 1\n"
|
||||
"OpTypeVoid 1\n"
|
||||
"OpTypeBool 2\n"
|
||||
"OpTypeInt 3 8 0\n"
|
||||
"OpTypeInt 4 8 1\n"
|
||||
"OpTypeInt 5 16 0\n"
|
||||
"OpTypeInt 6 16 1\n"
|
||||
"OpTypeInt 7 32 0\n"
|
||||
"OpTypeInt 8 32 1\n"
|
||||
"OpTypeInt 9 64 0\n"
|
||||
"OpTypeInt 10 64 1\n"
|
||||
"OpTypeFloat 11 16\n"
|
||||
"OpTypeFloat 12 32\n"
|
||||
"OpTypeFloat 13 64\n"
|
||||
"OpTypeVector 14 3 2\n";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_binary binary = nullptr;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic));
|
||||
EXPECT_NE(nullptr, binary);
|
||||
EXPECT_NE(nullptr, binary->code);
|
||||
EXPECT_NE(0, binary->wordCount);
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
|
||||
spv_text resultText = nullptr;
|
||||
EXPECT_EQ(SPV_SUCCESS,
|
||||
spvBinaryToText(binary, 0, opcodeTable, operandTable, extInstTable,
|
||||
&resultText, &diagnostic));
|
||||
spvBinaryDestroy(binary);
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
EXPECT_NE(nullptr, text.str);
|
||||
EXPECT_NE(0, text.length);
|
||||
spvTextDestroy(resultText);
|
||||
}
|
354
test/TextToBinary.cpp
Normal file
354
test/TextToBinary.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
union char_word_t {
|
||||
char cs[4];
|
||||
uint32_t u;
|
||||
};
|
||||
|
||||
TEST(TextToBinary, Default) {
|
||||
// TODO: Ensure that on big endian systems that this converts the word to
|
||||
// little endian for encoding comparison!
|
||||
spv_endianness_t endian = SPV_ENDIANNESS_LITTLE;
|
||||
|
||||
const char *textStr = R"(
|
||||
OpSource OpenCL 12
|
||||
OpMemoryModel Physical64 OpenCL1.2
|
||||
OpSourceExtension "PlaceholderExtensionName"
|
||||
OpEntryPoint Kernel $1
|
||||
OpExecutionMode $1 LocalSizeHint 1 1 1
|
||||
OpTypeVoid %2
|
||||
OpTypeBool %3
|
||||
; commment
|
||||
OpTypeInt %4 8 0 ; comment
|
||||
OpTypeInt %5 8 1
|
||||
OpTypeInt %6 16 0
|
||||
OpTypeInt %7 16 1
|
||||
OpTypeInt %8 32 0
|
||||
OpTypeInt %9 32 1
|
||||
OpTypeInt %10 64 0
|
||||
OpTypeInt %11 64 1
|
||||
OpTypeFloat %12 16
|
||||
OpTypeFloat %13 32
|
||||
OpTypeFloat %14 64
|
||||
OpTypeVector %15 4 2
|
||||
)";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
|
||||
spv_opcode_table opcodeTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||
|
||||
spv_operand_table operandTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||
|
||||
spv_ext_inst_table extInstTable;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||
|
||||
spv_binary binary;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic);
|
||||
|
||||
if (error) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
ASSERT_EQ(SPV_SUCCESS, error);
|
||||
}
|
||||
|
||||
struct bin {
|
||||
bin(spv_binary binary) : binary(binary) {}
|
||||
~bin() { spvBinaryDestroy(binary); }
|
||||
spv_binary binary;
|
||||
} bin(binary);
|
||||
|
||||
EXPECT_NE(nullptr, text.str);
|
||||
EXPECT_NE(0, text.length);
|
||||
|
||||
// TODO: Verify binary
|
||||
ASSERT_EQ(SPV_MAGIC_NUMBER, binary->code[SPV_INDEX_MAGIC_NUMBER]);
|
||||
ASSERT_EQ(SPV_VERSION_NUMBER, binary->code[SPV_INDEX_VERSION_NUMBER]);
|
||||
ASSERT_EQ(SPV_GENERATOR_CODEPLAY, binary->code[SPV_INDEX_GENERATOR_NUMBER]);
|
||||
ASSERT_EQ(16, binary->code[SPV_INDEX_BOUND]); // TODO: Bound?
|
||||
ASSERT_EQ(0, binary->code[SPV_INDEX_SCHEMA]); // Reserved: schema
|
||||
|
||||
uint64_t instIndex = SPV_INDEX_INSTRUCTION;
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(3, OpSource), binary->code[instIndex++]);
|
||||
ASSERT_EQ(SourceLanguageOpenCL, binary->code[instIndex++]);
|
||||
ASSERT_EQ(12, binary->code[instIndex++]);
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(3, OpMemoryModel), binary->code[instIndex++]);
|
||||
ASSERT_EQ(AddressingModelPhysical64, binary->code[instIndex++]);
|
||||
ASSERT_EQ(MemoryModelOpenCL12, binary->code[instIndex++]);
|
||||
|
||||
uint16_t sourceExtensionWordCount =
|
||||
(uint16_t)((strlen("PlaceholderExtensionName") / sizeof(uint32_t)) + 2);
|
||||
ASSERT_EQ(spvOpcodeMake(sourceExtensionWordCount, OpSourceExtension),
|
||||
binary->code[instIndex++]);
|
||||
// TODO: This only works on little endian systems!
|
||||
char_word_t cw = {{'P', 'l', 'a', 'c'}};
|
||||
ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
|
||||
cw = {{'e', 'h', 'o', 'l'}};
|
||||
ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
|
||||
cw = {{'d', 'e', 'r', 'E'}};
|
||||
ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
|
||||
cw = {{'x', 't', 'e', 'n'}};
|
||||
ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
|
||||
cw = {{'s', 'i', 'o', 'n'}};
|
||||
ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
|
||||
cw = {{'N', 'a', 'm', 'e'}};
|
||||
ASSERT_EQ(spvFixWord(cw.u, endian), binary->code[instIndex++]);
|
||||
ASSERT_EQ(0, binary->code[instIndex++]);
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(3, OpEntryPoint), binary->code[instIndex++]);
|
||||
ASSERT_EQ(ExecutionModelKernel, binary->code[instIndex++]);
|
||||
ASSERT_EQ(1, binary->code[instIndex++]);
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(6, OpExecutionMode), binary->code[instIndex++]);
|
||||
ASSERT_EQ(1, binary->code[instIndex++]);
|
||||
ASSERT_EQ(ExecutionModeLocalSizeHint, binary->code[instIndex++]);
|
||||
ASSERT_EQ(1, binary->code[instIndex++]);
|
||||
ASSERT_EQ(1, binary->code[instIndex++]);
|
||||
ASSERT_EQ(1, binary->code[instIndex++]);
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(2, OpTypeVoid), binary->code[instIndex++]);
|
||||
ASSERT_EQ(2, binary->code[instIndex++]);
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(2, OpTypeBool), binary->code[instIndex++]);
|
||||
ASSERT_EQ(3, binary->code[instIndex++]);
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
|
||||
ASSERT_EQ(4, binary->code[instIndex++]);
|
||||
ASSERT_EQ(8, binary->code[instIndex++]); // NOTE: 8 bits wide
|
||||
ASSERT_EQ(0, binary->code[instIndex++]); // NOTE: Unsigned
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
|
||||
ASSERT_EQ(5, binary->code[instIndex++]);
|
||||
ASSERT_EQ(8, binary->code[instIndex++]); // NOTE: 8 bits wide
|
||||
ASSERT_EQ(1, binary->code[instIndex++]); // NOTE: Signed
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
|
||||
ASSERT_EQ(6, binary->code[instIndex++]);
|
||||
ASSERT_EQ(16, binary->code[instIndex++]); // NOTE: 16 bits wide
|
||||
ASSERT_EQ(0, binary->code[instIndex++]); // NOTE: Unsigned
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
|
||||
ASSERT_EQ(7, binary->code[instIndex++]);
|
||||
ASSERT_EQ(16, binary->code[instIndex++]); // NOTE: 16 bits wide
|
||||
ASSERT_EQ(1, binary->code[instIndex++]); // NOTE: Signed
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
|
||||
ASSERT_EQ(8, binary->code[instIndex++]);
|
||||
ASSERT_EQ(32, binary->code[instIndex++]); // NOTE: 32 bits wide
|
||||
ASSERT_EQ(0, binary->code[instIndex++]); // NOTE: Unsigned
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
|
||||
ASSERT_EQ(9, binary->code[instIndex++]);
|
||||
ASSERT_EQ(32, binary->code[instIndex++]); // NOTE: 32 bits wide
|
||||
ASSERT_EQ(1, binary->code[instIndex++]); // NOTE: Signed
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
|
||||
ASSERT_EQ(10, binary->code[instIndex++]);
|
||||
ASSERT_EQ(64, binary->code[instIndex++]); // NOTE: 64 bits wide
|
||||
ASSERT_EQ(0, binary->code[instIndex++]); // NOTE: Unsigned
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeInt), binary->code[instIndex++]);
|
||||
ASSERT_EQ(11, binary->code[instIndex++]);
|
||||
ASSERT_EQ(64, binary->code[instIndex++]); // NOTE: 64 bits wide
|
||||
ASSERT_EQ(1, binary->code[instIndex++]); // NOTE: Signed
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(3, OpTypeFloat), binary->code[instIndex++]);
|
||||
ASSERT_EQ(12, binary->code[instIndex++]);
|
||||
ASSERT_EQ(16, binary->code[instIndex++]); // NOTE: 16 bits wide
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(3, OpTypeFloat), binary->code[instIndex++]);
|
||||
ASSERT_EQ(13, binary->code[instIndex++]);
|
||||
ASSERT_EQ(32, binary->code[instIndex++]); // NOTE: 32 bits wide
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(3, OpTypeFloat), binary->code[instIndex++]);
|
||||
ASSERT_EQ(14, binary->code[instIndex++]);
|
||||
ASSERT_EQ(64, binary->code[instIndex++]); // NOTE: 64 bits wide
|
||||
|
||||
ASSERT_EQ(spvOpcodeMake(4, OpTypeVector), binary->code[instIndex++]);
|
||||
ASSERT_EQ(15, binary->code[instIndex++]);
|
||||
ASSERT_EQ(4, binary->code[instIndex++]);
|
||||
ASSERT_EQ(2, binary->code[instIndex++]);
|
||||
}
|
||||
|
||||
class TextToBinaryTest : public ::testing::Test {
|
||||
public:
|
||||
TextToBinaryTest()
|
||||
: binary(nullptr),
|
||||
text(),
|
||||
opcodeTable(nullptr),
|
||||
operandTable(nullptr),
|
||||
diagnostic(nullptr) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
char textStr[] =
|
||||
"OpEntryPoint Kernel 0\n"
|
||||
"OpExecutionMode 0 LocalSizeHint 1 1 1\n";
|
||||
text.str = textStr;
|
||||
text.length = strlen(textStr);
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
if (diagnostic) {
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
spv_binary binary;
|
||||
spv_text_t text;
|
||||
spv_opcode_table opcodeTable;
|
||||
spv_operand_table operandTable;
|
||||
spv_ext_inst_table extInstTable;
|
||||
spv_diagnostic diagnostic;
|
||||
};
|
||||
|
||||
TEST_F(TextToBinaryTest, InvalidText) {
|
||||
spv_text_t text = {nullptr, 0};
|
||||
spv_binary binary;
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_TEXT,
|
||||
spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
|
||||
&binary, &diagnostic));
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, InvalidTable) {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
|
||||
spvTextToBinary(&text, nullptr, operandTable, extInstTable, &binary,
|
||||
&diagnostic));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
|
||||
spvTextToBinary(&text, opcodeTable, nullptr, extInstTable, &binary,
|
||||
&diagnostic));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_TABLE,
|
||||
spvTextToBinary(&text, opcodeTable, operandTable, nullptr, &binary,
|
||||
&diagnostic));
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, InvalidPointer) {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_POINTER,
|
||||
spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
|
||||
nullptr, &diagnostic));
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, InvalidDiagnostic) {
|
||||
spv_binary binary;
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DIAGNOSTIC,
|
||||
spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
|
||||
&binary, nullptr));
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, InvalidPrefix) {
|
||||
const char *spirv = R"(
|
||||
Invalid)";
|
||||
text.str = spirv;
|
||||
text.length = strlen(spirv);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_TEXT,
|
||||
spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
|
||||
&binary, &diagnostic));
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, ImmediateIntOpCode) {
|
||||
const char *spirv = R"(
|
||||
!0x00FF00FF
|
||||
)";
|
||||
text.str = spirv;
|
||||
text.length = strlen(spirv);
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic));
|
||||
EXPECT_EQ(0x00FF00FF, binary->code[5]);
|
||||
spvBinaryDestroy(binary);
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, ImmediateIntOperand) {
|
||||
const char *spirv = R"(
|
||||
OpCapability !0x00FF00FF)";
|
||||
text.str = spirv;
|
||||
text.length = strlen(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic));
|
||||
EXPECT_EQ(0x00FF00FF, binary->code[6]);
|
||||
spvBinaryDestroy(binary);
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, ExtInst) {
|
||||
const char *spirv = R"(
|
||||
OpCapability Shader
|
||||
OpExtInstImport %glsl450 "GLSL.std.450"
|
||||
OpMemoryModel Logical Simple
|
||||
OpEntryPoint Vertex $main "main"
|
||||
OpTypeVoid %void
|
||||
OpTypeFloat %float 32
|
||||
OpConstant $float %const1.5 1.5
|
||||
OpTypeFunction %fnMain %void
|
||||
OpFunction $void %main None $fnMain
|
||||
OpLabel %lbMain
|
||||
OpExtInst $float %result $glsl450 round $const1.5
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
text.str = spirv;
|
||||
text.length = strlen(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic));
|
||||
if (binary) {
|
||||
spvBinaryDestroy(binary);
|
||||
}
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, StringSpace) {
|
||||
const char *spirv = R"(
|
||||
OpSourceExtension "string with spaces"
|
||||
)";
|
||||
text.str = spirv;
|
||||
text.length = strlen(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic));
|
||||
if (binary) {
|
||||
spvBinaryDestroy(binary);
|
||||
}
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
}
|
||||
}
|
97
test/TextWordGet.cpp
Normal file
97
test/TextWordGet.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
TEST(TextWordGet, NullTerminator) {
|
||||
char textStr[] = "Word";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_position_t startPosition = {};
|
||||
std::string word;
|
||||
spv_position_t endPosition = {};
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvTextWordGet(&text, &startPosition, word, &endPosition));
|
||||
ASSERT_EQ(4, endPosition.column);
|
||||
ASSERT_EQ(0, endPosition.line);
|
||||
ASSERT_EQ(4, endPosition.index);
|
||||
ASSERT_STREQ("Word", word.c_str());
|
||||
}
|
||||
|
||||
TEST(TextWordGet, TabTerminator) {
|
||||
char textStr[] = "Word\t";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_position_t startPosition = {};
|
||||
std::string word;
|
||||
spv_position_t endPosition = {};
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvTextWordGet(&text, &startPosition, word, &endPosition));
|
||||
ASSERT_EQ(4, endPosition.column);
|
||||
ASSERT_EQ(0, endPosition.line);
|
||||
ASSERT_EQ(4, endPosition.index);
|
||||
ASSERT_STREQ("Word", word.c_str());
|
||||
}
|
||||
|
||||
TEST(TextWordGet, SpaceTerminator) {
|
||||
char textStr[] = "Word ";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
spv_position_t startPosition = {};
|
||||
std::string word;
|
||||
spv_position_t endPosition = {};
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvTextWordGet(&text, &startPosition, word, &endPosition));
|
||||
ASSERT_EQ(4, endPosition.column);
|
||||
ASSERT_EQ(0, endPosition.line);
|
||||
ASSERT_EQ(4, endPosition.index);
|
||||
ASSERT_STREQ("Word", word.c_str());
|
||||
}
|
||||
|
||||
TEST(TextWordGet, MultipleWords) {
|
||||
char textStr[] = "Words in a sentence";
|
||||
spv_text_t text = {textStr, strlen(textStr)};
|
||||
const char *words[] = {"Words", "in", "a", "sentence"};
|
||||
|
||||
spv_position_t startPosition = {};
|
||||
spv_position_t endPosition = {};
|
||||
|
||||
std::string word;
|
||||
for (uint32_t wordIndex = 0; wordIndex < 4; ++wordIndex) {
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvTextWordGet(&text, &startPosition, word, &endPosition));
|
||||
ASSERT_EQ(strlen(words[wordIndex]),
|
||||
endPosition.column - startPosition.column);
|
||||
ASSERT_EQ(0, endPosition.line);
|
||||
ASSERT_EQ(strlen(words[wordIndex]),
|
||||
endPosition.index - startPosition.index);
|
||||
ASSERT_STREQ(words[wordIndex], word.c_str());
|
||||
|
||||
startPosition = endPosition;
|
||||
if (3 != wordIndex) {
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextAdvance(&text, &startPosition));
|
||||
} else {
|
||||
ASSERT_EQ(SPV_END_OF_STREAM, spvTextAdvance(&text, &startPosition));
|
||||
}
|
||||
}
|
||||
}
|
54
test/UnitSPIRV.h
Normal file
54
test/UnitSPIRV.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef _CODEPLAY_UNITBIL_H_
|
||||
#define _CODEPLAY_UNITBIL_H_
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
#include "../source/binary.h"
|
||||
#include "../source/diagnostic.h"
|
||||
#include "../source/opcode.h"
|
||||
#include "../source/text.h"
|
||||
#include "../source/validate.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Determine endianness & predicate tests on it
|
||||
enum {
|
||||
I32_ENDIAN_LITTLE = 0x03020100ul,
|
||||
I32_ENDIAN_BIG = 0x00010203ul,
|
||||
};
|
||||
|
||||
static const union {
|
||||
unsigned char bytes[4];
|
||||
uint32_t value;
|
||||
} o32_host_order = {{0, 1, 2, 3}};
|
||||
|
||||
#define I32_ENDIAN_HOST (o32_host_order.value)
|
||||
|
||||
#endif
|
119
test/Validate.cpp
Normal file
119
test/Validate.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
|
||||
class Validate : public ::testing::Test {
|
||||
public:
|
||||
Validate() : binary(), opcodeTable(nullptr), operandTable(nullptr) {}
|
||||
|
||||
virtual void SetUp() {
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOpcodeTableGet(&opcodeTable));
|
||||
ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable));
|
||||
ASSERT_EQ(SPV_SUCCESS, spvExtInstTableGet(&extInstTable));
|
||||
}
|
||||
|
||||
virtual void TearDown() { spvBinaryDestroy(binary); }
|
||||
|
||||
spv_binary binary;
|
||||
spv_opcode_table opcodeTable;
|
||||
spv_operand_table operandTable;
|
||||
spv_ext_inst_table extInstTable;
|
||||
};
|
||||
|
||||
TEST_F(Validate, DISABLED_Default) {
|
||||
char str[] = R"(
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute 1
|
||||
OpExecutionMode 1 LocalSize 1 1 1
|
||||
OpTypeVoid 2
|
||||
OpTypeFunction 3 2
|
||||
OpFunction 2 1 NoControl 3
|
||||
OpLabel 4
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
spv_text_t text = {str, strlen(str)};
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic));
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvValidate(binary, opcodeTable, operandTable, extInstTable,
|
||||
SPV_VALIDATE_ALL, &diagnostic));
|
||||
if (diagnostic) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Validate, DISABLED_InvalidIdUndefined) {
|
||||
char str[] = R"(
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute 1
|
||||
OpExecutionMode 5 LocalSize 1 1 1
|
||||
OpTypeVoid 2
|
||||
OpTypeFunction 3 2
|
||||
OpFunction 2 1 NoControl 3
|
||||
OpLabel 4
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
spv_text_t text = {str, strlen(str)};
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID,
|
||||
spvValidate(binary, opcodeTable, operandTable, extInstTable,
|
||||
SPV_VALIDATE_ALL, &diagnostic));
|
||||
ASSERT_NE(nullptr, diagnostic);
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
}
|
||||
|
||||
TEST_F(Validate, DISABLED_InvalidIdRedefined) {
|
||||
char str[] = R"(
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute 1
|
||||
OpExecutionMode 1 LocalSize 1 1 1
|
||||
OpTypeVoid 2
|
||||
OpTypeFunction 2 2
|
||||
OpFunction 2 1 NoControl 3
|
||||
OpLabel 4
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
spv_text_t text = {str, strlen(str)};
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
ASSERT_EQ(SPV_SUCCESS, spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic));
|
||||
// TODO: Fix setting of bound in spvTextTo, then remove this!
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID,
|
||||
spvValidate(binary, opcodeTable, operandTable, extInstTable,
|
||||
SPV_VALIDATE_ALL, &diagnostic));
|
||||
ASSERT_NE(nullptr, diagnostic);
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
}
|
1342
test/ValidateID.cpp
Normal file
1342
test/ValidateID.cpp
Normal file
File diff suppressed because it is too large
Load Diff
32
test/main.cpp
Normal file
32
test/main.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
129
tools/as/as.cpp
Normal file
129
tools/as/as.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
void print_usage(char *argv0) {
|
||||
printf(
|
||||
"Assemble a *.svasm file into a *.sv binary.\n\n"
|
||||
"USAGE: %s [options] <filename>\n\n"
|
||||
" -o Set the output filename\n",
|
||||
argv0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (2 > argc) {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *inFile = nullptr;
|
||||
const char *outFile = nullptr;
|
||||
|
||||
for (int argi = 1; argi < argc; ++argi) {
|
||||
if ('-' == argv[argi][0]) {
|
||||
switch (argv[argi][1]) {
|
||||
case 'o': {
|
||||
if (!outFile && argi + 1 < argc) {
|
||||
outFile = argv[++argi];
|
||||
} else {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (!inFile) {
|
||||
inFile = argv[argi];
|
||||
} else {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!outFile) {
|
||||
outFile = "out.spv";
|
||||
}
|
||||
|
||||
spvCheck(!inFile, fprintf(stderr, "error: input file is empty.\n"); return 1);
|
||||
|
||||
std::vector<char> contents;
|
||||
if (FILE *fp = fopen(inFile, "r")) {
|
||||
char buf[1024];
|
||||
while (size_t len = fread(buf, 1, sizeof(buf), fp))
|
||||
contents.insert(contents.end(), buf, buf + len);
|
||||
fclose(fp);
|
||||
} else {
|
||||
fprintf(stderr, "error: file does not exist '%s'\n", inFile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spv_text_t text = {contents.data(), contents.size()};
|
||||
|
||||
spv_opcode_table opcodeTable;
|
||||
spv_result_t error = spvOpcodeTableGet(&opcodeTable);
|
||||
spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
|
||||
return error);
|
||||
|
||||
spv_operand_table operandTable;
|
||||
error = spvOperandTableGet(&operandTable);
|
||||
spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
|
||||
return error);
|
||||
|
||||
spv_ext_inst_table extInstTable;
|
||||
error = spvExtInstTableGet(&extInstTable);
|
||||
spvCheck(error, fprintf(stderr, "error: Internal malfunction.\n"));
|
||||
|
||||
spv_binary binary;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
error = spvTextToBinary(&text, opcodeTable, operandTable, extInstTable,
|
||||
&binary, &diagnostic);
|
||||
spvCheck(error, spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic); return error);
|
||||
|
||||
if (FILE *fp = fopen(outFile, "wb")) {
|
||||
size_t written =
|
||||
fwrite(binary->code, sizeof(uint32_t), (size_t)binary->wordCount, fp);
|
||||
if (binary->wordCount != written) {
|
||||
fprintf(stderr, "error: could not write to file '%s'\n", outFile);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "error: could not open file '%s'\n", outFile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spvBinaryDestroy(binary);
|
||||
|
||||
return 0;
|
||||
}
|
144
tools/dis/dis.cpp
Normal file
144
tools/dis/dis.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
void print_usage(char *argv0) {
|
||||
printf(
|
||||
"Dissassemble a *.sv file into a *.svasm text file.\n\n"
|
||||
"USAGE: %s [options] <filename>\n\n"
|
||||
" -o <filename> Set the output filename\n"
|
||||
" -p Print dissassembly to stdout, this\n"
|
||||
" overrides file output\n",
|
||||
argv0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (2 > argc) {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NONE;
|
||||
const char *inFile = nullptr;
|
||||
const char *outFile = nullptr;
|
||||
|
||||
for (int argi = 1; argi < argc; ++argi) {
|
||||
if ('-' == argv[argi][0]) {
|
||||
switch (argv[argi][1]) {
|
||||
case 'o': {
|
||||
if (!outFile && argi + 1 < argc) {
|
||||
outFile = argv[++argi];
|
||||
} else {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
case 'p': {
|
||||
options |= SPV_BINARY_TO_TEXT_OPTION_PRINT;
|
||||
#ifdef SPV_COLOR_TERMINAL
|
||||
options |= SPV_BINARY_TO_TEXT_OPTION_COLOR;
|
||||
#endif
|
||||
} break;
|
||||
default:
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (!inFile) {
|
||||
inFile = argv[argi];
|
||||
} else {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!outFile) {
|
||||
outFile = "out.spvasm";
|
||||
}
|
||||
|
||||
spvCheck(!inFile, fprintf(stderr, "error: input file is empty.\n"); return 1);
|
||||
|
||||
std::vector<uint32_t> contents;
|
||||
if (FILE *fp = fopen(inFile, "rb")) {
|
||||
uint32_t buf[1024];
|
||||
while (size_t len = fread(buf, sizeof(uint32_t), 1024, fp)) {
|
||||
contents.insert(contents.end(), buf, buf + len);
|
||||
}
|
||||
fclose(fp);
|
||||
} else {
|
||||
fprintf(stderr, "error: file does not exist '%s'\n", inFile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spv_binary_t binary = {contents.data(), contents.size()};
|
||||
|
||||
spv_opcode_table opcodeTable;
|
||||
spv_result_t error = spvOpcodeTableGet(&opcodeTable);
|
||||
spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
|
||||
return error);
|
||||
|
||||
spv_operand_table operandTable;
|
||||
error = spvOperandTableGet(&operandTable);
|
||||
spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
|
||||
return error);
|
||||
|
||||
spv_ext_inst_table extInstTable;
|
||||
error = spvExtInstTableGet(&extInstTable);
|
||||
spvCheck(error, fprintf(stderr, "error: Internal malfunction.\n"));
|
||||
|
||||
spv_text text;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
error = spvBinaryToText(&binary, options, opcodeTable, operandTable,
|
||||
extInstTable, &text, &diagnostic);
|
||||
spvCheck(error, spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic); return error);
|
||||
|
||||
if (spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options)) {
|
||||
printf("%s", text->str);
|
||||
} else {
|
||||
if (FILE *fp = fopen(outFile, "w")) {
|
||||
size_t written = fwrite(text->str, sizeof(char), (size_t)text->length, fp);
|
||||
if (text->length != written) {
|
||||
spvTextDestroy(text);
|
||||
fprintf(stderr, "error: could not write to file '%s'\n", outFile);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
spvTextDestroy(text);
|
||||
fprintf(stderr, "error: could not open file '%s'\n", outFile);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
spvTextDestroy(text);
|
||||
|
||||
return 0;
|
||||
}
|
119
tools/val/val.cpp
Normal file
119
tools/val/val.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
void print_usage(char *argv0) {
|
||||
printf(
|
||||
"Validate a SPIR-V binary file.\n\n"
|
||||
"USAGE: %s [options] <filename>\n\n"
|
||||
" -basic Perform basic validation (disabled)\n"
|
||||
" -layout Perform layout validation "
|
||||
"(disabled)\n"
|
||||
" -id Perform id validation (default ON)\n"
|
||||
" -capability <capability> Performs OpCode validation "
|
||||
"(disabled)\n",
|
||||
argv0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (2 > argc) {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *inFile = nullptr;
|
||||
uint32_t options = 0;
|
||||
|
||||
for (int argi = 1; argi < argc; ++argi) {
|
||||
if ('-' == argv[argi][0]) {
|
||||
if (!strcmp("basic", argv[argi] + 1)) {
|
||||
options |= SPV_VALIDATE_BASIC_BIT;
|
||||
} else if (!strcmp("layout", argv[argi] + 1)) {
|
||||
options |= SPV_VALIDATE_LAYOUT_BIT;
|
||||
} else if (!strcmp("id", argv[argi] + 1)) {
|
||||
options |= SPV_VALIDATE_ID_BIT;
|
||||
} else if (!strcmp("rules", argv[argi] + 1)) {
|
||||
options |= SPV_VALIDATE_RULES_BIT;
|
||||
} else {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (!inFile) {
|
||||
inFile = argv[argi];
|
||||
} else {
|
||||
print_usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spvCheck(!inFile, fprintf(stderr, "error: input file is empty.\n"); return 1);
|
||||
|
||||
std::vector<uint32_t> contents;
|
||||
if (FILE *fp = fopen(inFile, "rb")) {
|
||||
uint32_t buf[1024];
|
||||
while (size_t len = fread(buf, sizeof(uint32_t),
|
||||
sizeof(buf) / sizeof(uint32_t), fp)) {
|
||||
contents.insert(contents.end(), buf, buf + len);
|
||||
}
|
||||
fclose(fp);
|
||||
} else {
|
||||
fprintf(stderr, "error: file does not exist '%s'\n", inFile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spv_binary_t binary = {contents.data(), contents.size()};
|
||||
|
||||
spv_opcode_table opcodeTable;
|
||||
spv_result_t error = spvOpcodeTableGet(&opcodeTable);
|
||||
spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
|
||||
return error);
|
||||
|
||||
spv_operand_table operandTable;
|
||||
error = spvOperandTableGet(&operandTable);
|
||||
spvCheck(error, fprintf(stderr, "error: internal malfunction\n");
|
||||
return error);
|
||||
|
||||
spv_ext_inst_table extInstTable;
|
||||
error = spvExtInstTableGet(&extInstTable);
|
||||
spvCheck(error, fprintf(stderr, "error: Internal malfunction.\n"));
|
||||
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
error = spvValidate(&binary, opcodeTable, operandTable, extInstTable, options,
|
||||
&diagnostic);
|
||||
spvCheck(error, spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic); return error);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user