diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc index 48c3b7f209..0635a80309 100644 --- a/src/reader/spirv/function.cc +++ b/src/reader/spirv/function.cc @@ -2423,6 +2423,12 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { // So represent a load by a new const definition. return EmitConstDefinition( inst, MakeExpression(inst.GetSingleWordInOperand(0))); + case SpvOpCopyObject: + // Arguably, OpCopyObject is purely combinatorial. On the other hand, + // it exists to make a new name for something. So we choose to make + // a new named constant definition. + return EmitConstDefinition( + inst, MakeExpression(inst.GetSingleWordInOperand(0))); case SpvOpFunctionCall: // TODO(dneto): Fill this out. Make this pass, for existing tests return success(); diff --git a/src/reader/spirv/function_composite_test.cc b/src/reader/spirv/function_composite_test.cc index c3606179bf..af6d400668 100644 --- a/src/reader/spirv/function_composite_test.cc +++ b/src/reader/spirv/function_composite_test.cc @@ -509,6 +509,81 @@ TEST_F(SpvParserTest_CompositeExtract, Struct_Array_Matrix_Vector) { << ToString(fe.ast_body()); } +using SpvParserTest_CopyObject = SpvParserTest; + +TEST_F(SpvParserTest_CopyObject, Scalar) { + const auto assembly = Preamble() + R"( + %100 = OpFunction %void None %voidfn + %entry = OpLabel + %1 = OpCopyObject %uint %uint_3 + %2 = OpCopyObject %uint %1 + OpReturn + OpFunctionEnd + )"; + auto* p = parser(test::Assemble(assembly)); + ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly; + FunctionEmitter fe(p, *spirv_function(100)); + EXPECT_TRUE(fe.EmitBody()) << p->error(); + EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{ + Variable{ + x_1 + none + __u32 + { + ScalarConstructor{3} + } + } +} +VariableDeclStatement{ + Variable{ + x_2 + none + __u32 + { + Identifier{x_1} + } + } +})")) << ToString(fe.ast_body()); +} + +TEST_F(SpvParserTest_CopyObject, Pointer) { + const auto assembly = Preamble() + R"( + %ptr = OpTypePointer Function %uint + %10 = OpVariable %ptr Function + + %100 = OpFunction %void None %voidfn + %entry = OpLabel + %1 = OpCopyObject %ptr %10 + %2 = OpCopyObject %ptr %1 + OpReturn + OpFunctionEnd + )"; + auto* p = parser(test::Assemble(assembly)); + ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly; + FunctionEmitter fe(p, *spirv_function(100)); + EXPECT_TRUE(fe.EmitBody()) << p->error(); + EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{ + Variable{ + x_1 + none + __ptr_function__u32 + { + Identifier{x_10} + } + } +} +VariableDeclStatement{ + Variable{ + x_2 + none + __ptr_function__u32 + { + Identifier{x_1} + } + } +})")) << ToString(fe.ast_body()); +} + } // namespace } // namespace spirv } // namespace reader