blob: 1f0841455b340d842b8217db1d2afe60bccf6dbc [file] [log] [blame] [edit]
// Copyright 2025 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string>
#include "gmock/gmock.h"
#include "test/link/linker_fixture.h"
namespace spvtools {
namespace {
using FunctionVariants = spvtest::LinkerTest;
TEST_F(FunctionVariants, Dot4) {
constexpr const char* const dot4_fp32 = R"(
OpCapability Kernel
OpCapability Addresses
OpCapability Int8
OpCapability Int64
OpCapability Linkage
%1 = OpExtInstImport "OpenCL.std"
OpMemoryModel Physical64 OpenCL
OpEntryPoint Kernel %2 "dot4" %3
OpExecutionMode %2 ContractionOff
OpSource OpenCL_C 102000
OpName %2 "dot4"
OpName %3 "__spirv_BuiltInGlobalInvocationId"
OpName %4 "entry"
%5 = OpTypeFloat 32
%6 = OpTypePointer CrossWorkgroup %5
%7 = OpTypeInt 8 0
%8 = OpTypePointer CrossWorkgroup %7
%9 = OpTypeVoid
%10 = OpTypeFunction %9 %6 %6 %8
%11 = OpTypeInt 64 0
%12 = OpTypeInt 32 0
%13 = OpTypeVector %11 3
%14 = OpTypePointer Input %13
%15 = OpTypeVector %5 4
%16 = OpConstant %11 30
%17 = OpConstant %11 32
%18 = OpConstant %12 2
%3 = OpVariable %14 Input
%2 = OpFunction %9 None %10
%19 = OpFunctionParameter %6
%20 = OpFunctionParameter %6
%21 = OpFunctionParameter %8
%4 = OpLabel
%22 = OpLoad %13 %3 Aligned 1
%23 = OpCompositeExtract %11 %22 0
%24 = OpUConvert %12 %23
%25 = OpShiftLeftLogical %12 %24 %18
%26 = OpSConvert %11 %25
%27 = OpExtInst %15 %1 vloadn %26 %19 4
%28 = OpExtInst %15 %1 vloadn %26 %20 4
%29 = OpDot %5 %27 %28
%30 = OpShiftLeftLogical %11 %23 %17
%31 = OpShiftRightArithmetic %11 %30 %16
%32 = OpInBoundsPtrAccessChain %8 %21 %31
%33 = OpBitcast %6 %32
OpStore %33 %29 Aligned 4
OpReturn
OpFunctionEnd
)";
constexpr const char* const dot4_fp16 = R"(
OpCapability Kernel
OpCapability Addresses
OpCapability Int8
OpCapability Int64
OpCapability Float16
OpCapability Linkage
%1 = OpExtInstImport "OpenCL.std"
OpMemoryModel Physical64 OpenCL
OpEntryPoint Kernel %2 "dot4" %3
OpExecutionMode %2 ContractionOff
OpSource OpenCL_C 102000
OpName %2 "dot4"
OpName %3 "__spirv_BuiltInGlobalInvocationId"
OpName %4 "entry"
%5 = OpTypeFloat 16
%6 = OpTypePointer CrossWorkgroup %5
%7 = OpTypeInt 8 0
%8 = OpTypePointer CrossWorkgroup %7
%9 = OpTypeVoid
%10 = OpTypeFunction %9 %6 %6 %8
%11 = OpTypeInt 64 0
%12 = OpTypeInt 32 0
%13 = OpTypeVector %11 3
%14 = OpTypePointer Input %13
%15 = OpTypeVector %5 4
%16 = OpConstant %11 31
%17 = OpConstant %11 32
%18 = OpConstant %12 2
%3 = OpVariable %14 Input
%2 = OpFunction %9 None %10
%19 = OpFunctionParameter %6
%20 = OpFunctionParameter %6
%21 = OpFunctionParameter %8
%4 = OpLabel
%22 = OpLoad %13 %3 Aligned 1
%23 = OpCompositeExtract %11 %22 0
%24 = OpUConvert %12 %23
%25 = OpShiftLeftLogical %12 %24 %18
%26 = OpSConvert %11 %25
%27 = OpExtInst %15 %1 vloadn %26 %19 4
%28 = OpExtInst %15 %1 vloadn %26 %20 4
%29 = OpDot %5 %27 %28
%30 = OpShiftLeftLogical %11 %23 %17
%31 = OpShiftRightArithmetic %11 %30 %16
%32 = OpInBoundsPtrAccessChain %8 %21 %31
%33 = OpBitcast %6 %32
OpStore %33 %29 Aligned 4
OpReturn
OpFunctionEnd
)";
// clang-format off
const std::vector<const char*> expected_lines = {
"OpCapability FunctionVariantsINTEL",
"OpCapability SpecConditionalINTEL",
"OpCapability Kernel",
"OpCapability Addresses",
"OpCapability Int8",
"OpCapability Int64",
"OpCapability Linkage",
"OpConditionalCapabilityINTEL %dot4_fp16_spv Float16",
"OpExtension \"SPV_INTEL_function_variants\"",
"OpConditionalEntryPointINTEL %dot4_fp32_spv Kernel %dot4 \"dot4\" %__spirv_BuiltInGlobalInvocationId",
"OpConditionalEntryPointINTEL %dot4_fp16_spv Kernel %dot4_0 \"dot4\" %__spirv_BuiltInGlobalInvocationId_0",
"OpModuleProcessed \"SPV_INTEL_function_variants registry version 0\"",
"OpDecorate %ulong_30 ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %ulong_32 ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %uint_2 ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %__spirv_BuiltInGlobalInvocationId ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %dot4 ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %ulong_31 ConditionalINTEL %dot4_fp16_spv",
"OpDecorate %ulong_32_0 ConditionalINTEL %dot4_fp16_spv",
"OpDecorate %uint_2_0 ConditionalINTEL %dot4_fp16_spv",
"OpDecorate %__spirv_BuiltInGlobalInvocationId_0 ConditionalINTEL %dot4_fp16_spv",
"OpDecorate %dot4_0 ConditionalINTEL %dot4_fp16_spv",
"OpDecorate %float ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %_ptr_CrossWorkgroup_float ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %18 ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %v4float ConditionalINTEL %dot4_fp32_spv",
"OpDecorate %half ConditionalINTEL %dot4_fp16_spv",
"OpDecorate %_ptr_CrossWorkgroup_half ConditionalINTEL %dot4_fp16_spv",
"OpDecorate %22 ConditionalINTEL %dot4_fp16_spv",
"OpDecorate %v4half ConditionalINTEL %dot4_fp16_spv",
"%float = OpTypeFloat 32",
"%_ptr_CrossWorkgroup_float = OpTypePointer CrossWorkgroup %float",
"%18 = OpTypeFunction %void %_ptr_CrossWorkgroup_float %_ptr_CrossWorkgroup_float %_ptr_CrossWorkgroup_uchar",
"%v4float = OpTypeVector %float 4",
"%ulong_30 = OpConstant %ulong 30",
"%ulong_32 = OpConstant %ulong 32",
"%uint_2 = OpConstant %uint 2",
"%__spirv_BuiltInGlobalInvocationId = OpVariable %_ptr_Input_v3ulong Input",
"%bool = OpTypeBool",
"%32 = OpSpecConstantArchitectureINTEL %bool 2 3 174 0",
"%33 = OpSpecConstantTargetINTEL %bool 7",
"%34 = OpSpecConstantTargetINTEL %bool 8",
"%35 = OpSpecConstantCapabilitiesINTEL %bool Addresses Linkage Kernel Int64 Int8",
"%36 = OpSpecConstantOp %bool LogicalOr %33 %34",
"%37 = OpSpecConstantOp %bool LogicalAnd %35 %32",
"%38 = OpSpecConstantOp %bool LogicalAnd %37 %36",
"%half = OpTypeFloat 16",
"%_ptr_CrossWorkgroup_half = OpTypePointer CrossWorkgroup %half",
"%22 = OpTypeFunction %void %_ptr_CrossWorkgroup_half %_ptr_CrossWorkgroup_half %_ptr_CrossWorkgroup_uchar",
"%v4half = OpTypeVector %half 4",
"%ulong_31 = OpConstant %ulong 31",
"%ulong_32_0 = OpConstant %ulong 32",
"%uint_2_0 = OpConstant %uint 2",
"%__spirv_BuiltInGlobalInvocationId_0 = OpVariable %_ptr_Input_v3ulong Input",
"%39 = OpSpecConstantArchitectureINTEL %bool 2 3 174 4",
"%40 = OpSpecConstantTargetINTEL %bool 7",
"%41 = OpSpecConstantTargetINTEL %bool 8",
"%42 = OpSpecConstantCapabilitiesINTEL %bool Addresses Linkage Kernel Float16 Int64 Int8",
"%43 = OpSpecConstantOp %bool LogicalOr %40 %41",
"%44 = OpSpecConstantOp %bool LogicalAnd %42 %39",
"%dot4_fp16_spv = OpSpecConstantOp %bool LogicalAnd %44 %43",
"%45 = OpSpecConstantOp %bool LogicalNot %dot4_fp16_spv",
"%dot4_fp32_spv = OpSpecConstantOp %bool LogicalAnd %38 %45",
"%dot4 = OpFunction %void None %18",
"%56 = OpDot %float %54 %55",
"%dot4_0 = OpFunction %void None %22",
"%71 = OpDot %half %69 %70",
};
// clang-format on
const std::string targets_csv =
"module,target,features\n"
"dot4_fp32.spv,7,\n"
"dot4_fp32.spv,8,\n"
"dot4_fp16.spv,7,\n"
"dot4_fp16.spv,8,\n";
const std::string architectures_csv =
"module,category,family,op,architecture\n"
"dot4_fp32.spv,2,3,174,0\n"
"dot4_fp16.spv,2,3,174,4\n";
const std::vector<std::string> sources = {dot4_fp32, dot4_fp16};
const std::vector<std::string> in_files = {"dot4_fp32.spv", "dot4_fp16.spv"};
LinkerOptions options;
options.SetInFiles(in_files);
options.SetFnVarTargetsCsv(targets_csv);
options.SetFnVarArchitecturesCsv(architectures_csv);
options.SetHasFnVarCapabilities(true);
options.SetCreateLibrary(true);
options.SetVerifyIds(true);
spvtest::Binary linked_binary;
spv_result_t res = AssembleAndLink(sources, &linked_binary, options);
EXPECT_EQ(SPV_SUCCESS, res) << GetErrorMessage();
EXPECT_THAT(GetErrorMessage(), std::string());
EXPECT_TRUE(Validate(linked_binary));
std::string linked_asm;
res = Disassemble(linked_binary, &linked_asm);
EXPECT_EQ(SPV_SUCCESS, res) << GetErrorMessage();
for (const auto& expected : expected_lines) {
EXPECT_THAT(linked_asm, testing::HasSubstr(expected));
}
}
TEST_F(FunctionVariants, FAddAsm) {
constexpr const char* const foo_base = R"(
OpCapability Kernel
OpCapability Addresses
OpCapability Int8
OpCapability Int64
OpCapability Linkage
%1 = OpExtInstImport "OpenCL.std"
OpMemoryModel Physical64 OpenCL
OpSource OpenCL_CPP 100000
OpName %2 "foo"
OpName %3 "add"
OpName %4 "entry"
OpName %5 "work"
OpName %6 "call"
OpName %7 "entry"
OpDecorate %2 LinkageAttributes "foo" Export
OpDecorate %5 LinkageAttributes "work" Export
%8 = OpTypeFloat 32
%9 = OpTypePointer Function %8
%10 = OpTypeFunction %8 %9 %9 %9
%11 = OpTypeInt 8 0
%12 = OpTypePointer Function %11
%13 = OpTypeInt 64 0
%14 = OpConstant %13 28
%15 = OpConstant %13 24
%16 = OpConstant %13 20
%17 = OpConstant %13 16
%18 = OpConstant %13 12
%19 = OpConstant %13 8
%20 = OpConstant %13 4
%2 = OpFunction %8 DontInline %10
%21 = OpFunctionParameter %9
%22 = OpFunctionParameter %9
%23 = OpFunctionParameter %9
%4 = OpLabel
%24 = OpLoad %8 %21 Aligned 4
%25 = OpLoad %8 %22 Aligned 4
%3 = OpFAdd %8 %24 %25
OpStore %23 %3 Aligned 4
OpReturnValue %3
OpFunctionEnd
%5 = OpFunction %8 None %10
%26 = OpFunctionParameter %9
%27 = OpFunctionParameter %9
%28 = OpFunctionParameter %9
%7 = OpLabel
%6 = OpFunctionCall %8 %2 %26 %27 %28
%29 = OpFDiv %8 %6 %6
%30 = OpFDiv %8 %29 %6
OpReturnValue %30
OpFunctionEnd
)";
constexpr const char* const foo_asm = R"(
OpCapability Kernel
OpCapability Addresses
OpCapability Linkage
OpCapability AsmINTEL
OpExtension "SPV_INTEL_inline_assembly"
%1 = OpExtInstImport "OpenCL.std"
OpMemoryModel Physical64 OpenCL
OpSource OpenCL_CPP 100000
OpName %2 "a"
OpName %3 "b"
OpName %4 "c"
OpName %5 "foo"
OpName %6 "add"
OpName %7 "entry"
OpDecorate %2 FuncParamAttr NoWrite
OpDecorate %2 FuncParamAttr NoAlias
OpDecorate %3 FuncParamAttr NoWrite
OpDecorate %3 FuncParamAttr NoAlias
OpDecorate %4 FuncParamAttr NoAlias
OpDecorate %5 LinkageAttributes "foo" Export
OpDecorate %8 SideEffectsINTEL
%9 = OpTypeFloat 32
%10 = OpTypePointer Function %9
%11 = OpTypeFunction %9 %10 %10 %10
%12 = OpTypeVoid
%13 = OpTypeFunction %12
%14 = OpAsmTargetINTEL "spirv64-unknown-unknown"
%8 = OpAsmINTEL %12 %13 %14 "nop1" ""
%5 = OpFunction %9 None %11
%2 = OpFunctionParameter %10
%3 = OpFunctionParameter %10
%4 = OpFunctionParameter %10
%7 = OpLabel
%15 = OpLoad %9 %2 Aligned 4
%16 = OpLoad %9 %3 Aligned 4
%6 = OpFSub %9 %15 %16
OpStore %4 %6 Aligned 4
%17 = OpAsmCallINTEL %12 %8
OpReturnValue %6
OpFunctionEnd
)";
// same as foo_asm, just with OpFMul and a different assembly string in
// OpAsmINTEL
constexpr const char* const foo_asm2 = R"(
OpCapability Kernel
OpCapability Addresses
OpCapability Linkage
OpCapability AsmINTEL
OpExtension "SPV_INTEL_inline_assembly"
%1 = OpExtInstImport "OpenCL.std"
OpMemoryModel Physical64 OpenCL
OpSource OpenCL_CPP 100000
OpName %2 "a"
OpName %3 "b"
OpName %4 "c"
OpName %5 "foo"
OpName %6 "add"
OpName %7 "entry"
OpDecorate %2 FuncParamAttr NoWrite
OpDecorate %2 FuncParamAttr NoAlias
OpDecorate %3 FuncParamAttr NoWrite
OpDecorate %3 FuncParamAttr NoAlias
OpDecorate %4 FuncParamAttr NoAlias
OpDecorate %5 LinkageAttributes "foo" Export
OpDecorate %8 SideEffectsINTEL
%9 = OpTypeFloat 32
%10 = OpTypePointer Function %9
%11 = OpTypeFunction %9 %10 %10 %10
%12 = OpTypeVoid
%13 = OpTypeFunction %12
%14 = OpAsmTargetINTEL "spirv64-unknown-unknown"
%8 = OpAsmINTEL %12 %13 %14 "nop2" ""
%5 = OpFunction %9 None %11
%2 = OpFunctionParameter %10
%3 = OpFunctionParameter %10
%4 = OpFunctionParameter %10
%7 = OpLabel
%15 = OpLoad %9 %2 Aligned 4
%16 = OpLoad %9 %3 Aligned 4
%6 = OpFMul %9 %15 %16
OpStore %4 %6 Aligned 4
%17 = OpAsmCallINTEL %12 %8
OpReturnValue %6
OpFunctionEnd
)";
// clang-format off
const std::vector<const char*> expected_lines = {
"OpCapability FunctionVariantsINTEL",
"OpCapability SpecConditionalINTEL",
"OpCapability Kernel",
"OpCapability Addresses",
"OpConditionalCapabilityINTEL %foo_spv Int8",
"OpConditionalCapabilityINTEL %foo_spv Int64",
"OpCapability Linkage",
"OpConditionalCapabilityINTEL %2 AsmINTEL",
"OpExtension \"SPV_INTEL_function_variants\"",
"OpConditionalExtensionINTEL %2 \"SPV_INTEL_inline_assembly\"",
"OpModuleProcessed \"SPV_INTEL_function_variants registry version 0\"",
"OpDecorate %foo LinkageAttributes \"foo\" Export",
"OpDecorate %work LinkageAttributes \"work\" Export",
"OpDecorate %ulong_28 ConditionalINTEL %foo_spv",
"OpDecorate %ulong_24 ConditionalINTEL %foo_spv",
"OpDecorate %ulong_20 ConditionalINTEL %foo_spv",
"OpDecorate %ulong_16 ConditionalINTEL %foo_spv",
"OpDecorate %ulong_12 ConditionalINTEL %foo_spv",
"OpDecorate %ulong_8 ConditionalINTEL %foo_spv",
"OpDecorate %ulong_4 ConditionalINTEL %foo_spv",
"OpDecorate %foo ConditionalINTEL %foo_spv",
"OpDecorate %foo_0 LinkageAttributes \"foo\" Export",
"OpDecorate %32 ConditionalINTEL %foo_asm_spv",
"OpDecorate %31 ConditionalINTEL %foo_asm_spv",
"OpDecorate %foo_0 ConditionalINTEL %foo_asm_spv",
"OpDecorate %foo_1 LinkageAttributes \"foo\" Export",
"OpDecorate %34 ConditionalINTEL %foo_asm2_spv",
"OpDecorate %33 ConditionalINTEL %foo_asm2_spv",
"OpDecorate %foo_1 ConditionalINTEL %foo_asm2_spv",
"OpDecorate %call ConditionalINTEL %foo_spv",
"OpDecorate %35 ConditionalINTEL %foo_asm_spv",
"OpDecorate %36 ConditionalINTEL %foo_asm2_spv",
"OpDecorate %uchar ConditionalINTEL %foo_spv",
"OpDecorate %_ptr_Function_uchar ConditionalINTEL %foo_spv",
"OpDecorate %ulong ConditionalINTEL %foo_spv",
"OpDecorate %void ConditionalINTEL %2",
"OpDecorate %41 ConditionalINTEL %2",
"%ulong_28 = OpConstant %ulong 28",
"%ulong_24 = OpConstant %ulong 24",
"%ulong_20 = OpConstant %ulong 20",
"%ulong_16 = OpConstant %ulong 16",
"%ulong_12 = OpConstant %ulong 12",
"%ulong_8 = OpConstant %ulong 8",
"%ulong_4 = OpConstant %ulong 4",
"%bool = OpTypeBool",
"%46 = OpSpecConstantTargetINTEL %bool 4",
"%47 = OpSpecConstantCapabilitiesINTEL %bool Addresses Linkage Kernel Int64 Int8",
"%48 = OpSpecConstantOp %bool LogicalAnd %47 %46",
"%31 = OpAsmINTEL %void %41 %32 \"nop1\" \"\"",
"%49 = OpSpecConstantArchitectureINTEL %bool 1 1 170 1",
"%50 = OpSpecConstantTargetINTEL %bool 4 9 10",
"%51 = OpSpecConstantCapabilitiesINTEL %bool Addresses Linkage Kernel AsmINTEL",
"%52 = OpSpecConstantOp %bool LogicalAnd %51 %49",
"%foo_asm_spv = OpSpecConstantOp %bool LogicalAnd %52 %50",
"%33 = OpAsmINTEL %void %41 %34 \"nop2\" \"\"",
"%53 = OpSpecConstantArchitectureINTEL %bool 1 7 174 1",
"%54 = OpSpecConstantArchitectureINTEL %bool 1 7 178 3",
"%55 = OpSpecConstantArchitectureINTEL %bool 1 8 170 1",
"%56 = OpSpecConstantArchitectureINTEL %bool 1 9 174 1",
"%57 = OpSpecConstantArchitectureINTEL %bool 1 9 178 3",
"%58 = OpSpecConstantTargetINTEL %bool 5 2 4 5",
"%59 = OpSpecConstantTargetINTEL %bool 6 2 4 5",
"%60 = OpSpecConstantCapabilitiesINTEL %bool Addresses Linkage Kernel AsmINTEL",
"%61 = OpSpecConstantOp %bool LogicalAnd %53 %54",
"%62 = OpSpecConstantOp %bool LogicalAnd %56 %57",
"%63 = OpSpecConstantOp %bool LogicalOr %61 %55",
"%64 = OpSpecConstantOp %bool LogicalOr %63 %62",
"%65 = OpSpecConstantOp %bool LogicalOr %58 %59",
"%66 = OpSpecConstantOp %bool LogicalAnd %60 %64",
"%foo_asm2_spv = OpSpecConstantOp %bool LogicalAnd %66 %65",
"%67 = OpSpecConstantOp %bool LogicalOr %foo_asm_spv %foo_asm2_spv",
"%68 = OpSpecConstantOp %bool LogicalNot %67",
"%foo_spv = OpSpecConstantOp %bool LogicalAnd %48 %68",
"%2 = OpSpecConstantOp %bool LogicalOr %foo_asm_spv %foo_asm2_spv",
"%foo = OpFunction %float DontInline %44",
"%add = OpFAdd %float %72 %73",
"%work = OpFunction %float None %44",
"%call = OpFunctionCall %float %foo %74 %75 %76",
"%35 = OpFunctionCall %float %foo_0 %74 %75 %76",
"%36 = OpFunctionCall %float %foo_1 %74 %75 %76",
"%77 = OpConditionalCopyObjectINTEL %float %foo_spv %call %foo_asm_spv %35 %foo_asm2_spv %36",
"%78 = OpFDiv %float %77 %77",
"%79 = OpFDiv %float %78 %77",
"OpReturnValue %79",
"%foo_0 = OpFunction %float None %44",
"%add_0 = OpFSub %float %80 %81",
"%82 = OpAsmCallINTEL %void %31",
"%foo_1 = OpFunction %float None %44",
"%add_1 = OpFMul %float %83 %84",
"%85 = OpAsmCallINTEL %void %33",
};
// clang-format on
const std::string targets_csv =
"module,target,features\n"
"foo.spv,04,\n" // test leading zeros
"foo_asm.spv,4,9/0010\n" // test leading zeros
"foo_asm2.spv,5,2/4/5\n"
"foo_asm2.spv,6,2/4/5\n";
const std::string architectures_csv =
"module,category,family,op,architecture\n"
"foo_asm.spv,1,1,170,1\n"
"foo_asm2.spv,1,7,174,1\n"
"foo_asm2.spv,1,7,178,3\n"
"foo_asm2.spv,1,8,170,1\n"
"foo_asm2.spv,1,9,174,1\n"
"foo_asm2.spv,1,9,178,3\n";
const std::vector<std::string> sources = {foo_base, foo_asm, foo_asm2};
const std::vector<std::string> in_files = {"foo.spv", "foo_asm.spv",
"foo_asm2.spv"};
LinkerOptions options;
options.SetInFiles(in_files);
options.SetFnVarTargetsCsv(targets_csv);
options.SetFnVarArchitecturesCsv(architectures_csv);
options.SetHasFnVarCapabilities(true);
options.SetCreateLibrary(true);
options.SetVerifyIds(true);
spvtest::Binary linked_binary;
spv_result_t res = AssembleAndLink(sources, &linked_binary, options);
EXPECT_EQ(SPV_SUCCESS, res) << GetErrorMessage();
EXPECT_THAT(GetErrorMessage(), std::string());
EXPECT_TRUE(Validate(linked_binary));
std::string linked_asm;
res = Disassemble(linked_binary, &linked_asm);
EXPECT_EQ(SPV_SUCCESS, res) << GetErrorMessage();
for (const auto& expected : expected_lines) {
EXPECT_THAT(linked_asm, testing::HasSubstr(expected));
}
}
TEST_F(FunctionVariants, InvalidNumber1) {
const std::string targets_csv =
"module,target,features\n"
"foo.spv,-4,9/10\n";
const std::string architectures_csv = "";
const std::vector<std::string> sources = {""};
const std::vector<std::string> in_files = {"foo.spv"};
LinkerOptions options;
options.SetInFiles(in_files);
options.SetFnVarTargetsCsv(targets_csv);
options.SetFnVarArchitecturesCsv(architectures_csv);
options.SetHasFnVarCapabilities(true);
options.SetCreateLibrary(true);
options.SetVerifyIds(true);
spvtest::Binary linked_binary;
spv_result_t res = AssembleAndLink(sources, &linked_binary, options);
EXPECT_EQ(SPV_ERROR_FNVAR, res) << GetErrorMessage();
EXPECT_THAT(GetErrorMessage(), "ERROR: 0: Error converting -4 to target.");
}
TEST_F(FunctionVariants, InvalidNumber2) {
const std::string targets_csv =
"module,target,features\n"
"foo.spv,4,9/-10\n";
const std::string architectures_csv = "";
const std::vector<std::string> sources = {""};
const std::vector<std::string> in_files = {"foo.spv"};
LinkerOptions options;
options.SetInFiles(in_files);
options.SetFnVarTargetsCsv(targets_csv);
options.SetFnVarArchitecturesCsv(architectures_csv);
options.SetHasFnVarCapabilities(true);
options.SetCreateLibrary(true);
options.SetVerifyIds(true);
spvtest::Binary linked_binary;
spv_result_t res = AssembleAndLink(sources, &linked_binary, options);
EXPECT_EQ(SPV_ERROR_FNVAR, res) << GetErrorMessage();
EXPECT_THAT(GetErrorMessage(),
"ERROR: 0: Error converting -10 in 9/-10 to target feature.");
}
TEST_F(FunctionVariants, InvalidNumber3) {
const std::string targets_csv =
"module,target,features\n"
"foo.spv,4.0,9/10\n";
const std::string architectures_csv = "";
const std::vector<std::string> sources = {""};
const std::vector<std::string> in_files = {"foo.spv"};
LinkerOptions options;
options.SetInFiles(in_files);
options.SetFnVarTargetsCsv(targets_csv);
options.SetFnVarArchitecturesCsv(architectures_csv);
options.SetHasFnVarCapabilities(true);
options.SetCreateLibrary(true);
options.SetVerifyIds(true);
spvtest::Binary linked_binary;
spv_result_t res = AssembleAndLink(sources, &linked_binary, options);
EXPECT_EQ(SPV_ERROR_FNVAR, res) << GetErrorMessage();
EXPECT_THAT(GetErrorMessage(), "ERROR: 0: Error converting 4.0 to target.");
}
} // namespace
} // namespace spvtools