ack/lang/pc/comp/label.c
1989-05-03 10:30:22 +00:00

169 lines
3.4 KiB
C

/* L A B E L H A N D L I N G */
#include <alloc.h>
#include <em.h>
#include "LLlex.h"
#include "def.h"
#include "idf.h"
#include "main.h"
#include "node.h"
#include "scope.h"
#include "type.h"
DeclLabel(nd)
struct node *nd;
{
struct def *df;
if( !(df = define(nd->nd_IDF, CurrentScope, D_LABEL)) ) {
node_error(nd, "label %s redeclared", nd->nd_IDF->id_text);
}
else {
df->lab_no = ++text_label;
nd->nd_def = df;
}
}
chk_labels(Slevel)
{
register struct node *labnd = BlockScope->sc_lablist;
register struct def *df;
while( labnd ) {
df = labnd->nd_def;
if( Slevel == 1 ) {
if( !df->lab_level )
if( df->lab_next )
/* jump to undefined label */
error("jump to undefined label %s",
df->df_idf->id_text);
else
warning(
"label %s declared but never defined",
df->df_idf->id_text);
}
else if( df->lab_level == Slevel )
df->lab_level = -1;
else if( !df->lab_level ) {
struct lab *plab = df->lab_next;
while( plab ) {
if( plab->lb_level > 1 )
plab->lb_level--;
plab = plab->lb_next;
}
}
labnd = labnd->nd_next;
}
}
TstLabel(nd, Slevel)
register struct node *nd;
{
register struct def *df;
df = lookfor(nd, CurrVis, 0);
if( df->df_kind == D_ERROR ) {
node_error(nd, "label %s not declared", df->df_idf->id_text);
df->df_kind = D_LABEL;
nd->nd_def = df;
nd->nd_next = BlockScope->sc_lablist;
BlockScope->sc_lablist = nd;
}
else
FreeNode(nd);
df->df_flags = D_USED;
if( !df->lab_level ) {
/* forward jump */
register struct lab *labelptr;
labelptr = new_lab();
labelptr->lb_next = df->lab_next;
df->lab_next = labelptr;
if( df->df_scope == BlockScope ) {
/* local jump */
labelptr->lb_level = Slevel;
CodeLabel(df, 1);
}
else {
/* non-local jump, only permitted to
outermost level (ISO 6.8.1 Note 2)
*/
labelptr->lb_level = 1;
CodeLabel(df, 0);
}
}
else if( df->lab_level == -1 || df->lab_level > Slevel )
node_error(nd, "illegal jump to label %s", df->df_idf->id_text);
else
CodeLabel(df, 1);
}
DefLabel(nd, Slevel)
register struct node *nd;
{
register struct def *df;
if( !(df = lookup(nd->nd_IDF, BlockScope, D_INUSE)) ) {
node_error(nd, "label %s must be declared in same block"
, nd->nd_IDF->id_text);
df = define(nd->nd_IDF, BlockScope, D_LABEL);
nd->nd_def = df;
df->lab_no = ++text_label;
nd->nd_next = BlockScope->sc_lablist;
BlockScope->sc_lablist = nd;
}
else FreeNode(nd);
df->df_flags |= D_SET;
if( df->lab_level)
node_error(nd, "label %s already defined", nd->nd_IDF->id_text);
else {
register struct lab *labelptr;
df->lab_level = Slevel;
labelptr = df->lab_next;
while( labelptr ) {
if( labelptr->lb_level < Slevel ) {
node_error(nd, "illegal jump to label %s",
nd->nd_IDF->id_text);
return;
}
labelptr = labelptr->lb_next;
}
C_df_ilb(df->lab_no);
}
}
CodeLabel(df, local)
register struct def *df;
{
if( err_occurred ) return;
if( local )
C_bra(df->lab_no);
else {
/* non-local jump */
int level = df->df_scope->sc_level;
if( !df->lab_descr ) {
/* generate label for goto descriptor */
df->lab_descr = ++data_label;
C_ina_dlb(data_label);
}
/* perform the jump */
C_lae_dlb(df->lab_descr, (arith) 0);
/* LB of target procedure */
if( level > 0 )
C_lxl((arith) proclevel - level);
else
C_zer(pointer_size);
C_cal("_gto");
C_asp( 2 * pointer_size);
}
}