diff --git a/lang/cem/cemcom.ansi/code.c b/lang/cem/cemcom.ansi/code.c index ed321be36..03205cd4b 100644 --- a/lang/cem/cemcom.ansi/code.c +++ b/lang/cem/cemcom.ansi/code.c @@ -46,7 +46,6 @@ label lab_count = 1; label datlab_count = 1; -arith fbytes; int fp_used; extern arith NewLocal(); /* util.c */ @@ -318,7 +317,8 @@ begin_proc(ds, idf) /* to be called when entering a procedure */ #endif } -end_proc() +end_proc(fbytes) + arith fbytes; { /* end_proc() deals with the code to be generated at the end of a function, as there is: @@ -347,7 +347,7 @@ end_proc() prc_exit(); if (return_expr_occurred) { if (struct_return != 0) { - LoadLocal(fbytes, pointer_size); + LoadLocal((arith) 0, pointer_size); C_ret(pointer_size); } else @@ -366,7 +366,6 @@ end_proc() C_beginpart(pro_id); C_pro(func_name, nbytes); #endif - if (struct_return) fbytes += pointer_size; if (fbytes > max_int) { error("%s has more than %ld parameter bytes", func_name, (long) max_int); @@ -411,7 +410,7 @@ do_return_expr(expr) ch3cast(&expr, RETURN, func_type); code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); if (struct_return != 0) { - LoadLocal(fbytes, pointer_size); + LoadLocal((arith) 0, pointer_size); store_block(func_size, func_type->tp_align); } C_bra(return_label); diff --git a/lang/cem/cemcom.ansi/eval.c b/lang/cem/cemcom.ansi/eval.c index be4250abf..a037c8f07 100644 --- a/lang/cem/cemcom.ansi/eval.c +++ b/lang/cem/cemcom.ansi/eval.c @@ -489,12 +489,6 @@ EVAL(expr, val, code, true_label, false_label) ParSize += pointer_size; } } - if (is_struct_or_union(tp->tp_fund)) { - retspace = NewLocal(tp->tp_size, tp->tp_align, - -1, 0); - C_lal(retspace); - ParSize += pointer_size; - } if ((ex = right) != NILEXPR) { /* function call with parameters*/ while ( ex->ex_class == Oper && @@ -508,6 +502,12 @@ EVAL(expr, val, code, true_label, false_label) EVAL(ex, RVAL, TRUE, NO_LABEL, NO_LABEL); ParSize += ATW(ex->ex_type->tp_size); } + if (is_struct_or_union(tp->tp_fund)) { + retspace = NewLocal(tp->tp_size, tp->tp_align, + -1, 0); + C_lal(retspace); + ParSize += pointer_size; + } if (ISNAME(left)) { /* e.g., main() { (*((int (*)())0))(); } */ C_cal(left->VL_IDF->id_text); diff --git a/lang/cem/cemcom.ansi/idf.c b/lang/cem/cemcom.ansi/idf.c index ae0ec370b..84d0d0309 100644 --- a/lang/cem/cemcom.ansi/idf.c +++ b/lang/cem/cemcom.ansi/idf.c @@ -522,6 +522,10 @@ declare_formals(idf, fp) if (options['t']) dumpidftab("start declare_formals", 0); #endif /* DEBUG */ + if (is_struct_or_union(idf->id_def->df_type->tp_up->tp_fund)) { + /* create space for address of return value */ + f_offset = pointer_size; + } while (se) { register struct def *def = se->se_idf->id_def; diff --git a/lang/cem/cemcom.ansi/program.g b/lang/cem/cemcom.ansi/program.g index 36f20619f..1c1a8047c 100644 --- a/lang/cem/cemcom.ansi/program.g +++ b/lang/cem/cemcom.ansi/program.g @@ -67,7 +67,6 @@ extern arith ifval; #endif /* NOPP */ -extern arith fbytes; extern error(); } @@ -198,6 +197,7 @@ non_function(register struct decspecs *ds; register struct declarator *dc;) /* 3.7.1 */ function(struct decspecs *ds; struct declarator *dc;) { + arith fbytes; register struct idf *idf = dc->dc_idf; } : @@ -222,7 +222,7 @@ function(struct decspecs *ds; struct declarator *dc;) } compound_statement { - end_proc(); + end_proc(fbytes); #ifdef LINT lint_implicit_return(); #endif /* LINT */