Emit prototypes in Pipeline for every defined function.
In complex programs with multiple functions, the Inliner can cause code to be reordered in ways that cause a function call to be raised above its declaration. The Pipeline stage code generator will now emit a prototype for every function defined in the program, before emitting any function bodies at all. With this change, ES2 conformance test `copy_global_inout_on_call` now passes. Change-Id: I85485710a34b778adef3cbc4a7ebe110a21a2a03 Bug: skia:12488 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/454742 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Osman <brianosman@google.com> Commit-Queue: John Stiles <johnstiles@google.com> Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
2f5cfb6af0
commit
6868f78d40
@ -69,7 +69,7 @@ private:
|
||||
|
||||
String functionName(const FunctionDeclaration& decl);
|
||||
void writeFunction(const FunctionDefinition& f);
|
||||
void writeFunctionPrototype(const FunctionPrototype& f);
|
||||
void writeFunctionDeclaration(const FunctionDeclaration& decl);
|
||||
|
||||
String modifierString(const Modifiers& modifiers);
|
||||
String functionDeclaration(const FunctionDeclaration& decl);
|
||||
@ -102,7 +102,8 @@ private:
|
||||
void writeReturnStatement(const ReturnStatement& r);
|
||||
void writeSwitchStatement(const SwitchStatement& s);
|
||||
|
||||
void writeProgramElement(const ProgramElement& e);
|
||||
void writeProgramElementFirstPass(const ProgramElement& e);
|
||||
void writeProgramElementSecondPass(const ProgramElement& e);
|
||||
|
||||
struct AutoOutputBuffer {
|
||||
AutoOutputBuffer(PipelineStageCodeGenerator* generator) : fGenerator(generator) {
|
||||
@ -364,9 +365,10 @@ String PipelineStageCodeGenerator::functionDeclaration(const FunctionDeclaration
|
||||
return declString + ")";
|
||||
}
|
||||
|
||||
void PipelineStageCodeGenerator::writeFunctionPrototype(const FunctionPrototype& f) {
|
||||
const FunctionDeclaration& decl = f.declaration();
|
||||
fCallbacks->declareFunction(this->functionDeclaration(decl).c_str());
|
||||
void PipelineStageCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& decl) {
|
||||
if (!decl.isMain()) {
|
||||
fCallbacks->declareFunction(this->functionDeclaration(decl).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void PipelineStageCodeGenerator::writeGlobalVarDeclaration(const GlobalVarDeclaration& g) {
|
||||
@ -407,16 +409,17 @@ void PipelineStageCodeGenerator::writeStructDefinition(const StructDefinition& s
|
||||
fCallbacks->defineStruct(definition.c_str());
|
||||
}
|
||||
|
||||
void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& e) {
|
||||
void PipelineStageCodeGenerator::writeProgramElementFirstPass(const ProgramElement& e) {
|
||||
switch (e.kind()) {
|
||||
case ProgramElement::Kind::kGlobalVar:
|
||||
this->writeGlobalVarDeclaration(e.as<GlobalVarDeclaration>());
|
||||
break;
|
||||
case ProgramElement::Kind::kFunction:
|
||||
this->writeFunction(e.as<FunctionDefinition>());
|
||||
this->writeFunctionDeclaration(e.as<FunctionDefinition>().declaration());
|
||||
break;
|
||||
case ProgramElement::Kind::kFunctionPrototype:
|
||||
this->writeFunctionPrototype(e.as<FunctionPrototype>());
|
||||
// Skip this; we're already emitting prototypes for every FunctionDefinition.
|
||||
// (See case kFunction, directly above.)
|
||||
break;
|
||||
case ProgramElement::Kind::kStructDefinition:
|
||||
this->writeStructDefinition(e.as<StructDefinition>());
|
||||
@ -431,6 +434,12 @@ void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& e) {
|
||||
}
|
||||
}
|
||||
|
||||
void PipelineStageCodeGenerator::writeProgramElementSecondPass(const ProgramElement& e) {
|
||||
if (e.is<FunctionDefinition>()) {
|
||||
this->writeFunction(e.as<FunctionDefinition>());
|
||||
}
|
||||
}
|
||||
|
||||
String PipelineStageCodeGenerator::typeName(const Type& type) {
|
||||
if (type.isArray()) {
|
||||
// This is necessary so that name mangling on arrays-of-structs works properly.
|
||||
@ -738,20 +747,16 @@ void PipelineStageCodeGenerator::writeForStatement(const ForStatement& f) {
|
||||
}
|
||||
|
||||
void PipelineStageCodeGenerator::generateCode() {
|
||||
// Write all the program elements except for functions.
|
||||
// Write all the program elements except for functions; prototype all the functions.
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (!e->is<FunctionDefinition>()) {
|
||||
this->writeProgramElement(*e);
|
||||
}
|
||||
this->writeProgramElementFirstPass(*e);
|
||||
}
|
||||
|
||||
// We always place FunctionDefinition elements last, because the inliner likes to move function
|
||||
// bodies around. After inlining, code can inadvertently move upwards, above ProgramElements
|
||||
// that the code relies on.
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<FunctionDefinition>()) {
|
||||
this->writeProgramElement(*e);
|
||||
}
|
||||
this->writeProgramElementSecondPass(*e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
const half r_0 = 0.0;
|
||||
noinline half opt_barrier_0(const half x);
|
||||
half2 compute_ba_0(const half2 rg);
|
||||
noinline half opt_barrier_0(const half x)
|
||||
{
|
||||
return x;
|
||||
|
@ -1,5 +1,6 @@
|
||||
float gInitializedFromOther_0 = 1.0;
|
||||
float gUninitialized_0;
|
||||
void init_globals_0();
|
||||
void init_globals_0()
|
||||
{
|
||||
gUninitialized_0 = 1.0;
|
||||
|
@ -1,3 +1,7 @@
|
||||
void d_0(inout int i);
|
||||
void c_0(inout int i);
|
||||
void b_0(inout int i);
|
||||
void a_0(inout int i);
|
||||
void d_0(inout int i)
|
||||
{
|
||||
++i;
|
||||
|
@ -1,3 +1,7 @@
|
||||
void d_0(inout int i);
|
||||
void c_0(inout int i);
|
||||
void b_0(inout int i);
|
||||
void a_0(inout int i);
|
||||
void d_0(inout int i)
|
||||
{
|
||||
for (int x = 0;x < 10; ++x) ++i;
|
||||
|
@ -1,5 +1,11 @@
|
||||
half4 color_0;
|
||||
void f1_0();
|
||||
void f8_0();
|
||||
void f7_0();
|
||||
void f6_0();
|
||||
void f5_0();
|
||||
void f4_0();
|
||||
void f3_0();
|
||||
void f2_0();
|
||||
half4 main(float2 xy)
|
||||
{
|
||||
f2_0();
|
||||
|
@ -1,7 +1,17 @@
|
||||
uniform half4 colorRed;
|
||||
uniform half4 colorGreen;
|
||||
const float kZero_0 = 0.0;
|
||||
float return_loop_0();
|
||||
const float kTen_0 = 10.0;
|
||||
float continue_loop_0();
|
||||
float break_loop_0();
|
||||
float float_loop_0();
|
||||
bool loop_operator_le_0();
|
||||
bool loop_operator_lt_0();
|
||||
bool loop_operator_ge_0();
|
||||
bool loop_operator_gt_0();
|
||||
bool loop_operator_ne_0();
|
||||
bool loop_operator_eq_0();
|
||||
float return_loop_0()
|
||||
{
|
||||
for (float i = kZero_0;i < 10.0; ++i)
|
||||
|
@ -1,7 +1,16 @@
|
||||
uniform half4 colorRed;
|
||||
uniform half4 colorGreen;
|
||||
const int kZero_0 = 0;
|
||||
int return_loop_0();
|
||||
const int kTen_0 = 10;
|
||||
int continue_loop_0();
|
||||
int break_loop_0();
|
||||
bool loop_operator_le_0();
|
||||
bool loop_operator_lt_0();
|
||||
bool loop_operator_ge_0();
|
||||
bool loop_operator_gt_0();
|
||||
bool loop_operator_ne_0();
|
||||
bool loop_operator_eq_0();
|
||||
int return_loop_0()
|
||||
{
|
||||
for (int i = kZero_0;i < 10; ++i)
|
||||
|
@ -1,5 +1,8 @@
|
||||
uniform half4 colorGreen;
|
||||
uniform half4 colorRed;
|
||||
bool test_vector_0();
|
||||
bool test_matrix_0();
|
||||
bool test_array_0();
|
||||
bool test_vector_0()
|
||||
{
|
||||
half2 mp2 = half2(2.0);
|
||||
|
@ -1,5 +1,6 @@
|
||||
uniform half4 colorGreen;
|
||||
uniform half4 colorRed;
|
||||
bool switch_fallthrough_twice_0(int value);
|
||||
bool switch_fallthrough_twice_0(int value)
|
||||
{
|
||||
bool ok = false;
|
||||
|
@ -1,5 +1,7 @@
|
||||
uniform half4 colorGreen;
|
||||
uniform half4 colorRed;
|
||||
bool switch_with_continue_in_loop_0(int x);
|
||||
bool loop_with_break_in_switch_0(int x);
|
||||
bool switch_with_continue_in_loop_0(int x)
|
||||
{
|
||||
int val = 0;
|
||||
|
@ -2,6 +2,7 @@ uniform float4 u1;
|
||||
uniform float4 u2;
|
||||
uniform float4 u3;
|
||||
uniform float4 u4;
|
||||
float index_clamped_out_of_bounds_0();
|
||||
float index_clamped_out_of_bounds_0()
|
||||
{
|
||||
for (int i = 7;i < 8; i++)
|
||||
|
Loading…
Reference in New Issue
Block a user