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>(
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -3294,7 +3301,7 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
|
|||
|
||||
if (opcode == SpvOpUndef) {
|
||||
// Replace undef with the null value.
|
||||
return {ast_type, parser_impl_.MakeNullValue(ast_type)};
|
||||
return parser_impl_.MakeNullExpression(ast_type);
|
||||
}
|
||||
|
||||
if (opcode == SpvOpSelect) {
|
||||
|
|
|
@ -40,6 +40,7 @@ std::string CommonTypes() {
|
|||
%int = OpTypeInt 32 1
|
||||
%float = OpTypeFloat 32
|
||||
|
||||
%v2bool = OpTypeVector %bool 2
|
||||
%v2uint = OpTypeVector %uint 2
|
||||
%v2int = OpTypeVector %int 2
|
||||
%v2float = OpTypeVector %float 2
|
||||
|
@ -48,6 +49,149 @@ std::string CommonTypes() {
|
|||
|
||||
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) {
|
||||
const auto assembly = CommonTypes() + R"(
|
||||
%100 = OpFunction %void None %voidfn
|
||||
|
|
|
@ -1538,6 +1538,10 @@ ast::Expression* ParserImpl::MakeNullValue(type::Type* type) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
TypedExpression ParserImpl::MakeNullExpression(type::Type* type) {
|
||||
return {type, MakeNullValue(type)};
|
||||
}
|
||||
|
||||
TypedExpression ParserImpl::RectifyOperandSignedness(
|
||||
const spvtools::opt::Instruction& inst,
|
||||
TypedExpression&& expr) {
|
||||
|
|
|
@ -326,6 +326,11 @@ class ParserImpl : Reader {
|
|||
/// @returns a new expression
|
||||
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
|
||||
/// of the given SPIR-V instruction, if required. If the instruction assumes
|
||||
/// signed integer operands, and `expr` is unsigned, then return an
|
||||
|
|
Loading…
Reference in New Issue