spirv-reader: handle OpUndef at module scope
Fixed: tint:523 Change-Id: I47639c8f701ca049c7215874cdea27f86d8a415b Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/43760 Auto-Submit: David Neto <dneto@google.com> Commit-Queue: David Neto <dneto@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
parent
5a13258981
commit
ec44eef965
|
@ -2091,6 +2091,13 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) {
|
||||||
create<ast::IdentifierExpression>(
|
create<ast::IdentifierExpression>(
|
||||||
Source{}, builder_.Symbols().Register(name))};
|
Source{}, builder_.Symbols().Register(name))};
|
||||||
}
|
}
|
||||||
|
case SpvOpUndef:
|
||||||
|
// Substitute a null value for undef.
|
||||||
|
// This case occurs when OpUndef appears at module scope, as if it were
|
||||||
|
// a constant.
|
||||||
|
return parser_impl_.MakeNullExpression(
|
||||||
|
parser_impl_.ConvertType(inst->type_id()));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3294,7 +3301,7 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
|
||||||
|
|
||||||
if (opcode == SpvOpUndef) {
|
if (opcode == SpvOpUndef) {
|
||||||
// Replace undef with the null value.
|
// Replace undef with the null value.
|
||||||
return {ast_type, parser_impl_.MakeNullValue(ast_type)};
|
return parser_impl_.MakeNullExpression(ast_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == SpvOpSelect) {
|
if (opcode == SpvOpSelect) {
|
||||||
|
|
|
@ -40,6 +40,7 @@ std::string CommonTypes() {
|
||||||
%int = OpTypeInt 32 1
|
%int = OpTypeInt 32 1
|
||||||
%float = OpTypeFloat 32
|
%float = OpTypeFloat 32
|
||||||
|
|
||||||
|
%v2bool = OpTypeVector %bool 2
|
||||||
%v2uint = OpTypeVector %uint 2
|
%v2uint = OpTypeVector %uint 2
|
||||||
%v2int = OpTypeVector %int 2
|
%v2int = OpTypeVector %int 2
|
||||||
%v2float = OpTypeVector %float 2
|
%v2float = OpTypeVector %float 2
|
||||||
|
@ -48,6 +49,149 @@ std::string CommonTypes() {
|
||||||
|
|
||||||
using SpvParserTestMiscInstruction = SpvParserTest;
|
using SpvParserTestMiscInstruction = SpvParserTest;
|
||||||
|
|
||||||
|
TEST_F(SpvParserTestMiscInstruction, OpUndef_BeforeFunction_Scalar) {
|
||||||
|
const auto assembly = CommonTypes() + R"(
|
||||||
|
%1 = OpUndef %bool
|
||||||
|
%2 = OpUndef %uint
|
||||||
|
%3 = OpUndef %int
|
||||||
|
%4 = OpUndef %float
|
||||||
|
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
%11 = OpCopyObject %bool %1
|
||||||
|
%12 = OpCopyObject %uint %2
|
||||||
|
%13 = OpCopyObject %int %3
|
||||||
|
%14 = OpCopyObject %float %4
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
EXPECT_THAT(ToString(p->builder(), fe.ast_body()),
|
||||||
|
HasSubstr(R"(VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_11
|
||||||
|
none
|
||||||
|
__bool
|
||||||
|
{
|
||||||
|
ScalarConstructor[not set]{false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_12
|
||||||
|
none
|
||||||
|
__u32
|
||||||
|
{
|
||||||
|
ScalarConstructor[not set]{0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_13
|
||||||
|
none
|
||||||
|
__i32
|
||||||
|
{
|
||||||
|
ScalarConstructor[not set]{0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_14
|
||||||
|
none
|
||||||
|
__f32
|
||||||
|
{
|
||||||
|
ScalarConstructor[not set]{0.000000}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})")) << ToString(p->builder(), fe.ast_body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTestMiscInstruction, OpUndef_BeforeFunction_Vector) {
|
||||||
|
const auto assembly = CommonTypes() + R"(
|
||||||
|
%4 = OpUndef %v2bool
|
||||||
|
%1 = OpUndef %v2uint
|
||||||
|
%2 = OpUndef %v2int
|
||||||
|
%3 = OpUndef %v2float
|
||||||
|
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
|
||||||
|
%14 = OpCopyObject %v2uint %4
|
||||||
|
%11 = OpCopyObject %v2uint %1
|
||||||
|
%12 = OpCopyObject %v2int %2
|
||||||
|
%13 = OpCopyObject %v2float %3
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
EXPECT_THAT(ToString(p->builder(), fe.ast_body()),
|
||||||
|
HasSubstr(R"(VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_14
|
||||||
|
none
|
||||||
|
__vec_2__bool
|
||||||
|
{
|
||||||
|
TypeConstructor[not set]{
|
||||||
|
__vec_2__bool
|
||||||
|
ScalarConstructor[not set]{false}
|
||||||
|
ScalarConstructor[not set]{false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_11
|
||||||
|
none
|
||||||
|
__vec_2__u32
|
||||||
|
{
|
||||||
|
TypeConstructor[not set]{
|
||||||
|
__vec_2__u32
|
||||||
|
ScalarConstructor[not set]{0}
|
||||||
|
ScalarConstructor[not set]{0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_12
|
||||||
|
none
|
||||||
|
__vec_2__i32
|
||||||
|
{
|
||||||
|
TypeConstructor[not set]{
|
||||||
|
__vec_2__i32
|
||||||
|
ScalarConstructor[not set]{0}
|
||||||
|
ScalarConstructor[not set]{0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_13
|
||||||
|
none
|
||||||
|
__vec_2__f32
|
||||||
|
{
|
||||||
|
TypeConstructor[not set]{
|
||||||
|
__vec_2__f32
|
||||||
|
ScalarConstructor[not set]{0.000000}
|
||||||
|
ScalarConstructor[not set]{0.000000}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})")) << ToString(p->builder(), fe.ast_body());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserTestMiscInstruction, OpUndef_InFunction_Scalar) {
|
TEST_F(SpvParserTestMiscInstruction, OpUndef_InFunction_Scalar) {
|
||||||
const auto assembly = CommonTypes() + R"(
|
const auto assembly = CommonTypes() + R"(
|
||||||
%100 = OpFunction %void None %voidfn
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
|
@ -1538,6 +1538,10 @@ ast::Expression* ParserImpl::MakeNullValue(type::Type* type) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypedExpression ParserImpl::MakeNullExpression(type::Type* type) {
|
||||||
|
return {type, MakeNullValue(type)};
|
||||||
|
}
|
||||||
|
|
||||||
TypedExpression ParserImpl::RectifyOperandSignedness(
|
TypedExpression ParserImpl::RectifyOperandSignedness(
|
||||||
const spvtools::opt::Instruction& inst,
|
const spvtools::opt::Instruction& inst,
|
||||||
TypedExpression&& expr) {
|
TypedExpression&& expr) {
|
||||||
|
|
|
@ -326,6 +326,11 @@ class ParserImpl : Reader {
|
||||||
/// @returns a new expression
|
/// @returns a new expression
|
||||||
ast::Expression* MakeNullValue(type::Type* type);
|
ast::Expression* MakeNullValue(type::Type* type);
|
||||||
|
|
||||||
|
/// Make a typed expression for the null value for the given type.
|
||||||
|
/// @param type the AST type
|
||||||
|
/// @returns a new typed expression
|
||||||
|
TypedExpression MakeNullExpression(type::Type* type);
|
||||||
|
|
||||||
/// Converts a given expression to the signedness demanded for an operand
|
/// Converts a given expression to the signedness demanded for an operand
|
||||||
/// of the given SPIR-V instruction, if required. If the instruction assumes
|
/// of the given SPIR-V instruction, if required. If the instruction assumes
|
||||||
/// signed integer operands, and `expr` is unsigned, then return an
|
/// signed integer operands, and `expr` is unsigned, then return an
|
||||||
|
|
Loading…
Reference in New Issue