case SLANG_OPER_RETURN:
/* do return replacement here too */
assert(oper->num_children == 0 || oper->num_children == 1);
- if (!_slang_is_noop(oper)) {
+ if (oper->num_children == 1 && !_slang_is_noop(&oper->children[0])) {
/* replace:
* return expr;
* with:
* then do substitutions on the assignment.
*/
slang_operation *blockOper, *assignOper, *returnOper;
+
+ /* check if function actually has a return type */
+ assert(A->CurFunction);
+ if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
+ slang_info_log_error(A->log, "illegal return expression");
+ return;
+ }
+
blockOper = slang_operation_new(1);
blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
blockOper->num_children = 2;
slang_operation_copy(oper, blockOper);
slang_operation_destruct(blockOper);
}
+ else {
+ /* check if return value was expected */
+ assert(A->CurFunction);
+ if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
+ slang_info_log_error(A->log, "return statement requires an expression");
+ return;
+ }
+ }
break;
case SLANG_OPER_ASSIGN:
slang_variable **substOld;
slang_operation **substNew;
GLuint substCount, numCopyIn, i;
+ slang_function *prevFunction;
+
+ /* save / push */
+ prevFunction = A->CurFunction;
+ A->CurFunction = fun;
/*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */
assert(fun->param_count == totalArgs);
fun->parameters->num_variables, numArgs);
slang_print_tree(top, 0);
#endif
+
+ /* pop */
+ A->CurFunction = prevFunction;
+
return top;
}
static slang_ir_node *
_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
{
- if (oper->num_children == 0 ||
- (oper->num_children == 1 &&
- oper->children[0].type == SLANG_OPER_VOID)) {
+ const GLboolean haveReturnValue
+ = (oper->num_children == 1 &&
+ oper->children[0].type != SLANG_OPER_VOID);
+
+ /* error checking */
+ assert(A->CurFunction);
+ if (haveReturnValue &&
+ A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
+ slang_info_log_error(A->log, "illegal return expression");
+ return NULL;
+ }
+ else if (!haveReturnValue &&
+ A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
+ slang_info_log_error(A->log, "return statement requires an expression");
+ return NULL;
+ }
+
+ if (!haveReturnValue) {
/* Convert from:
* return;
* To:
gotoOp.label = A->curFuncEndLabel;
assert(gotoOp.label);
- /* assemble the new code */
n = _slang_gen_operation(A, &gotoOp);
/* destroy temp code */
slang_operation_destruct(&gotoOp);
{
slang_variable *v
= _slang_locate_variable(oper->locals, a_retVal, GL_TRUE);
- assert(v);
+ if (!v) {
+ /* trying to return a value in a void-valued function */
+ return NULL;
+ }
}
#endif
_slang_simplify(v->initializer, &A->space, A->atoms);
rhs = _slang_gen_operation(A, v->initializer);
#endif
+ if (!rhs)
+ return NULL;
+
assert(rhs);
init = new_node2(IR_MOVE, var, rhs);
/*
assert(A->program->Parameters );
assert(A->program->Varying);
assert(A->vartable);
+ A->CurLoop = NULL;
+ A->CurFunction = fun;
/* fold constant expressions, etc. */
_slang_simplify(fun->body, &A->space, A->atoms);