diff --git a/lang/cem/cemcom.ansi/code.c b/lang/cem/cemcom.ansi/code.c index 09b12f86e..ed321be36 100644 --- a/lang/cem/cemcom.ansi/code.c +++ b/lang/cem/cemcom.ansi/code.c @@ -46,6 +46,7 @@ label lab_count = 1; label datlab_count = 1; +arith fbytes; int fp_used; extern arith NewLocal(); /* util.c */ @@ -212,7 +213,7 @@ code_scope(text, def) static label return_label, return2_label; static char return_expr_occurred; static arith func_size; -static label func_res_label; +static int struct_return; static char *last_fn_given = (char *)0; static label file_name_label; @@ -281,12 +282,11 @@ begin_proc(ds, idf) /* to be called when entering a procedure */ if (func_size <= 0) { error("unknown return type for function %s", name); } else { - C_df_dlb(func_res_label = data_label()); - C_bss_cst(func_size, (arith)0, 1); + struct_return = 1; } } else - func_res_label = 0; + struct_return = 0; /* Special arrangements if the function result doesn't fit in the function return area of the EM machine. The size of the function return area is implementation dependent. @@ -318,8 +318,7 @@ begin_proc(ds, idf) /* to be called when entering a procedure */ #endif } -end_proc(fbytes) - arith fbytes; +end_proc() { /* end_proc() deals with the code to be generated at the end of a function, as there is: @@ -341,14 +340,14 @@ end_proc(fbytes) DfaEndFunction(); #endif /* DATAFLOW */ C_df_ilb(return2_label); - if (return_expr_occurred && func_res_label == 0) { + if (return_expr_occurred && struct_return == 0) { C_asp(-func_size); } C_df_ilb(return_label); prc_exit(); if (return_expr_occurred) { - if (func_res_label != 0) { - C_lae_dlb(func_res_label, (arith)0); + if (struct_return != 0) { + LoadLocal(fbytes, pointer_size); C_ret(pointer_size); } else @@ -357,8 +356,8 @@ end_proc(fbytes) else C_ret((arith) 0); /* getting the number of "local" bytes is posponed until here, - because copying the function result in "func_res_label" may - need temporaries! However, local_level is now L_FORMAL2, because + because copying the function result may need temporaries! + However, local_level is now L_FORMAL2, because L_LOCAL is already unstacked. Therefore, "unstack_level" must also pass "sl_max_block" to the level above L_LOCAL. */ @@ -367,6 +366,7 @@ end_proc(fbytes) 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); @@ -410,8 +410,8 @@ do_return_expr(expr) */ ch3cast(&expr, RETURN, func_type); code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); - if (func_res_label != 0) { - C_lae_dlb(func_res_label, (arith)0); + if (struct_return != 0) { + LoadLocal(fbytes, 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 ccc6ed169..be4250abf 100644 --- a/lang/cem/cemcom.ansi/eval.c +++ b/lang/cem/cemcom.ansi/eval.c @@ -475,6 +475,7 @@ EVAL(expr, val, code, true_label, false_label) register struct expr *ex; arith ParSize = (arith)0; label setjmp_label = 0; + arith retspace = 0; if (ISNAME(left)) { if (left->VL_IDF->id_special == SP_SETJMP) { @@ -488,6 +489,12 @@ 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 && @@ -525,8 +532,10 @@ EVAL(expr, val, code, true_label, false_label) if (gencode) { if (is_struct_or_union(tp->tp_fund)) { C_lfr(pointer_size); - if (val == RVAL) + if (val == RVAL) { load_block(tp->tp_size, (int) word_size); + FreeLocal(retspace); + } } else C_lfr(ATW(tp->tp_size)); @@ -551,7 +560,7 @@ EVAL(expr, val, code, true_label, false_label) break; case ',': EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL); - EVAL(right, RVAL, gencode, true_label, false_label); + EVAL(right, val, gencode, true_label, false_label); break; case '~': EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL); diff --git a/lang/cem/cemcom.ansi/program.g b/lang/cem/cemcom.ansi/program.g index 1c1a8047c..36f20619f 100644 --- a/lang/cem/cemcom.ansi/program.g +++ b/lang/cem/cemcom.ansi/program.g @@ -67,6 +67,7 @@ extern arith ifval; #endif /* NOPP */ +extern arith fbytes; extern error(); } @@ -197,7 +198,6 @@ 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(fbytes); + end_proc(); #ifdef LINT lint_implicit_return(); #endif /* LINT */