Changed method for returning big values; Instead of using a chunk of

global data area, caller creates space on the stack just above parameters
to store the result
This commit is contained in:
ceriel 1989-03-10 10:40:07 +00:00
parent 18d134bda7
commit 162b824030
3 changed files with 30 additions and 32 deletions

View file

@ -321,6 +321,12 @@ CodeCall(nd)
assert(IsProc(left)); assert(IsProc(left));
if (result_tp = ResultType(left->nd_type)) {
if (TooBigForReturnArea(result_tp)) {
C_asp(-WA(result_tp->tp_size));
}
}
if (nd->nd_right) { if (nd->nd_right) {
CodeParameters(ParamList(left->nd_type), nd->nd_right); CodeParameters(ParamList(left->nd_type), nd->nd_right);
} }
@ -349,13 +355,10 @@ CodeCall(nd)
C_cai(); C_cai();
} }
C_asp(left->nd_type->prc_nbpar); C_asp(left->nd_type->prc_nbpar);
if (result_tp = ResultType(left->nd_type)) { if (result_tp) {
arith sz = WA(result_tp->tp_size); if (TooBigForReturnArea(result_tp)) {
if (IsConstructed(result_tp)) {
C_lfr(pointer_size);
C_loi(sz);
} }
else C_lfr(sz); else C_lfr(WA(result_tp->tp_size));
} }
DoFilename(needs_fn); DoFilename(needs_fn);
DoLineno(nd); DoLineno(nd);

View file

@ -220,6 +220,7 @@ extern t_type
#define BaseType(tpx) ((tpx)->tp_fund == T_SUBRANGE ? (tpx)->tp_next : \ #define BaseType(tpx) ((tpx)->tp_fund == T_SUBRANGE ? (tpx)->tp_next : \
(tpx)) (tpx))
#define IsConstructed(tpx) ((tpx)->tp_fund & T_CONSTRUCTED) #define IsConstructed(tpx) ((tpx)->tp_fund & T_CONSTRUCTED)
#define TooBigForReturnArea(tpx) ((tpx)->tp_size > dword_size)
extern long full_mask[]; extern long full_mask[];
extern long max_int[]; extern long max_int[];

View file

@ -215,7 +215,7 @@ WalkProcedure(procedure)
register t_scope *procscope = procedure->prc_vis->sc_scope; register t_scope *procscope = procedure->prc_vis->sc_scope;
register t_type *tp; register t_type *tp;
register t_param *param; register t_param *param;
label func_res_label = 0; int too_big = 0;
arith StackAdjustment = 0; arith StackAdjustment = 0;
arith retsav = 0; arith retsav = 0;
arith func_res_size = 0; arith func_res_size = 0;
@ -227,10 +227,24 @@ WalkProcedure(procedure)
*/ */
WalkDefList(procscope->sc_def, WalkDef); WalkDefList(procscope->sc_def, WalkDef);
func_type = tp = RemoveEqual(ResultType(procedure->df_type));
if (tp) {
func_res_size = WA(tp->tp_size);
if (TooBigForReturnArea(tp)) {
/* The result type of this procedure is constructed.
The caller will have reserved space on its stack,
above the parameters, to store the result.
*/
too_big = 1;
}
}
/* Generate code for this procedure /* Generate code for this procedure
*/ */
C_pro_narg(procscope->sc_name); C_pro_narg(procscope->sc_name);
C_ms_par(procedure->df_type->prc_nbpar); C_ms_par(procedure->df_type->prc_nbpar +
(too_big ? func_res_size : 0));
TmpOpen(procscope); TmpOpen(procscope);
DoPriority(); DoPriority();
/* generate code for filename only when the procedure can be /* generate code for filename only when the procedure can be
@ -240,25 +254,6 @@ WalkProcedure(procedure)
*/ */
DoFilename(! procscope->sc_level); DoFilename(! procscope->sc_level);
func_type = tp = RemoveEqual(ResultType(procedure->df_type));
if (tp) {
func_res_size = WA(tp->tp_size);
if (IsConstructed(tp)) {
/* The result type of this procedure is constructed.
The actual procedure will return a pointer to a
global data area in which the function result is
stored.
Notice that this does make the code non-reentrant.
Here, we create the data area for the function
result.
*/
func_res_label = ++data_label;
C_df_dlb(func_res_label);
C_bss_cst(func_res_size, (arith) 0, 0);
}
}
/* Generate calls to initialization routines of modules defined within /* Generate calls to initialization routines of modules defined within
this procedure this procedure
*/ */
@ -295,7 +290,7 @@ WalkProcedure(procedure)
if (! StackAdjustment) { if (! StackAdjustment) {
/* First time we get here /* First time we get here
*/ */
if (func_type && !func_res_label) { if (func_type && !too_big) {
/* Some local space, only /* Some local space, only
needed if the value itself needed if the value itself
is returned is returned
@ -332,11 +327,11 @@ WalkProcedure(procedure)
C_asp(-func_res_size); C_asp(-func_res_size);
} }
def_ilb(RETURN_LABEL); /* label at end */ def_ilb(RETURN_LABEL); /* label at end */
if (func_res_label) { if (too_big) {
/* Fill the data area reserved for the function result /* Fill the data area reserved for the function result
with the result with the result
*/ */
c_lae_dlb(func_res_label); C_lal(procedure->df_type->prc_nbpar);
C_sti(func_res_size); C_sti(func_res_size);
if (StackAdjustment) { if (StackAdjustment) {
/* Remove copies of conformant arrays /* Remove copies of conformant arrays
@ -344,8 +339,7 @@ WalkProcedure(procedure)
LOL(StackAdjustment, pointer_size); LOL(StackAdjustment, pointer_size);
C_str((arith) 1); C_str((arith) 1);
} }
c_lae_dlb(func_res_label); func_res_size = 0;
func_res_size = pointer_size;
} }
else if (StackAdjustment) { else if (StackAdjustment) {
/* First save the function result in a safe place. /* First save the function result in a safe place.