Disallow function calls to main().

In practice, calls to main are not meaningful:
- If main is called in live code, it's recursive
- If main is called in dead code, it's eliminated

However, if optimization/dead-stripping is turned off, the dead-code
case emits bad code in our GLSL/Metal backends. Rather than add a
special case to the backends to work around an error in a meaningless
edge case, we now reject the function call entirely.

Prototyping main() is, as far as I can tell, harmless, so this
continues to be allowed.

Change-Id: I69916840c06810cd948bd74ff168ada1c4fc74f8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/557578
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Arman Uguray <armansito@google.com>
Commit-Queue: Arman Uguray <armansito@google.com>
This commit is contained in:
John Stiles 2022-07-11 13:29:15 -04:00 committed by SkCQ
parent a4aa32d24f
commit 5186379e5e
7 changed files with 24 additions and 0 deletions

View File

@ -59,6 +59,7 @@ sksl_error_tests = [
"/sksl/errors/BitShiftFloatVector.rts",
"/sksl/errors/BooleanArithmetic.sksl",
"/sksl/errors/BreakOutsideLoop.rts",
"/sksl/errors/CallMain.rts",
"/sksl/errors/CallNonFunction.rts",
"/sksl/errors/CanExitWithoutReturningValue.sksl",
"/sksl/errors/CommasAsConstantExpressions.rts",

View File

@ -0,0 +1,9 @@
half4 main(float2 coords);
void func(float2 coords) {
main(coords);
}
/*%%*
call to 'main' is not allowed
*%%*/

View File

@ -4,6 +4,7 @@ float this_function_is_prototyped_at_the_start_and_never_defined();
half4 this_function_is_defined_before_use(half4 x);
half4 this_function_is_defined_after_use(half4 x);
half4 this_function_is_defined_near_the_end(half4 x);
half4 main(float2 coords); // prototyping main is allowed (although not particularly useful)
half4 this_function_is_defined_before_use(half4 x) {
return -this_function_is_defined_near_the_end(x);

View File

@ -1007,6 +1007,11 @@ std::unique_ptr<Expression> FunctionCall::Convert(const Context& context,
}
}
if (function.isMain()) {
context.fErrors->error(pos, "call to 'main' is not allowed");
return nullptr;
}
if (function.intrinsicKind() == k_eval_IntrinsicKind) {
// This is a method call on an effect child. Translate it into a ChildCall, which simplifies
// handling in the generators and analysis code.

View File

@ -0,0 +1,6 @@
### Compilation failed:
error: 4: call to 'main' is not allowed
main(coords);
^^^^^^^^^^^^
1 error

View File

@ -5,6 +5,7 @@ float this_function_is_prototyped_at_the_start_and_never_defined_f();
vec4 this_function_is_defined_before_use_h4h4(vec4 x);
vec4 this_function_is_defined_after_use_h4h4(vec4 x);
vec4 this_function_is_defined_near_the_end_h4h4(vec4 x);
vec4 main();
bool this_function_is_prototyped_in_the_middle_and_never_defined_bf44(mat4 a);
ivec3 this_function_is_prototyped_at_the_very_end_and_never_defined_i3h22b2(mat2 x, bvec2 y);
vec4 this_function_is_defined_before_use_h4h4(vec4 x) {

View File

@ -13,6 +13,7 @@ float this_function_is_prototyped_at_the_start_and_never_defined_f();
half4 this_function_is_defined_before_use_h4h4(half4 x);
half4 this_function_is_defined_after_use_h4h4(half4 x);
half4 this_function_is_defined_near_the_end_h4h4(half4 x);
fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]);
half4 this_function_is_defined_before_use_h4h4(half4 x) {
return -x;
}