home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource4
/
204_01
/
genstmt.c
< prev
next >
Wrap
Text File
|
1979-12-31
|
12KB
|
392 lines
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
int breaklab;
int contlab;
int retlab;
extern TYP stdfunc;
extern struct amode push[], pop[];
struct amode *makedreg(r)
/*
* make an address reference to a data register.
*/
int r;
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_dreg;
ap->preg = r;
return ap;
}
struct amode *makeareg(r)
/*
* make an address reference to an address register.
*/
int r;
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_areg;
ap->preg = r;
return ap;
}
struct amode *make_mask(mask)
/*
* generate the mask address structure.
*/
int mask;
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_mask;
ap->offset = mask;
return ap;
}
struct amode *make_direct(i)
/*
* make a direct reference to an immediate value.
*/
int i;
{ return make_offset(makenode(en_icon,i,0));
}
struct amode *make_strlab(s)
/*
* generate a direct reference to a string label.
*/
char *s;
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_direct;
ap->offset = makenode(en_nacon,s,0);
return ap;
}
genwhile(stmt)
/*
* generate code to evaluate a while statement.
*/
struct snode *stmt;
{ int lab1, lab2;
initstack(); /* initialize temp registers */
lab1 = contlab; /* save old continue label */
lab2 = breaklab; /* save old break label */
contlab = nextlabel++; /* new continue label */
gen_label(contlab);
if( stmt->s1 != 0 ) /* has block */
{
breaklab = nextlabel++;
initstack();
falsejp(stmt->exp,breaklab);
genstmt(stmt->s1);
gen_code(op_bra,0,make_label(contlab),0);
gen_label(breaklab);
breaklab = lab2; /* restore old break label */
}
else /* no loop code */
{
initstack();
truejp(stmt->exp,contlab);
}
contlab = lab1; /* restore old continue label */
}
gen_for(stmt)
/*
* generate code to evaluate a for loop
*/
struct snode *stmt;
{ int old_break, old_cont, exit_label, loop_label;
old_break = breaklab;
old_cont = contlab;
loop_label = nextlabel++;
exit_label = nextlabel++;
contlab = loop_label;
initstack();
if( stmt->label != 0 )
gen_expr(stmt->label,F_ALL | F_NOVALUE
,natural_size(stmt->label));
gen_label(loop_label);
initstack();
if( stmt->exp != 0 )
falsejp(stmt->exp,exit_label);
if( stmt->s1 != 0 )
{
breaklab = exit_label;
genstmt(stmt->s1);
}
initstack();
if( stmt->s2 != 0 )
gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2));
gen_code(op_bra,0,make_label(loop_label),0);
breaklab = old_break;
contlab = old_cont;
gen_label(exit_label);
}
genif(stmt)
/*
* generate code to evaluate an if statement.
*/
struct snode *stmt;
{ int lab1, lab2, oldbreak;
lab1 = nextlabel++; /* else label */
lab2 = nextlabel++; /* exit label */
oldbreak = breaklab; /* save break label */
initstack(); /* clear temps */
falsejp(stmt->exp,lab1);
if( stmt->s1 != 0 && stmt->s1->next != 0 )
if( stmt->s2 != 0 )
breaklab = lab2;
else
breaklab = lab1;
genstmt(stmt->s1);
if( stmt->s2 != 0 ) /* else part exists */
{
gen_code(op_bra,0,make_label(lab2),0);
gen_label(lab1);
if( stmt->s2 == 0 || stmt->s2->next == 0 )
breaklab = oldbreak;
else
breaklab = lab2;
genstmt(stmt->s2);
gen_label(lab2);
}
else /* no else code */
gen_label(lab1);
breaklab = oldbreak;
}
gendo(stmt)
/*
* generate code for a do - while loop.
*/
struct snode *stmt;
{ int oldcont, oldbreak;
oldcont = contlab;
oldbreak = breaklab;
contlab = nextlabel++;
gen_label(contlab);
if( stmt->s1 != 0 && stmt->s1->next != 0 )
{
breaklab = nextlabel++;
genstmt(stmt->s1); /* generate body */
initstack();
truejp(stmt->exp,contlab);
gen_label(breaklab);
}
else
{
genstmt(stmt->s1);
initstack();
truejp(stmt->exp,contlab);
}
breaklab = oldbreak;
contlab = oldcont;
}
call_library(lib_name)
/*
* generate a call to a library routine.
*/
char *lib_name;
{ SYM *sp;
sp = gsearch(lib_name);
if( sp == 0 )
{
++global_flag;
sp = xalloc(sizeof(SYM));
sp->tp = &stdfunc;
sp->name = lib_name;
sp->storage_class = sc_external;
insert(sp,&gsyms);
--global_flag;
}
gen_code(op_jsr,0,make_strlab(lib_name),0);
}
genswitch(stmt)
/*
* generate a linear search switch statement.
*/
struct snode *stmt;
{ int curlab;
struct snode *defcase;
struct amode *ap;
curlab = nextlabel++;
defcase = 0;
initstack();
ap = gen_expr(stmt->exp,F_DREG | F_VOL,4);
if( ap->preg != 0 )
gen_code(op_move,4,ap,makedreg(0));
stmt = stmt->s1;
call_library("c%switch");
while( stmt != 0 )
{
if( stmt->s2 ) /* default case ? */
{
stmt->label = curlab;
defcase = stmt;
}
else
{
gen_code(op_dc,4,make_label(curlab),
make_direct(stmt->label));
stmt->label = curlab;
}
if( stmt->s1 != 0 && stmt->next != 0 )
curlab = nextlabel++;
stmt = stmt->next;
}
if( defcase == 0 )
gen_code(op_dc,4,make_direct(0),make_label(breaklab));
else
gen_code(op_dc,4,make_direct(0),make_label(defcase->label));
}
gencase(stmt)
/*
* generate all cases for a switch statement.
*/
struct snode *stmt;
{ while( stmt != 0 )
{
if( stmt->s1 != 0 )
{
gen_label(stmt->label);
genstmt(stmt->s1);
}