Browse Source

glsl: use new _slang_loop_contains_continue() helper function

tags/mesa_7_5_rc4
Brian Paul 17 years ago
parent
commit
4dafac2b2f
1 changed files with 126 additions and 5 deletions
  1. 126
    5
      src/mesa/shader/slang/slang_codegen.c

+ 126
- 5
src/mesa/shader/slang/slang_codegen.c View File

@@ -2347,11 +2347,123 @@ _slang_is_boolean(slang_assemble_ctx *A, slang_operation *oper)
}


/**
* Check if a loop contains a 'continue' statement.
* Stop looking if we find a nested loop.
*/
static GLboolean
_slang_loop_contains_continue(const slang_operation *oper)
{
switch (oper->type) {
case SLANG_OPER_CONTINUE:
return GL_TRUE;
case SLANG_OPER_FOR:
case SLANG_OPER_DO:
case SLANG_OPER_WHILE:
/* stop upon finding a nested loop */
return GL_FALSE;
default:
/* recurse */
{
GLuint i;
for (i = 0; i < oper->num_children; i++) {
if (_slang_loop_contains_continue(slang_oper_child((slang_operation *) oper, i)))
return GL_TRUE;
}
}
return GL_FALSE;
}
}


static slang_ir_node *
_slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
{
#if 0
slang_operation *top;
slang_operation *innerBody;

assert(oper->type == SLANG_OPER_DO);

top = slang_operation_new(1);
top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
top->locals->outer_scope = oper->locals->outer_scope;
slang_operation_add_children(top, 2);

/* declare: bool _notBreakFlag = true */
{
slang_operation *condDecl = slang_oper_child(top, 0);
slang_variable *var;

condDecl->type = SLANG_OPER_VARIABLE_DECL;
var = slang_variable_scope_grow(top->locals);
slang_fully_specified_type_construct(&var->type);
var->type.specifier.type = SLANG_SPEC_BOOL;
var->a_name = slang_atom_pool_atom(A->atoms, "_notBreakFlag");
condDecl->a_id = var->a_name;
var->initializer = slang_operation_new(1);
slang_operation_literal_bool(var->initializer, GL_TRUE);
}

/* build outer do-loop: do { ... } while (_notBreakFlag && LOOPCOND) */
{
slang_operation *outerDo = slang_oper_child(top, 1);
outerDo->type = SLANG_OPER_DO;
slang_operation_add_children(outerDo, 2);

/* inner do-loop */
{
slang_operation *innerDo = slang_oper_child(outerDo, 0);
innerDo->type = SLANG_OPER_DO;
slang_operation_add_children(innerDo, 2);

/* copy original do-loop body into inner do-loop's body */
innerBody = slang_oper_child(innerDo, 0);
slang_operation_copy(innerBody, slang_oper_child(oper, 0));
innerBody->locals->outer_scope = innerDo->locals;

/* inner do-loop's condition is constant/false */
{
slang_operation *constFalse = slang_oper_child(innerDo, 1);
slang_operation_literal_bool(constFalse, GL_FALSE);
}
}

/* _notBreakFlag && LOOPCOND */
{
slang_operation *cond = slang_oper_child(outerDo, 1);
cond->type = SLANG_OPER_LOGICALAND;
slang_operation_add_children(cond, 2);
{
slang_operation *notBreak = slang_oper_child(cond, 0);
slang_operation_identifier(notBreak, A, "_notBreakFlag");
}
{
slang_operation *origCond = slang_oper_child(cond, 1);
slang_operation_copy(origCond, slang_oper_child(oper, 1));
}
}
}

/* Finally, in innerBody,
* replace "break" with "_notBreakFlag = 0; break"
* replace "continue" with "break"
*/
replace_break_and_cont(A, innerBody);

slang_print_tree(top, 0);

return _slang_gen_operation(A, top);
#endif
return NULL;
}


/**
* Generate loop code using high-level IR_LOOP instruction
*/
static slang_ir_node *
_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
_slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
{
/*
* LOOP:
@@ -2361,6 +2473,15 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
slang_ir_node *prevLoop, *loop, *breakIf, *body;
GLboolean isConst, constTrue;

if (!A->EmitContReturn) {
/* We don't want to emit CONT instructions. If this while-loop has
* a continue, translate it away.
*/
if (_slang_loop_contains_continue(slang_oper_child(oper, 1))) {
return _slang_gen_while_without_continue(A, oper);
}
}

/* type-check expression */
if (!_slang_is_boolean(A, &oper->children[0])) {
slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'");
@@ -2581,7 +2702,7 @@ _slang_gen_do_without_continue(slang_assemble_ctx *A, slang_operation *oper)
* Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
*/
static slang_ir_node *
_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
_slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
{
/*
* LOOP:
@@ -2596,8 +2717,8 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
/* We don't want to emit CONT instructions. If this do-loop has
* a continue, translate it away.
*/
if (_slang_find_node_type((slang_operation *) oper, SLANG_OPER_CONTINUE)) {
return _slang_gen_do_without_continue(A, (slang_operation *) oper);
if (_slang_loop_contains_continue(slang_oper_child(oper, 0))) {
return _slang_gen_do_without_continue(A, oper);
}
}

@@ -3029,7 +3150,7 @@ _slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
/* We don't want to emit CONT instructions. If this for-loop has
* a continue, translate it away.
*/
if (_slang_find_node_type(oper, SLANG_OPER_CONTINUE)) {
if (_slang_loop_contains_continue(slang_oper_child(oper, 3))) {
return _slang_gen_for_without_continue(A, oper);
}
}

Loading…
Cancel
Save