Assert on unimplemented instructions Replace the runtime `warning` with something that will actually crash us, and add stub implementations of OpLabel and OpReturn to allow trivial shaders to work. There's little point in continuing beyond an unimplemented instruction -- if you get lucky, you hit a crash on use of the instruction's result. If you get unlucky, you wander off into undefined behavior. Change-Id: I3b222ea74446754276096c81fc3669c311872316 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26088 Tested-by: Chris Forbes <chrisforbes@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp index ed2beee..77d3393 100644 --- a/src/Pipeline/SpirvShader.cpp +++ b/src/Pipeline/SpirvShader.cpp
@@ -31,6 +31,13 @@ // - There is exactly one entrypoint in the module, and it's the one we want // - The only input/output OpVariables present are those used by the entrypoint + // TODO: Add real support for control flow. For now, track whether we've seen + // a label or a return already (if so, the shader does things we will mishandle). + // We expect there to be one of each in a simple shader -- the first and last instruction + // of the entrypoint function. + bool seenLabel = false; + bool seenReturn = false; + for (auto insn : *this) { switch (insn.opcode()) @@ -101,6 +108,18 @@ break; } + case spv::OpLabel: + if (seenLabel) + UNIMPLEMENTED("Shader contains multiple labels, has control flow"); + seenLabel = true; + break; + + case spv::OpReturn: + if (seenReturn) + UNIMPLEMENTED("Shader contains multiple returns, has control flow"); + seenReturn = true; + break; + case spv::OpTypeVoid: case spv::OpTypeBool: case spv::OpTypeInt: @@ -278,7 +297,6 @@ } case spv::OpStore: - case spv::OpReturn: // Don't need to do anything during analysis pass break; @@ -287,8 +305,7 @@ break; default: - printf("Warning: ignored opcode %s\n", OpcodeName(insn.opcode()).c_str()); - break; // This is OK, these passes are intentionally partial + UNIMPLEMENTED(OpcodeName(insn.opcode()).c_str()); } } } @@ -875,6 +892,14 @@ // or don't require any work at all. break; + case spv::OpLabel: + case spv::OpReturn: + // TODO: when we do control flow, will need to do some work here. + // Until then, there is nothing to do -- we expect there to be an initial OpLabel + // in the entrypoint function, for which we do nothing; and a final OpReturn at the + // end of the entrypoint function, for which we do nothing. + break; + case spv::OpVariable: EmitVariable(insn, routine); break; @@ -956,7 +981,7 @@ break; default: - printf("emit: ignoring opcode %s\n", OpcodeName(insn.opcode()).c_str()); + UNIMPLEMENTED(OpcodeName(insn.opcode()).c_str()); break; } }