Skip to content

Commit 78acd32

Browse files
author
Tim Foley
authored
Replace /* unhandled */ in source emit with a real error (shader-slang#1313)
For a long time the various source-to-source back-ends have been emitted the text `/* unhandled */` when they encounter an IR instruction opcode that didn't have any emit logic implemented. This choice had two apparent benefits: * In most common cases, emitting `/* unhandled */` in place of an expression would lead to downstream compilation failure, so most catastrophic cases seemed to work as desired (e.g., if we emit `int i = /* unhandled */;` we get a downstream parse error and we know something is wrong. * In a few cases, if a dead-but-harmless instruction slips through (e.g., a type formed in the body of a specialized generic function), we would emit `/* unhandled */;`, which is a valid empty statement. It is already clear from the above write-up that the benefits of the policy aren't really that compelling, and where it has recently turned out to be a big liability is that there are actually plenty of cases where emitting `/* unhandled */` instead of a sub-expression won't cause downstream compilation failure, and will instead silently compute incorrect results: * Emitting `/* unhandled */ + b` instead of `a + b` * Emitting `/* unhandled */(a)` instead of `f(a)`, or even `/* unhandled */(a, b)` instead of `f(a,b)` * Emitting `f(/*unhandled*/)` instead of `f(a)` in cases where `f` is a built-in with both zero-argument and one-argument overloads The right fix here is simple: where we would have emitted `/* unhandled */` to the output we should instead diagnose an internal compiler error, thus leading to compilation failure. This change appears to pass all our current tests, but it is possible that there are going to be complicated cases in user code that were relying on the previous lax behavior. I know from experience that we sometimes see `/* unhandled */` in output for generics, and while we have eliminated many of those cases I don't have confidence we've dealt with them all. When this change lands we should make sure that the first release that incorporates it is marked as potentially breaking for clients, and we should make sure to test the changes in the context of the client codebases before those codebases integrate the new release.
1 parent 6274e17 commit 78acd32

File tree

4 files changed

+9
-3
lines changed

4 files changed

+9
-3
lines changed

source/slang/slang-emit-c-like.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -1883,6 +1883,11 @@ void CLikeSourceEmitter::emitInstExpr(IRInst* inst, const EmitOpInfo& inOuterPre
18831883
defaultEmitInstExpr(inst, inOuterPrec);
18841884
}
18851885

1886+
void CLikeSourceEmitter::diagnoseUnhandledInst(IRInst* inst)
1887+
{
1888+
getSink()->diagnose(inst, Diagnostics::unimplemented, "unexpected IR opcode during code emit");
1889+
}
1890+
18861891
void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inOuterPrec)
18871892
{
18881893
EmitOpInfo outerPrec = inOuterPrec;
@@ -2195,7 +2200,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
21952200
break;
21962201

21972202
default:
2198-
m_writer->emit("/* unhandled */");
2203+
diagnoseUnhandledInst(inst);
21992204
break;
22002205
}
22012206
maybeCloseParens(needClose);

source/slang/slang-emit-c-like.h

+1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ class CLikeSourceEmitter: public RefObject
196196

197197
void emitInstExpr(IRInst* inst, EmitOpInfo const& inOuterPrec);
198198
void defaultEmitInstExpr(IRInst* inst, EmitOpInfo const& inOuterPrec);
199+
void diagnoseUnhandledInst(IRInst* inst);
199200

200201
BaseType extractBaseType(IRType* inType);
201202

source/slang/slang-emit-glsl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ bool GLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
11281128
switch (toType)
11291129
{
11301130
default:
1131-
m_writer->emit("/* unhandled */");
1131+
diagnoseUnhandledInst(inst);
11321132
break;
11331133

11341134
case BaseType::UInt:

source/slang/slang-emit-hlsl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
439439
switch (toType)
440440
{
441441
default:
442-
m_writer->emit("/* unhandled */");
442+
diagnoseUnhandledInst(inst);
443443
break;
444444
case BaseType::UInt:
445445
break;

0 commit comments

Comments
 (0)