ack/lang/m2/comp/walk.c

904 lines
19 KiB
C
Raw Normal View History

/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*
* Author: Ceriel J.H. Jacobs
*/
1986-04-21 17:27:06 +00:00
/* P A R S E T R E E W A L K E R */
/* $Header$ */
1986-04-21 17:27:06 +00:00
/* Routines to walk through parts of the parse tree, and generate
code for these parts.
*/
1986-05-01 19:06:53 +00:00
#include "debug.h"
1986-04-21 17:27:06 +00:00
#include <em_arith.h>
#include <em_label.h>
1986-06-17 12:04:05 +00:00
#include <em_reg.h>
1986-07-08 14:59:02 +00:00
#include <em_code.h>
1987-07-13 10:30:37 +00:00
#include <m2_traps.h>
1986-04-21 17:27:06 +00:00
#include <assert.h>
#include <alloc.h>
1986-04-21 17:27:06 +00:00
#include "strict3rd.h"
#include "LLlex.h"
1986-04-21 17:27:06 +00:00
#include "def.h"
#include "type.h"
#include "scope.h"
#include "main.h"
#include "node.h"
1986-04-22 22:36:16 +00:00
#include "Lpars.h"
1986-05-16 17:15:36 +00:00
#include "desig.h"
1986-05-23 09:46:31 +00:00
#include "f_info.h"
1986-05-28 18:36:51 +00:00
#include "idf.h"
1986-06-17 12:04:05 +00:00
#include "chk_expr.h"
1986-06-20 14:36:49 +00:00
#include "walk.h"
#include "misc.h"
1986-11-05 14:33:00 +00:00
#include "warning.h"
1986-04-21 17:27:06 +00:00
extern arith NewPtr();
extern arith NewInt();
extern int proclevel;
label text_label;
label data_label = 1;
struct withdesig *WithDesigs;
t_node *Modules;
static t_type *func_type;
static arith priority;
1986-04-21 17:27:06 +00:00
static int RegisterMessage();
static int WalkDef();
static int MkCalls();
static int UseWarnings();
1986-09-25 19:39:06 +00:00
#define NO_EXIT_LABEL ((label) 0)
#define RETURN_LABEL ((label) 1)
LblWalkNode(lbl, nd, exit)
label lbl, exit;
register t_node *nd;
{
/* Generate code for node "nd", after generating instruction
label "lbl". "exit" is the exit label for the closest
enclosing LOOP.
*/
C_df_ilb(lbl);
WalkNode(nd, exit);
}
1986-12-01 10:06:53 +00:00
STATIC
DoPriority()
{
/* For the time being (???), handle priorities by calls to
the runtime system
*/
if (priority) {
C_loc(priority);
1986-12-01 10:06:53 +00:00
C_cal("_stackprio");
C_asp(word_size);
}
}
STATIC
EndPriority()
{
if (priority) {
C_cal("_unstackprio");
}
}
1986-06-17 12:04:05 +00:00
STATIC
1986-05-23 09:46:31 +00:00
DoProfil()
{
static label filename_label = 0;
1986-05-30 18:48:00 +00:00
if (! options['L']) {
1986-11-26 16:40:45 +00:00
if (! filename_label) {
filename_label = 1;
C_df_dlb((label) 1);
1986-06-04 09:01:48 +00:00
C_rom_scon(FileName, (arith) (strlen(FileName) + 1));
1986-05-23 09:46:31 +00:00
}
C_fil_dlb((label) 1, (arith) 0);
1986-05-23 09:46:31 +00:00
}
}
1986-04-21 17:27:06 +00:00
WalkModule(module)
register t_def *module;
1986-04-21 17:27:06 +00:00
{
/* Walk through a module, and all its local definitions.
Also generate code for its body.
1986-09-25 19:39:06 +00:00
This code is collected in an initialization routine.
1986-04-21 17:27:06 +00:00
*/
register t_scope *sc;
t_scopelist *savevis = CurrVis;
1986-04-21 17:27:06 +00:00
1986-04-28 18:06:58 +00:00
CurrVis = module->mod_vis;
priority = module->mod_priority ? module->mod_priority->nd_INT : 0;
1986-05-23 19:25:21 +00:00
sc = CurrentScope;
1986-04-22 22:36:16 +00:00
1986-06-26 09:39:36 +00:00
/* Walk through it's local definitions
1986-04-21 17:27:06 +00:00
*/
WalkDefList(sc->sc_def, WalkDef);
1986-04-21 17:27:06 +00:00
/* Now, generate initialization code for this module.
First call initialization routines for modules defined within
this module.
*/
1986-07-08 14:59:02 +00:00
sc->sc_off = 0; /* no locals (yet) */
1986-09-25 19:39:06 +00:00
text_label = 1; /* label at end of initialization routine */
1986-07-08 14:59:02 +00:00
TmpOpen(sc); /* Initialize for temporaries */
1986-06-26 09:39:36 +00:00
C_pro_narg(sc->sc_name);
1986-12-01 10:06:53 +00:00
DoPriority();
1986-05-23 09:46:31 +00:00
DoProfil();
1986-06-20 14:36:49 +00:00
if (module == Defined) {
1986-05-28 18:36:51 +00:00
/* Body of implementation or program module.
Call initialization routines of imported modules.
Also prevent recursive calls of this one.
*/
register t_node *nd = Modules;
1986-05-28 18:36:51 +00:00
1986-06-04 09:01:48 +00:00
if (state == IMPLEMENTATION) {
/* We don't actually prevent recursive calls,
1986-06-04 09:01:48 +00:00
but do nothing if called recursively
*/
1987-05-18 15:57:33 +00:00
C_df_dlb(++data_label);
C_con_cst((arith) 0);
1986-09-25 19:39:06 +00:00
/* if this one is set to non-zero, the initialization
was already done.
*/
1987-05-18 15:57:33 +00:00
C_loe_dlb(data_label, (arith) 0);
1986-09-25 19:39:06 +00:00
C_zne(RETURN_LABEL);
1987-05-18 15:57:33 +00:00
C_ine_dlb(data_label, (arith) 0);
1986-06-04 09:01:48 +00:00
}
1986-05-28 18:36:51 +00:00
1987-07-16 19:51:40 +00:00
for (; nd; nd = nd->nd_left) {
1986-05-28 18:36:51 +00:00
C_cal(nd->nd_IDF->id_text);
}
}
WalkDefList(sc->sc_def, MkCalls);
1986-05-28 18:36:51 +00:00
proclevel++;
1986-09-25 19:39:06 +00:00
WalkNode(module->mod_body, NO_EXIT_LABEL);
DO_DEBUG(options['X'], PrNode(module->mod_body, 0));
1986-09-25 19:39:06 +00:00
C_df_ilb(RETURN_LABEL);
1986-12-01 10:06:53 +00:00
EndPriority();
1986-05-28 18:36:51 +00:00
C_ret((arith) 0);
1986-05-23 19:25:21 +00:00
C_end(-sc->sc_off);
1986-05-28 18:36:51 +00:00
proclevel--;
1986-05-23 09:46:31 +00:00
TmpClose();
1986-04-21 17:27:06 +00:00
1986-06-26 09:39:36 +00:00
CurrVis = savevis;
WalkDefList(sc->sc_def, UseWarnings);
1986-04-21 17:27:06 +00:00
}
WalkProcedure(procedure)
register t_def *procedure;
1986-04-21 17:27:06 +00:00
{
/* Walk through the definition of a procedure and all its
1986-06-26 09:39:36 +00:00
local definitions, checking and generating code.
1986-04-21 17:27:06 +00:00
*/
t_scopelist *savevis = CurrVis;
register t_scope *sc = procedure->prc_vis->sc_scope;
register t_type *tp;
register t_param *param;
1986-06-20 14:36:49 +00:00
label func_res_label = 0;
1986-09-25 19:39:06 +00:00
arith StackAdjustment = 0;
1986-08-26 14:33:24 +00:00
arith retsav = 0;
1986-09-25 19:39:06 +00:00
arith func_res_size = 0;
1986-04-21 17:27:06 +00:00
1986-05-16 17:15:36 +00:00
proclevel++;
1986-04-28 18:06:58 +00:00
CurrVis = procedure->prc_vis;
1986-06-26 09:39:36 +00:00
1986-06-20 14:36:49 +00:00
/* Generate code for all local modules and procedures
*/
WalkDefList(sc->sc_def, WalkDef);
1986-04-21 17:27:06 +00:00
/* Generate code for this procedure
*/
1986-05-23 19:25:21 +00:00
C_pro_narg(sc->sc_name);
1986-12-01 10:06:53 +00:00
DoPriority();
1986-05-23 09:46:31 +00:00
DoProfil();
1986-07-08 14:59:02 +00:00
TmpOpen(sc);
1986-06-20 14:36:49 +00:00
1986-11-05 14:33:00 +00:00
func_type = tp = RemoveEqual(ResultType(procedure->df_type));
1986-08-26 14:33:24 +00:00
1987-07-13 10:30:37 +00:00
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);
}
1986-08-26 14:33:24 +00:00
}
1986-06-20 14:36:49 +00:00
/* Generate calls to initialization routines of modules defined within
1986-04-21 17:27:06 +00:00
this procedure
*/
WalkDefList(sc->sc_def, MkCalls);
1986-06-20 14:36:49 +00:00
/* Make sure that arguments of size < word_size are on a
fixed place.
1986-08-26 14:33:24 +00:00
Also make copies of conformant arrays when neccessary.
1986-06-20 14:36:49 +00:00
*/
for (param = ParamList(procedure->df_type);
param;
1987-07-16 19:51:40 +00:00
param = param->par_next) {
1986-06-20 14:36:49 +00:00
if (! IsVarParam(param)) {
tp = TypeOfParam(param);
1986-06-20 14:36:49 +00:00
if (! IsConformantArray(tp)) {
if (tp->tp_size < word_size &&
(int) word_size % (int) tp->tp_size == 0) {
1986-08-26 14:33:24 +00:00
C_lol(param->par_def->var_off);
C_lal(param->par_def->var_off);
C_sti(tp->tp_size);
1986-08-26 14:33:24 +00:00
}
}
else {
/* Here, we have to make a copy of the
array. We must also remember how much
room is reserved for copies, because
we have to adjust the stack pointer before
a RET is done. This is even more complicated
when the procedure returns a value.
Then, the value must be saved (in retval),
the stack adjusted, the return value pushed
again, and then RET
*/
1986-09-25 19:39:06 +00:00
if (! StackAdjustment) {
/* First time we get here
*/
if (func_type && !func_res_label) {
1986-08-26 14:33:24 +00:00
/* Some local space, only
needed if the value itself
is returned
*/
1986-09-25 19:39:06 +00:00
sc->sc_off -= func_res_size;
1986-08-26 14:33:24 +00:00
retsav = sc->sc_off;
}
1987-06-23 17:12:25 +00:00
StackAdjustment = NewPtr();
C_lor((arith) 1);
1986-09-25 19:39:06 +00:00
C_stl(StackAdjustment);
1986-08-26 14:33:24 +00:00
}
1987-06-23 17:12:25 +00:00
/* First compute new stackpointer */
C_lal(param->par_def->var_off);
C_cal("_new_stackptr");
C_asp(pointer_size);
C_lfr(pointer_size);
C_str((arith) 1);
1986-08-26 14:33:24 +00:00
/* adjusted stack pointer */
C_lol(param->par_def->var_off);
1986-08-26 14:33:24 +00:00
/* push source address */
1987-06-23 17:12:25 +00:00
C_cal("_copy_array");
/* copy */
C_asp(word_size);
1986-06-20 14:36:49 +00:00
}
}
1986-05-28 18:36:51 +00:00
}
1986-06-20 14:36:49 +00:00
1986-09-25 19:39:06 +00:00
text_label = 1; /* label at end of procedure */
1986-06-20 14:36:49 +00:00
1986-09-25 19:39:06 +00:00
WalkNode(procedure->prc_body, NO_EXIT_LABEL);
DO_DEBUG(options['X'], PrNode(procedure->prc_body, 0));
1987-07-13 10:30:37 +00:00
if (func_res_size) {
c_loc(M2_NORESULT);
1987-07-13 10:30:37 +00:00
C_trp();
C_asp(-func_res_size);
}
1986-09-25 19:39:06 +00:00
C_df_ilb(RETURN_LABEL); /* label at end */
1986-08-26 14:33:24 +00:00
if (func_res_label) {
1986-09-25 19:39:06 +00:00
/* Fill the data area reserved for the function result
with the result
*/
c_lae_dlb(func_res_label);
1987-07-13 10:30:37 +00:00
C_sti(func_res_size);
1986-09-25 19:39:06 +00:00
if (StackAdjustment) {
/* Remove copies of conformant arrays
*/
C_lol(StackAdjustment);
1987-06-23 17:12:25 +00:00
C_str((arith) 1);
1986-05-14 09:03:51 +00:00
}
c_lae_dlb(func_res_label);
func_res_size = pointer_size;
1986-05-14 09:03:51 +00:00
}
1987-06-23 17:12:25 +00:00
else if (StackAdjustment) {
/* First save the function result in a safe place.
Then remove copies of conformant arrays,
and put function result back on the stack
*/
if (func_type) {
1986-08-26 14:33:24 +00:00
C_lal(retsav);
1986-09-25 19:39:06 +00:00
C_sti(func_res_size);
1987-06-23 17:12:25 +00:00
}
C_lol(StackAdjustment);
C_str((arith) 1);
if (func_type) {
1986-08-26 14:33:24 +00:00
C_lal(retsav);
1986-09-25 19:39:06 +00:00
C_loi(func_res_size);
1986-08-26 14:33:24 +00:00
}
1987-06-23 17:12:25 +00:00
FreePtr(StackAdjustment);
1986-08-26 14:33:24 +00:00
}
1987-06-23 17:12:25 +00:00
EndPriority();
C_ret(func_res_size);
if (! options['n']) WalkDefList(sc->sc_def, RegisterMessage);
1986-05-23 19:25:21 +00:00
C_end(-sc->sc_off);
1986-05-23 09:46:31 +00:00
TmpClose();
1986-06-20 14:36:49 +00:00
CurrVis = savevis;
1986-05-16 17:15:36 +00:00
proclevel--;
WalkDefList(sc->sc_def, UseWarnings);
1986-04-21 17:27:06 +00:00
}
static int
1986-04-21 17:27:06 +00:00
WalkDef(df)
register t_def *df;
1986-04-21 17:27:06 +00:00
{
/* Walk through a list of definitions
*/
1986-04-28 18:06:58 +00:00
switch(df->df_kind) {
case D_MODULE:
WalkModule(df);
break;
case D_PROCEDURE:
WalkProcedure(df);
break;
case D_VARIABLE:
if (!proclevel && !(df->df_flags & D_ADDRGIVEN)) {
C_df_dnam(df->var_name);
C_bss_cst(
WA(df->df_type->tp_size),
(arith) 0, 0);
1986-04-21 17:27:06 +00:00
}
break;
default:
/* nothing */
;
1986-04-21 17:27:06 +00:00
}
}
static int
1986-04-21 17:27:06 +00:00
MkCalls(df)
register t_def *df;
1986-04-21 17:27:06 +00:00
{
/* Generate calls to initialization routines of modules
*/
1986-04-28 18:06:58 +00:00
if (df->df_kind == D_MODULE) {
C_lxl((arith) 0);
C_cal(df->mod_vis->sc_scope->sc_name);
C_asp(pointer_size);
1986-04-21 17:27:06 +00:00
}
}
1986-09-25 19:39:06 +00:00
WalkLink(nd, exit_label)
register t_node *nd;
1986-09-25 19:39:06 +00:00
label exit_label;
1986-04-21 17:27:06 +00:00
{
1986-06-20 14:36:49 +00:00
/* Walk node "nd", which is a link.
1986-04-22 22:36:16 +00:00
*/
1986-04-28 18:06:58 +00:00
1986-06-20 14:36:49 +00:00
while (nd && nd->nd_class == Link) { /* statement list */
1986-09-25 19:39:06 +00:00
WalkNode(nd->nd_left, exit_label);
1986-04-22 22:36:16 +00:00
nd = nd->nd_right;
}
1986-09-25 19:39:06 +00:00
WalkNode(nd, exit_label);
1986-06-20 14:36:49 +00:00
}
STATIC
ForLoopVarExpr(nd)
register t_node *nd;
{
register t_type *tp = nd->nd_type;
CodePExpr(nd);
CodeCoercion(tp, BaseType(tp));
}
1986-09-25 19:39:06 +00:00
WalkStat(nd, exit_label)
register t_node *nd;
1986-09-25 19:39:06 +00:00
label exit_label;
1986-04-22 22:36:16 +00:00
{
/* Walk through a statement, generating code for it.
*/
register t_node *left = nd->nd_left;
register t_node *right = nd->nd_right;
1986-05-23 09:46:31 +00:00
1986-04-22 22:36:16 +00:00
assert(nd->nd_class == Stat);
if (! options['L'] && nd->nd_lineno) C_lin((arith) nd->nd_lineno);
1986-04-22 22:36:16 +00:00
switch(nd->nd_symb) {
case '(':
if (ChkCall(nd)) {
if (nd->nd_type != 0) {
node_error(nd, "procedure call expected");
break;
}
CodeCall(nd);
}
break;
case ';':
break;
1986-05-28 18:36:51 +00:00
case BECOMES:
DoAssign(left, right);
1986-04-22 22:36:16 +00:00
break;
case IF:
1986-10-06 20:36:30 +00:00
{ label l1 = ++text_label, l3 = ++text_label;
1986-04-22 22:36:16 +00:00
1986-05-21 18:32:20 +00:00
ExpectBool(left, l3, l1);
1986-04-22 22:36:16 +00:00
assert(right->nd_symb == THEN);
LblWalkNode(l3, right->nd_left, exit_label);
1986-04-22 22:36:16 +00:00
if (right->nd_right) { /* ELSE part */
1986-10-06 20:36:30 +00:00
label l2 = ++text_label;
1986-04-22 22:36:16 +00:00
C_bra(l2);
LblWalkNode(l1, right->nd_right, exit_label);
l1 = l2;
1986-04-22 22:36:16 +00:00
}
C_df_ilb(l1);
1986-04-22 22:36:16 +00:00
break;
}
case CASE:
1986-09-25 19:39:06 +00:00
CaseCode(nd, exit_label);
1986-05-01 19:06:53 +00:00
break;
1986-04-22 22:36:16 +00:00
case WHILE:
1986-10-06 20:36:30 +00:00
{ label loop = ++text_label,
exit = ++text_label,
dummy = ++text_label;
1986-04-22 22:36:16 +00:00
1986-10-06 20:36:30 +00:00
C_df_ilb(loop);
ExpectBool(left, dummy, exit);
LblWalkNode(dummy, right, exit_label);
1986-10-06 20:36:30 +00:00
C_bra(loop);
C_df_ilb(exit);
1986-04-22 22:36:16 +00:00
break;
}
case REPEAT:
1986-10-06 20:36:30 +00:00
{ label loop = ++text_label, exit = ++text_label;
1986-04-22 22:36:16 +00:00
LblWalkNode(loop, left, exit_label);
1986-10-06 20:36:30 +00:00
ExpectBool(right, exit, loop);
C_df_ilb(exit);
1986-04-22 22:36:16 +00:00
break;
}
case LOOP:
1986-10-06 20:36:30 +00:00
{ label loop = ++text_label, exit = ++text_label;
1986-04-22 22:36:16 +00:00
LblWalkNode(loop, right, exit);
1986-10-06 20:36:30 +00:00
C_bra(loop);
C_df_ilb(exit);
1986-04-22 22:36:16 +00:00
break;
}
case FOR:
1986-05-28 18:36:51 +00:00
{
1987-09-14 11:24:12 +00:00
arith tmp = NewInt();
arith tmp2;
register t_node *fnd;
1986-11-26 16:40:45 +00:00
int good_forvar;
1986-06-20 14:36:49 +00:00
label l1 = ++text_label;
label l2 = ++text_label;
int uns = 0;
1987-08-10 13:01:54 +00:00
arith stepsize;
t_type *bstp;
1986-05-28 18:36:51 +00:00
1987-08-10 13:01:54 +00:00
good_forvar = DoForInit(nd);
if ((stepsize = left->nd_INT) == 0) {
node_warning(left,
W_ORDINARY,
"zero stepsize in FOR loop");
1987-08-10 13:01:54 +00:00
}
1986-05-28 18:36:51 +00:00
fnd = left->nd_right;
1986-11-26 16:40:45 +00:00
if (good_forvar) {
bstp = BaseType(nd->nd_type);
uns = bstp->tp_fund != T_INTEGER;
C_dup(int_size);
CodeDStore(nd);
1987-08-10 13:01:54 +00:00
CodePExpr(fnd);
C_stl(tmp);
C_lol(tmp);
if (uns) C_cmu(int_size);
else C_cmi(int_size);
1987-08-10 13:01:54 +00:00
if (left->nd_INT >= 0) {
C_zgt(l2);
1987-08-10 13:01:54 +00:00
C_lol(tmp);
ForLoopVarExpr(nd);
}
1987-08-10 13:01:54 +00:00
else {
stepsize = -stepsize;
1987-08-10 13:01:54 +00:00
C_zlt(l2);
ForLoopVarExpr(nd);
1987-08-10 13:01:54 +00:00
C_lol(tmp);
}
C_sbu(int_size);
if (stepsize) {
C_loc(stepsize);
C_dvu(int_size);
}
C_stl(tmp);
1987-08-10 13:01:54 +00:00
nd->nd_def->df_flags |= D_FORLOOP;
C_df_ilb(l1);
1987-09-14 12:41:08 +00:00
if (! options['R']) {
tmp2 = NewInt();
ForLoopVarExpr(nd);
C_stl(tmp2);
}
1987-09-14 11:24:12 +00:00
}
1986-09-25 19:39:06 +00:00
WalkNode(right, exit_label);
1987-08-10 13:01:54 +00:00
nd->nd_def->df_flags &= ~D_FORLOOP;
1987-09-14 12:41:08 +00:00
if (good_forvar) {
if (! options['R']) {
1987-11-09 10:17:20 +00:00
label x = ++text_label;
1987-09-14 12:41:08 +00:00
C_lol(tmp2);
ForLoopVarExpr(nd);
1987-11-09 10:17:20 +00:00
C_beq(x);
c_loc(M2_FORCH);
C_trp();
C_df_ilb(x);
1987-09-14 12:41:08 +00:00
FreeInt(tmp2);
}
if (stepsize) {
C_lol(tmp);
C_zeq(l2);
C_lol(tmp);
c_loc(1);
1987-09-14 12:41:08 +00:00
C_sbu(int_size);
C_stl(tmp);
C_loc(left->nd_INT);
ForLoopVarExpr(nd);
C_adu(int_size);
RangeCheck(nd->nd_type, bstp);
CodeDStore(nd);
}
1986-11-26 16:40:45 +00:00
}
1987-08-10 13:01:54 +00:00
C_bra(l1);
C_df_ilb(l2);
FreeInt(tmp);
#ifdef DEBUG
nd->nd_left = left;
nd->nd_right = right;
#endif
1986-05-28 18:36:51 +00:00
}
1986-04-22 22:36:16 +00:00
break;
case WITH:
1986-04-28 18:06:58 +00:00
{
t_scopelist link;
1986-05-16 17:15:36 +00:00
struct withdesig wds;
t_desig ds;
1986-04-28 18:06:58 +00:00
if (! WalkDesignator(left, &ds, D_USED|D_DEFINED)) break;
1986-04-28 18:06:58 +00:00
if (left->nd_type->tp_fund != T_RECORD) {
node_error(left, "record variable expected");
break;
}
1986-05-16 17:15:36 +00:00
wds.w_next = WithDesigs;
WithDesigs = &wds;
wds.w_scope = left->nd_type->rec_scope;
1986-07-08 14:59:02 +00:00
CodeAddress(&ds);
ds.dsg_kind = DSG_FIXED;
1986-09-25 19:39:06 +00:00
/* Create a designator structure for the temporary.
1986-07-08 14:59:02 +00:00
*/
1986-10-06 20:36:30 +00:00
ds.dsg_offset = NewPtr();
1986-07-08 14:59:02 +00:00
ds.dsg_name = 0;
1987-06-23 17:12:25 +00:00
CodeStore(&ds, address_type);
1986-07-08 14:59:02 +00:00
ds.dsg_kind = DSG_PFIXED;
/* the record is indirectly available */
1986-06-17 12:04:05 +00:00
wds.w_desig = ds;
1986-05-16 17:15:36 +00:00
link.sc_scope = wds.w_scope;
1987-07-16 19:51:40 +00:00
link.sc_next = CurrVis;
1986-04-28 18:06:58 +00:00
CurrVis = &link;
1986-09-25 19:39:06 +00:00
WalkNode(right, exit_label);
1987-07-16 19:51:40 +00:00
CurrVis = link.sc_next;
1986-05-16 17:15:36 +00:00
WithDesigs = wds.w_next;
1986-10-06 20:36:30 +00:00
FreePtr(ds.dsg_offset);
1986-04-28 18:06:58 +00:00
break;
}
1986-04-22 22:36:16 +00:00
case EXIT:
1986-09-25 19:39:06 +00:00
assert(exit_label != 0);
1986-04-22 22:36:16 +00:00
1986-09-25 19:39:06 +00:00
C_bra(exit_label);
1986-04-22 22:36:16 +00:00
break;
case RETURN:
1986-04-23 22:12:22 +00:00
if (right) {
1986-11-26 16:40:45 +00:00
if (! ChkExpression(right)) break;
1986-06-20 14:36:49 +00:00
/* The type of the return-expression must be
assignment compatible with the result type of the
function procedure (See Rep. 9.11).
1986-04-28 18:06:58 +00:00
*/
if (!ChkAssCompat(&(nd->nd_right), func_type, "RETURN")) {
1986-11-26 16:40:45 +00:00
break;
1986-04-23 22:12:22 +00:00
}
right = nd->nd_right;
1986-11-26 16:40:45 +00:00
if (right->nd_type->tp_fund == T_STRING) {
1986-12-01 10:06:53 +00:00
CodePString(right, func_type);
1986-11-26 16:40:45 +00:00
}
else CodePExpr(right);
1986-04-23 22:12:22 +00:00
}
1986-09-25 19:39:06 +00:00
C_bra(RETURN_LABEL);
1986-04-22 22:36:16 +00:00
break;
default:
1986-06-17 12:04:05 +00:00
crash("(WalkStat)");
1986-04-22 22:36:16 +00:00
}
}
1986-06-20 14:36:49 +00:00
extern int NodeCrash();
STATIC
WalkOption(nd)
t_node *nd;
{
1987-08-20 13:12:43 +00:00
/* Set option indicated by node "nd"
*/
1987-08-20 13:12:43 +00:00
options[nd->nd_symb] = nd->nd_INT;
}
1986-06-20 14:36:49 +00:00
int (*WalkTable[])() = {
NodeCrash,
NodeCrash,
NodeCrash,
NodeCrash,
NodeCrash,
NodeCrash,
1986-06-20 14:36:49 +00:00
NodeCrash,
NodeCrash,
NodeCrash,
NodeCrash,
WalkStat,
WalkLink,
WalkOption
1986-06-20 14:36:49 +00:00
};
1986-05-21 18:32:20 +00:00
ExpectBool(nd, true_label, false_label)
register t_node *nd;
1986-05-21 18:32:20 +00:00
label true_label, false_label;
1986-04-22 22:36:16 +00:00
{
/* "nd" must indicate a boolean expression. Check this and
generate code to evaluate the expression.
*/
register t_desig *ds = new_desig();
1986-04-22 22:36:16 +00:00
if (ChkExpression(nd)) {
if (nd->nd_type != bool_type && nd->nd_type != error_type) {
node_error(nd, "boolean expression expected");
}
1986-04-22 22:36:16 +00:00
CodeExpr(nd, ds, true_label, false_label);
1986-04-22 22:36:16 +00:00
}
free_desig(ds);
1986-04-23 22:12:22 +00:00
}
1986-08-26 14:33:24 +00:00
int
WalkDesignator(nd, ds, flags)
t_node *nd;
t_desig *ds;
1986-04-25 10:14:08 +00:00
{
/* Check designator and generate code for it
*/
if (! ChkVariable(nd, flags)) return 0;
1986-05-01 19:06:53 +00:00
clear((char *) ds, sizeof(t_desig));
1986-06-17 12:04:05 +00:00
CodeDesig(nd, ds);
1986-08-26 14:33:24 +00:00
return 1;
1986-05-30 18:48:00 +00:00
}
1987-08-10 13:01:54 +00:00
DoForInit(nd)
register t_node *nd;
1986-05-30 18:48:00 +00:00
{
register t_node *left = nd->nd_left;
register t_def *df;
t_type *tpl, *tpr;
1986-05-28 18:36:51 +00:00
1986-05-30 18:48:00 +00:00
nd->nd_left = nd->nd_right = 0;
nd->nd_class = Name;
nd->nd_symb = IDENT;
if (!( ChkVariable(nd, D_USED|D_DEFINED) &
ChkExpression(left->nd_left) &
ChkExpression(left->nd_right))) return 0;
1986-05-30 18:48:00 +00:00
1986-06-20 14:36:49 +00:00
df = nd->nd_def;
if (df->df_kind == D_FIELD) {
1986-10-06 20:36:30 +00:00
node_error(nd,
"FOR-loop variable may not be a field of a record");
1986-11-26 16:40:45 +00:00
return 1;
1986-06-20 14:36:49 +00:00
}
if (!df->var_name && df->var_off >= 0) {
node_error(nd, "FOR-loop variable may not be a parameter");
1986-11-26 16:40:45 +00:00
return 1;
1986-06-20 14:36:49 +00:00
}
if (df->df_scope != CurrentScope) {
register t_scopelist *sc = CurrVis;
1986-06-20 14:36:49 +00:00
1986-10-06 20:36:30 +00:00
for (;;) {
if (!sc) {
node_error(nd,
"FOR-loop variable may not be imported");
1986-11-26 16:40:45 +00:00
return 1;
1986-10-06 20:36:30 +00:00
}
if (sc->sc_scope == df->df_scope) break;
1986-06-20 14:36:49 +00:00
sc = nextvisible(sc);
}
}
if (df->df_type->tp_size > word_size ||
!(df->df_type->tp_fund & T_DISCRETE)) {
1986-05-30 18:48:00 +00:00
node_error(nd, "illegal type of FOR loop variable");
1986-11-26 16:40:45 +00:00
return 1;
1986-05-30 18:48:00 +00:00
}
tpl = left->nd_left->nd_type;
tpr = left->nd_right->nd_type;
#ifndef STRICT_3RD_ED
if (! options['3']) {
if (!ChkAssCompat(&(left->nd_left), df->df_type, "FOR statement") ||
!ChkAssCompat(&(left->nd_right), BaseType(df->df_type), "FOR statement")) {
return 1;
}
if (!TstCompat(df->df_type, tpl) ||
!TstCompat(df->df_type, tpr)) {
1986-11-05 14:33:00 +00:00
node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement");
}
} else
#endif
if (!ChkCompat(&(left->nd_left), df->df_type, "FOR statement") ||
!ChkCompat(&(left->nd_right), BaseType(df->df_type), "FOR statement")) {
return 1;
1986-05-30 18:48:00 +00:00
}
CodePExpr(left->nd_left);
1986-06-06 02:22:09 +00:00
return 1;
1986-05-28 18:36:51 +00:00
}
DoAssign(left, right)
register t_node *left;
t_node *right;
1986-05-28 18:36:51 +00:00
{
1986-09-25 19:39:06 +00:00
/* May we do it in this order (expression first) ???
The reference manual sais nothing about it, but the book does:
it sais that the left hand side is evaluated first.
1986-10-06 20:36:30 +00:00
DAMN THE BOOK!
1986-09-25 19:39:06 +00:00
*/
register t_desig *dsr;
register t_type *tp;
1986-05-28 18:36:51 +00:00
if (! (ChkExpression(right) & ChkVariable(left, D_DEFINED))) return;
1987-08-03 09:09:07 +00:00
tp = left->nd_type;
1986-10-06 20:36:30 +00:00
1987-08-03 09:09:07 +00:00
if (right->nd_symb == STRING) TryToString(right, tp);
1986-05-28 18:36:51 +00:00
1987-08-03 09:09:07 +00:00
if (! ChkAssCompat(&right, tp, "assignment")) {
1986-05-28 18:36:51 +00:00
return;
}
dsr = new_desig();
1986-05-28 18:36:51 +00:00
#define StackNeededFor(ds) ((ds)->dsg_kind == DSG_PLOADED \
|| (ds)->dsg_kind == DSG_INDEXED)
1987-08-03 09:09:07 +00:00
CodeExpr(right, dsr, NO_LABEL, NO_LABEL);
tp = right->nd_type;
if (complex(tp)) {
if (StackNeededFor(dsr)) CodeAddress(dsr);
}
1986-05-28 18:36:51 +00:00
else {
1987-08-03 09:09:07 +00:00
CodeValue(dsr, tp);
1986-05-28 18:36:51 +00:00
}
1987-08-03 09:09:07 +00:00
CodeMove(dsr, left, tp);
free_desig(dsr);
1986-06-17 12:04:05 +00:00
}
static int
RegisterMessage(df)
register t_def *df;
1986-06-17 12:04:05 +00:00
{
register t_type *tp;
1987-09-14 11:24:12 +00:00
arith sz;
int regtype;
1986-05-28 18:36:51 +00:00
if (df->df_kind == D_VARIABLE) {
if ( !(df->df_flags & D_NOREG)) {
1986-06-17 12:04:05 +00:00
/* Examine type and size
*/
regtype = -1;
1986-06-26 09:39:36 +00:00
tp = BaseType(df->df_type);
if ((df->df_flags & D_VARPAR) ||
(tp->tp_fund&(T_POINTER|T_HIDDEN|T_EQUAL))) {
1987-09-14 11:24:12 +00:00
sz = pointer_size;
regtype = reg_pointer;
1986-06-26 09:39:36 +00:00
}
1986-09-25 19:39:06 +00:00
else if (tp->tp_fund & T_NUMERIC) {
1987-09-14 11:24:12 +00:00
sz = tp->tp_size;
regtype = tp->tp_fund == T_REAL ?
reg_float : reg_any;
}
if (regtype >= 0) {
C_ms_reg(df->var_off, sz, regtype, 0);
1986-06-17 12:04:05 +00:00
}
}
}
1986-04-25 10:14:08 +00:00
}
static int
UseWarnings(df)
register t_def *df;
{
if (is_anon_idf(df->df_idf)) return;
if (df->df_kind & (D_IMPORTED | D_VARIABLE | D_PROCEDURE)) {
struct node *nd;
if (df->df_flags & (D_EXPORTED | D_QEXPORTED)) return;
if (df->df_kind & D_IMPORTED) {
register t_def *df1 = df->imp_def;
df1->df_flags |= df->df_flags & (D_USED|D_DEFINED);
if (df->df_kind == D_INUSE) return;
if ( !(df->df_flags & D_IMP_BY_EXP)) {
if (! (df->df_flags & (D_USED | D_DEFINED))) {
node_warning(
df->df_scope->sc_end,
W_ORDINARY,
"identifier \"%s\" imported but not used/assigned",
df->df_idf->id_text);
}
return;
}
df = df1;
}
if (! (df->df_kind & (D_VARIABLE|D_PROCEDURE))) return;
nd = df->df_scope->sc_end;
if (! (df->df_flags & D_DEFINED)) {
node_warning(nd,
W_ORDINARY,
"identifier \"%s\" never assigned",
df->df_idf->id_text);
}
if (! (df->df_flags & D_USED)) {
node_warning(nd,
W_ORDINARY,
"identifier \"%s\" never used",
df->df_idf->id_text);
}
}
}
WalkDefList(df, proc)
register t_def *df;
int (*proc)();
{
for (; df; df = df->df_nextinscope) {
(*proc)(df);
}
}