mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 16:08:04 +02:00
Get rid of SLANG_OPER_GOTO, start rewrite of 'return' handling.
This commit is contained in:
parent
813a0e11f1
commit
c042a91b8b
4 changed files with 65 additions and 56 deletions
|
|
@ -472,9 +472,9 @@ new_float_literal(const float v[4], GLuint size)
|
|||
* Unconditional jump.
|
||||
*/
|
||||
static slang_ir_node *
|
||||
new_jump(slang_label *dest)
|
||||
new_return(slang_label *dest)
|
||||
{
|
||||
slang_ir_node *n = new_node0(IR_JUMP);
|
||||
slang_ir_node *n = new_node0(IR_RETURN);
|
||||
assert(dest);
|
||||
if (n)
|
||||
n->Label = dest;
|
||||
|
|
@ -606,6 +606,24 @@ _slang_is_noop(const slang_operation *oper)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively search tree for a node of the given type.
|
||||
*/
|
||||
static slang_operation *
|
||||
_slang_find_node_type(slang_operation *oper, slang_operation_type type)
|
||||
{
|
||||
GLuint i;
|
||||
if (oper->type == type)
|
||||
return oper;
|
||||
for (i = 0; i < oper->num_children; i++) {
|
||||
slang_operation *p = _slang_find_node_type(&oper->children[i], type);
|
||||
if (p)
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Produce inline code for a call to an assembly instruction.
|
||||
* XXX Note: children are passed as asm args in-order, not by name!
|
||||
|
|
@ -749,7 +767,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
|
|||
slang_operation_copy(&assignOper->children[1],
|
||||
&oper->children[0]);
|
||||
|
||||
returnOper->type = SLANG_OPER_RETURN;
|
||||
returnOper->type = SLANG_OPER_RETURN; /* return w/ no value */
|
||||
assert(returnOper->num_children == 0);
|
||||
|
||||
/* do substitutions on the "__retVal = expr" sub-tree */
|
||||
|
|
@ -1744,22 +1762,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
|
|||
}
|
||||
|
||||
if (!haveReturnValue) {
|
||||
/* Convert from:
|
||||
* return;
|
||||
* To:
|
||||
* goto __endOfFunction;
|
||||
*/
|
||||
slang_ir_node *n;
|
||||
slang_operation gotoOp;
|
||||
slang_operation_construct(&gotoOp);
|
||||
gotoOp.type = SLANG_OPER_GOTO;
|
||||
gotoOp.label = A->curFuncEndLabel;
|
||||
assert(gotoOp.label);
|
||||
|
||||
n = _slang_gen_operation(A, &gotoOp);
|
||||
/* destroy temp code */
|
||||
slang_operation_destruct(&gotoOp);
|
||||
return n;
|
||||
return new_return(A->curFuncEndLabel);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
|
|
@ -1767,9 +1770,9 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
|
|||
* return expr;
|
||||
* To:
|
||||
* __retVal = expr;
|
||||
* goto __endOfFunction;
|
||||
* return; // goto __endOfFunction
|
||||
*/
|
||||
slang_operation *block, *assign, *jump;
|
||||
slang_operation *assign;
|
||||
slang_atom a_retVal;
|
||||
slang_ir_node *n;
|
||||
|
||||
|
|
@ -1787,17 +1790,8 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
|
|||
}
|
||||
#endif
|
||||
|
||||
block = slang_operation_new(1);
|
||||
block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
|
||||
assert(block->locals);
|
||||
block->locals->outer_scope = oper->locals->outer_scope;
|
||||
block->num_children = 2;
|
||||
block->children = slang_operation_new(2);
|
||||
|
||||
/* child[0]: __retVal = expr; */
|
||||
assign = &block->children[0];
|
||||
assign = slang_operation_new(1);
|
||||
assign->type = SLANG_OPER_ASSIGN;
|
||||
assign->locals->outer_scope = block->locals;
|
||||
assign->num_children = 2;
|
||||
assign->children = slang_operation_new(2);
|
||||
/* lhs (__retVal) */
|
||||
|
|
@ -1808,22 +1802,11 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
|
|||
/* XXX we might be able to avoid this copy someday */
|
||||
slang_operation_copy(&assign->children[1], &oper->children[0]);
|
||||
|
||||
/* child[1]: goto __endOfFunction */
|
||||
jump = &block->children[1];
|
||||
jump->type = SLANG_OPER_GOTO;
|
||||
assert(A->curFuncEndLabel);
|
||||
/* XXX don't call function? */
|
||||
jump->label = A->curFuncEndLabel;
|
||||
assert(jump->label);
|
||||
|
||||
#if 0 /* debug */
|
||||
printf("NEW RETURN:\n");
|
||||
slang_print_tree(block, 0);
|
||||
#endif
|
||||
|
||||
/* assemble the new code */
|
||||
n = _slang_gen_operation(A, block);
|
||||
slang_operation_delete(block);
|
||||
n = new_seq(_slang_gen_operation(A, assign),
|
||||
new_return(A->curFuncEndLabel));
|
||||
|
||||
slang_operation_delete(assign);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
|
@ -2552,8 +2535,6 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
|
|||
oper, NULL);
|
||||
case SLANG_OPER_RETURN:
|
||||
return _slang_gen_return(A, oper);
|
||||
case SLANG_OPER_GOTO:
|
||||
return new_jump(oper->label);
|
||||
case SLANG_OPER_LABEL:
|
||||
return new_label(oper->label);
|
||||
case SLANG_OPER_IDENTIFIER:
|
||||
|
|
@ -2817,6 +2798,23 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
|
|||
/* we only really generate code for main, all other functions get
|
||||
* inlined.
|
||||
*/
|
||||
#if 0
|
||||
/* do some basic error checking though */
|
||||
if (fun->header.type.specifier.type != SLANG_SPEC_VOID) {
|
||||
/* check that non-void functions actually return something */
|
||||
slang_operation *op
|
||||
= _slang_find_node_type(fun->body, SLANG_OPER_RETURN);
|
||||
if (!op) {
|
||||
slang_info_log_error(A->log,
|
||||
"function \"%s\" has no return statement",
|
||||
(char *) fun->header.a_name);
|
||||
printf(
|
||||
"function \"%s\" has no return statement\n",
|
||||
(char *) fun->header.a_name);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return GL_TRUE; /* not an error */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ typedef enum slang_operation_type_
|
|||
SLANG_OPER_CONTINUE, /* "continue" statement */
|
||||
SLANG_OPER_DISCARD, /* "discard" (kill fragment) statement */
|
||||
SLANG_OPER_RETURN, /* "return" [expr] */
|
||||
SLANG_OPER_GOTO, /* jump to label */
|
||||
SLANG_OPER_LABEL, /* a jump target */
|
||||
SLANG_OPER_EXPRESSION, /* [expr] */
|
||||
SLANG_OPER_IF, /* "if" [0] then [1] else [2] */
|
||||
|
|
@ -118,7 +117,7 @@ typedef struct slang_operation_
|
|||
slang_variable_scope *locals; /**< local vars for scope */
|
||||
struct slang_function_ *fun; /**< If type == SLANG_OPER_CALL */
|
||||
struct slang_variable_ *var; /**< If type == slang_oper_identier */
|
||||
struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL or GOTO */
|
||||
struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL */
|
||||
} slang_operation;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -726,6 +726,23 @@ emit_jump(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
}
|
||||
|
||||
|
||||
static struct prog_instruction *
|
||||
emit_return(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||
{
|
||||
struct prog_instruction *inst;
|
||||
assert(n);
|
||||
assert(n->Opcode == IR_RETURN);
|
||||
assert(n->Label);
|
||||
inst = new_instruction(emitInfo, OPCODE_BRA /*RET*/); /*XXX TEMPORARY*/
|
||||
inst->DstReg.CondMask = COND_TR; /* always branch */
|
||||
inst->BranchTarget = _slang_label_get_location(n->Label);
|
||||
if (inst->BranchTarget < 0) {
|
||||
_slang_label_add_reference(n->Label, emitInfo->prog->NumInstructions - 1);
|
||||
}
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
static struct prog_instruction *
|
||||
emit_kill(slang_emit_info *emitInfo)
|
||||
{
|
||||
|
|
@ -1528,7 +1545,7 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
|
|||
case IR_END_SUB:
|
||||
return new_instruction(emitInfo, OPCODE_ENDSUB);
|
||||
case IR_RETURN:
|
||||
return new_instruction(emitInfo, OPCODE_RET);
|
||||
return emit_return(emitInfo, n);
|
||||
|
||||
case IR_NOP:
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -308,11 +308,6 @@ slang_print_tree(const slang_operation *op, int indent)
|
|||
slang_print_tree(&op->children[0], indent + 3);
|
||||
break;
|
||||
|
||||
case SLANG_OPER_GOTO:
|
||||
spaces(indent);
|
||||
printf("GOTO %s\n", (char *) op->a_id);
|
||||
break;
|
||||
|
||||
case SLANG_OPER_LABEL:
|
||||
spaces(indent);
|
||||
printf("LABEL %s\n", (char *) op->a_id);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue