/* Copyright (c) 1979 Regents of the University of California */
static char sccsid
[] = "@(#)stat.c 1.13 %G%";
register struct tnode
*sl
;
for (sl
=r
; sl
!= TR_NIL
; sl
=sl
->list_node
.next
)
statement(sl
->list_node
.list
);
register struct tnode
*tree_node
;
register struct nl
*snlp
;
soffset
= sizes
[cbn
].curtmps
;
line
= tree_node
->lined
.line_no
;
if (tree_node
->tag
== T_LABEL
) {
labeled(tree_node
->label_node
.lbl_ptr
);
tree_node
= tree_node
->label_node
.stmnt
;
error("Unreachable statement");
switch (tree_node
->tag
) {
asgnop(&(tree_node
->asg_node
));
gotoop(tree_node
->goto_node
.lbl_ptr
);
switch (tree_node
->tag
) {
ifop(&(tree_node
->if_node
));
whilop(&(tree_node
->whi_cas
));
repop(&(tree_node
->repeat
));
statlist(tree_node
->stmnt_blck
.stmnt_list
);
caseop(&(tree_node
->whi_cas
));
pccaseop(&(tree_node
->whi_cas
));
withop(&(tree_node
->with_node
));
* Free the temporary name list entries defined in
* expressions, e.g. STRs, and WITHPTRs from withs.
* free any temporaries allocated for this statement
* these come from strings and sets.
for (p
= gotos
[cbn
]; p
!= NLNIL
; p
= p
->chain
)
if ((p
->nl_flags
& NFORWD
) != 0) {
if (p
->value
[NL_GOLEV
] != NOTYET
)
if (p
->value
[NL_GOLEV
] > level
)
p
->value
[NL_GOLEV
] = level
;
if (p
->value
[NL_GOLEV
] != DEAD
)
if (p
->value
[NL_GOLEV
] > level
)
p
->value
[NL_GOLEV
] = DEAD
;
(void) put(2, O_COUNT
, counter
);
putRV( PCPCOUNT
, 0 , counter
* sizeof (long) , NGLOBAL
, P2INT
);
putleaf( P2ICON
, 1 , 0 , P2INT
, (char *) 0 );
putop( P2ASG P2PLUS
, P2INT
);
putdot( filename
, line
);
(void) put(2, O_LINO
, line
);
* put out line number information for pdx
if ( line
!= lastline
) {
putleaf( P2ICON
, 0 , 0 , ADDTYPE( P2FTN
| P2INT
, P2PTR
)
putop( P2UNARY P2CALL
, P2INT
);
putdot( filename
, line
);
putRV( STMTCOUNT
, 0 , 0 , NGLOBAL
, P2INT
);
putleaf( P2ICON
, 1 , 0 , P2INT
, (char *) 0 );
putop( P2ASG P2PLUS
, P2INT
);
putdot( filename
, line
);
* With statement requires an extra word
* in automatic storage for each level of withing.
* These indirect pointers are initialized here, and
* the scoping effect of the with statement occurs
* because lookup examines the field names of the records
* associated with the WITHPTRs on the withlist.
register struct tnode
*p
;
* no one uses the allocated temporary namelist entry,
* since we have to use it before we know its type;
* but we use its runtime location for the with pointer.
(void) put(2, O_LV
| cbn
<<8+INDX
, tempnlp
-> value
[ NL_OFFS
] );
putRV( (char *) 0 , cbn
, tempnlp
-> value
[ NL_OFFS
] ,
tempnlp
-> extra_flags
, P2PTR
|P2STRTY
);
r
= lvalue(p
->list_node
.list
, MOD
, LREQ
);
if (r
->class != RECORD
) {
error("Variable in with statement refers to %s, not to a record", nameof(r
));
r
= defnl((char *) 0, WITHPTR
, r
, tempnlp
-> value
[ NL_OFFS
] );
r
-> extra_flags
|= tempnlp
-> extra_flags
;
putop( P2ASSIGN
, P2PTR
|P2STRTY
);
putdot( filename
, line
);
register struct tnode
*av
;
* Asgnop's only function is
* to handle function variable
* assignments. All other assignment
* stuff is handled by asgnop1.
* the if below checks for unqualified lefthandside:
if (av
!= TR_NIL
&& av
->tag
== T_VAR
&& av
->var_node
.qual
== TR_NIL
) {
p
= lookup1(av
->var_node
.cptr
);
if (p
!= NLNIL
&& p
->class == FVAR
) {
p
->nl_flags
|= NUSED
|NMOD
;
p
= rvalue(r
->rhs_expr
, NLNIL
, RREQ
);
(void) put(2, O_LV
| bn
<< 8+INDX
, (int)p
->value
[NL_OFFS
]);
if (isa(p
->type
, "i") && width(p
->type
) == 1)
(void) asgnop1(r
, nl
+T2INT
);
(void) asgnop1(r
, p
->type
);
* this should be the lvalue of the fvar,
* but since the second pass knows to use
* the address of the left operand of an
* assignment, what i want here is an rvalue.
* see note in funchdr about fvar allocation.
putRV( p
-> symbol
, bn
, p
-> value
[ NL_OFFS
] ,
p
-> extra_flags
, p2type( p
-> type
) );
(void) asgnop1( r
, p
-> type
);
(void) asgnop1(r
, NLNIL
);
* Asgnop1 handles all assignments.
* If p is not nil then we are assigning
* to a function variable, otherwise
* we look the variable up ourselves.
p
= lvalue(r
->lhs_var
, MOD
|ASGN
|NOUSE
, LREQ
);
* since the second pass knows that it should reference
* the lefthandside of asignments, what i need here is
p
= lvalue( r
->lhs_var
, MOD
|ASGN
|NOUSE
, RREQ
);
(void) rvalue( r
->rhs_expr
, NLNIL
, RREQ
);
* assigning to the return value, which is at least
* of width two since it resides on the stack
p1
= rvalue(r
->rhs_expr
, p
, RREQ
);
* if this is a scalar assignment,
* then i want to rvalue the righthandside.
* if this is a structure assignment,
* then i want an lvalue to the righthandside.
* that's what the intermediate form sez.
switch ( classify( p
) ) {
precheck( p
, "_RANG4" , "_RSNG4" );
p1
= rvalue( r
->rhs_expr
, p
, RREQ
);
p1
= rvalue( r
->rhs_expr
, p
, LREQ
);
if (incompat(p1
, p
, r
->rhs_expr
)) {
cerror("Type of expression clashed with type of variable in assignment");
(void) gen(O_AS2
, O_AS2
, w
, width(p1
));
(void) gen(O_AS2
, O_AS2
, w
, width(p1
));
sconv(p2type(p1
), p2type(p
));
putop( P2ASSIGN
, p2type( p
) );
putdot( filename
, line
);
putop( P2ASSIGN
, p2type( p
) );
putdot( filename
, line
);
sconv(p2type(p1
), p2type(p
));
putop( P2ASSIGN
, p2type( p
) );
putdot( filename
, line
);
putstrop(P2STASG
, ADDTYPE(p2type(p
), P2PTR
),
(int) lwidth(p
), align(p
));
putdot( filename
, line
);
return (p
); /* Used by for statement */
* if expr then stat [ else stat ]
register l1
, l2
; /* l1 is start of else, l2 is end of else */
p
= rvalue(if_n
->cond_expr
, NLNIL
, RREQ
);
statement(if_n
->then_stmnt
);
statement(if_n
->else_stmnt
);
error("Type of expression in if statement must be Boolean, not %s", nameof(p
));
statement(if_n
->then_stmnt
);
statement(if_n
->else_stmnt
);
l1
= put(2, O_IF
, getlab());
putleaf( P2ICON
, l1
, 0 , P2INT
, (char *) 0 );
putop( P2CBRANCH
, P2INT
);
putdot( filename
, line
);
statement(if_n
->then_stmnt
);
if (if_n
->else_stmnt
!= TR_NIL
) {
l2
= put(2, O_TRA
, getlab());
statement(if_n
->else_stmnt
);
noreach
= (noreach
&& nr
)?TRUE
:FALSE
;
p
= rvalue(w_node
->expr
, NLNIL
, RREQ
);
statement(w_node
->stmnt_list
);
error("Type of expression in while statement must be Boolean, not %s", nameof(p
));
statement(w_node
->stmnt_list
);
putleaf( P2ICON
, (int) l2
, 0 , P2INT
, (char *) 0 );
putop( P2CBRANCH
, P2INT
);
putdot( filename
, line
);
statement(w_node
->stmnt_list
);
(void) put(2, O_TRA
, l1
);
* repeat stat* until expr
l
= (int) putlab(getlab());
p
= rvalue(r
->term_expr
, NLNIL
, RREQ
);
error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p
));
putleaf( P2ICON
, l
, 0 , P2INT
, (char *) 0 );
putop( P2CBRANCH
, P2INT
);
putdot( filename
, line
);