mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
[qfcc] Move .return handling into statements.c
The means that the actual call expression is not in the statement lint of the enclosing block expression, but just its result, whether the call is void or not. This actually simplifies several things, but most importantly will make Ruamoko calls easier to implement. The test is because I had some trouble with double-calls, and is how I found the return-postop issue :P
This commit is contained in:
parent
64da1b603a
commit
33a3f92503
6 changed files with 73 additions and 8 deletions
|
@ -647,6 +647,7 @@ int is_math_op (int op) __attribute__((const));
|
|||
int is_logic (int op) __attribute__((const));
|
||||
|
||||
int has_function_call (expr_t *e) __attribute__((pure));
|
||||
int is_function_call (expr_t *e) __attribute__((pure));
|
||||
|
||||
int is_nil (expr_t *e) __attribute__((pure));
|
||||
int is_string_val (expr_t *e) __attribute__((pure));
|
||||
|
|
|
@ -216,9 +216,10 @@ get_type (expr_t *e)
|
|||
convert_name (e);
|
||||
switch (e->type) {
|
||||
case ex_branch:
|
||||
case ex_labelref:
|
||||
type = e->e.branch.ret_type;
|
||||
break;
|
||||
case ex_labelref:
|
||||
return &type_void;
|
||||
case ex_memset:
|
||||
return e->e.memset.type;
|
||||
case ex_error:
|
||||
|
@ -504,6 +505,7 @@ copy_expr (expr_t *e)
|
|||
n = new_expr ();
|
||||
*n = *e;
|
||||
n->e.branch.target = copy_expr (e->e.branch.target);
|
||||
n->e.branch.index = copy_expr (e->e.branch.index);
|
||||
n->e.branch.test = copy_expr (e->e.branch.test);
|
||||
n->e.branch.args = copy_expr (e->e.branch.args);
|
||||
return n;
|
||||
|
@ -1658,6 +1660,12 @@ has_function_call (expr_t *e)
|
|||
internal_error (e, "invalid expression type");
|
||||
}
|
||||
|
||||
int
|
||||
is_function_call (expr_t *e)
|
||||
{
|
||||
return e->type == ex_branch && e->e.branch.type == pr_branch_call;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
asx_expr (int op, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
|
@ -2116,12 +2124,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params)
|
|||
append_expr (call, e);
|
||||
}
|
||||
e = expr_file_line (call_expr (fexpr, args, ftype->t.func.type), fexpr);
|
||||
append_expr (call, e);
|
||||
if (!is_void(ftype->t.func.type)) {
|
||||
call->e.block.result = new_ret_expr (ftype->t.func.type);
|
||||
} else if (options.traditional) {
|
||||
call->e.block.result = new_ret_expr (&type_float);
|
||||
}
|
||||
call->e.block.result = e;
|
||||
return call;
|
||||
}
|
||||
|
||||
|
|
|
@ -248,6 +248,9 @@ message_expr (expr_t *receiver, keywordarg_t *message)
|
|||
if (call->type == ex_error)
|
||||
return receiver;
|
||||
|
||||
call->e.block.result = new_ret_expr (return_type);
|
||||
if (!is_function_call (call->e.block.result)) {
|
||||
internal_error (call, "unexpected block result type");
|
||||
}
|
||||
call->e.block.result->e.branch.ret_type = return_type;
|
||||
return call;
|
||||
}
|
||||
|
|
|
@ -1071,6 +1071,9 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op)
|
|||
sblock = statement_subexpr (sblock, func, &s->opa);
|
||||
s->opb = arguments[0];
|
||||
s->opc = arguments[1];
|
||||
if (op) {
|
||||
*op = return_operand (call->e.branch.ret_type, call);
|
||||
}
|
||||
sblock_add_statement (sblock, s);
|
||||
sblock->next = new_sblock ();
|
||||
return sblock->next;
|
||||
|
@ -1118,6 +1121,16 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op)
|
|||
return sblock->next;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
expr_branch (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||
{
|
||||
if (e->e.branch.type != pr_branch_call) {
|
||||
internal_error (e, "unexpected branch type in expression: %d",
|
||||
e->e.branch.type);
|
||||
}
|
||||
return expr_call (sblock, e, op);
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
statement_branch (sblock_t *sblock, expr_t *e)
|
||||
{
|
||||
|
@ -1618,6 +1631,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
|
|||
[ex_alias] = expr_alias,
|
||||
[ex_address] = expr_address,
|
||||
[ex_assign] = expr_assign,
|
||||
[ex_branch] = expr_branch,
|
||||
};
|
||||
if (!e) {
|
||||
*op = 0;
|
||||
|
@ -1804,6 +1818,11 @@ statement_block (sblock_t *sblock, expr_t *e)
|
|||
sblock = sblock->next;
|
||||
}
|
||||
sblock = statement_slist (sblock, e->e.block.head);
|
||||
if (e->e.block.is_call) {
|
||||
// for a fuction call, the call expresion is in only the result, not
|
||||
// the actual block
|
||||
sblock = statement_slist (sblock, e->e.block.result);
|
||||
}
|
||||
return sblock;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ test_progs_dat=\
|
|||
tools/qfcc/test/structstruct.dat \
|
||||
tools/qfcc/test/swap.dat \
|
||||
tools/qfcc/test/triangle.dat \
|
||||
tools/qfcc/test/twice-called.dat \
|
||||
tools/qfcc/test/typedef.dat \
|
||||
tools/qfcc/test/typelinker.dat \
|
||||
tools/qfcc/test/unaryminus.dat \
|
||||
|
@ -605,6 +606,16 @@ tools/qfcc/test/triangle.run: $(qfcc_test_run_deps)
|
|||
include $(triangle_dep) # am--include-marker
|
||||
r_depfiles_remade += $(triangle_dep)
|
||||
|
||||
tools_qfcc_test_twice_called_dat_SOURCES=tools/qfcc/test/twice-called.r
|
||||
twice_called_obj=$(tools_qfcc_test_twice_called_dat_SOURCES:.r=.o)
|
||||
twice_called_dep=$(call qcautodep,$(tools_qfcc_test_twice_called_dat_SOURCES))
|
||||
tools/qfcc/test/twice-called.dat$(EXEEXT): $(twice_called_obj) $(QFCC_DEP)
|
||||
$(V_QFCCLD)$(QLINK) -o $@ $(twice_called_obj)
|
||||
tools/qfcc/test/twice-called.run: $(qfcc_test_run_deps)
|
||||
@$(top_srcdir)/tools/qfcc/test/build-run $@ 100000 100000 1.00005 50002.4961
|
||||
include $(twice_called_dep) # am--include-marker
|
||||
r_depfiles_remade += $(twice_called_dep)
|
||||
|
||||
tools_qfcc_test_typedef_dat_SOURCES=tools/qfcc/test/typedef.r
|
||||
typedef_obj=$(tools_qfcc_test_typedef_dat_SOURCES:.r=.o)
|
||||
typedef_dep=$(call qcautodep,$(tools_qfcc_test_typedef_dat_SOURCES))
|
||||
|
|
28
tools/qfcc/test/twice-called.r
Normal file
28
tools/qfcc/test/twice-called.r
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "test-harness.h"
|
||||
|
||||
int counter;
|
||||
|
||||
int
|
||||
function (void)
|
||||
{
|
||||
return ++counter;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int ret = 0;
|
||||
counter = 0;
|
||||
//function ();
|
||||
//if (counter != 1) {
|
||||
//printf ("discarded return not called only once\n");
|
||||
// ret = 1;
|
||||
//}
|
||||
counter = 0;
|
||||
printf ("function: %d\n", function ());
|
||||
if (counter != 1) {
|
||||
//printf ("used return not called only once\n");
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
Loading…
Reference in a new issue