diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index aad052963..430c5487b 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -290,6 +290,8 @@ typedef enum { OP_RCALL6, OP_RCALL7, OP_RCALL8, + + OP_RETURN_V, } pr_opcode_e; typedef struct opcode_s { @@ -358,7 +360,7 @@ typedef struct pr_va_list_s { |(((0x##b) & 0xfff) << 12) \ |(((0x##c) & 0xfff) << 0) ) #define PROG_ID_VERSION 6 -#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,006) +#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,007) typedef struct dprograms_s { pr_uint_t version; diff --git a/libs/gamecode/engine/pr_exec.c b/libs/gamecode/engine/pr_exec.c index 54fa5093b..61957827d 100644 --- a/libs/gamecode/engine/pr_exec.c +++ b/libs/gamecode/engine/pr_exec.c @@ -923,6 +923,8 @@ op_call: else if (&R_INT (pr) != &OPA.integer_var) memcpy (&R_INT (pr), &OPA, pr->pr_param_size * sizeof (OPA)); + // fallthrough + case OP_RETURN_V: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; PR_LeaveFunction (pr); diff --git a/libs/gamecode/engine/pr_opcode.c b/libs/gamecode/engine/pr_opcode.c index 3e3059282..2f8d028a6 100644 --- a/libs/gamecode/engine/pr_opcode.c +++ b/libs/gamecode/engine/pr_opcode.c @@ -655,6 +655,12 @@ VISIBLE opcode_t pr_opcodes[] = { "%Ra", }, + {"", "return", OP_RETURN_V, false, + ev_invalid, ev_invalid, ev_invalid, + PROG_VERSION, + "", + }, + {"!", "not.f", OP_NOT_F, false, ev_float, ev_invalid, ev_integer, PROG_ID_VERSION, diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index db6e547a4..eb9af8769 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -34,6 +34,7 @@ extern struct opcode_s *op_done; extern struct opcode_s *op_return; +extern struct opcode_s *op_return_v; extern struct opcode_s *op_if; extern struct opcode_s *op_ifnot; extern struct opcode_s *op_ifbe; diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 6c5515453..6e35adf26 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -877,7 +877,10 @@ emit_expr (expr_t *e) def = 0; if (e->e.expr.e1) def = emit_sub_expr (e->e.expr.e1, 0); - emit_statement (e, op_return, def, 0, 0); + if (!def && op_return_v) + emit_statement (e, op_return_v, 0, 0, 0); + else + emit_statement (e, op_return, def, 0, 0); break; case 'g': emit_branch (e, op_goto, 0, e->e.expr.e1); diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index df77e3b52..dd787f450 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -55,6 +55,7 @@ hashtab_t *opcode_type_table_abc; opcode_t *op_done; opcode_t *op_return; +opcode_t *op_return_v; opcode_t *op_if; opcode_t *op_ifnot; opcode_t *op_ifbe; @@ -152,6 +153,8 @@ opcode_init (void) op_done = op; } else if (!strcmp (op->name, "")) { op_return = op; + } else if (!strcmp (op->name, "")) { + op_return_v = op; } else if (!strcmp (op->name, "")) { op_if = op; } else if (!strcmp (op->name, "")) { diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 6accb9378..f90e24962 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -258,13 +258,12 @@ subprogram_declaration } declarations compound_statement ';' { - type_t *ret_type = $1->type->t.func.type; current_scope = current_scope->parent; //current_storage = st_global; - //FIXME want a true void return - if (ret_type) - append_expr ($5, return_expr (current_func, - new_ret_expr (ret_type))); + // functions in pascal are always effectively void + // but their type is needed for checking func := retval + // so bypass the checks + append_expr ($5, new_unary_expr ('r', 0)); build_code_function (current_func, 0, $5); current_func = 0; }