170 lines
3.5 KiB
C
170 lines
3.5 KiB
C
/* L A B E L H A N D L I N G */
|
|
|
|
#include <alloc.h>
|
|
#include <em.h>
|
|
|
|
#include "parameters.h"
|
|
#include "LLlex.h"
|
|
#include "def.h"
|
|
#include "idf.h"
|
|
#include "main.h"
|
|
#include "node.h"
|
|
#include "scope.h"
|
|
#include "type.h"
|
|
#include "label.h"
|
|
#include "error.h"
|
|
|
|
static void CodeLabel(register struct def *df, int local);
|
|
|
|
|
|
void DeclLabel(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;
|
|
}
|
|
}
|
|
|
|
void chk_labels(int 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 == Slevel )
|
|
plab->lb_level--;
|
|
plab = plab->lb_next;
|
|
}
|
|
}
|
|
labnd = labnd->nd_next;
|
|
}
|
|
}
|
|
|
|
void TstLabel(register struct node *nd, int Slevel)
|
|
{
|
|
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);
|
|
}
|
|
|
|
void DefLabel(register struct node *nd, int Slevel)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
static void CodeLabel(register struct def *df, int local)
|
|
{
|
|
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);
|
|
}
|
|
}
|