# generated source files
GSRC = char.c symbol2str.c next.c \
code.h declar.h decspecs.h def.h expr.h field.h \
- idf.h macro.h stack.h struct.h switch.h type.h
+ idf.h macro.h stack.h stmt.h struct.h switch.h type.h
# .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE!
GHSRC = botch_free.h dataflow.h debug.h density.h errout.h \
# include files containing ALLOCDEF specifications
NEXTFILES = code.str declar.str decspecs.str def.str expr.str field.str \
- idf.str macro.str stack.str struct.str switch.str type.str
+ idf.str macro.str stack.str stmt.str struct.str switch.str type.str
.SUFFIXES: .str .h
.str.h:
lint.cem: cem.c
lint -abx cem.c
-hfiles: Parameters
+hfiles: ./make.hfiles Parameters
./make.hfiles Parameters
@touch hfiles
idf.h: make.allocd
macro.h: make.allocd
stack.h: make.allocd
+stmt.h: make.allocd
struct.h: make.allocd
switch.h: make.allocd
type.h: make.allocd
cstoper.o: Lpars.h arith.h assert.h debug.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h target_sizes.h type.h
arith.o: Lpars.h alloc.h arith.h botch_free.h expr.h field.h idf.h label.h mes.h nobitfield.h nopp.h spec_arith.h storage.h type.h
alloc.o: alloc.h assert.h debug.h myalloc.h
-code.o: LLlex.h Lpars.h alloc.h arith.h assert.h atw.h botch_free.h code.h dataflow.h debug.h declar.h decspecs.h def.h expr.h idf.h label.h level.h mes.h nobitfield.h nopp.h sizes.h spec_arith.h specials.h stack.h storage.h type.h use_tmp.h
+code.o: LLlex.h Lpars.h alloc.h arith.h assert.h atw.h botch_free.h code.h dataflow.h debug.h declar.h decspecs.h def.h expr.h idf.h label.h level.h mes.h nobitfield.h nopp.h sizes.h spec_arith.h specials.h stack.h stmt.h storage.h type.h use_tmp.h
dumpidf.o: Lpars.h arith.h debug.h def.h expr.h field.h idf.h label.h nobitfield.h nopp.h spec_arith.h stack.h struct.h type.h
error.o: LLlex.h arith.h debug.h errout.h expr.h label.h nopp.h spec_arith.h tokenname.h use_tmp.h
field.o: Lpars.h arith.h assert.h code.h debug.h expr.h field.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h type.h
scan.o: class.h idf.h input.h interface.h lapbuf.h macro.h nopp.h nparams.h
skip.o: LLlex.h arith.h class.h input.h interface.h nopp.h spec_arith.h
stack.o: Lpars.h alloc.h arith.h botch_free.h debug.h def.h idf.h level.h mes.h nobitfield.h nopp.h spec_arith.h stack.h storage.h struct.h type.h use_tmp.h
-type.o: Lpars.h align.h alloc.h arith.h def.h idf.h nobitfield.h nopp.h sizes.h spec_arith.h type.h
+type.o: Lpars.h align.h alloc.h arith.h def.h idf.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h type.h
ch7mon.o: Lpars.h arith.h botch_free.h def.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h storage.h type.h
label.o: Lpars.h arith.h def.h idf.h label.h level.h nobitfield.h nopp.h spec_arith.h type.h
eval.o: Lpars.h align.h arith.h assert.h atw.h code.h dataflow.h debug.h def.h expr.h idf.h label.h level.h mes.h nobitfield.h nopp.h sizes.h spec_arith.h stack.h type.h
blocks.o: arith.h atw.h sizes.h spec_arith.h
dataflow.o: dataflow.h
tokenfile.o: Lpars.h
-declar.o: LLlex.h Lpars.h arith.h debug.h declar.h decspecs.h def.h expr.h field.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h struct.h type.h
+declar.o: LLlex.h Lpars.h arith.h debug.h declar.h decspecs.h def.h expr.h field.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h struct.h type.h
statement.o: LLlex.h Lpars.h arith.h botch_free.h code.h debug.h def.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h stack.h storage.h type.h
expression.o: LLlex.h Lpars.h arith.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h type.h
program.o: LLlex.h Lpars.h alloc.h arith.h code.h declar.h decspecs.h def.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h type.h
!File: myalloc.h
-#define OWNALLOC 1 /* use own superfast allocation */
+#define OWNALLOC 1 /* use own superfast allocation */
#define ALLOCSIZ 4096 /* allocate pieces of 4K */
#define ALIGNSIZE 8 /* needed for alloc.c */
#include "idf.h"
#include "label.h"
#include "code.h"
+#include "stmt.h"
#include "alloc.h"
#include "def.h"
#include "expr.h"
#include "atw.h"
#include "assert.h"
-static struct stat_block *stat_sp, *stat_head;
+static struct stmt_block *stmt_stack;
char *symbol2str();
int fp_used;
extern char options[];
-/* init_code() initialises the output file on which the compact
- EM code is written
-*/
init_code(dst_file)
char *dst_file;
{
+ /* init_code() initialises the output file on which the
+ compact EM code is written
+ */
C_init(word_size, pointer_size); /* initialise EM module */
if (C_open(dst_file) == 0)
fatal("cannot write to %s\n", dst_file);
#ifndef USE_TMP
famous_first_words();
#endif USE_TMP
- stat_sp = stat_head = new_stat_block();
- clear((char *)stat_sp, sizeof(struct stat_block));
}
famous_first_words()
static char *last_fn_given = "";
static label file_name_label;
-/* begin_proc() is called at the entrance of a new function
- and performs the necessary code generation:
- - a scope indicator (if needed) exp/inp
- - the procedure entry pro $name
- - reserves some space if the result of the function
- does not fit in the return area
- - a fil pseudo instruction
-*/
begin_proc(name, def) /* to be called when entering a procedure */
char *name;
struct def *def;
{
+ /* begin_proc() is called at the entrance of a new function
+ and performs the necessary code generation:
+ - a scope indicator (if needed) exp/inp
+ - the procedure entry pro $name
+ - reserves some space if the result of the function
+ does not fit in the return area
+ - a fil pseudo instruction
+ */
arith size;
#ifndef USE_TMP
}
}
-/* end_proc() deals with the code to be generated at the end of
- a function, as there is:
- - the EM ret instruction: "ret 0"
- - loading of the function result in the function result area
- if there has been a return <expr> in the function body
- (see do_return_expr())
- - indication of the use of floating points
- - indication of the number of bytes used for formal parameters
- - use of special identifiers such as "setjmp"
- - "end" + number of bytes used for local variables
-*/
end_proc(fbytes, nbytes)
arith fbytes, nbytes;
{
+ /* end_proc() deals with the code to be generated at the end of
+ a function, as there is:
+ - the EM ret instruction: "ret 0"
+ - loading of the function result in the function
+ result area if there has been a return <expr>
+ in the function body (see do_return_expr())
+ - indication of the use of floating points
+ - indication of the number of bytes used for
+ formal parameters
+ - use of special identifiers such as "setjmp"
+ - "end" + number of bytes used for local variables
+ */
static int mes_flt_given = 0; /* once for the whole program */
#ifdef DATAFLOW
- global variables, coded only if initialized;
- local static variables;
- local automatic variables;
+ Since the expression may be modified in the process,
+ code_declaration() frees it after use, as the caller can
+ no longer do so.
+
If there is a storage class indication (EXTERN/STATIC),
code_declaration() will generate an exa or ina.
The sc is the actual storage class, as given in the
def->df_alloc = ALLOC_DONE;
C_df_dnam(text);
do_ival(&(def->df_type), expr);
+ free_expression(expr);
}
}
else
integer label in EM.
*/
C_df_dlb((label)def->df_address);
- if (expr) /* there is an initialisation */
+ if (expr) {
+ /* there is an initialisation */
do_ival(&(def->df_type), expr);
+ free_expression(expr);
+ }
else { /* produce blank space */
if (size <= 0) {
error("size of %s unknown", text);
{
/* loc_init() generates code for the assignment of
expression expr to the local variable described by id.
+ It frees the expression afterwards.
*/
register struct type *tp = id->id_def->df_type;
case STRUCT:
case UNION:
error("no automatic aggregate initialisation");
+ free_expression(expr);
return;
}
else { /* not embraced */
struct value vl;
- ch7cast(&expr, '=', tp);
+ ch7cast(&expr, '=', tp); /* may modify expr */
EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
+ free_expression(expr);
vl.vl_class = Name;
vl.vl_data.vl_idf = id;
vl.vl_value = (arith)0;
}
}
-/* bss() allocates bss space for the global idf.
-*/
bss(idf)
struct idf *idf;
{
+ /* bss() allocates bss space for the global idf.
+ */
register struct def *def = idf->id_def;
arith size = def->df_type->tp_size;
}
}
-/* code_expr() is the parser's interface to the expression code
- generator.
- If line number trace is wanted, it generates a lin instruction.
- EVAL() is called directly.
-*/
code_expr(expr, val, code, tlbl, flbl)
struct expr *expr;
label tlbl, flbl;
{
+ /* code_expr() is the parser's interface to the expression code
+ generator.
+ If line number trace is wanted, it generates a
+ lin instruction. EVAL() is called directly.
+ */
if (options['p']) /* profiling */
C_lin((arith)LineNumber);
EVAL(expr, val, code, tlbl, flbl);
}
/* The FOR/WHILE/DO/SWITCH stacking mechanism:
- stat_stack() has to be called at the entrance of a
+ stack_stmt() has to be called at the entrance of a
for, while, do or switch statement to indicate the
EM labels where a subsequent break or continue causes
the program to jump to.
*/
-/* do_break() generates EM code needed at the occurrence of "break":
+/* code_break() generates EM code needed at the occurrence of "break":
it generates a branch instruction to the break label of the
innermost statement in which break has a meaning.
As "break" is legal in any of 'while', 'do', 'for' or 'switch',
which are the only ones that are stacked, only the top of
the stack is interesting.
- 0 is returned if the break cannot be bound to any enclosing
- statement.
*/
-int
-do_break()
+code_break()
{
- register struct stat_block *stat_ptr = stat_sp;
+ register struct stmt_block *stmt_block = stmt_stack;
- if (stat_ptr) {
- C_bra(stat_ptr->st_break);
- return 1;
+ if (stmt_block) {
+ C_bra(stmt_block->st_break);
+ return;
}
- return 0; /* break is illegal */
+ error("break not inside for, while, do or switch");
}
-/* do_continue() generates EM code needed at the occurrence of "continue":
+/* code_continue() generates EM code needed at the occurrence of
+ "continue":
it generates a branch instruction to the continue label of the
innermost statement in which continue has a meaning.
- 0 is returned if the continue cannot be bound to any enclosing
- statement.
*/
-int
-do_continue()
+code_continue()
{
- register struct stat_block *stat_ptr = stat_sp;
+ register struct stmt_block *stmt_block = stmt_stack;
- while (stat_ptr) {
- if (stat_ptr->st_continue) {
- C_bra(stat_ptr->st_continue);
- return 1;
+ while (stmt_block) {
+ if (stmt_block->st_continue) {
+ C_bra(stmt_block->st_continue);
+ return;
}
- stat_ptr = stat_ptr->next;
+ stmt_block = stmt_block->next;
}
- return 0;
+ error("continue not inside for, while or do");
}
-stat_stack(break_label, cont_label)
+stack_stmt(break_label, cont_label)
label break_label, cont_label;
{
- register struct stat_block *newb = new_stat_block();
+ register struct stmt_block *stmt_block = new_stmt_block();
- newb->next = stat_sp;
- newb->st_break = break_label;
- newb->st_continue = cont_label;
- stat_sp = newb;
+ stmt_block->next = stmt_stack;
+ stmt_block->st_break = break_label;
+ stmt_block->st_continue = cont_label;
+ stmt_stack = stmt_block;
}
-/* stat_unstack() unstacks the data of a statement
- which may contain break or continue
-*/
-stat_unstack()
+unstack_stmt()
{
- register struct stat_block *sbp = stat_sp;
- stat_sp = stat_sp->next;
- free_stat_block(sbp);
+ /* unstack_stmt() unstacks the data of a statement
+ which may contain break or continue
+ */
+ register struct stmt_block *sbp = stmt_stack;
+ stmt_stack = stmt_stack->next;
+ free_stmt_block(sbp);
}
/* $Header$ */
/* C O D E - G E N E R A T O R D E F I N I T I O N S */
-struct stat_block {
- struct stat_block *next;
- label st_break;
- label st_continue;
-};
-
-/* ALLOCDEF "stat_block" */
-
struct string_cst { /* storing string constants */
struct string_cst *next;
char *sc_value;
cut_size(*expp);
(*expp)->ex_flags |= expr->ex_flags;
(*expp)->ex_flags &= ~EX_PARENS;
+ free_expression(expr);
}
cut_size(expr)
#include "label.h"
#include "expr.h"
#include "sizes.h"
+#include "storage.h"
extern char options[];
}
initializer(Dc.dc_idf, &expr)?
{
code_declaration(Dc.dc_idf, expr, level, ds->ds_sc);
- free_expression(expr);
}
]
{remove_declarator(&Dc);}
declarator(struct declarator *dc;)
{
arith count;
- struct idstack_item *is = 0;
+ struct formal *fm = 0;
}
:
[
old-fashioned initialization.
*/
'('
- formal_list(&is) ? /* semantic check later... */
+ formal_list(&fm) ? /* semantic check later... */
')'
{
- add_decl_unary(dc, FUNCTION, (arith)0, is);
- is = 0;
+ add_decl_unary(dc, FUNCTION, (arith)0, fm);
+ fm = 0;
}
|
arrayer(&count)
']'
;
-formal_list (struct idstack_item **is;)
+formal_list (struct formal **fmp;)
:
- formal(is) [ ',' formal(is) ]*
+ formal(fmp) [ ',' formal(fmp) ]*
;
-formal(struct idstack_item **is;)
+formal(struct formal **fmp;)
{struct idf *idf; }
:
identifier(&idf)
{
- struct idstack_item *new = new_idstack_item();
+ struct formal *new = new_formal();
- new->is_idf = idf;
- new->next = *is;
- *is = new;
+ new->fm_idf = idf;
+ new->next = *fmp;
+ *fmp = new;
}
;
struct declarator *next;
struct idf *dc_idf;
struct decl_unary *dc_decl_unary;
- struct idstack_item *dc_fparams; /* params for function */
+ struct formal *dc_formal; /* params for function */
};
/* ALLOCDEF "declarator" */
-#define NO_PARAMS ((struct idstack_item *) 0)
+
+struct formal { /* list of formals */
+ struct formal *next;
+ struct idf *fm_idf;
+};
+
+/* ALLOCDEF "formal" */
+
+#define NO_PARAMS ((struct formal *) 0)
struct decl_unary {
struct decl_unary *next;
return tp;
}
-add_decl_unary(dc, fund, count, is)
+add_decl_unary(dc, fund, count, fm)
struct declarator *dc;
arith count;
- struct idstack_item *is;
+ struct formal *fm;
{
/* A decl_unary describing a constructor with fundamental
type fund and with size count is inserted in front of the
new->next = dc->dc_decl_unary;
new->du_fund = fund;
new->du_count = count;
- if (is) {
+ if (fm) {
if (dc->dc_decl_unary) {
/* paramlist only allowed at first decl_unary */
error("formal parameter list discarded");
}
else {
/* register the parameters */
- dc->dc_fparams = is;
+ dc->dc_formal = fm;
}
}
dc->dc_decl_unary = new;
/* The declarator is checked to have no parameters, if it
is a function.
*/
- if (dc->dc_fparams) {
+ if (dc->dc_formal) {
error("non_empty formal parameter pack");
- del_idfstack(dc->dc_fparams);
- dc->dc_fparams = 0;
+ free_formals(dc->dc_formal);
+ dc->dc_formal = 0;
}
}
string2expr(*expp);
break;
case INTEGER:
- *expp = intexpr(dot.tk_ival, dot.tk_fund);
+ int2expr(*expp);
break;
case FLOATING:
float2expr(*expp);
expr->SG_DATLAB = 0;
}
+int2expr(expr)
+ struct expr *expr;
+{
+ /* Dot contains an integer constant which is turned
+ into an expression.
+ */
+ fill_int_expr(expr, dot.tk_ival, dot.tk_fund);
+}
+
+float2expr(expr)
+ struct expr *expr;
+{
+ /* Dot contains a floating point constant which is turned
+ into an expression.
+ */
+ expr->ex_type = double_type;
+ expr->ex_class = Float;
+ expr->FL_VALUE = dot.tk_fval;
+ expr->FL_DATLAB = 0;
+}
+
struct expr*
intexpr(ivalue, fund)
arith ivalue;
expr->ex_file = dot.tk_file;
expr->ex_line = dot.tk_line;
+ fill_int_expr(expr, ivalue, fund);
+ return expr;
+}
+
+fill_int_expr(expr, ivalue, fund)
+ struct expr *expr;
+ arith ivalue;
+{
+ /* Details derived from ivalue and fund are put into the
+ constant integer expression expr.
+ */
switch (fund) {
case INT:
expr->ex_type = int_type;
expr->VL_VALUE = ivalue;
cut_size(expr);
- return expr;
-}
-
-float2expr(expr)
- struct expr *expr;
-{
- /* Dot contains a floating point constant which is turned
- into an expression.
- */
- expr->ex_type = double_type;
- expr->ex_class = Float;
- expr->FL_VALUE = dot.tk_fval;
- expr->FL_DATLAB = 0;
}
struct expr *
{
/* Declares the formal parameters if they exist.
*/
- register struct idstack_item *is = dc->dc_fparams;
+ register struct formal *fm = dc->dc_formal;
- while (is) {
- declare_parameter(is->is_idf);
- is = is->next;
+ while (fm) {
+ declare_parameter(fm->fm_idf);
+ fm = fm->next;
}
- del_idfstack(dc->dc_fparams);
- dc->dc_fparams = 0;
+ free_formals(dc->dc_formal);
+ dc->dc_formal = 0;
}
init_idf(idf)
TYPE_IDENTIFIER : IDENTIFIER;
}
-del_idfstack(is)
- struct idstack_item *is;
+free_formals(fm)
+ struct formal *fm;
{
- while (is) {
- register struct idstack_item *tmp = is->next;
- free_idstack_item(is);
- is = tmp;
+ while (fm) {
+ register struct formal *tmp = fm->next;
+ free_formal(fm);
+ fm = tmp;
}
}
#define ENHASH(hs,ch,ps) (hs + (ch ^ hmask[ps]))
#define STOPHASH(hs) (hs & HASHMASK)
-struct idstack_item { /* stack of identifiers */
- struct idstack_item *next;
- struct idf *is_idf;
-};
-
-/* ALLOCDEF "idstack_item" */
-
struct idf {
struct idf *next;
char *id_text;
#endif USE_TMP
#ifdef DEBUG
- if (options['u']) /* unstack L_UNIVERSAL */
- unstack_level();
+ if (options['u']) {
+ unstack_level(); /* unstack L_GLOBAL */
+ }
if (options['f'] || options['t'])
dumpidftab("end of main", options['f'] ? 0 : 0);
#endif DEBUG
#ifndef NOPP
}
-#endif NOPP
+#endif NOPP
PopLex();
}
sed '
s:^.*ALLOCDEF.*"\(.*\)".*$:\
/* allocation definitions of struct \1 */\
-extern char *st_alloc();\
extern struct \1 *h_\1;\
#define new_\1() ((struct \1 *) \\\
st_alloc((char **)\&h_\1, sizeof(struct \1)))\
:
{reject_params(dc);}
initializer(dc->dc_idf, &expr)?
- {
- code_declaration(dc->dc_idf, expr, level, ds->ds_sc);
- free_expression(expr);
- }
+ {
+ code_declaration(dc->dc_idf, expr, level, ds->ds_sc);
+ }
[
','
init_declarator(ds)
-/* DERIVED FROM $Header$ */
+/* $Header$ */
/* S T A C K / U N S T A C K R O U T I N E S */
#include <system.h>
/* space must be allocated */
bss(idf);
namelist(idf->id_text); /* may be common */
- def->df_alloc = ALLOC_DONE; /* *) */
+ def->df_alloc = ALLOC_DONE; /* see Note below */
}
se = se->next;
}
- /* *) df_alloc must be set to ALLOC_DONE because the idf entry
+ /* Note:
+ df_alloc must be set to ALLOC_DONE because the idf entry
may occur several times in the list.
The reason for this is that the same name may be used
- for different purposes on the same level, e.g
+ for different purposes on the same level, e.g.
struct s {int s;} s;
- is a legal definition and contains 3 defining occurrences of s.
- Each definition has been entered into the idfstack.
+ is a legal definition and contains 3 defining occurrences
+ of s.
+ Each definition has been entered into the identifier stack.
Although only one of them concerns a variable, we meet the
- s 3 times when scanning the idfstack.
+ s 3 times when scanning the identifier stack.
*/
}
:
WHILE
{
- stat_stack(l_break, l_continue);
+ stack_stmt(l_break, l_continue);
C_df_ilb(l_continue);
}
'('
{
C_bra(l_continue);
C_df_ilb(l_break);
- stat_unstack();
+ unstack_stmt();
free_expression(expr);
}
;
:
DO
{ C_df_ilb(l_body);
- stat_stack(l_break, l_continue);
+ stack_stmt(l_break, l_continue);
}
statement
WHILE
')'
';'
{
- stat_unstack();
+ unstack_stmt();
free_expression(expr);
}
;
}
:
FOR
- { stat_stack(l_break, l_continue);
+ { stack_stmt(l_break, l_continue);
}
'('
[
NO_LABEL, NO_LABEL);
C_bra(l_test);
C_df_ilb(l_break);
- stat_unstack();
+ unstack_stmt();
free_expression(e_init);
free_expression(e_test);
free_expression(e_incr);
break_statement
:
BREAK
- {
- if (!do_break())
- error("invalid break");
- }
+ {code_break();}
';'
;
continue_statement
:
CONTINUE
- {
- if (!do_continue())
- error("invalid continue");
- }
+ {code_continue();}
';'
;
};
char *
-st_alloc(phead, size)
+head_alloc(phead, size)
char **phead;
int size;
{
/* $Header$ */
/* S T R U C T U R E - S T O R A G E D E F I N I T I O N S */
+/* Storage allocation is one of the most expensive operations in
+ the compiler and consequently much thought and experimentation
+ has gone into it. To simplify the hooking in of new super-fancy
+ algorithms, all allocating and freeing of storage for structs
+ goes through the macros
+ st_alloc(&head, size)
+ st_free(ptr, head, size)
+ which, hopefully, convey enough information.
+*/
+
+extern char *head_alloc();
+
+#define st_alloc(headp, size) head_alloc((char **)headp, size)
+
#ifndef BOTCH_FREE
-#define st_free(ptr, head, size) {ptr->next = head; head = ptr;}
+#define st_free(ptr, head, size) (ptr->next = head, head = ptr)
#else def BOTCH_FREE
-#define st_free(ptr, head, size) {botch((char *)(ptr), size); \
- ptr->next = head; head = ptr;}
+#define st_free(ptr, head, size) (botch((char *)(ptr), size), \
+ ptr->next = head, head = ptr)
#endif BOTCH_FREE
arith sd_offset;
};
-extern char *st_alloc();
-
/* ALLOCDEF "sdef" */
struct tag { /* for struct-, union- and enum tags */
break;
}
- stat_stack(l_break, NO_LABEL);
+ stack_stmt(l_break, NO_LABEL);
sh->sh_break = l_break;
sh->sh_default = 0;
sh->sh_table = l_table;
ce = tmp;
}
free_switch_hdr(sh);
- stat_unstack();
+ unstack_stmt();
}
code_case(expr)
#include "def.h"
#include "sizes.h"
#include "align.h"
+#include "storage.h"
struct type *function_of(), *array_of();
#ifndef NOBITFIELD