New version with different parameter passing mechanism and some

minor fixes
This commit is contained in:
ceriel 1989-03-20 13:32:06 +00:00
parent 346bc839a3
commit f9b6acf1dc
15 changed files with 197 additions and 105 deletions

View file

@ -152,9 +152,11 @@ GetString(upto)
} }
} }
str->s_length = p - str->s_str; str->s_length = p - str->s_str;
*p = '\0'; len = (str->s_length+(int)word_size) & ~((int)word_size-1);
str->s_str = Realloc(str->s_str, while (p - str->s_str < len) {
(unsigned)((str->s_length+(int)word_size) & ~((int)word_size-1))); *p++ = '\0';
}
str->s_str = Realloc(str->s_str, (unsigned) len);
if (str->s_length == 0) str->s_length = 1; if (str->s_length == 0) str->s_length = 1;
/* ??? string length at least 1 ??? */ /* ??? string length at least 1 ??? */
return str; return str;

View file

@ -1 +1 @@
static char Version[] = "ACK Modula-2 compiler Version 0.47"; static char Version[] = "ACK Modula-2 compiler Version 0.48";

View file

@ -77,7 +77,8 @@ compact(nr, low, up)
diff / nr <= (DENSITY - 1)); diff / nr <= (DENSITY - 1));
} }
CaseCode(nd, exitlabel) int
CaseCode(nd, exitlabel, end_reached)
t_node *nd; t_node *nd;
label exitlabel; label exitlabel;
{ {
@ -91,6 +92,7 @@ CaseCode(nd, exitlabel)
register struct case_entry *ce; register struct case_entry *ce;
register arith val; register arith val;
label CaseDescrLab; label CaseDescrLab;
int rval;
assert(pnode->nd_class == Stat && pnode->nd_symb == CASE); assert(pnode->nd_class == Stat && pnode->nd_symb == CASE);
@ -109,15 +111,12 @@ CaseCode(nd, exitlabel)
/* non-empty case /* non-empty case
*/ */
pnode->nd_lab = ++text_label; pnode->nd_lab = ++text_label;
if (! AddCases(sh, /* to descriptor */ AddCases(sh, /* to descriptor */
pnode->nd_left->nd_left, pnode->nd_left->nd_left,
/* of case labels */ /* of case labels */
pnode->nd_lab pnode->nd_lab
/* and code label */ /* and code label */
)) { );
FreeSh(sh);
return;
}
} }
} }
else { else {
@ -135,8 +134,6 @@ CaseCode(nd, exitlabel)
*/ */
if (! (sh->sh_type->tp_fund & T_DISCRETE)) { if (! (sh->sh_type->tp_fund & T_DISCRETE)) {
node_error(nd, "illegal type in CASE-expression"); node_error(nd, "illegal type in CASE-expression");
FreeSh(sh);
return;
} }
} }
@ -184,12 +181,13 @@ CaseCode(nd, exitlabel)
/* Now generate code for the cases /* Now generate code for the cases
*/ */
pnode = nd; pnode = nd;
rval = 0;
while (pnode = pnode->nd_right) { while (pnode = pnode->nd_right) {
if (pnode->nd_class == Link && pnode->nd_symb == '|') { if (pnode->nd_class == Link && pnode->nd_symb == '|') {
if (pnode->nd_left) { if (pnode->nd_left) {
LblWalkNode(pnode->nd_lab, rval |= LblWalkNode(pnode->nd_lab,
pnode->nd_left->nd_right, pnode->nd_left->nd_right,
exitlabel); exitlabel, end_reached);
C_bra(sh->sh_break); C_bra(sh->sh_break);
} }
} }
@ -198,13 +196,15 @@ CaseCode(nd, exitlabel)
*/ */
assert(sh->sh_default != 0); assert(sh->sh_default != 0);
LblWalkNode(sh->sh_default, pnode, exitlabel); rval |= LblWalkNode(sh->sh_default,
pnode, exitlabel, end_reached);
break; break;
} }
} }
def_ilb(sh->sh_break); def_ilb(sh->sh_break);
FreeSh(sh); FreeSh(sh);
return rval;
} }
FreeSh(sh) FreeSh(sh)
@ -241,22 +241,23 @@ AddCases(sh, node, lbl)
node->nd_type = node->nd_left->nd_type; node->nd_type = node->nd_left->nd_type;
node->nd_INT = node->nd_left->nd_INT; node->nd_INT = node->nd_left->nd_INT;
for (;;) { for (;;) {
if (! AddOneCase(sh, node, lbl)) return 0; AddOneCase(sh, node, lbl);
if (node->nd_INT == node->nd_right->nd_INT) { if (node->nd_INT == node->nd_right->nd_INT) {
break; break;
} }
node->nd_INT++; node->nd_INT++;
} }
return 1; return;
} }
assert(node->nd_symb == ','); assert(node->nd_symb == ',');
return AddCases(sh, node->nd_left, lbl) && AddCases(sh, node->nd_left, lbl);
AddCases(sh, node->nd_right, lbl); AddCases(sh, node->nd_right, lbl);
return;
} }
assert(node->nd_class == Value); assert(node->nd_class == Value);
return AddOneCase(sh, node, lbl); AddOneCase(sh, node, lbl);
} }
AddOneCase(sh, node, lbl) AddOneCase(sh, node, lbl)
@ -271,8 +272,6 @@ AddOneCase(sh, node, lbl)
ce->ce_label = lbl; ce->ce_label = lbl;
ce->ce_value = node->nd_INT; ce->ce_value = node->nd_INT;
if (! ChkCompat(&node, sh->sh_type, "case")) { if (! ChkCompat(&node, sh->sh_type, "case")) {
free_case_entry(ce);
return 0;
} }
if (sh->sh_entries == 0) { if (sh->sh_entries == 0) {
/* first case entry /* first case entry
@ -311,7 +310,6 @@ AddOneCase(sh, node, lbl)
if (c1->ce_value == ce->ce_value) { if (c1->ce_value == ce->ce_value) {
node_error(node, "multiple case entry for value %ld", ce->ce_value); node_error(node, "multiple case entry for value %ld", ce->ce_value);
free_case_entry(ce); free_case_entry(ce);
return 0;
} }
if (c2) { if (c2) {
ce->ce_next = c2->ce_next; ce->ce_next = c2->ce_next;
@ -330,5 +328,4 @@ node_error(node, "multiple case entry for value %ld", ce->ce_value);
} }
(sh->sh_nrofentries)++; (sh->sh_nrofentries)++;
} }
return 1;
} }

View file

@ -207,23 +207,24 @@ ChkArr(expp, flags)
"index type"); "index type");
} }
#ifdef DEBUG /*ARGSUSED*/
STATIC int STATIC int
ChkValue(expp) ChkValue(expp)
t_node *expp; t_node *expp;
{ {
#ifdef DEBUG
switch(expp->nd_symb) { switch(expp->nd_symb) {
case REAL: case REAL:
case STRING: case STRING:
case INTEGER: case INTEGER:
return 1; break;
default: default:
crash("(ChkValue)"); crash("(ChkValue)");
} }
/*NOTREACHED*/
}
#endif #endif
return 1;
}
STATIC int STATIC int
ChkLinkOrName(expp, flags) ChkLinkOrName(expp, flags)
@ -430,7 +431,6 @@ MkSet(size)
{ {
register arith *s; register arith *s;
size = (size / (int) word_size + 1) * sizeof(arith);
s = (arith *) Malloc(size); s = (arith *) Malloc(size);
clear((char *) s , size); clear((char *) s , size);
s++; s++;
@ -492,7 +492,7 @@ ChkSet(expp)
First allocate room for the set. First allocate room for the set.
*/ */
expp->nd_set = MkSet((unsigned)(tp->tp_size)); expp->nd_set = MkSet(tp->set_sz);
/* Now check the elements, one by one /* Now check the elements, one by one
*/ */
@ -1163,7 +1163,7 @@ ChkStandard(expp)
} }
left = getvariable(&arg, left = getvariable(&arg,
edf, edf,
edf->df_value.df_stdname == S_NEW ? D_DEFINED : D_USED); D_USED|D_DEFINED);
expp->nd_type = 0; expp->nd_type = 0;
if (! left) return 0; if (! left) return 0;
if (! (left->nd_type->tp_fund == T_POINTER)) { if (! (left->nd_type->tp_fund == T_POINTER)) {
@ -1395,19 +1395,17 @@ no_desig(expp)
} }
STATIC int STATIC int
done_before() add_flags(expp, flags)
t_node *expp;
{ {
expp->nd_def->df_flags |= flags;
return 1; return 1;
} }
extern int NodeCrash(); extern int NodeCrash();
int (*ExprChkTable[])() = { int (*ExprChkTable[])() = {
#ifdef DEBUG
ChkValue, ChkValue,
#else
done_before,
#endif
ChkArr, ChkArr,
ChkBinOper, ChkBinOper,
ChkUnOper, ChkUnOper,
@ -1416,7 +1414,7 @@ int (*ExprChkTable[])() = {
ChkExLinkOrName, ChkExLinkOrName,
NodeCrash, NodeCrash,
ChkSet, ChkSet,
done_before, add_flags,
NodeCrash, NodeCrash,
ChkExLinkOrName, ChkExLinkOrName,
}; };
@ -1431,7 +1429,7 @@ int (*DesigChkTable[])() = {
ChkLinkOrName, ChkLinkOrName,
NodeCrash, NodeCrash,
no_desig, no_desig,
done_before, add_flags,
NodeCrash, NodeCrash,
ChkLinkOrName, ChkLinkOrName,
}; };

View file

@ -417,6 +417,8 @@ CodeParameters(param, arg)
C_loc(left_type->arr_high - left_type->arr_low); C_loc(left_type->arr_high - left_type->arr_low);
} }
c_loc(0); c_loc(0);
}
if (IsConformantArray(tp) || IsVarParam(param) || IsBigParamTp(tp)) {
if (left->nd_symb == STRING) { if (left->nd_symb == STRING) {
CodeString(left); CodeString(left);
} }
@ -438,10 +440,6 @@ CodeParameters(param, arg)
} }
return; return;
} }
if (IsVarParam(param)) {
CodeDAddress(left, 1);
return;
}
if (left_type->tp_fund == T_STRING) { if (left_type->tp_fund == T_STRING) {
CodePString(left, tp); CodePString(left, tp);
return; return;

View file

@ -371,6 +371,10 @@ cstset(expp)
setsize = (unsigned) (expp->nd_right->nd_type->tp_size) / (unsigned) word_size; setsize = (unsigned) (expp->nd_right->nd_type->tp_size) / (unsigned) word_size;
if (expp->nd_symb == IN) { if (expp->nd_symb == IN) {
/* The setsize must fit in an unsigned, as it is
allocated with Malloc, so we can do the arithmetic
in an unsigned too.
*/
unsigned i; unsigned i;
assert(expp->nd_left->nd_class == Value); assert(expp->nd_left->nd_class == Value);
@ -378,6 +382,10 @@ cstset(expp)
expp->nd_left->nd_INT -= expp->nd_right->nd_type->set_low; expp->nd_left->nd_INT -= expp->nd_right->nd_type->set_low;
i = expp->nd_left->nd_INT; i = expp->nd_left->nd_INT;
expp->nd_class = Value; expp->nd_class = Value;
/* Careful here; use expp->nd_left->nd_INT to see if
it falls in the range of the set. Do not use i
for this, as i may be truncated.
*/
expp->nd_INT = (expp->nd_left->nd_INT >= 0 && expp->nd_INT = (expp->nd_left->nd_INT >= 0 &&
expp->nd_left->nd_INT < setsize * wrd_bits && expp->nd_left->nd_INT < setsize * wrd_bits &&
(set2[i / wrd_bits] & (1 << (i % wrd_bits)))); (set2[i / wrd_bits] & (1 << (i % wrd_bits))));
@ -393,7 +401,7 @@ cstset(expp)
case '-': /* Set difference */ case '-': /* Set difference */
case '*': /* Set intersection */ case '*': /* Set intersection */
case '/': /* Symmetric set difference */ case '/': /* Symmetric set difference */
expp->nd_set = resultset = MkSet(setsize * (unsigned) word_size); expp->nd_set = resultset = MkSet(expp->nd_type->set_sz);
for (j = 0; j < setsize; j++) { for (j = 0; j < setsize; j++) {
switch(expp->nd_symb) { switch(expp->nd_symb) {
case '+': case '+':

View file

@ -402,7 +402,7 @@ CaseLabels(t_type **ptp; register t_node **pnd;)
{ {
if (*ptp != 0) { if (*ptp != 0) {
t_type *tp = intorcard(*ptp, t_type *tp = intorcard(*ptp,
BaseType((*pnd)->nd_type), 0); BaseType((*pnd)->nd_type));
if (tp) *ptp = tp; if (tp) *ptp = tp;
ChkCompat(pnd, *ptp, "case label"); ChkCompat(pnd, *ptp, "case label");
} }

View file

@ -55,6 +55,7 @@ typedef struct desig t_desig;
struct withdesig { struct withdesig {
struct withdesig *w_next; struct withdesig *w_next;
int w_flags; /* D_USED|D_DEFINED */
struct scope *w_scope; /* scope in which fields of this record struct scope *w_scope; /* scope in which fields of this record
reside reside
*/ */

View file

@ -514,6 +514,7 @@ CodeFieldDesig(df, ds)
/* Found it. Now, act like it was a selection. /* Found it. Now, act like it was a selection.
*/ */
*ds = wds->w_desig; *ds = wds->w_desig;
wds->w_flags |= df->df_flags;
assert(ds->dsg_kind == DSG_PFIXED); assert(ds->dsg_kind == DSG_PFIXED);
} }
@ -583,10 +584,11 @@ CodeVarDesig(df, ds)
*/ */
C_lxa((arith) difflevel); C_lxa((arith) difflevel);
if ((df->df_flags & D_VARPAR) || if ((df->df_flags & D_VARPAR) ||
IsBigParamTp(df->df_type) ||
IsConformantArray(df->df_type)) { IsConformantArray(df->df_type)) {
/* var parameter or conformant array. /* var parameter, big parameter,
For conformant array's, the address is or conformant array.
passed. The address is passed.
*/ */
C_adp(df->var_off); C_adp(df->var_off);
C_loi(pointer_size); C_loi(pointer_size);
@ -603,7 +605,9 @@ CodeVarDesig(df, ds)
/* Now, finally, we have a local variable or a local parameter /* Now, finally, we have a local variable or a local parameter
*/ */
if ((df->df_flags & D_VARPAR) || IsConformantArray(df->df_type)) { if ((df->df_flags & D_VARPAR) ||
((df->df_flags & D_VALPAR) && IsBigParamTp(df->df_type)) ||
IsConformantArray(df->df_type)) {
/* a var parameter; address directly accessible. /* a var parameter; address directly accessible.
*/ */
ds->dsg_kind = DSG_PFIXED; ds->dsg_kind = DSG_PFIXED;

View file

@ -222,7 +222,7 @@ EnterParamList(ppr, Idlist, type, VARp, off)
*/ */
*off += pointer_size + word_size + dword_size; *off += pointer_size + word_size + dword_size;
} }
else if (VARp == D_VARPAR) { else if (VARp == D_VARPAR || IsBigParamTp(type)) {
*off += pointer_size; *off += pointer_size;
} }
else { else {

View file

@ -53,7 +53,7 @@ main(argc, argv)
register char **Nargv = &argv[0]; register char **Nargv = &argv[0];
ProgName = *argv++; ProgName = *argv++;
DEFPATH = (char **) Malloc(mDEF * sizeof(char *)); DEFPATH = (char **) Malloc((unsigned)mDEF * sizeof(char *));
while (--argc > 0) { while (--argc > 0) {
if (**argv == '-') if (**argv == '-')

View file

@ -64,14 +64,16 @@ struct record {
struct proc { struct proc {
struct paramlist *pr_params; struct paramlist *pr_params;
arith pr_nbpar; arith pr_nbpar; /* number of bytes parameters accessed */
#define prc_params tp_value.tp_proc.pr_params #define prc_params tp_value.tp_proc.pr_params
#define prc_nbpar tp_value.tp_proc.pr_nbpar #define prc_nbpar tp_value.tp_proc.pr_nbpar
}; };
struct set { struct set {
arith st_low; arith st_low; /* lowerbound of subrange type of set */
unsigned st_sz; /* size of constant set in compiler */
#define set_low tp_value.tp_set.st_low #define set_low tp_value.tp_set.st_low
#define set_sz tp_value.tp_set.st_sz
}; };
struct type { struct type {
@ -224,6 +226,7 @@ extern t_type
(tpx)) (tpx))
#define IsConstructed(tpx) ((tpx)->tp_fund & T_CONSTRUCTED) #define IsConstructed(tpx) ((tpx)->tp_fund & T_CONSTRUCTED)
#define TooBigForReturnArea(tpx) ((tpx)->tp_size > ret_area_size) #define TooBigForReturnArea(tpx) ((tpx)->tp_size > ret_area_size)
#define IsBigParamTp(tpx) ((tpx)->tp_size > double_size)
extern long full_mask[]; extern long full_mask[];
extern long max_int[]; extern long max_int[];

View file

@ -503,7 +503,7 @@ set_type(tp)
/* Construct a set type with base type "tp", but first /* Construct a set type with base type "tp", but first
perform some checks perform some checks
*/ */
arith lb, ub, diff; arith lb, ub, diff, alloc_size;
if (! bounded(tp) || tp->tp_size > word_size) { if (! bounded(tp) || tp->tp_size > word_size) {
error("illegal base type for set"); error("illegal base type for set");
@ -526,6 +526,12 @@ set_type(tp)
tp = construct_type(T_SET, tp); tp = construct_type(T_SET, tp);
tp->tp_size = WA((diff + 7) >> 3); tp->tp_size = WA((diff + 7) >> 3);
alloc_size = (tp->tp_size / word_size + 1) * sizeof(arith);
tp->set_sz = alloc_size;
if (tp->set_sz != alloc_size) {
error("set size too large");
return error_type;
}
tp->set_low = lb; tp->set_low = lb;
return tp; return tp;
} }

View file

@ -41,6 +41,7 @@
extern arith NewPtr(); extern arith NewPtr();
extern arith NewInt(); extern arith NewInt();
extern arith TmpSpace();
extern int proclevel; extern int proclevel;
@ -61,7 +62,11 @@ static int UseWarnings();
#define NO_EXIT_LABEL ((label) 0) #define NO_EXIT_LABEL ((label) 0)
#define RETURN_LABEL ((label) 1) #define RETURN_LABEL ((label) 1)
LblWalkNode(lbl, nd, exit) #define REACH_FLAG 1
#define EXIT_FLAG 2
int
LblWalkNode(lbl, nd, exit, reach)
label lbl, exit; label lbl, exit;
register t_node *nd; register t_node *nd;
{ {
@ -71,7 +76,7 @@ LblWalkNode(lbl, nd, exit)
*/ */
def_ilb(lbl); def_ilb(lbl);
WalkNode(nd, exit); return WalkNode(nd, exit, reach);
} }
static arith tmpprio; static arith tmpprio;
@ -104,6 +109,8 @@ EndPriority()
def_ilb(l) def_ilb(l)
label l; label l;
{ {
/* Instruction label definition. Forget about line number.
*/
C_df_ilb(l); C_df_ilb(l);
oldlineno = 0; oldlineno = 0;
} }
@ -111,7 +118,11 @@ def_ilb(l)
DoLineno(nd) DoLineno(nd)
register t_node *nd; register t_node *nd;
{ {
if (! options['L'] && nd->nd_lineno && nd->nd_lineno != oldlineno) { /* Generate line number information, if necessary.
*/
if (! options['L'] &&
nd->nd_lineno &&
nd->nd_lineno != oldlineno) {
oldlineno = nd->nd_lineno; oldlineno = nd->nd_lineno;
C_lin((arith) nd->nd_lineno); C_lin((arith) nd->nd_lineno);
} }
@ -119,6 +130,11 @@ DoLineno(nd)
DoFilename(needed) DoFilename(needed)
{ {
/* Generate filename information, when needed.
This routine is called at the generation of a
procedure entry, and after generating a call to
another procedure.
*/
static label filename_label = 0; static label filename_label = 0;
oldlineno = 0; /* always invalidate remembered line number */ oldlineno = 0; /* always invalidate remembered line number */
@ -182,6 +198,9 @@ WalkModule(module)
C_ine_dlb(data_label, (arith) 0); C_ine_dlb(data_label, (arith) 0);
} }
else if (! options['R']) { else if (! options['R']) {
/* put funny value in BSS, in an attempt to detect
uninitialized variables
*/
C_cal("killbss"); C_cal("killbss");
} }
@ -192,7 +211,7 @@ WalkModule(module)
} }
WalkDefList(sc->sc_def, MkCalls); WalkDefList(sc->sc_def, MkCalls);
proclevel++; proclevel++;
WalkNode(module->mod_body, NO_EXIT_LABEL); WalkNode(module->mod_body, NO_EXIT_LABEL, REACH_FLAG);
DO_DEBUG(options['X'], PrNode(module->mod_body, 0)); DO_DEBUG(options['X'], PrNode(module->mod_body, 0));
def_ilb(RETURN_LABEL); def_ilb(RETURN_LABEL);
EndPriority(); EndPriority();
@ -215,10 +234,13 @@ 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;
int too_big = 0; int too_big = 0; /* returnsize larger than returnarea */
arith StackAdjustment = 0; arith StackAdjustment = 0; /* space for conformant arrays */
arith retsav = 0; arith retsav = 0; /* temporary space for return value */
arith func_res_size = 0; arith func_res_size = 0;
int partno = C_getid();
int partno2 = C_getid();
int end_reached; /* can fall through ... */
proclevel++; proclevel++;
CurrVis = procedure->prc_vis; CurrVis = procedure->prc_vis;
@ -242,17 +264,22 @@ WalkProcedure(procedure)
/* Generate code for this procedure /* Generate code for this procedure
*/ */
C_pro_narg(procscope->sc_name);
C_ms_par(procedure->df_type->prc_nbpar +
(too_big ? func_res_size : 0));
TmpOpen(procscope); TmpOpen(procscope);
C_insertpart(partno2);
C_insertpart(partno);
text_label = 1; /* label at end of procedure */
end_reached = WalkNode(procedure->prc_body, NO_EXIT_LABEL, REACH_FLAG);
C_beginpart(partno);
DoPriority(); DoPriority();
/* generate code for filename only when the procedure can be /* generate code for filename only when the procedure can be
exported, either directly or by taking the address. exported, either directly or by taking the address.
This cannot be done if the level is not zero (because in This cannot be done if the level is bigger than one (because in
this case it is a nested procedure). this case it is a nested procedure).
*/ */
DoFilename(! procscope->sc_level); DoFilename(procscope->sc_level == 1);
/* Generate calls to initialization routines of modules defined within /* Generate calls to initialization routines of modules defined within
this procedure this procedure
@ -261,7 +288,7 @@ WalkProcedure(procedure)
/* Make sure that arguments of size < word_size are on a /* Make sure that arguments of size < word_size are on a
fixed place. fixed place.
Also make copies of conformant arrays when neccessary. Also make copies of parameters when neccessary.
*/ */
for (param = ParamList(procedure->df_type); for (param = ParamList(procedure->df_type);
param; param;
@ -273,17 +300,37 @@ WalkProcedure(procedure)
if (tp->tp_size < word_size && if (tp->tp_size < word_size &&
(int) word_size % (int) tp->tp_size == 0) { (int) word_size % (int) tp->tp_size == 0) {
C_lol(param->par_def->var_off); C_lol(param->par_def->var_off);
STL(param->par_def->var_off, tp->tp_size); STL(param->par_def->var_off,
tp->tp_size);
continue;
} }
if (IsBigParamTp(tp) &&
(param->par_def->df_flags & D_DEFINED)){
/* Value parameter changed in body.
Make a copy
*/
arith tmp = TmpSpace(tp->tp_size,
tp->tp_align);
LOL(param->par_def->var_off,
pointer_size);
C_lal(tmp);
CodeConst(WA(tp->tp_size),
(int)pointer_size);
C_bls(pointer_size);
C_lal(tmp);
STL(param->par_def->var_off,
pointer_size);
}
continue;
} }
else { if (param->par_def->df_flags & D_DEFINED) {
/* Here, we have to make a copy of the /* Here, we have to make a copy of the
array. We must also remember how much array. We must also remember how much
room is reserved for copies, because room is reserved for copies, because
we have to adjust the stack pointer before we have to adjust the stack pointer before
a RET is done. This is even more complicated a RET is done. This is even more complicated
when the procedure returns a value. when the procedure returns a value.
Then, the value must be saved (in retval), Then, the value must be saved,
the stack adjusted, the return value pushed the stack adjusted, the return value pushed
again, and then RET again, and then RET
*/ */
@ -295,9 +342,8 @@ WalkProcedure(procedure)
needed if the value itself needed if the value itself
is returned is returned
*/ */
procscope->sc_off -= retsav= TmpSpace(func_res_size,
func_res_size; 1);
retsav = procscope->sc_off;
} }
StackAdjustment = NewPtr(); StackAdjustment = NewPtr();
C_lor((arith) 1); C_lor((arith) 1);
@ -316,12 +362,13 @@ WalkProcedure(procedure)
} }
} }
} }
C_endpart(partno);
text_label = 1; /* label at end of procedure */
WalkNode(procedure->prc_body, NO_EXIT_LABEL);
DO_DEBUG(options['X'], PrNode(procedure->prc_body, 0)); DO_DEBUG(options['X'], PrNode(procedure->prc_body, 0));
if (func_res_size) { if ((end_reached & REACH_FLAG) && func_res_size) {
node_warning(procscope->sc_end,
W_ORDINARY,
"function procedure \"%s\" does not always return a value",
procedure->df_idf->id_text);
c_loc(M2_NORESULT); c_loc(M2_NORESULT);
C_trp(); C_trp();
C_asp(-func_res_size); C_asp(-func_res_size);
@ -357,10 +404,16 @@ WalkProcedure(procedure)
} }
EndPriority(); EndPriority();
C_ret(func_res_size); C_ret(func_res_size);
C_beginpart(partno2);
C_pro(procscope->sc_name, -procscope->sc_off);
C_ms_par(procedure->df_type->prc_nbpar +
(too_big ? func_res_size : 0));
if (! options['n']) WalkDefList(procscope->sc_def, RegisterMessage); if (! options['n']) WalkDefList(procscope->sc_def, RegisterMessage);
C_endpart(partno2);
C_end(-procscope->sc_off); C_end(-procscope->sc_off);
if (! fit(procscope->sc_off, (int) word_size)) { if (! fit(procscope->sc_off, (int) word_size)) {
node_error(procedure->prc_body, "maximum local byte count exceeded"); node_error(procedure->prc_body,
"maximum local byte count exceeded");
} }
TmpClose(); TmpClose();
CurrVis = savevis; CurrVis = savevis;
@ -409,19 +462,22 @@ MkCalls(df)
} }
} }
WalkLink(nd, exit_label) WalkLink(nd, exit_label, end_reached)
register t_node *nd; register t_node *nd;
label exit_label; label exit_label;
{ {
/* Walk node "nd", which is a link. /* Walk node "nd", which is a link.
"exit_label" is set to a label number when inside a LOOP.
"end_reached" maintains info about reachability (REACH_FLAG),
and whether an EXIT statement was seen (EXIT_FLAG).
*/ */
while (nd && nd->nd_class == Link) { /* statement list */ while (nd && nd->nd_class == Link) { /* statement list */
WalkNode(nd->nd_left, exit_label); end_reached = WalkNode(nd->nd_left, exit_label, end_reached);
nd = nd->nd_right; nd = nd->nd_right;
} }
WalkNode(nd, exit_label); return WalkNode(nd, exit_label, end_reached);
} }
STATIC STATIC
@ -434,7 +490,8 @@ ForLoopVarExpr(nd)
CodeCoercion(tp, BaseType(tp)); CodeCoercion(tp, BaseType(tp));
} }
WalkStat(nd, exit_label) int
WalkStat(nd, exit_label, end_reached)
register t_node *nd; register t_node *nd;
label exit_label; label exit_label;
{ {
@ -445,8 +502,11 @@ WalkStat(nd, exit_label)
assert(nd->nd_class == Stat); assert(nd->nd_class == Stat);
if (nd->nd_symb == ';') return; if (nd->nd_symb == ';') return 1;
if (! end_reached & REACH_FLAG) {
node_warning(nd, W_ORDINARY, "statement not reached");
}
DoLineno(nd); DoLineno(nd);
options['R'] = (nd->nd_flags & ROPTION); options['R'] = (nd->nd_flags & ROPTION);
options['A'] = (nd->nd_flags & AOPTION); options['A'] = (nd->nd_flags & AOPTION);
@ -467,24 +527,26 @@ WalkStat(nd, exit_label)
case IF: case IF:
{ label l1 = ++text_label, l3 = ++text_label; { label l1 = ++text_label, l3 = ++text_label;
int end_r;
ExpectBool(left, l3, l1); ExpectBool(left, l3, l1);
assert(right->nd_symb == THEN); assert(right->nd_symb == THEN);
LblWalkNode(l3, right->nd_left, exit_label); end_r = LblWalkNode(l3, right->nd_left, exit_label, end_reached);
if (right->nd_right) { /* ELSE part */ if (right->nd_right) { /* ELSE part */
label l2 = ++text_label; label l2 = ++text_label;
C_bra(l2); C_bra(l2);
LblWalkNode(l1, right->nd_right, exit_label); end_reached = end_r | LblWalkNode(l1, right->nd_right, exit_label, end_reached);
l1 = l2; l1 = l2;
} }
else end_reached |= end_r;
def_ilb(l1); def_ilb(l1);
break; break;
} }
case CASE: case CASE:
CaseCode(nd, exit_label); end_reached = CaseCode(nd, exit_label, end_reached);
break; break;
case WHILE: case WHILE:
@ -492,10 +554,10 @@ WalkStat(nd, exit_label)
exit = ++text_label, exit = ++text_label,
dummy = ++text_label; dummy = ++text_label;
def_ilb(loop); C_bra(dummy);
ExpectBool(left, dummy, exit); end_reached |= LblWalkNode(loop, right, exit_label, end_reached);
LblWalkNode(dummy, right, exit_label); def_ilb(dummy);
C_bra(loop); ExpectBool(left, loop, exit);
def_ilb(exit); def_ilb(exit);
break; break;
} }
@ -503,7 +565,7 @@ WalkStat(nd, exit_label)
case REPEAT: case REPEAT:
{ label loop = ++text_label, exit = ++text_label; { label loop = ++text_label, exit = ++text_label;
LblWalkNode(loop, left, exit_label); end_reached = LblWalkNode(loop, left, exit_label, end_reached);
ExpectBool(right, exit, loop); ExpectBool(right, exit, loop);
def_ilb(exit); def_ilb(exit);
break; break;
@ -512,7 +574,10 @@ WalkStat(nd, exit_label)
case LOOP: case LOOP:
{ label loop = ++text_label, exit = ++text_label; { label loop = ++text_label, exit = ++text_label;
LblWalkNode(loop, right, exit); if (LblWalkNode(loop, right, exit, end_reached) & EXIT_FLAG) {
end_reached &= REACH_FLAG;
}
else end_reached = 0;
C_bra(loop); C_bra(loop);
def_ilb(exit); def_ilb(exit);
break; break;
@ -575,7 +640,7 @@ WalkStat(nd, exit_label)
ForLoopVarExpr(nd); ForLoopVarExpr(nd);
C_stl(tmp2); C_stl(tmp2);
WalkNode(right, exit_label); end_reached |= WalkNode(right, exit_label, end_reached);
C_lol(tmp2); C_lol(tmp2);
ForLoopVarExpr(nd); ForLoopVarExpr(nd);
C_beq(x); C_beq(x);
@ -583,7 +648,7 @@ WalkStat(nd, exit_label)
C_trp(); C_trp();
def_ilb(x); def_ilb(x);
} }
else WalkNode(right, exit_label); else end_reached |= WalkNode(right, exit_label, end_reached);
nd->nd_def->df_flags &= ~D_FORLOOP; nd->nd_def->df_flags &= ~D_FORLOOP;
FreeInt(tmp2); FreeInt(tmp2);
if (stepsize) { if (stepsize) {
@ -601,7 +666,7 @@ WalkStat(nd, exit_label)
} }
} }
else { else {
WalkNode(right, exit_label); end_reached |= WalkNode(right, exit_label, end_reached);
nd->nd_def->df_flags &= ~D_FORLOOP; nd->nd_def->df_flags &= ~D_FORLOOP;
} }
C_bra(l1); C_bra(l1);
@ -620,13 +685,14 @@ WalkStat(nd, exit_label)
struct withdesig wds; struct withdesig wds;
t_desig ds; t_desig ds;
if (! WalkDesignator(left, &ds, D_USED|D_DEFINED)) break; if (! WalkDesignator(left, &ds, D_USED)) break;
if (left->nd_type->tp_fund != T_RECORD) { if (left->nd_type->tp_fund != T_RECORD) {
node_error(left, "record variable expected"); node_error(left, "record variable expected");
break; break;
} }
wds.w_next = WithDesigs; wds.w_next = WithDesigs;
wds.w_flags = D_USED;
WithDesigs = &wds; WithDesigs = &wds;
wds.w_scope = left->nd_type->rec_scope; wds.w_scope = left->nd_type->rec_scope;
CodeAddress(&ds); CodeAddress(&ds);
@ -642,20 +708,23 @@ WalkStat(nd, exit_label)
link.sc_scope = wds.w_scope; link.sc_scope = wds.w_scope;
link.sc_next = CurrVis; link.sc_next = CurrVis;
CurrVis = &link; CurrVis = &link;
WalkNode(right, exit_label); end_reached = WalkNode(right, exit_label, end_reached);
CurrVis = link.sc_next; CurrVis = link.sc_next;
WithDesigs = wds.w_next; WithDesigs = wds.w_next;
FreePtr(ds.dsg_offset); FreePtr(ds.dsg_offset);
WalkDesignator(left, &ds, wds.w_flags & (D_USED|D_DEFINED));
break; break;
} }
case EXIT: case EXIT:
assert(exit_label != 0); assert(exit_label != 0);
if (end_reached & REACH_FLAG) end_reached = EXIT_FLAG;
C_bra(exit_label); C_bra(exit_label);
break; break;
case RETURN: case RETURN:
end_reached &= ~REACH_FLAG;
if (right) { if (right) {
if (! ChkExpression(right)) break; if (! ChkExpression(right)) break;
/* The type of the return-expression must be /* The type of the return-expression must be
@ -677,6 +746,7 @@ WalkStat(nd, exit_label)
default: default:
crash("(WalkStat)"); crash("(WalkStat)");
} }
return end_reached;
} }
extern int NodeCrash(); extern int NodeCrash();
@ -900,16 +970,18 @@ UseWarnings(df)
} }
switch(df->df_flags & (D_USED|D_DEFINED|D_VALPAR|D_VARPAR)) { switch(df->df_flags & (D_USED|D_DEFINED|D_VALPAR|D_VARPAR)) {
case 0: case 0:
case D_VALPAR:
case D_VARPAR: case D_VARPAR:
warning = "never used/assigned"; warning = "never used/assigned";
break; break;
case D_USED|D_VARPAR: case D_USED|D_VARPAR:
warning = "never assigned, could be value parameter"; if (df->df_type->tp_fund != T_EQUAL) {
warning = "never assigned, could be value parameter";
}
break; break;
case D_USED: case D_USED:
warning = "never assigned"; warning = "never assigned";
break; break;
case D_VALPAR:
case D_DEFINED: case D_DEFINED:
case D_DEFINED|D_VALPAR: case D_DEFINED|D_VALPAR:
warning = "never used"; warning = "never used";
@ -924,7 +996,10 @@ warn:
"%s \"%s\" %s", "%s \"%s\" %s",
(df->df_flags & D_VALPAR) ? "value parameter" : (df->df_flags & D_VALPAR) ? "value parameter" :
(df->df_flags & D_VARPAR) ? "variable parameter" : (df->df_flags & D_VARPAR) ? "variable parameter" :
"identifier", (df->df_kind == D_VARIABLE) ? "variable" :
(df->df_kind == D_TYPE) ? "type" :
(df->df_kind == D_CONST) ? "constant" :
"procedure",
df->df_idf->id_text, warning); df->df_idf->id_text, warning);
} }
} }

View file

@ -14,7 +14,7 @@
extern int (*WalkTable[])(); extern int (*WalkTable[])();
#define WalkNode(xnd, xlab) (*WalkTable[(xnd)->nd_class])((xnd), (xlab)) #define WalkNode(xnd, xlab, rch) (*WalkTable[(xnd)->nd_class])((xnd), (xlab),(rch))
extern label text_label; extern label text_label;
extern label data_label; extern label data_label;