glsl: rework loop nesting code
This commit is contained in:
@@ -440,6 +440,56 @@ _slang_output_index(const char *name, GLenum target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when we begin code/IR generation for a new while/do/for loop.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
push_loop(slang_assemble_ctx *A, slang_operation *loopOper, slang_ir_node *loopIR)
|
||||||
|
{
|
||||||
|
A->LoopOperStack[A->LoopDepth] = loopOper;
|
||||||
|
A->LoopIRStack[A->LoopDepth] = loopIR;
|
||||||
|
A->LoopDepth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when we end code/IR generation for a new while/do/for loop.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pop_loop(slang_assemble_ctx *A)
|
||||||
|
{
|
||||||
|
assert(A->LoopDepth > 0);
|
||||||
|
A->LoopDepth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return pointer to slang_operation for the loop we're currently inside,
|
||||||
|
* or NULL if not in a loop.
|
||||||
|
*/
|
||||||
|
static const slang_operation *
|
||||||
|
current_loop_oper(const slang_assemble_ctx *A)
|
||||||
|
{
|
||||||
|
if (A->LoopDepth > 0)
|
||||||
|
return A->LoopOperStack[A->LoopDepth - 1];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return pointer to slang_ir_node for the loop we're currently inside,
|
||||||
|
* or NULL if not in a loop.
|
||||||
|
*/
|
||||||
|
static slang_ir_node *
|
||||||
|
current_loop_ir(const slang_assemble_ctx *A)
|
||||||
|
{
|
||||||
|
if (A->LoopDepth > 0)
|
||||||
|
return A->LoopIRStack[A->LoopDepth - 1];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
@@ -661,7 +711,7 @@ new_break(slang_ir_node *loopNode)
|
|||||||
static slang_ir_node *
|
static slang_ir_node *
|
||||||
new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
|
new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
|
||||||
{
|
{
|
||||||
slang_ir_node *loopNode = A->CurLoop;
|
slang_ir_node *loopNode = current_loop_ir(A);
|
||||||
slang_ir_node *n;
|
slang_ir_node *n;
|
||||||
assert(loopNode);
|
assert(loopNode);
|
||||||
assert(loopNode->Opcode == IR_LOOP);
|
assert(loopNode->Opcode == IR_LOOP);
|
||||||
@@ -681,7 +731,7 @@ new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
|
|||||||
static slang_ir_node *
|
static slang_ir_node *
|
||||||
new_cont_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
|
new_cont_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
|
||||||
{
|
{
|
||||||
slang_ir_node *loopNode = A->CurLoop;
|
slang_ir_node *loopNode = current_loop_ir(A);
|
||||||
slang_ir_node *n;
|
slang_ir_node *n;
|
||||||
assert(loopNode);
|
assert(loopNode);
|
||||||
assert(loopNode->Opcode == IR_LOOP);
|
assert(loopNode->Opcode == IR_LOOP);
|
||||||
@@ -2712,8 +2762,7 @@ _slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
* BREAK if !expr (child[0])
|
* BREAK if !expr (child[0])
|
||||||
* body code (child[1])
|
* body code (child[1])
|
||||||
*/
|
*/
|
||||||
const slang_operation *prevLoopOper;
|
slang_ir_node *loop, *breakIf, *body;
|
||||||
slang_ir_node *prevLoop, *loop, *breakIf, *body;
|
|
||||||
GLboolean isConst, constTrue;
|
GLboolean isConst, constTrue;
|
||||||
|
|
||||||
if (!A->EmitContReturn) {
|
if (!A->EmitContReturn) {
|
||||||
@@ -2739,13 +2788,11 @@ _slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
return new_node0(IR_NOP);
|
return new_node0(IR_NOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Begin new loop */
|
||||||
loop = new_loop(NULL);
|
loop = new_loop(NULL);
|
||||||
|
|
||||||
/* save old, push new loop */
|
/* save loop state */
|
||||||
prevLoop = A->CurLoop;
|
push_loop(A, oper, loop);
|
||||||
A->CurLoop = loop;
|
|
||||||
prevLoopOper = A->CurLoopOper;
|
|
||||||
A->CurLoopOper = oper;
|
|
||||||
|
|
||||||
if (isConst && constTrue) {
|
if (isConst && constTrue) {
|
||||||
/* while(nonzero constant), no conditional break */
|
/* while(nonzero constant), no conditional break */
|
||||||
@@ -2763,14 +2810,13 @@ _slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
/* loop->List is head of linked list of break/continue nodes */
|
/* loop->List is head of linked list of break/continue nodes */
|
||||||
if (!loop->List && isConst && constTrue) {
|
if (!loop->List && isConst && constTrue) {
|
||||||
/* infinite loop detected */
|
/* infinite loop detected */
|
||||||
A->CurLoop = prevLoop; /* clean-up */
|
pop_loop(A);
|
||||||
slang_info_log_error(A->log, "Infinite loop detected!");
|
slang_info_log_error(A->log, "Infinite loop detected!");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pop loop, restore prev */
|
/* restore loop state */
|
||||||
A->CurLoop = prevLoop;
|
pop_loop(A);
|
||||||
A->CurLoopOper = prevLoopOper;
|
|
||||||
|
|
||||||
return loop;
|
return loop;
|
||||||
}
|
}
|
||||||
@@ -2893,8 +2939,7 @@ _slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
* tail code:
|
* tail code:
|
||||||
* BREAK if !expr (child[1])
|
* BREAK if !expr (child[1])
|
||||||
*/
|
*/
|
||||||
const slang_operation *prevLoopOper;
|
slang_ir_node *loop;
|
||||||
slang_ir_node *prevLoop, *loop;
|
|
||||||
GLboolean isConst, constTrue;
|
GLboolean isConst, constTrue;
|
||||||
|
|
||||||
if (!A->EmitContReturn) {
|
if (!A->EmitContReturn) {
|
||||||
@@ -2914,11 +2959,8 @@ _slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
|
|
||||||
loop = new_loop(NULL);
|
loop = new_loop(NULL);
|
||||||
|
|
||||||
/* save old, push new loop */
|
/* save loop state */
|
||||||
prevLoop = A->CurLoop;
|
push_loop(A, oper, loop);
|
||||||
A->CurLoop = loop;
|
|
||||||
prevLoopOper = A->CurLoopOper;
|
|
||||||
A->CurLoopOper = oper;
|
|
||||||
|
|
||||||
/* loop body: */
|
/* loop body: */
|
||||||
loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
|
loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
|
||||||
@@ -2937,9 +2979,8 @@ _slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
|
|
||||||
/* XXX we should do infinite loop detection, as above */
|
/* XXX we should do infinite loop detection, as above */
|
||||||
|
|
||||||
/* pop loop, restore prev */
|
/* restore loop state */
|
||||||
A->CurLoop = prevLoop;
|
pop_loop(A);
|
||||||
A->CurLoopOper = prevLoopOper;
|
|
||||||
|
|
||||||
return loop;
|
return loop;
|
||||||
}
|
}
|
||||||
@@ -3349,16 +3390,12 @@ _slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
* tail code:
|
* tail code:
|
||||||
* incr code (child[2]) // XXX continue here
|
* incr code (child[2]) // XXX continue here
|
||||||
*/
|
*/
|
||||||
const slang_operation *prevLoopOper;
|
slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr;
|
||||||
slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr;
|
|
||||||
init = _slang_gen_operation(A, &oper->children[0]);
|
init = _slang_gen_operation(A, &oper->children[0]);
|
||||||
loop = new_loop(NULL);
|
loop = new_loop(NULL);
|
||||||
|
|
||||||
/* save old, push new loop */
|
/* save loop state */
|
||||||
prevLoop = A->CurLoop;
|
push_loop(A, oper, loop);
|
||||||
A->CurLoop = loop;
|
|
||||||
prevLoopOper = A->CurLoopOper;
|
|
||||||
A->CurLoopOper = oper;
|
|
||||||
|
|
||||||
cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
|
cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
|
||||||
breakIf = new_break_if_true(A, cond);
|
breakIf = new_break_if_true(A, cond);
|
||||||
@@ -3368,9 +3405,8 @@ _slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
loop->Children[0] = new_seq(breakIf, body);
|
loop->Children[0] = new_seq(breakIf, body);
|
||||||
loop->Children[1] = incr; /* tail code */
|
loop->Children[1] = incr; /* tail code */
|
||||||
|
|
||||||
/* pop loop, restore prev */
|
/* restore loop state */
|
||||||
A->CurLoop = prevLoop;
|
pop_loop(A);
|
||||||
A->CurLoopOper = prevLoopOper;
|
|
||||||
|
|
||||||
return new_seq(init, loop);
|
return new_seq(init, loop);
|
||||||
}
|
}
|
||||||
@@ -3383,7 +3419,7 @@ _slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
|
|||||||
slang_ir_node *n, *cont, *incr = NULL, *loopNode;
|
slang_ir_node *n, *cont, *incr = NULL, *loopNode;
|
||||||
|
|
||||||
assert(oper->type == SLANG_OPER_CONTINUE);
|
assert(oper->type == SLANG_OPER_CONTINUE);
|
||||||
loopNode = A->CurLoop;
|
loopNode = current_loop_ir(A);
|
||||||
assert(loopNode);
|
assert(loopNode);
|
||||||
assert(loopNode->Opcode == IR_LOOP);
|
assert(loopNode->Opcode == IR_LOOP);
|
||||||
|
|
||||||
@@ -3470,8 +3506,8 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
|
|||||||
}
|
}
|
||||||
else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
|
else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
|
||||||
&& !haveElseClause
|
&& !haveElseClause
|
||||||
&& A->CurLoopOper
|
&& current_loop_oper(A)
|
||||||
&& A->CurLoopOper->type != SLANG_OPER_FOR) {
|
&& current_loop_oper(A)->type != SLANG_OPER_FOR) {
|
||||||
/* Special case: generate a conditional continue */
|
/* Special case: generate a conditional continue */
|
||||||
ifBody = new_cont_if_true(A, cond);
|
ifBody = new_cont_if_true(A, cond);
|
||||||
return ifBody;
|
return ifBody;
|
||||||
@@ -4714,13 +4750,13 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
|
|||||||
case SLANG_OPER_WHILE:
|
case SLANG_OPER_WHILE:
|
||||||
return _slang_gen_while(A, oper);
|
return _slang_gen_while(A, oper);
|
||||||
case SLANG_OPER_BREAK:
|
case SLANG_OPER_BREAK:
|
||||||
if (!A->CurLoop) {
|
if (!current_loop_oper(A)) {
|
||||||
slang_info_log_error(A->log, "'break' not in loop");
|
slang_info_log_error(A->log, "'break' not in loop");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return new_break(A->CurLoop);
|
return new_break(current_loop_ir(A));
|
||||||
case SLANG_OPER_CONTINUE:
|
case SLANG_OPER_CONTINUE:
|
||||||
if (!A->CurLoop) {
|
if (!current_loop_oper(A)) {
|
||||||
slang_info_log_error(A->log, "'continue' not in loop");
|
slang_info_log_error(A->log, "'continue' not in loop");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -5265,8 +5301,12 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
|
|||||||
assert(A->program->Parameters );
|
assert(A->program->Parameters );
|
||||||
assert(A->program->Varying);
|
assert(A->program->Varying);
|
||||||
assert(A->vartable);
|
assert(A->vartable);
|
||||||
|
#if 0
|
||||||
A->CurLoop = NULL;
|
A->CurLoop = NULL;
|
||||||
A->CurLoopOper = NULL;
|
A->CurLoopOper = NULL;
|
||||||
|
#else
|
||||||
|
A->LoopDepth = 0;
|
||||||
|
#endif
|
||||||
A->CurFunction = fun;
|
A->CurFunction = fun;
|
||||||
|
|
||||||
/* fold constant expressions, etc. */
|
/* fold constant expressions, etc. */
|
||||||
|
@@ -31,6 +31,9 @@
|
|||||||
#include "slang_compile.h"
|
#include "slang_compile.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_LOOP_DEPTH 30
|
||||||
|
|
||||||
|
|
||||||
typedef struct slang_assemble_ctx_
|
typedef struct slang_assemble_ctx_
|
||||||
{
|
{
|
||||||
slang_atom_pool *atoms;
|
slang_atom_pool *atoms;
|
||||||
@@ -40,8 +43,11 @@ typedef struct slang_assemble_ctx_
|
|||||||
slang_var_table *vartable;
|
slang_var_table *vartable;
|
||||||
slang_info_log *log;
|
slang_info_log *log;
|
||||||
struct slang_label_ *curFuncEndLabel;
|
struct slang_label_ *curFuncEndLabel;
|
||||||
const slang_operation *CurLoopOper;
|
|
||||||
struct slang_ir_node_ *CurLoop;
|
const slang_operation *LoopOperStack[MAX_LOOP_DEPTH];
|
||||||
|
struct slang_ir_node_ *LoopIRStack[MAX_LOOP_DEPTH];
|
||||||
|
GLuint LoopDepth;
|
||||||
|
|
||||||
struct slang_function_ *CurFunction;
|
struct slang_function_ *CurFunction;
|
||||||
GLboolean UnresolvedRefs;
|
GLboolean UnresolvedRefs;
|
||||||
GLboolean EmitContReturn;
|
GLboolean EmitContReturn;
|
||||||
|
Reference in New Issue
Block a user