modified the treatment of op=, ++ and -- operators

This commit is contained in:
erikb 1986-09-29 14:01:34 +00:00
parent 42112db262
commit 5af21dfc79
15 changed files with 421 additions and 601 deletions

View file

@ -17,7 +17,8 @@ EMELIB = $(EM)/modules/lib/libeme.a
STRLIB = $(EM)/modules/lib/libstr.a STRLIB = $(EM)/modules/lib/libstr.a
PRTLIB = $(EM)/modules/lib/libprint.a PRTLIB = $(EM)/modules/lib/libprint.a
EMMESLIB = $(EM)/modules/lib/libem_mes.a EMMESLIB = $(EM)/modules/lib/libem_mes.a
CH3LIB = $(EM)/modules/lib/libch3.a #CH3LIB = $(EM)/modules/lib/libch3.a
CH3LIB =
LIBS = $(CH3LIB) $(EMMESLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) $(SYSLIB) LIBS = $(CH3LIB) $(EMMESLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) $(SYSLIB)
ELIBS = $(CH3LIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) $(SYSLIB) ELIBS = $(CH3LIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) $(SYSLIB)
LIB_INCLUDES = $(EM)/modules/h LIB_INCLUDES = $(EM)/modules/h

View file

@ -423,6 +423,10 @@ is_asgn_op(oper)
case ANDAB: case ANDAB:
case ORAB: case ORAB:
case XORAB: case XORAB:
case PLUSPLUS:
case POSTINCR:
case MINMIN:
case POSTDECR:
return 1; return 1;
default: default:
return 0; return 0;

View file

@ -1,10 +1,14 @@
/* $Header$ */ /* $Header$ */
/* B L O C K S T O R I N G A N D L O A D I N G */ /* B L O C K S T O R I N G A N D L O A D I N G */
#include <em.h> #include <em.h>
#include "arith.h" #include "arith.h"
#include "sizes.h" #include "sizes.h"
#include "atw.h" #include "atw.h"
#ifndef STB
#include "label.h"
#include "stack.h"
#endif STB
/* Because EM does not support the loading and storing of /* Because EM does not support the loading and storing of
objects having other sizes than word fragment and multiple, objects having other sizes than word fragment and multiple,
@ -38,17 +42,33 @@ store_block(sz, al)
arith sz; arith sz;
int al; int al;
{ {
/* Next condition contains Lots of Irritating Stupid Parentheses
*/
if ( if (
((sz == al) && (word_align % al == 0)) || ((sz == al) && (word_align % al == 0)) ||
( (
(sz % word_size == 0 || word_size % sz == 0) && (sz % word_size == 0 || word_size % sz == 0) &&
(al % word_align == 0) (al % word_align == 0)
) )
) ) /* Lots of Irritating Stupid Parentheses */
C_sti(sz); C_sti(sz);
else { else {
#ifndef STB
arith src, dst, src_offs, dst_offs;
/* allocate two pointer temporaries */
src = tmp_pointer_var(&src_offs);
dst = tmp_pointer_var(&dst_offs);
/* load the addresses */
C_lal(dst);
C_sti(pointer_size);
C_lor((arith)1); /* push current sp */
C_lal(src);
C_sti(pointer_size);
copy_loop(sz, src, dst);
C_asp(ATW(sz));
free_tmp_var(dst_offs);
free_tmp_var(src_offs);
#else STB
/* address of destination lies on the stack */ /* address of destination lies on the stack */
/* push address of first byte of block on stack onto /* push address of first byte of block on stack onto
@ -60,6 +80,7 @@ store_block(sz, al)
C_loc(sz); /* number of bytes to transfer */ C_loc(sz); /* number of bytes to transfer */
C_cal("__stb"); /* call transfer routine */ C_cal("__stb"); /* call transfer routine */
C_asp(pointer_size + pointer_size + int_size + ATW(sz)); C_asp(pointer_size + pointer_size + int_size + ATW(sz));
#endif STB
} }
} }
@ -75,7 +96,23 @@ load_block(sz, al)
if (al % word_align == 0) if (al % word_align == 0)
C_loi(esz); C_loi(esz);
else { else {
/* do not try to understand this... */ #ifndef STB
arith src, dst, src_offs, dst_offs;
/* allocate two pointer temporaries */
src = tmp_pointer_var(&src_offs);
dst = tmp_pointer_var(&dst_offs);
C_lal(src);
C_sti(pointer_size);
C_asp(-esz); /* allocate stack block */
C_lor((arith)1); /* push & of stack block as dst */
C_lal(dst);
C_sti(pointer_size);
copy_loop(sz, src, dst);
free_tmp_var(dst_offs);
free_tmp_var(src_offs);
#else STB
C_asp(-(esz - pointer_size)); /* allocate stack block */ C_asp(-(esz - pointer_size)); /* allocate stack block */
C_lor((arith)1); /* push & of stack block as dst */ C_lor((arith)1); /* push & of stack block as dst */
C_dup(pointer_size); /* fetch source address */ C_dup(pointer_size); /* fetch source address */
@ -84,5 +121,38 @@ load_block(sz, al)
C_loc(sz); /* # bytes to copy */ C_loc(sz); /* # bytes to copy */
C_cal("__stb"); /* library copy routine */ C_cal("__stb"); /* library copy routine */
C_asp(int_size + pointer_size + pointer_size); C_asp(int_size + pointer_size + pointer_size);
#endif STB
} }
} }
#ifndef STB
copy_loop(sz, src, dst)
arith sz, src, dst;
{
/* generate inline byte-copy loop */
label l_cont = text_label(), l_stop = text_label();
C_loc(sz); /* amount of bytes */
C_df_ilb(l_cont);
C_dup(word_size);
C_zle(l_stop);
C_dec();
C_lal(src);
C_loi(pointer_size);
C_dup(pointer_size);
C_adp((arith)1);
C_lal(src);
C_sti(pointer_size);
C_loi((arith)1);
C_lal(dst);
C_loi(pointer_size);
C_dup(pointer_size);
C_adp((arith)1);
C_lal(dst);
C_sti(pointer_size);
C_sti((arith)1);
C_bra(l_cont);
C_df_ilb(l_stop);
C_asp(word_size);
}
#endif STB

View file

@ -121,11 +121,9 @@ ch7sel(expp, oper, idf)
intexpr(sd->sd_offset, INT)); intexpr(sd->sd_offset, INT));
} }
} }
else { else /* oper == ARROW */
/* oper == ARROW */
*expp = new_oper(sd->sd_type, *expp = new_oper(sd->sd_type,
*expp, oper, intexpr(sd->sd_offset, INT)); *expp, oper, intexpr(sd->sd_offset, INT));
}
(*expp)->ex_lvalue = (sd->sd_type->tp_fund != ARRAY); (*expp)->ex_lvalue = (sd->sd_type->tp_fund != ARRAY);
} }
@ -135,44 +133,7 @@ ch7incr(expp, oper)
/* The monadic prefix/postfix incr/decr operator oper is /* The monadic prefix/postfix incr/decr operator oper is
applied to *expp. applied to *expp.
*/ */
arith addend; ch7asgn(expp, oper, intexpr((arith)1, INT));
struct expr *expr;
register int fund = (*expp)->ex_type->tp_fund;
if (!(*expp)->ex_lvalue) {
expr_error(*expp, "no lvalue with %s", symbol2str(oper));
return;
}
if (fund == ENUM) {
expr_warning(*expp, "%s on enum", symbol2str(oper));
addend = (arith)1;
}
else
if (is_arith_type((*expp)->ex_type))
addend = (arith)1;
else
if (fund == POINTER)
addend = size_of_type((*expp)->ex_type->tp_up, "object");
#ifndef NOBITFIELD
else
if (fund == FIELD)
addend = (arith)1;
#endif NOBITFIELD
else {
expr_error(*expp, "%s on %s",
symbol2str(oper),
symbol2str((*expp)->ex_type->tp_fund)
);
return;
}
expr = intexpr(addend, INT);
ch7cast(&expr, CAST, (*expp)->ex_type);
#ifndef NOBITFIELD
if (fund == FIELD)
*expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr);
else
#endif NOBITFIELD
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
} }
ch7cast(expp, oper, tp) ch7cast(expp, oper, tp)
@ -293,10 +254,8 @@ ch7cast(expp, oper, tp)
(*expp)->ex_type = tp; (*expp)->ex_type = tp;
} }
else else
if (oldtp->tp_fund == ERRONEOUS) { if (oldtp->tp_fund == ERRONEOUS) /* we just won't look */
/* we just won't look */ (*expp)->ex_type = tp; /* brute force */
(*expp)->ex_type = tp; /* brute force */
}
else else
if (oldtp->tp_size == tp->tp_size && oper == CAST) { if (oldtp->tp_size == tp->tp_size && oper == CAST) {
expr_warning(*expp, "dubious conversion based on equal size"); expr_warning(*expp, "dubious conversion based on equal size");
@ -365,7 +324,6 @@ ch7asgn(expp, oper, expr)
else else
expr = extmp; expr = extmp;
} }
#ifndef NOBITFIELD #ifndef NOBITFIELD
if (fund == FIELD) if (fund == FIELD)
*expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr); *expp = new_oper((*expp)->ex_type->tp_up, *expp, oper, expr);
@ -374,7 +332,6 @@ ch7asgn(expp, oper, expr)
#else NOBITFIELD #else NOBITFIELD
*expp = new_oper((*expp)->ex_type, *expp, oper, expr); *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
#endif NOBITFIELD #endif NOBITFIELD
(*expp)->OP_TYPE = tp; /* for EVAL() */ (*expp)->OP_TYPE = tp; /* for EVAL() */
} }

View file

@ -82,16 +82,6 @@ ch7bin(expp, oper, expr)
break; break;
case '%': case '%':
case MODAB: case MODAB:
/*** NB "not float" means "integral" !!!
fund = arithbalance(expp, oper, &expr);
if (fund == DOUBLE) {
expr_error(*expp, "floating operand to %s",
symbol2str(oper));
erroneous2int(expp);
}
else
non_commutative_binop(expp, oper, expr);
***/
opnd2integral(expp, oper); opnd2integral(expp, oper);
opnd2integral(&expr, oper); opnd2integral(&expr, oper);
fund = arithbalance(expp, oper, &expr); fund = arithbalance(expp, oper, &expr);
@ -111,21 +101,19 @@ ch7bin(expp, oper, expr)
non_commutative_binop(expp, oper, expr); non_commutative_binop(expp, oper, expr);
break; break;
case '+': case '+':
if (expr->ex_type->tp_fund == POINTER) { if (expr->ex_type->tp_fund == POINTER) { /* swap operands */
/* swap operands */
struct expr *etmp = expr; struct expr *etmp = expr;
expr = *expp; expr = *expp;
*expp = etmp; *expp = etmp;
} }
/*FALLTHROUGH*/ /*FALLTHROUGH*/
case PLUSAB: case PLUSAB:
case POSTINCR:
case PLUSPLUS:
if ((*expp)->ex_type->tp_fund == POINTER) { if ((*expp)->ex_type->tp_fund == POINTER) {
pointer_arithmetic(expp, oper, &expr); pointer_arithmetic(expp, oper, &expr);
if ( expr->ex_type->tp_size != if (expr->ex_type->tp_size != (*expp)->ex_type->tp_size)
(*expp)->ex_type->tp_size
) {
ch7cast(&expr, CAST, (*expp)->ex_type); ch7cast(&expr, CAST, (*expp)->ex_type);
}
pointer_binary(expp, oper, expr); pointer_binary(expp, oper, expr);
} }
else { else {
@ -138,6 +126,8 @@ ch7bin(expp, oper, expr)
break; break;
case '-': case '-':
case MINAB: case MINAB:
case POSTDECR:
case MINMIN:
if ((*expp)->ex_type->tp_fund == POINTER) { if ((*expp)->ex_type->tp_fund == POINTER) {
if (expr->ex_type->tp_fund == POINTER) if (expr->ex_type->tp_fund == POINTER)
pntminuspnt(expp, oper, expr); pntminuspnt(expp, oper, expr);
@ -231,13 +221,11 @@ ch7bin(expp, oper, expr)
if ( is_struct_or_union((*expp)->ex_type->tp_fund) if ( is_struct_or_union((*expp)->ex_type->tp_fund)
|| is_struct_or_union(expr->ex_type->tp_fund) || is_struct_or_union(expr->ex_type->tp_fund)
) { ) {
if ((*expp)->ex_type != expr->ex_type) { if ((*expp)->ex_type != expr->ex_type)
expr_error(*expp, "illegal balance"); expr_error(*expp, "illegal balance");
}
} }
else { else
relbalance(expp, oper, &expr); relbalance(expp, oper, &expr);
}
*expp = new_oper((*expp)->ex_type, *expp, oper, expr); *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
break; break;
case '?': case '?':

View file

@ -28,16 +28,15 @@
#include "atw.h" #include "atw.h"
#include "assert.h" #include "assert.h"
static struct stmt_block *stmt_stack;
char *symbol2str();
#ifndef NOFLOAT
int fp_used;
#endif NOFLOAT
label lab_count = 1; label lab_count = 1;
label datlab_count = 1; label datlab_count = 1;
#ifndef NOFLOAT
int fp_used;
#endif NOFLOAT
extern char options[]; extern char options[];
char *symbol2str();
init_code(dst_file) init_code(dst_file)
char *dst_file; char *dst_file;
@ -112,16 +111,11 @@ prepend_scopes(dst_file)
fatal("cannot create %s", dst_file ? dst_file : "stdout"); fatal("cannot create %s", dst_file ? dst_file : "stdout");
famous_first_words(); famous_first_words();
while (se != 0) { while (se != 0) {
register struct idf *idf = se->se_idf; register struct idf *id = se->se_idf;
register struct def *def = idf->id_def; register struct def *df = id->id_def;
if (def && if (df && (df->df_initialized || df->df_used || df->df_alloc))
( def->df_initialized || code_scope(id->id_text, df);
def->df_used ||
def->df_alloc
)
)
code_scope(idf->id_text, def);
se = se->next; se = se->next;
} }
C_close(); C_close();
@ -198,7 +192,6 @@ begin_proc(name, def) /* to be called when entering a procedure */
} }
else else
func_res_label = 0; func_res_label = 0;
/* Special arrangements if the function result doesn't fit in /* Special arrangements if the function result doesn't fit in
the function return area of the EM machine. The size of the function return area of the EM machine. The size of
the function return area is implementation dependent. the function return area is implementation dependent.
@ -206,15 +199,12 @@ begin_proc(name, def) /* to be called when entering a procedure */
lab_count = (label) 1; lab_count = (label) 1;
return_label = text_label(); return_label = text_label();
return_expr_occurred = 0; return_expr_occurred = 0;
if (options['p']) { /* profiling */ if (options['p']) { /* profiling */
if (strcmp(last_fn_given, FileName) != 0) { if (strcmp(last_fn_given, FileName) != 0) {
/* previous function came from other file */ /* previous function came from other file */
C_df_dlb(file_name_label = data_label()); C_df_dlb(file_name_label = data_label());
C_con_scon( C_con_scon(last_fn_given = FileName,
last_fn_given = FileName, (arith)(strlen(FileName) + 1));
(arith)(strlen(FileName) + 1)
);
} }
/* enable debug trace of EM source */ /* enable debug trace of EM source */
C_fil_dlb(file_name_label, (arith)0); C_fil_dlb(file_name_label, (arith)0);
@ -345,17 +335,14 @@ code_declaration(idf, expr, lvl, sc)
} }
else else
if (lvl >= L_LOCAL) { /* local variable */ if (lvl >= L_LOCAL) { /* local variable */
/* they are STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or /* STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or REGISTER */
REGISTER
*/
switch (def_sc) { switch (def_sc) {
case STATIC: case STATIC:
/* they are handled on the spot and get an /* they are handled on the spot and get an
integer label in EM. integer label in EM.
*/ */
C_df_dlb((label)def->df_address); C_df_dlb((label)def->df_address);
if (expr) { if (expr) { /* there is an initialisation */
/* there is an initialisation */
do_ival(&(def->df_type), expr); do_ival(&(def->df_type), expr);
free_expression(expr); free_expression(expr);
} }
@ -364,8 +351,7 @@ code_declaration(idf, expr, lvl, sc)
error("size of %s unknown", text); error("size of %s unknown", text);
size = (arith)0; size = (arith)0;
} }
C_bss_cst(align(size, word_align), C_bss_cst(align(size, word_align), (arith)0, 1);
(arith)0, 1);
} }
break; break;
case EXTERN: case EXTERN:
@ -399,7 +385,6 @@ loc_init(expr, id)
register struct type *tp = id->id_def->df_type; register struct type *tp = id->id_def->df_type;
ASSERT(id->id_def->df_sc != STATIC); ASSERT(id->id_def->df_sc != STATIC);
/* automatic aggregates cannot be initialised. */
switch (tp->tp_fund) { switch (tp->tp_fund) {
case ARRAY: case ARRAY:
case STRUCT: case STRUCT:
@ -408,7 +393,6 @@ loc_init(expr, id)
free_expression(expr); free_expression(expr);
return; return;
} }
if (ISCOMMA(expr)) { /* embraced: int i = {12}; */ if (ISCOMMA(expr)) { /* embraced: int i = {12}; */
if (options['R']) { if (options['R']) {
if (ISCOMMA(expr->OP_LEFT)) /* int i = {{1}} */ if (ISCOMMA(expr->OP_LEFT)) /* int i = {{1}} */
@ -463,14 +447,15 @@ formal_cvt(df)
*/ */
register struct type *tp = df->df_type; register struct type *tp = df->df_type;
if (tp->tp_size != int_size) if (tp->tp_size != int_size &&
if (tp->tp_fund == CHAR || tp->tp_fund == SHORT) { (tp->tp_fund == CHAR || tp->tp_fund == SHORT)
C_lol(df->df_address); ) {
conversion(int_type, df->df_type); C_lol(df->df_address);
C_lal(df->df_address); /* conversion(int_type, df->df_type); ??? */
C_sti(tp->tp_size); C_lal(df->df_address);
df->df_register = REG_NONE; C_sti(tp->tp_size);
} df->df_register = REG_NONE;
}
} }
code_expr(expr, val, code, tlbl, flbl) code_expr(expr, val, code, tlbl, flbl)
@ -478,8 +463,7 @@ code_expr(expr, val, code, tlbl, flbl)
label tlbl, flbl; label tlbl, flbl;
{ {
/* code_expr() is the parser's interface to the expression code /* code_expr() is the parser's interface to the expression code
generator. generator. If line number trace is wanted, it generates a
If line number trace is wanted, it generates a
lin instruction. EVAL() is called directly. lin instruction. EVAL() is called directly.
*/ */
if (options['p']) /* profiling */ if (options['p']) /* profiling */
@ -493,6 +477,8 @@ code_expr(expr, val, code, tlbl, flbl)
EM labels where a subsequent break or continue causes EM labels where a subsequent break or continue causes
the program to jump to. the program to jump to.
*/ */
static struct stmt_block *stmt_stack; /* top of statement stack */
/* code_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 it generates a branch instruction to the break label of the
innermost statement in which break has a meaning. innermost statement in which break has a meaning.
@ -504,11 +490,10 @@ code_break()
{ {
register struct stmt_block *stmt_block = stmt_stack; register struct stmt_block *stmt_block = stmt_stack;
if (stmt_block) { if (stmt_block)
C_bra(stmt_block->st_break); C_bra(stmt_block->st_break);
return; else
} error("break not inside for, while, do or switch");
error("break not inside for, while, do or switch");
} }
/* code_continue() generates EM code needed at the occurrence of /* code_continue() generates EM code needed at the occurrence of

View file

@ -1,7 +1,7 @@
/* $Header$ */ /* $Header$ */
/* D E C L A R A T O R M A N I P U L A T I O N */ /* D E C L A R A T O R M A N I P U L A T I O N */
#include "botch_free.h" /* UF */ #include "botch_free.h"
#include "alloc.h" #include "alloc.h"
#include "arith.h" #include "arith.h"
#include "type.h" #include "type.h"

View file

@ -17,7 +17,6 @@
#include "parbufsize.h" #include "parbufsize.h"
#include "textsize.h" #include "textsize.h"
#include "idfsize.h" #include "idfsize.h"
#include "assert.h" #include "assert.h"
#include "alloc.h" #include "alloc.h"
#include "class.h" #include "class.h"
@ -301,14 +300,10 @@ PRIVATE
do_elif() do_elif()
{ {
if (nestlevel < 0 || (ifstack[nestlevel])) { if (nestlevel < 0 || (ifstack[nestlevel])) {
/* invalid elif encountered.. */
lexerror("#elif without corresponding #if"); lexerror("#elif without corresponding #if");
SkipRestOfLine(); SkipRestOfLine();
} }
else { else { /* restart at this level as if a #if is detected. */
/* restart at this level as if a #if
is detected.
*/
nestlevel--; nestlevel--;
push_if(); push_if();
skip_block(); skip_block();
@ -377,8 +372,7 @@ do_undef()
if (id && id->id_macro) { /* forget the macro */ if (id && id->id_macro) { /* forget the macro */
free_macro(id->id_macro); free_macro(id->id_macro);
id->id_macro = (struct macro *) 0; id->id_macro = (struct macro *) 0;
} } /* else: don't complain */
/* else: don't complain */
} }
else else
lexerror("illegal #undef construction"); lexerror("illegal #undef construction");
@ -470,8 +464,7 @@ macro_def(id, text, nformals, length, flags)
if (macroeq(newdef->mc_text, text)) if (macroeq(newdef->mc_text, text))
return; return;
lexwarning("redefine \"%s\"", id->id_text); lexwarning("redefine \"%s\"", id->id_text);
} } /* else: overwrite pre-definition */
/* else: overwrite pre-definition */
} }
else else
id->id_macro = newdef = new_macro(); id->id_macro = newdef = new_macro();

View file

@ -1,17 +1,6 @@
/* $Header$ */ /* $Header$ */
/* EXPRESSION-CODE GENERATOR */ /* EXPRESSION-CODE GENERATOR */
/* main functions :
EVAL() -- expression tree evaluator
tmp_pointer_var() -- deliver temporary pointer variable
free_tmp_var() -- return the pointer var
store_val() -- store primary expression
load_val() -- load primary expression
auxiliary functions:
assop()
compare()
*/
#include "nofloat.h" #include "nofloat.h"
#include <em.h> #include <em.h>
#include "debug.h" #include "debug.h"
@ -40,45 +29,40 @@ char *symbol2str();
char *long2str(); char *long2str();
arith tmp_pointer_var(); arith tmp_pointer_var();
/* EVAL() serves as the main expression tree evaluator, which turns /* EVAL() is the main expression-tree evaluator, which turns
any legal expression tree into legal EM code. any legal expression tree into EM code. Parameters:
The parameters describe how EVAL should treat the expression tree:
struct expr *expr: pointer to root of the expression tree to struct expr *expr
be evaluated pointer to root of the expression tree to be evaluated
int val: indicates whether the resulting expression int val
is to be dereferenced (if val == RVAL and indicates whether the resulting expression is to be
expr->ex_lvalue == 1) or not (val == LVAL). dereferenced (if val == RVAL and expr->ex_lvalue == 1)
The latter case indicates that the resulting or not (val == LVAL). The latter case indicates that
expression is an lvalue expression which should the resulting expression is an lvalue expression which
not be dereferenced by EVAL should not be dereferenced by EVAL
int code: indicates whether the expression tree must be int code
turned into EM code or not. E.g. the expression indicates whether the expression tree must be turned
statement "12;" delivers the expression "12" to into EM code or not. E.g. the expression statement "12;"
EVAL while this should not result in any EM delivers the expression "12" to EVAL while this should
code not result in any EM code
label false_label: label false_label, label true_label
label true_label: if the expression is a logical or relational if the expression is a logical or relational expression
expression and if the loop of the program and if the loop of the program depends on the resulting
depends on the resulting value then EVAL value then EVAL generates jumps to the specified program
generates jumps to the specified program labels, in case they are specified (i.e. are non-zero)
labels, in case they are specified
(i.e. are non-zero)
*/ */
EVAL(expr, val, code, true_label, false_label) EVAL(expr, val, code, true_label, false_label)
register struct expr *expr; /* the expression tree itself */ register struct expr *expr;
int val; /* either RVAL or LVAL */ int val, code;
int code; /* generate explicit code or not */ label true_label, false_label;
label true_label;
label false_label; /* labels to jump to in logical expr's */
{ {
register int gencode = (code == TRUE); register int gencode = (code == TRUE);
switch (expr->ex_class) { switch (expr->ex_class) {
case Value: /* just a simple value */ case Value: /* just a simple value */
if (gencode) if (gencode)
load_val(expr, val); load_val(expr, val);
@ -107,23 +91,22 @@ EVAL(expr, val, code, true_label, false_label)
case Oper: /* compound expression */ case Oper: /* compound expression */
{ {
int oper = expr->OP_OPER; int oper = expr->OP_OPER;
register struct expr *leftop = expr->OP_LEFT; register struct expr *left = expr->OP_LEFT;
register struct expr *rightop = expr->OP_RIGHT; register struct expr *right = expr->OP_RIGHT;
register struct type *tp = expr->OP_TYPE; register struct type *tp = expr->OP_TYPE;
if (tp->tp_fund == ERRONEOUS) /* stop immediately */ if (tp->tp_fund == ERRONEOUS) /* stop immediately */
break; break;
switch (oper) { switch (oper) {
case '+': case '+':
/* We have the following possibilities : /* We have the following possibilities :
int + int, pointer + int, pointer + long, int + int, pointer + int, pointer + long,
long + long, double + double long + long, double + double
*/ */
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) { if (gencode) {
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
if (tp->tp_unsigned) if (tp->tp_unsigned)
@ -132,7 +115,7 @@ EVAL(expr, val, code, true_label, false_label)
C_adi(tp->tp_size); C_adi(tp->tp_size);
break; break;
case POINTER: case POINTER:
C_ads(rightop->ex_type->tp_size); C_ads(right->ex_type->tp_size);
break; break;
#ifndef NOFLOAT #ifndef NOFLOAT
case DOUBLE: case DOUBLE:
@ -145,10 +128,10 @@ EVAL(expr, val, code, true_label, false_label)
} }
break; break;
case '-': case '-':
if (leftop == 0) { /* unary */ if (left == 0) { /* unary */
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) { if (gencode) {
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case POINTER: case POINTER:
@ -165,16 +148,15 @@ EVAL(expr, val, code, true_label, false_label)
} }
break; break;
} }
/* Binary: we have the following flavours: /* else binary; we have the following flavours:
int - int, pointer - int, pointer - long, int - int, pointer - int, pointer - long,
pointer - pointer, long - long, double - double pointer - pointer, long - long, double - double
*/ */
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (!gencode) if (!gencode)
break; break;
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
if (tp->tp_unsigned) if (tp->tp_unsigned)
@ -183,11 +165,11 @@ EVAL(expr, val, code, true_label, false_label)
C_sbi(tp->tp_size); C_sbi(tp->tp_size);
break; break;
case POINTER: case POINTER:
if (rightop->ex_type->tp_fund == POINTER) if (right->ex_type->tp_fund == POINTER)
C_sbs(pointer_size); C_sbs(pointer_size);
else { else {
C_ngi(rightop->ex_type->tp_size); C_ngi(right->ex_type->tp_size);
C_ads(rightop->ex_type->tp_size); C_ads(right->ex_type->tp_size);
} }
break; break;
#ifndef NOFLOAT #ifndef NOFLOAT
@ -200,13 +182,13 @@ EVAL(expr, val, code, true_label, false_label)
} }
break; break;
case '*': case '*':
if (leftop == 0) /* unary */ if (left == 0) /* unary */
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
else { /* binary */ else { /* binary */
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) if (gencode)
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case POINTER: case POINTER:
@ -226,10 +208,10 @@ EVAL(expr, val, code, true_label, false_label)
} }
break; break;
case '/': case '/':
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) if (gencode)
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case POINTER: case POINTER:
@ -248,8 +230,8 @@ EVAL(expr, val, code, true_label, false_label)
} }
break; break;
case '%': case '%':
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG); ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG);
if (gencode) if (gencode)
if (tp->tp_unsigned) if (tp->tp_unsigned)
@ -258,8 +240,8 @@ EVAL(expr, val, code, true_label, false_label)
C_rmi(tp->tp_size); C_rmi(tp->tp_size);
break; break;
case LEFT: case LEFT:
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) if (gencode)
if (tp->tp_unsigned) if (tp->tp_unsigned)
C_slu(tp->tp_size); C_slu(tp->tp_size);
@ -267,8 +249,8 @@ EVAL(expr, val, code, true_label, false_label)
C_sli(tp->tp_size); C_sli(tp->tp_size);
break; break;
case RIGHT: case RIGHT:
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) if (gencode)
if (tp->tp_unsigned) if (tp->tp_unsigned)
C_sru(tp->tp_size); C_sru(tp->tp_size);
@ -281,16 +263,16 @@ EVAL(expr, val, code, true_label, false_label)
case GREATEREQ: case GREATEREQ:
case EQUAL: case EQUAL:
case NOTEQUAL: case NOTEQUAL:
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) { if (gencode) {
/* The operands have the same type */ /* The operands have the same type */
arith size = leftop->ex_type->tp_size; arith size = left->ex_type->tp_size;
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
if (leftop->ex_type->tp_unsigned) if (left->ex_type->tp_unsigned)
C_cmu(size); C_cmu(size);
else else
C_cmi(size); C_cmi(size);
@ -310,11 +292,11 @@ EVAL(expr, val, code, true_label, false_label)
default: default:
CRASH(); CRASH();
} }
if (true_label != 0) { if (true_label != 0) {
compare(oper, true_label); compare(oper, true_label);
C_bra(false_label); C_bra(false_label);
} }
else { else {
label l_true = text_label(); label l_true = text_label();
label l_end = text_label(); label l_end = text_label();
@ -331,14 +313,14 @@ EVAL(expr, val, code, true_label, false_label)
case '|': case '|':
case '^': case '^':
/* both operands should have type int */ /* both operands should have type int */
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) { if (gencode) {
arith size = tp->tp_size; arith size = tp->tp_size;
if (size < word_size) if (size < word_size)
size = word_size; size = word_size;
switch (oper) { switch (oper) {
case '&': case '&':
C_and(size); C_and(size);
break; break;
@ -353,26 +335,21 @@ EVAL(expr, val, code, true_label, false_label)
break; break;
case '=': case '=':
#ifndef NOBITFIELD #ifndef NOBITFIELD
if (leftop->ex_type->tp_fund == FIELD) { if (left->ex_type->tp_fund == FIELD) {
/* assignment to bitfield variable
*/
eval_field(expr, code); eval_field(expr, code);
break; break;
} }
#endif NOBITFIELD #endif NOBITFIELD
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
if (gencode) if (gencode)
C_dup(ATW(tp->tp_size)); C_dup(ATW(tp->tp_size));
if (left->ex_class != Value) {
if (leftop->ex_class != Value) { EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
store_block(tp->tp_size, tp->tp_align); store_block(tp->tp_size, tp->tp_align);
} }
else else
store_val( store_val(&(left->ex_object.ex_value),
&(leftop->ex_object.ex_value), left->ex_type);
leftop->ex_type
);
break; break;
case PLUSAB: case PLUSAB:
case MINAB: case MINAB:
@ -384,47 +361,60 @@ EVAL(expr, val, code, true_label, false_label)
case ANDAB: case ANDAB:
case XORAB: case XORAB:
case ORAB: case ORAB:
case POSTINCR:
case POSTDECR:
case PLUSPLUS:
case MINMIN:
{ {
arith old_offset; arith old_offset, tmp;
arith tmpvar = tmp_pointer_var(&old_offset); int compl; /* Complexity of left operand */
#ifndef NOBITFIELD #ifndef NOBITFIELD
if (leftop->ex_type->tp_fund == FIELD) { if (left->ex_type->tp_fund == FIELD) {
eval_field(expr, code); eval_field(expr, code);
break; break;
} }
#endif NOBITFIELD #endif NOBITFIELD
if (leftop->ex_class != Value) { if (left->ex_class == Value) {
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); compl = 0; /* Value */
C_lal(tmpvar); load_val(left, RVAL);
C_sti(pointer_size);
C_lal(tmpvar);
C_loi(pointer_size);
C_loi(leftop->ex_type->tp_size);
} }
else { else
load_val(leftop, RVAL); if (left->ex_depth == 1 && left->OP_OPER == ARROW) {
} compl = 1; /* Value->sel */
conversion(leftop->ex_type, tp); ASSERT(left->OP_LEFT->ex_class == Value);
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); EVAL(left, RVAL, TRUE, NO_LABEL, NO_LABEL);
assop(tp, oper);
conversion(tp, leftop->ex_type);
if (gencode)
C_dup(toword(leftop->ex_type->tp_size));
if (leftop->ex_class != Value) {
C_lal(tmpvar);
C_loi(pointer_size);
C_sti(leftop->ex_type->tp_size);
free_tmp_var(old_offset);
} }
else { else {
store_val( compl = 2; /* otherwise */
&(leftop->ex_object.ex_value), tmp = tmp_pointer_var(&old_offset);
leftop->ex_type EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
); C_dup(pointer_size);
C_lal(tmp);
C_sti(pointer_size);
C_loi(left->ex_type->tp_size);
}
conversion(left->ex_type, tp);
if (gencode && (oper == POSTINCR || oper == POSTDECR))
C_dup(tp->tp_size);
EVAL(right, RVAL, TRUE, NO_LABEL, NO_LABEL);
assop(tp, oper);
if (gencode && oper != POSTINCR && oper != POSTDECR)
C_dup(tp->tp_size);
conversion(tp, left->ex_type);
if (compl == 0)
store_val(&(left->ex_object.ex_value),
left->ex_type);
else
if (compl == 1) {
EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
C_sti(left->ex_type->tp_size);
}
else {
C_lal(tmp); /* always init'd */
C_loi(pointer_size);
C_sti(left->ex_type->tp_size);
free_tmp_var(old_offset);
} }
if (gencode)
conversion(leftop->ex_type, expr->ex_type);
break; break;
} }
case '(': case '(':
@ -432,7 +422,7 @@ EVAL(expr, val, code, true_label, false_label)
register struct expr *ex; register struct expr *ex;
arith ParSize = (arith)0; arith ParSize = (arith)0;
if ((ex = rightop) != NILEXPR) { if ((ex = right) != NILEXPR) {
/* function call with parameters*/ /* function call with parameters*/
while ( ex->ex_class == Oper && while ( ex->ex_class == Oper &&
ex->OP_OPER == PARCOMMA ex->OP_OPER == PARCOMMA
@ -445,24 +435,19 @@ EVAL(expr, val, code, true_label, false_label)
EVAL(ex, RVAL, TRUE, NO_LABEL, NO_LABEL); EVAL(ex, RVAL, TRUE, NO_LABEL, NO_LABEL);
ParSize += ATW(ex->ex_type->tp_size); ParSize += ATW(ex->ex_type->tp_size);
} }
if ( leftop->ex_class == Value if (left->ex_class == Value && left->VL_CLASS == Name) {
&& leftop->VL_CLASS == Name /* e.g., main() { (*((int (*)())0))(); } */
) { C_cal(left->VL_IDF->id_text);
/* just an example:
main() { (*((int (*)())0))(); }
*/
C_cal(leftop->VL_IDF->id_text);
#ifdef DATAFLOW #ifdef DATAFLOW
{ extern char options[]; { extern char options[];
if (options['d']) if (options['d'])
DfaCallFunction( DfaCallFunction(
leftop->VL_IDF->id_text left->VL_IDF->id_text);
);
} }
#endif DATAFLOW #endif DATAFLOW
} }
else { else {
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
C_cai(); C_cai();
} }
/* remove parameters from stack */ /* remove parameters from stack */
@ -479,124 +464,53 @@ EVAL(expr, val, code, true_label, false_label)
break; break;
} }
case '.': case '.':
EVAL(leftop, LVAL, code, NO_LABEL, NO_LABEL); EVAL(left, LVAL, code, NO_LABEL, NO_LABEL);
ASSERT(is_cp_cst(rightop)); ASSERT(is_cp_cst(right));
if (gencode) if (gencode)
C_adp(rightop->VL_VALUE); C_adp(right->VL_VALUE);
break; break;
case ARROW: case ARROW:
EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(left, RVAL, code, NO_LABEL, NO_LABEL);
ASSERT(is_cp_cst(rightop)); ASSERT(is_cp_cst(right));
if (gencode) if (gencode)
C_adp(rightop->VL_VALUE); C_adp(right->VL_VALUE);
break; break;
case ',': case ',':
EVAL(leftop, RVAL, FALSE, NO_LABEL, NO_LABEL); EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL);
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
break; break;
case '~': case '~':
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) if (gencode)
C_com(tp->tp_size); C_com(tp->tp_size);
break; break;
case POSTINCR:
case POSTDECR:
case PLUSPLUS:
case MINMIN:
{
arith old_offset, tmp;
arith esize = tp->tp_size;
int compl; /* Complexity of left operand */
#ifndef NOBITFIELD
if (leftop->ex_type->tp_fund == FIELD) {
eval_field(expr, code);
break;
}
#endif NOBITFIELD
if (leftop->ex_class == Value) {
compl = 0; /* Value */
load_val(leftop, RVAL);
}
else
if (leftop->ex_depth == 1 && leftop->OP_OPER == ARROW) {
compl = 1; /* Value->sel */
ASSERT(leftop->OP_LEFT->ex_class == Value);
EVAL(leftop, RVAL, TRUE, NO_LABEL, NO_LABEL);
}
else {
compl = 2; /* otherwise */
tmp = tmp_pointer_var(&old_offset);
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
C_dup(pointer_size);
C_lal(tmp);
C_sti(pointer_size);
C_loi(esize);
}
/* We made the choice to put this stuff here
and not to put the conversion in the expression
tree because this conversion is EM dependent
and not described in C
*/
if (esize < word_size) {
conversion(tp, word_type);
esize = word_size;
}
if (gencode && (oper == POSTINCR || oper == POSTDECR))
C_dup(esize);
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
assop(tp, oper);
if (gencode && (oper == PLUSPLUS || oper == MINMIN))
C_dup(esize);
if (tp->tp_size < word_size)
conversion(word_type, tp);
if (compl == 0) {
store_val(
&(leftop->ex_object.ex_value),
leftop->ex_type
);
}
else
if (compl == 1) {
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
C_sti(tp->tp_size);
}
else {
C_lal(tmp); /* always init'd */
C_loi(pointer_size);
C_sti(tp->tp_size);
free_tmp_var(old_offset);
}
break;
}
case '?': /* must be followed by ':' */ case '?': /* must be followed by ':' */
{ {
label l_true = text_label(); label l_true = text_label();
label l_false = text_label(); label l_false = text_label();
label l_end = text_label(); label l_end = text_label();
EVAL(leftop, RVAL, TRUE, l_true, l_false); EVAL(left, RVAL, TRUE, l_true, l_false);
C_df_ilb(l_true); C_df_ilb(l_true);
EVAL(rightop->OP_LEFT, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right->OP_LEFT, RVAL, code, NO_LABEL, NO_LABEL);
C_bra(l_end); C_bra(l_end);
C_df_ilb(l_false); C_df_ilb(l_false);
EVAL(rightop->OP_RIGHT, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right->OP_RIGHT, RVAL, code, NO_LABEL, NO_LABEL);
C_df_ilb(l_end); C_df_ilb(l_end);
break; break;
} }
case AND: case AND:
if (true_label == 0) { if (true_label == 0) {
label l_true = text_label(); label l_true = text_label();
label l_false = text_label(); label l_false = text_label();
label l_maybe = text_label(); label l_maybe = text_label();
label l_end = text_label(); label l_end = text_label();
EVAL(leftop, RVAL, TRUE, l_maybe, l_false); EVAL(left, RVAL, TRUE, l_maybe, l_false);
C_df_ilb(l_maybe); C_df_ilb(l_maybe);
if (gencode) { if (gencode) {
EVAL(rightop, RVAL, TRUE, EVAL(right, RVAL, TRUE, l_true,
l_true, l_false); l_false);
C_df_ilb(l_true); C_df_ilb(l_true);
C_loc((arith)1); C_loc((arith)1);
C_bra(l_end); C_bra(l_end);
@ -605,32 +519,32 @@ EVAL(expr, val, code, true_label, false_label)
C_df_ilb(l_end); C_df_ilb(l_end);
} }
else { else {
EVAL(rightop, RVAL, FALSE, l_false, EVAL(right, RVAL, FALSE, l_false,
l_false); l_false);
C_df_ilb(l_false); C_df_ilb(l_false);
} }
} }
else { else {
label l_maybe = text_label(); label l_maybe = text_label();
EVAL(leftop, RVAL, TRUE, l_maybe, false_label); EVAL(left, RVAL, TRUE, l_maybe, false_label);
C_df_ilb(l_maybe); C_df_ilb(l_maybe);
EVAL(rightop, RVAL, code, true_label, EVAL(right, RVAL, code, true_label,
false_label); false_label);
} }
break; break;
case OR: case OR:
if (true_label == 0) { if (true_label == 0) {
label l_true = text_label(); label l_true = text_label();
label l_false = text_label(); label l_false = text_label();
label l_maybe = text_label(); label l_maybe = text_label();
label l_end = text_label(); label l_end = text_label();
EVAL(leftop, RVAL, TRUE, l_true, l_maybe); EVAL(left, RVAL, TRUE, l_true, l_maybe);
C_df_ilb(l_maybe); C_df_ilb(l_maybe);
if (gencode) { if (gencode) {
EVAL(rightop, RVAL, TRUE, EVAL(right, RVAL, TRUE, l_true,
l_true, l_false); l_false);
C_df_ilb(l_false); C_df_ilb(l_false);
C_loc((arith)0); C_loc((arith)0);
C_bra(l_end); C_bra(l_end);
@ -638,30 +552,30 @@ EVAL(expr, val, code, true_label, false_label)
C_loc((arith)1); C_loc((arith)1);
C_df_ilb(l_end); C_df_ilb(l_end);
} }
else { else {
EVAL(rightop, RVAL, FALSE, l_true, EVAL(right, RVAL, FALSE, l_true,
l_true); l_true);
C_df_ilb(l_true); C_df_ilb(l_true);
} }
} }
else { else {
label l_maybe = text_label(); label l_maybe = text_label();
EVAL(leftop, RVAL, TRUE, true_label, l_maybe); EVAL(left, RVAL, TRUE, true_label, l_maybe);
C_df_ilb(l_maybe); C_df_ilb(l_maybe);
EVAL(rightop, RVAL, code, true_label, EVAL(right, RVAL, code, true_label,
false_label); false_label);
} }
break; break;
case '!': case '!':
if (true_label == 0) { if (true_label == 0) {
if (gencode) { if (gencode) {
label l_true = text_label(); label l_true = text_label();
label l_false = text_label(); label l_false = text_label();
label l_end = text_label(); label l_end = text_label();
EVAL(rightop, RVAL, TRUE, EVAL(right, RVAL, TRUE, l_false,
l_false, l_true); l_true);
C_df_ilb(l_false); C_df_ilb(l_false);
C_loc((arith)0); C_loc((arith)0);
C_bra(l_end); C_bra(l_end);
@ -670,11 +584,11 @@ EVAL(expr, val, code, true_label, false_label)
C_df_ilb(l_end); C_df_ilb(l_end);
} }
else else
EVAL(rightop, RVAL, FALSE, EVAL(right, RVAL, FALSE, NO_LABEL,
NO_LABEL, NO_LABEL); NO_LABEL);
} }
else else
EVAL(rightop, RVAL, code, false_label, EVAL(right, RVAL, code, false_label,
true_label); true_label);
break; break;
case INT2INT: case INT2INT:
@ -683,14 +597,13 @@ EVAL(expr, val, code, true_label, false_label)
case FLOAT2INT: case FLOAT2INT:
case FLOAT2FLOAT: case FLOAT2FLOAT:
#endif NOFLOAT #endif NOFLOAT
EVAL(rightop, RVAL, code, NO_LABEL, NO_LABEL); EVAL(right, RVAL, code, NO_LABEL, NO_LABEL);
if (gencode) if (gencode)
conversion(rightop->ex_type, leftop->ex_type); conversion(right->ex_type, left->ex_type);
break; break;
default: default:
crash("(EVAL) bad operator %s\n", symbol2str(oper)); crash("(EVAL) bad operator %s\n", symbol2str(oper));
} }
/* If the rvalue of the expression is required but /* If the rvalue of the expression is required but
only its lvalue is evaluated, its rvalue is only its lvalue is evaluated, its rvalue is
loaded by the following statements: loaded by the following statements:
@ -710,7 +623,7 @@ compare(relop, lbl)
int relop; int relop;
label lbl; label lbl;
{ {
switch (relop) { switch (relop) {
case '<': case '<':
C_zlt(lbl); C_zlt(lbl);
break; break;
@ -744,13 +657,13 @@ assop(type, oper)
if ((size = type->tp_size) < word_size) if ((size = type->tp_size) < word_size)
size = word_size; size = word_size;
switch (type->tp_fund) { switch (type->tp_fund) {
case CHAR: case CHAR:
case SHORT: case SHORT:
case INT: case INT:
case LONG: case LONG:
case ENUM: case ENUM:
switch (oper) { switch (oper) {
case PLUSAB: case PLUSAB:
case PLUSPLUS: case PLUSPLUS:
case POSTINCR: case POSTINCR:
@ -811,7 +724,7 @@ assop(type, oper)
#ifndef NOFLOAT #ifndef NOFLOAT
case FLOAT: case FLOAT:
case DOUBLE: case DOUBLE:
switch (oper) { switch (oper) {
case PLUSAB: case PLUSAB:
case PLUSPLUS: case PLUSPLUS:
case POSTINCR: case POSTINCR:
@ -888,21 +801,19 @@ store_val(vl, tp)
register int indword; register int indword;
arith val = vl->vl_value; arith val = vl->vl_value;
if (vl->vl_class == Const) { /* absolute addressing */ if (vl->vl_class == Const) { /* absolute addressing */
load_cst(val, pointer_size); load_cst(val, pointer_size);
store_block(size, tpalign); store_block(size, tpalign);
return; return;
} }
al_on_word = (tpalign % word_align == 0); al_on_word = (tpalign % word_align == 0);
if (!(inword = (size == word_size && al_on_word))) if (!(inword = (size == word_size && al_on_word)))
indword = (size == dword_size && al_on_word); indword = (size == dword_size && al_on_word);
if (vl->vl_class == Name) {
if (vl->vl_class == Name) {
register struct idf *id = vl->vl_data.vl_idf; register struct idf *id = vl->vl_data.vl_idf;
register struct def *df = id->id_def; register struct def *df = id->id_def;
if (df->df_level == L_GLOBAL) { if (df->df_level == L_GLOBAL) {
if (inword) if (inword)
C_ste_dnam(id->id_text, val); C_ste_dnam(id->id_text, val);
else else
@ -920,7 +831,7 @@ store_val(vl, tp)
else else
if (indword) if (indword)
C_sdl(df->df_address + val); C_sdl(df->df_address + val);
else { else {
C_lal(df->df_address + val); C_lal(df->df_address + val);
store_block(size, tpalign); store_block(size, tpalign);
df->df_register = REG_NONE; df->df_register = REG_NONE;
@ -965,8 +876,8 @@ load_val(expr, val)
register int inword, indword; register int inword, indword;
arith val = expr->VL_VALUE; arith val = expr->VL_VALUE;
if (expr->VL_CLASS == Const) { if (expr->VL_CLASS == Const) {
if (rvalue) { /* absolute addressing */ if (rvalue) { /* absolute addressing */
load_cst(val, pointer_size); load_cst(val, pointer_size);
load_block(size, tpalign); load_block(size, tpalign);
} }
@ -980,7 +891,7 @@ load_val(expr, val)
indword = (size == dword_size && al_on_word); indword = (size == dword_size && al_on_word);
} }
if (expr->VL_CLASS == Label) { if (expr->VL_CLASS == Label) {
if (rvalue) { if (rvalue) {
if (inword) if (inword)
C_loe_dlb(expr->VL_LBL, val); C_loe_dlb(expr->VL_LBL, val);
else else
@ -992,7 +903,7 @@ load_val(expr, val)
} }
} }
else { else {
C_lae_dlb(expr->VL_LBL, (arith)0); C_lae_dlb(expr->VL_LBL, (arith)0);
C_adp(val); C_adp(val);
} }
@ -1010,8 +921,8 @@ load_val(expr, val)
*/ */
C_lpi(id->id_text); C_lpi(id->id_text);
else else
if (df->df_level == L_GLOBAL) { if (df->df_level == L_GLOBAL) {
if (rvalue) { if (rvalue) {
if (inword) if (inword)
C_loe_dnam(id->id_text, val); C_loe_dnam(id->id_text, val);
else else
@ -1022,14 +933,14 @@ load_val(expr, val)
load_block(size, tpalign); load_block(size, tpalign);
} }
} }
else { else {
C_lae_dnam(id->id_text, (arith)0); C_lae_dnam(id->id_text, (arith)0);
C_adp(val); C_adp(val);
} }
} }
else { else {
ASSERT(df->df_sc != STATIC); ASSERT(df->df_sc != STATIC);
if (rvalue) { if (rvalue) {
if (inword) if (inword)
C_lol(df->df_address + val); C_lol(df->df_address + val);
else else
@ -1041,7 +952,7 @@ load_val(expr, val)
df->df_register = REG_NONE; df->df_register = REG_NONE;
} }
} }
else { else {
C_lal(df->df_address); C_lal(df->df_address);
C_adp(val); C_adp(val);
df->df_register = REG_NONE; df->df_register = REG_NONE;

View file

@ -92,14 +92,14 @@ rank_of(oper)
} }
int int
rank_of_expression(expr) rank_of_expression(ex)
register struct expr *expr; register struct expr *ex;
{ {
/* Returns the rank of the top node in the expression. /* Returns the rank of the top node in the expression.
*/ */
if (!expr || (expr->ex_flags & EX_PARENS) || expr->ex_class != Oper) if (!ex || (ex->ex_flags & EX_PARENS) || ex->ex_class != Oper)
return 0; return 0;
return rank_of(expr->OP_OPER); return rank_of(ex->OP_OPER);
} }
check_conditional(expr, oper, pos_descr) check_conditional(expr, oper, pos_descr)
@ -158,15 +158,12 @@ idf2expr(expr)
register struct def *def = idf->id_def; register struct def *def = idf->id_def;
if (def == 0) { if (def == 0) {
if (AHEAD == '(') { if (AHEAD == '(') /* function call, declare name IMPLICITly */
/* Function call, so declare the name IMPLICITly. */ add_def(idf, IMPLICIT, funint_type, level); /* RM 13 */
/* See RM 13. */
add_def(idf, IMPLICIT, funint_type, level);
}
else { else {
if (!is_anon_idf(idf)) if (!is_anon_idf(idf))
error("%s undefined", idf->id_text); error("%s undefined", idf->id_text);
/* Declare the idf anyway */ /* declare idf anyway */
add_def(idf, 0, error_type, level); add_def(idf, 0, error_type, level);
} }
def = idf->id_def; def = idf->id_def;
@ -254,25 +251,24 @@ intexpr(ivalue, fund)
clear((char *)expr, sizeof(struct expr)); clear((char *)expr, sizeof(struct expr));
expr->ex_file = dot.tk_file; expr->ex_file = dot.tk_file;
expr->ex_line = dot.tk_line; expr->ex_line = dot.tk_line;
fill_int_expr(expr, ivalue, fund); fill_int_expr(expr, ivalue, fund);
return expr; return expr;
} }
fill_int_expr(expr, ivalue, fund) fill_int_expr(ex, ivalue, fund)
register struct expr *expr; register struct expr *ex;
arith ivalue; arith ivalue;
int fund; int fund;
{ {
/* Details derived from ivalue and fund are put into the /* Details derived from ivalue and fund are put into the
constant integer expression expr. constant integer expression ex.
*/ */
switch (fund) { switch (fund) {
case INT: case INT:
expr->ex_type = int_type; ex->ex_type = int_type;
break; break;
case LONG: case LONG:
expr->ex_type = long_type; ex->ex_type = long_type;
break; break;
case UNSIGNED: case UNSIGNED:
/* We cannot make a test like /* We cannot make a test like
@ -284,20 +280,18 @@ fill_int_expr(expr, ivalue, fund)
answer. We assume that the type "unsigned long" answer. We assume that the type "unsigned long"
is not part of portable C ! is not part of portable C !
*/ */
expr->ex_type = ex->ex_type = (ivalue & ~max_unsigned) ? long_type : uint_type;
(ivalue & ~max_unsigned) ? long_type : uint_type;
break; break;
case INTEGER: case INTEGER:
expr->ex_type = (ivalue <= max_int) ? int_type : long_type; ex->ex_type = (ivalue <= max_int) ? int_type : long_type;
break; break;
default: default:
crash("(intexpr) bad fund %s\n", symbol2str(fund)); crash("(intexpr) bad fund %s\n", symbol2str(fund));
} }
expr->ex_class = Value; ex->ex_class = Value;
expr->VL_CLASS = Const; ex->VL_CLASS = Const;
expr->VL_VALUE = ivalue; ex->VL_VALUE = ivalue;
cut_size(ex);
cut_size(expr);
} }
struct expr * struct expr *
@ -344,8 +338,7 @@ new_oper(tp, e1, oper, e2)
int e1_flags = e1 ? e1->ex_flags : 0; int e1_flags = e1 ? e1->ex_flags : 0;
expr->ex_depth = expr->ex_depth =
(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) (e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1;
+ 1;
expr->ex_flags = (e1_flags | e2->ex_flags) & ~EX_PARENS; expr->ex_flags = (e1_flags | e2->ex_flags) & ~EX_PARENS;
} }
op = &expr->ex_object.ex_oper; op = &expr->ex_object.ex_oper;
@ -353,7 +346,6 @@ new_oper(tp, e1, oper, e2)
op->op_oper = oper; op->op_oper = oper;
op->op_left = e1; op->op_left = e1;
op->op_right = e2; op->op_right = e2;
return expr; return expr;
} }
@ -397,17 +389,14 @@ chk_cst_expr(expp)
#endif DEBUG #endif DEBUG
if ( fund != CHAR && fund != SHORT && fund != INT && if ( fund != CHAR && fund != SHORT && fund != INT &&
fund != ENUM && fund != LONG fund != ENUM && fund != LONG
) { )
expr_error(expr, "non-numerical constant expression"), err++; expr_error(expr, "non-numerical constant expression"), err++;
}
else else
if (!is_ld_cst(expr)) if (!is_ld_cst(expr))
expr_error(expr, "expression is not constant"), err++; expr_error(expr, "expression is not constant"), err++;
if (options['R']) { if (options['R']) {
if (flags & EX_CAST) if (flags & EX_CAST)
expr_warning(expr, expr_warning(expr, "cast in constant expression");
"cast in constant expression");
if (flags & EX_LOGICAL) if (flags & EX_LOGICAL)
expr_warning(expr, expr_warning(expr,
"logical operator in constant expression"); "logical operator in constant expression");
@ -475,11 +464,11 @@ free_expression(expr)
{ {
/* The expression expr is freed recursively. /* The expression expr is freed recursively.
*/ */
if (!expr) if (expr) {
return; if (expr->ex_class == Oper) {
if (expr->ex_class == Oper) { free_expression(expr->OP_LEFT);
free_expression(expr->OP_LEFT); free_expression(expr->OP_RIGHT);
free_expression(expr->OP_RIGHT); }
free_expr(expr);
} }
free_expr(expr);
} }

View file

@ -5,9 +5,7 @@
#ifndef NOBITFIELD #ifndef NOBITFIELD
#include <em.h> #include <em.h>
#include "debug.h" #include "debug.h"
#include "arith.h" #include "arith.h"
#include "type.h" #include "type.h"
#include "idf.h" #include "idf.h"
@ -27,39 +25,33 @@ char *symbol2str(); /* symbol2str.c */
tree and are therefore dealt with in this function. tree and are therefore dealt with in this function.
The actions taken at any operation are described clearly by the The actions taken at any operation are described clearly by the
code for this actions. code for this actions.
Note: the bitfields are packed in target machine integers! Notes
[1] the bitfields are packed in target machine integers!
[2] op is either an assignment operator or an increment/
decrement operator
[3] atype: the type in which the bitfield arithmetic is done;
and in which bitfields are stored!
*/ */
eval_field(expr, code) eval_field(expr, code)
struct expr *expr; struct expr *expr;
int code; int code;
{ {
int op = expr->OP_OPER; int op = expr->OP_OPER;
struct expr *leftop = expr->OP_LEFT; register struct expr *leftop = expr->OP_LEFT;
struct expr *rightop = expr->OP_RIGHT; register struct expr *rightop = expr->OP_RIGHT;
struct field *fd = leftop->ex_type->tp_field; register struct field *fd = leftop->ex_type->tp_field;
struct type *tp = leftop->ex_type->tp_up; struct type *tp = leftop->ex_type->tp_up;
arith old_offset, tmpvar; arith old_offset, tmpvar;
/* The type in which the bitfield arithmetic is done;
AND IN WHICH BITFIELDS ARE STORED!
*/
struct type *atype = tp->tp_unsigned ? uword_type : word_type; struct type *atype = tp->tp_unsigned ? uword_type : word_type;
arith asize = atype->tp_size; arith asize = atype->tp_size;
/* First some assertions to be sure that the rest is legal */ /* First some assertions to be sure that the rest is legal */
ASSERT(asize == word_size); /* make sure that C_loc() is legal */ ASSERT(asize == word_size); /* make sure that C_loc() is legal */
ASSERT(leftop->ex_type->tp_fund == FIELD); ASSERT(leftop->ex_type->tp_fund == FIELD);
leftop->ex_type = atype; /* this is cheating but it works... */ leftop->ex_type = atype; /* this is cheating but it works... */
/* Note that op is either an assignment operator or an increment/
decrement operator
*/
if (op == '=') { if (op == '=') {
/* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) /* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) */
*/
ASSERT(tp == rightop->ex_type); ASSERT(tp == rightop->ex_type);
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
conversion(tp, atype); conversion(tp, atype);
C_loc(fd->fd_mask); C_loc(fd->fd_mask);
@ -116,10 +108,9 @@ eval_field(expr, code)
C_and(asize); C_and(asize);
if (code == TRUE && (op == POSTINCR || op == POSTDECR)) if (code == TRUE && (op == POSTINCR || op == POSTDECR))
C_dup(asize); C_dup(asize);
/* the 'op' operation: */
conversion(atype, rightop->ex_type); conversion(atype, rightop->ex_type);
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
/* the 'op' operation: */
if (op == PLUSPLUS || op == POSTINCR) if (op == PLUSPLUS || op == POSTINCR)
assop(rightop->ex_type, PLUSAB); assop(rightop->ex_type, PLUSAB);
else else
@ -128,7 +119,6 @@ eval_field(expr, code)
else else
assop(rightop->ex_type, op); assop(rightop->ex_type, op);
conversion(rightop->ex_type, atype); conversion(rightop->ex_type, atype);
C_loc(fd->fd_mask); C_loc(fd->fd_mask);
C_and(asize); C_and(asize);
if (code == TRUE && op != POSTINCR && op != POSTDECR) if (code == TRUE && op != POSTINCR && op != POSTDECR)

View file

@ -201,7 +201,6 @@ declare_idf(ds, dc, lvl)
/* some additional work for formal definitions */ /* some additional work for formal definitions */
if (lvl == L_FORMAL2) { if (lvl == L_FORMAL2) {
switch (type->tp_fund) { switch (type->tp_fund) {
case FUNCTION: case FUNCTION:
warning("%s is a function; cannot be formal", warning("%s is a function; cannot be formal",
idf->id_text); idf->id_text);
@ -227,7 +226,6 @@ declare_idf(ds, dc, lvl)
break; break;
} }
} }
/* The tests on types, postponed from do_decspecs(), can now /* The tests on types, postponed from do_decspecs(), can now
be performed. be performed.
*/ */
@ -241,23 +239,15 @@ declare_idf(ds, dc, lvl)
ds->ds_sc = sc = GLOBAL; ds->ds_sc = sc = GLOBAL;
} }
} }
else { /* non-FUNCTION */ else /* non-FUNCTION */
if (sc == 0) if (sc == 0)
sc = sc = lvl == L_GLOBAL ? GLOBAL
lvl == L_GLOBAL ? : lvl == L_FORMAL1 || lvl == L_FORMAL2 ? FORMAL
GLOBAL : : AUTO;
lvl == L_FORMAL1 || lvl == L_FORMAL2 ? if (options['R']) { /* some special K & R tests */
FORMAL :
AUTO;
}
if (options['R']) {
/* some special K & R tests */
/* is it also an enum? */ /* is it also an enum? */
if (idf->id_enum && idf->id_enum->tg_level == level) if (idf->id_enum && idf->id_enum->tg_level == level)
warning("%s is also an enum tag", idf->id_text); warning("%s is also an enum tag", idf->id_text);
/* is it a universal typedef? */ /* is it a universal typedef? */
if (def && def->df_level == L_UNIVERSAL) if (def && def->df_level == L_UNIVERSAL)
warning("redeclaring reserved word %s", idf->id_text); warning("redeclaring reserved word %s", idf->id_text);
@ -299,15 +289,13 @@ declare_idf(ds, dc, lvl)
*/ */
if ( options['R'] && if ( options['R'] &&
(sc == STATIC && type->tp_fund == FUNCTION) (sc == STATIC && type->tp_fund == FUNCTION)
) { )
if (!is_anon_idf(idf)) if (!is_anon_idf(idf))
warning("non-global static function %s", warning("non-global static function %s",
idf->id_text); idf->id_text);
}
declare_idf(ds, dc, L_GLOBAL); declare_idf(ds, dc, L_GLOBAL);
} }
else { else { /* fill in the def block */
/* fill in the def block */
register struct def *newdef = new_def(); register struct def *newdef = new_def();
clear((char *)newdef, sizeof(struct def)); clear((char *)newdef, sizeof(struct def));
@ -315,24 +303,19 @@ declare_idf(ds, dc, lvl)
newdef->df_level = lvl; newdef->df_level = lvl;
newdef->df_type = type; newdef->df_type = type;
newdef->df_sc = sc; newdef->df_sc = sc;
/* link it into the name list in the proper place */ /* link it into the name list in the proper place */
idf->id_def = newdef; idf->id_def = newdef;
update_ahead(idf); update_ahead(idf);
stack_idf(idf, stl); stack_idf(idf, stl);
/* We now calculate the address. /* We now calculate the address.
Globals have names and don't get addresses, they Globals have names and don't get addresses, they
get numbers instead (through data_label()). get numbers instead (through data_label()).
Formals are handled by declare_formals(). Formals are handled by declare_formals().
So here we hand out local addresses only. So here we hand out local addresses only.
*/ */
if (lvl >= L_LOCAL) { if (lvl >= L_LOCAL) {
ASSERT(sc);
switch (sc) { switch (sc) {
case 0:
crash("local sc == 0");
break;
case REGISTER: case REGISTER:
case AUTO: case AUTO:
if (type->tp_size == (arith)-1) { if (type->tp_size == (arith)-1) {
@ -341,8 +324,8 @@ declare_idf(ds, dc, lvl)
/** type = idf->id_def->df_type = int_type; **/ /** type = idf->id_def->df_type = int_type; **/
} }
idf->id_def->df_register = idf->id_def->df_register =
(sc == REGISTER) (sc == REGISTER) ? REG_BONUS
? REG_BONUS : REG_DEFAULT; : REG_DEFAULT;
idf->id_def->df_address = idf->id_def->df_address =
stl->sl_max_block = stl->sl_max_block =
stl->sl_local_offset = stl->sl_local_offset =
@ -358,17 +341,17 @@ declare_idf(ds, dc, lvl)
} }
actual_declaration(sc, tp) actual_declaration(sc, tp)
int sc;
struct type *tp; struct type *tp;
{ {
/* An actual_declaration needs space, right here and now. /* An actual_declaration needs space, right here and now.
*/ */
register int fund = tp->tp_fund; register int fund = tp->tp_fund;
/* virtual declarations */ if (sc == ENUM || sc == TYPEDEF) /* virtual declarations */
if (sc == ENUM || sc == TYPEDEF)
return 0; return 0;
/* allocation solved in other ways */
if (fund == FUNCTION || fund == ARRAY) if (fund == FUNCTION || fund == ARRAY)
/* allocation solved in other ways */
return 0; return 0;
/* to be allocated */ /* to be allocated */
return 1; return 1;
@ -388,7 +371,6 @@ global_redecl(idf, new_sc, tp)
if (tp != def->df_type) { if (tp != def->df_type) {
register struct type *otp = def->df_type; register struct type *otp = def->df_type;
if ( tp->tp_fund != ARRAY || otp->tp_fund != ARRAY || if ( tp->tp_fund != ARRAY || otp->tp_fund != ARRAY ||
tp->tp_up != otp->tp_up tp->tp_up != otp->tp_up
) { ) {
@ -409,9 +391,8 @@ global_redecl(idf, new_sc, tp)
error("inconsistent size in redeclaration of array %s", error("inconsistent size in redeclaration of array %s",
idf->id_text); idf->id_text);
} }
/* Now we may be able to update the storage class.
/* Now we may be able to update the storage class. */ Clean out this mess as soon as we know all the possibilities
/* Clean out this mess as soon as we know all the possibilities
for new_sc. for new_sc.
For now we have: For now we have:
EXTERN: we have seen the word "extern" EXTERN: we have seen the word "extern"
@ -424,7 +405,6 @@ global_redecl(idf, new_sc, tp)
*/ */
if (new_sc == IMPLICIT) if (new_sc == IMPLICIT)
return; /* no new information */ return; /* no new information */
switch (def->df_sc) { /* the old storage class */ switch (def->df_sc) { /* the old storage class */
case EXTERN: case EXTERN:
switch (new_sc) { /* the new storage class */ switch (new_sc) { /* the new storage class */
@ -456,10 +436,9 @@ global_redecl(idf, new_sc, tp)
case GLOBAL: case GLOBAL:
break; break;
case STATIC: case STATIC:
if (def->df_initialized) { if (def->df_initialized)
error("cannot redeclare %s to static", error("cannot redeclare %s to static",
idf->id_text); idf->id_text);
}
else { else {
if (options['R']) if (options['R'])
warning("%s redeclared to static", warning("%s redeclared to static",
@ -475,10 +454,9 @@ global_redecl(idf, new_sc, tp)
case STATIC: case STATIC:
switch (new_sc) { /* the new storage class */ switch (new_sc) { /* the new storage class */
case EXTERN: case EXTERN:
if (def->df_initialized) { if (def->df_initialized)
error("cannot redeclare %s to extern", error("cannot redeclare %s to extern",
idf->id_text); idf->id_text);
}
else { else {
warning("%s redeclared to extern", warning("%s redeclared to extern",
idf->id_text); idf->id_text);
@ -531,11 +509,9 @@ good_formal(def, idf)
/* Succeeds if def is a proper L_FORMAL1 definition and /* Succeeds if def is a proper L_FORMAL1 definition and
gives an error message otherwise. gives an error message otherwise.
*/ */
if (!def || def->df_level != L_FORMAL1) { if (!def || def->df_level != L_FORMAL1) { /* not in parameter list */
/* not in parameter list */
if (!is_anon_idf(idf)) if (!is_anon_idf(idf))
error("%s not in parameter list", error("%s not in parameter list", idf->id_text);
idf->id_text);
return 0; return 0;
} }
return 1; return 1;
@ -610,17 +586,12 @@ declare_formals(fp)
register struct def *def = se->se_idf->id_def; register struct def *def = se->se_idf->id_def;
def->df_address = f_offset; def->df_address = f_offset;
/* the alignment convention for parameters is: align on /* the alignment convention for parameters is: align on
word boundaries, i.e. take care that the following word boundaries, i.e. take care that the following
parameter starts on a new word boundary. parameter starts on a new word boundary.
*/ */
f_offset = align(f_offset + def->df_type->tp_size, word_align); f_offset = align(f_offset + def->df_type->tp_size, word_align);
formal_cvt(def); /* cvt int to char or short, if necessary */
/* the following is absurd: any char or short formal
must be converted from integer to that type
*/
formal_cvt(def);
se = se->next; se = se->next;
} }
*fp = f_offset; *fp = f_offset;

View file

@ -24,7 +24,6 @@
char *symbol2str(); char *symbol2str();
char *long2str(); char *long2str();
struct expr *do_array(), *do_struct(), *IVAL(); struct expr *do_array(), *do_struct(), *IVAL();
/* do_ival() performs the initialisation of a global variable /* do_ival() performs the initialisation of a global variable
@ -58,26 +57,23 @@ IVAL(tpp, ex)
register struct type *tp = *tpp; register struct type *tp = *tpp;
switch (tp->tp_fund) { switch (tp->tp_fund) {
case ARRAY: case ARRAY: /* array initialisation */
/* array initialisation */
if (valid_type(tp->tp_up, "array element") == 0) if (valid_type(tp->tp_up, "array element") == 0)
return 0; return 0;
if (ISCOMMA(ex)) /* list of initialisation expressions */ if (ISCOMMA(ex)) /* list of initialisation expressions */
return do_array(ex, tpp); return do_array(ex, tpp);
/* catch initialisations like char s[] = "I am a string" */
if (tp->tp_up->tp_fund == CHAR && ex->ex_class == String) if (tp->tp_up->tp_fund == CHAR && ex->ex_class == String)
/* initialisation like char s[] = "I am a string" */
ch_array(tpp, ex); ch_array(tpp, ex);
else /* " int i[24] = 12;" */ else /* " int i[24] = 12;" */
check_and_pad(ex, tpp); check_and_pad(ex, tpp);
break; break;
case STRUCT: case STRUCT: /* struct initialisation */
/* struct initialisation */
if (valid_type(tp, "struct") == 0) if (valid_type(tp, "struct") == 0)
return 0; return 0;
if (ISCOMMA(ex)) /* list of initialisation expressions */ if (ISCOMMA(ex)) /* list of initialisation expressions */
return do_struct(ex, tp); return do_struct(ex, tp);
/* "struct foo f = 12;" */ check_and_pad(ex, tpp); /* "struct foo f = 12;" */
check_and_pad(ex, tpp);
break; break;
case UNION: case UNION:
error("union initialisation not allowed"); error("union initialisation not allowed");
@ -85,7 +81,7 @@ IVAL(tpp, ex)
case ERRONEOUS: case ERRONEOUS:
break; break;
default: /* fundamental type */ default: /* fundamental type */
if (ISCOMMA(ex)) { /* " int i = {12};" */ if (ISCOMMA(ex)) { /* " int i = {12};" */
if (IVAL(tpp, ex->OP_LEFT) != 0) if (IVAL(tpp, ex->OP_LEFT) != 0)
too_many_initialisers(ex); too_many_initialisers(ex);
/* return remainings of the list for the /* return remainings of the list for the
@ -94,8 +90,7 @@ IVAL(tpp, ex)
*/ */
return ex->OP_RIGHT; return ex->OP_RIGHT;
} }
/* "int i = 12;" */ check_ival(ex, tp); /* "int i = 12;" */
check_ival(ex, tp);
break; break;
} }
return 0; return 0;
@ -131,8 +126,7 @@ do_array(ex, tpp)
is completely foolish, we did it!! (no applause, thank you) is completely foolish, we did it!! (no applause, thank you)
*/ */
if (tp->tp_up->tp_fund == CHAR) { if (tp->tp_up->tp_fund == CHAR) {
register struct expr *f = ex->OP_LEFT; register struct expr *f = ex->OP_LEFT, *g = NILEXPR;
register struct expr *g = 0;
while (ISCOMMA(f)) { /* eat the brackets!!! */ while (ISCOMMA(f)) { /* eat the brackets!!! */
g = f; g = f;
@ -150,8 +144,7 @@ do_array(ex, tpp)
/* declared with unknown size: [] */ /* declared with unknown size: [] */
for (elem_count = 0; ex; elem_count++) { for (elem_count = 0; ex; elem_count++) {
/* eat whole initialisation expression */ /* eat whole initialisation expression */
if (ISCOMMA(ex->OP_LEFT)) { if (ISCOMMA(ex->OP_LEFT)) { /* embraced member */
/* the member expression is embraced */
if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0) if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0)
too_many_initialisers(ex); too_many_initialisers(ex);
ex = ex->OP_RIGHT; ex = ex->OP_RIGHT;
@ -172,15 +165,13 @@ do_array(ex, tpp)
arith dim = tp->tp_size / tp->tp_up->tp_size; arith dim = tp->tp_size / tp->tp_up->tp_size;
for (elem_count = 0; elem_count < dim && ex; elem_count++) { for (elem_count = 0; elem_count < dim && ex; elem_count++) {
if (ISCOMMA(ex->OP_LEFT)) { if (ISCOMMA(ex->OP_LEFT)) { /* embraced member */
/* embraced member initialisation */
if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0) if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0)
too_many_initialisers(ex); too_many_initialisers(ex);
ex = ex->OP_RIGHT; ex = ex->OP_RIGHT;
} }
else { else {
if (aggregate_type(tp->tp_up)) if (aggregate_type(tp->tp_up))
/* the member is an aggregate */
ex = IVAL(&(tp->tp_up), ex); ex = IVAL(&(tp->tp_up), ex);
else { else {
check_ival(ex->OP_LEFT, tp->tp_up); check_ival(ex->OP_LEFT, tp->tp_up);
@ -194,7 +185,7 @@ do_array(ex, tpp)
is returned is returned
*/ */
return ex; return ex;
if ((ex == 0) && elem_count < dim) { if ((ex == 0) && elem_count < dim)
/* the expression tree is completely absorbed /* the expression tree is completely absorbed
but there are still members which must be but there are still members which must be
initialised with zeroes initialised with zeroes
@ -202,7 +193,6 @@ do_array(ex, tpp)
do do
pad(tp->tp_up); pad(tp->tp_up);
while (++elem_count < dim); while (++elem_count < dim);
}
} }
return 0; return 0;
} }
@ -245,16 +235,14 @@ do_struct(ex, tp)
definition. definition.
*/ */
put_bf(sd->sd_type, (arith)0); put_bf(sd->sd_type, (arith)0);
else { else { /* fundamental type, not embraced */
/* fundamental type, not embraced */
check_ival(ex->OP_LEFT, sd->sd_type); check_ival(ex->OP_LEFT, sd->sd_type);
ex = ex->OP_RIGHT; ex = ex->OP_RIGHT;
} }
#endif NOBITFIELD #endif NOBITFIELD
} }
} }
/* align upto the next selector boundary */ if (sd->sd_sdef) /* align upto the next selector boundary */
if (sd->sd_sdef)
bytes_upto_here += zero_bytes(sd); bytes_upto_here += zero_bytes(sd);
if (last_offset != sd->sd_offset) { if (last_offset != sd->sd_offset) {
/* don't take the field-width more than once */ /* don't take the field-width more than once */
@ -266,9 +254,7 @@ do_struct(ex, tp)
} }
/* perfect fit if (ex && (sd == 0)) holds */ /* perfect fit if (ex && (sd == 0)) holds */
if ((ex == 0) && (sd != 0)) { if ((ex == 0) && (sd != 0)) {
/* there are selectors left which must be padded with /* there are selectors left which must be padded with zeroes */
zeroes
*/
do { do {
pad(sd->sd_type); pad(sd->sd_type);
/* take care of the alignment restrictions */ /* take care of the alignment restrictions */
@ -307,7 +293,7 @@ check_and_pad(ex, tpp)
*/ */
tp = *tpp = construct_type(ARRAY, tp->tp_up, (arith)1); tp = *tpp = construct_type(ARRAY, tp->tp_up, (arith)1);
else { else {
register dim = tp->tp_size / tp->tp_up->tp_size; register int dim = tp->tp_size / tp->tp_up->tp_size;
/* pad remaining members with zeroes */ /* pad remaining members with zeroes */
while (--dim > 0) while (--dim > 0)
pad(tp->tp_up); pad(tp->tp_up);
@ -320,7 +306,7 @@ check_and_pad(ex, tpp)
if (valid_type(tp, "struct") == 0) if (valid_type(tp, "struct") == 0)
return; return;
check_and_pad(ex, &(sd->sd_type)); check_and_pad(ex, &(sd->sd_type));
/* Next selector is aligned by adding extra zeroes */ /* next selector is aligned by adding extra zeroes */
if (sd->sd_sdef) if (sd->sd_sdef)
zero_bytes(sd); zero_bytes(sd);
while (sd = sd->sd_sdef) { /* pad remaining selectors */ while (sd = sd->sd_sdef) { /* pad remaining selectors */
@ -346,10 +332,8 @@ pad(tp)
if (valid_type(tp->tp_up, "array element") == 0) if (valid_type(tp->tp_up, "array element") == 0)
return; return;
dim = tp->tp_size / tp->tp_up->tp_size; dim = tp->tp_size / tp->tp_up->tp_size;
/* assume dimension is known */
/* Assume the dimension is known */
while (dim-- > 0) while (dim-- > 0)
pad(tp->tp_up); pad(tp->tp_up);
break; break;
@ -360,7 +344,6 @@ pad(tp)
if (valid_type(tp, "struct") == 0) if (valid_type(tp, "struct") == 0)
return; return;
do { do {
pad(sdef->sd_type); pad(sdef->sd_type);
if (sdef->sd_sdef) if (sdef->sd_sdef)
@ -462,10 +445,8 @@ check_ival(ex, tp)
/* float f = 1; */ /* float f = 1; */
ex = ex->OP_RIGHT; ex = ex->OP_RIGHT;
if (is_cp_cst(ex)) if (is_cp_cst(ex))
C_con_fcon( C_con_fcon(long2str((long)ex->VL_VALUE, 10),
long2str((long)ex->VL_VALUE, 10), tp->tp_size);
tp->tp_size
);
else else
illegal_init_cst(ex); illegal_init_cst(ex);
} }
@ -509,7 +490,7 @@ ch_array(tpp, ex)
ASSERT(ex->ex_class == String); ASSERT(ex->ex_class == String);
length = ex->SG_LEN; length = ex->SG_LEN;
if (tp->tp_size == (arith)-1) { if (tp->tp_size == (arith)-1) {
/* set the dimension */ /* set the dimension */
tp = *tpp = construct_type(ARRAY, tp->tp_up, length); tp = *tpp = construct_type(ARRAY, tp->tp_up, length);
ntopad = align(tp->tp_size, word_align) - tp->tp_size; ntopad = align(tp->tp_size, word_align) - tp->tp_size;
@ -591,8 +572,7 @@ zero_bytes(sd)
/* fills the space between a selector of a struct /* fills the space between a selector of a struct
and the next selector of that struct with zero-bytes. and the next selector of that struct with zero-bytes.
*/ */
register int n = register int n = sd->sd_sdef->sd_offset - sd->sd_offset -
sd->sd_sdef->sd_offset - sd->sd_offset -
size_of_type(sd->sd_type, "struct member"); size_of_type(sd->sd_type, "struct member");
register count = n; register count = n;

View file

@ -7,7 +7,6 @@
#include "debug.h" /* UF */ #include "debug.h" /* UF */
#include "pathlength.h" /* UF */ #include "pathlength.h" /* UF */
#include "strsize.h" /* UF */ #include "strsize.h" /* UF */
#include "alloc.h" #include "alloc.h"
#include "idf.h" #include "idf.h"
#include "input.h" #include "input.h"
@ -52,13 +51,11 @@ replace(idef)
} }
actpars = getactuals(idef); /* get act.param. list */ actpars = getactuals(idef); /* get act.param. list */
} }
if ((flags & PREDEF) && (UnknownIdIsZero == 0)) if ((flags & PREDEF) && (UnknownIdIsZero == 0)) /* don't replace */
/* don't replace this one... */ return 0;
return 0;
if (flags & FUNC) /* this macro leads to special action */ if (flags & FUNC) /* this macro leads to special action */
macro_func(idef); macro_func(idef);
/* create and input buffer */ reptext = macro2buffer(idef, actpars, &size); /* create input buffer */
reptext = macro2buffer(idef, actpars, &size);
InsertText(reptext, size); InsertText(reptext, size);
return 1; return 1;
} }
@ -74,8 +71,7 @@ macro_func(idef)
replacement texts must be evaluated at the time they are replacement texts must be evaluated at the time they are
used. used.
*/ */
/* This switch is very blunt... */ switch (idef->id_text[2]) { /* This switch is very blunt... */
switch (idef->id_text[2]) {
case 'F' : /* __FILE__ */ case 'F' : /* __FILE__ */
FilNamBuf[0] = '"'; FilNamBuf[0] = '"';
strcpy(&FilNamBuf[1], FileName); strcpy(&FilNamBuf[1], FileName);
@ -126,8 +122,7 @@ macro2buffer(idef, actpars, siztext)
for (p = actpars[n - 1]; *p; p++) { for (p = actpars[n - 1]; *p; p++) {
text[pos++] = *p; text[pos++] = *p;
if (pos == size) if (pos == size)
text = Srealloc(text, text = Srealloc(text, size += RSTRSIZE);
size += RSTRSIZE);
} }
} }
else { else {

View file

@ -27,7 +27,6 @@ static struct switch_hdr *switch_stack = 0;
- the expression E in "switch(E)" is cast to 'int' (RM 9.7) - the expression E in "switch(E)" is cast to 'int' (RM 9.7)
- the expression E in "case E:" must be 'int' (RM 9.7) - the expression E in "case E:" must be 'int' (RM 9.7)
- the values in the CSA/CSB tables are words (EM 7.4) - the values in the CSA/CSB tables are words (EM 7.4)
For simplicity, we suppose int_size == word_size. For simplicity, we suppose int_size == word_size.
*/ */
@ -42,7 +41,7 @@ code_startswitch(expp)
register struct switch_hdr *sh = new_switch_hdr(); register struct switch_hdr *sh = new_switch_hdr();
int fund = any2arith(expp, SWITCH); /* INT, LONG or DOUBLE */ int fund = any2arith(expp, SWITCH); /* INT, LONG or DOUBLE */
switch (fund) { switch (fund) {
case LONG: case LONG:
if (options['R']) if (options['R'])
warning("long in switch (cast to int)"); warning("long in switch (cast to int)");
@ -55,7 +54,6 @@ code_startswitch(expp)
break; break;
#endif NOFLOAT #endif NOFLOAT
} }
stack_stmt(l_break, NO_LABEL); stack_stmt(l_break, NO_LABEL);
sh->sh_break = l_break; sh->sh_break = l_break;
sh->sh_default = 0; sh->sh_default = 0;
@ -66,8 +64,8 @@ code_startswitch(expp)
sh->sh_entries = (struct case_entry *) 0; /* case-entry list */ sh->sh_entries = (struct case_entry *) 0; /* case-entry list */
sh->next = switch_stack; /* push onto switch-stack */ sh->next = switch_stack; /* push onto switch-stack */
switch_stack = sh; switch_stack = sh;
/* evaluate the switch expr. */
code_expr(*expp, RVAL, TRUE, NO_LABEL, NO_LABEL); code_expr(*expp, RVAL, TRUE, NO_LABEL, NO_LABEL);
/* evaluate the switch expr. */
C_bra(l_table); /* goto start of switch_table */ C_bra(l_table); /* goto start of switch_table */
} }
@ -93,7 +91,7 @@ code_endswitch()
ce = sh->sh_entries; ce = sh->sh_entries;
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) { for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
ASSERT(ce); ASSERT(ce);
if (val == ce->ce_value) { if (val == ce->ce_value) {
C_rom_ilb(ce->ce_label); C_rom_ilb(ce->ce_label);
ce = ce->next; ce = ce->next;
} }
@ -103,9 +101,9 @@ code_endswitch()
C_lae_dlb(tablabel, (arith)0); /* perform the switch */ C_lae_dlb(tablabel, (arith)0); /* perform the switch */
C_csa(sh->sh_type->tp_size); C_csa(sh->sh_type->tp_size);
} }
else { /* CSB */ else { /* CSB */
C_rom_cst((arith)sh->sh_nrofentries); C_rom_cst((arith)sh->sh_nrofentries);
for (ce = sh->sh_entries; ce; ce = ce->next) { for (ce = sh->sh_entries; ce; ce = ce->next) {
/* generate the entries: value + prog.label */ /* generate the entries: value + prog.label */
C_rom_cst(ce->ce_value); C_rom_cst(ce->ce_value);
C_rom_ilb(ce->ce_label); C_rom_ilb(ce->ce_label);
@ -115,11 +113,9 @@ code_endswitch()
} }
C_df_ilb(sh->sh_break); C_df_ilb(sh->sh_break);
switch_stack = sh->next; /* unstack the switch descriptor */ switch_stack = sh->next; /* unstack the switch descriptor */
for (ce = sh->sh_entries; ce;) { /* free allocated switch structure */
/* free the allocated switch structure */
ce = sh->sh_entries;
while (ce) {
register struct case_entry *tmp = ce->next; register struct case_entry *tmp = ce->next;
free_case_entry(ce); free_case_entry(ce);
ce = tmp; ce = tmp;
} }
@ -135,28 +131,23 @@ code_case(expr)
register struct switch_hdr *sh = switch_stack; register struct switch_hdr *sh = switch_stack;
ASSERT(is_cp_cst(expr)); ASSERT(is_cp_cst(expr));
if (sh == 0) { if (sh == 0) {
error("case statement not in switch"); error("case statement not in switch");
return; return;
} }
if (expr->ex_flags & EX_ERROR) { if (expr->ex_flags & EX_ERROR) /* is probably 0 anyway */
/* is probably 0 anyway */
return; return;
}
ch7cast(&expr, SWITCH, sh->sh_type); ch7cast(&expr, SWITCH, sh->sh_type);
ce = new_case_entry(); ce = new_case_entry();
C_df_ilb(ce->ce_label = text_label()); C_df_ilb(ce->ce_label = text_label());
ce->ce_value = val = expr->VL_VALUE; ce->ce_value = val = expr->VL_VALUE;
if (sh->sh_entries == 0) { if (sh->sh_entries == 0) { /* first case entry */
/* first case entry */
ce->next = (struct case_entry *) 0; ce->next = (struct case_entry *) 0;
sh->sh_entries = ce; sh->sh_entries = ce;
sh->sh_lowerbd = sh->sh_upperbd = val; sh->sh_lowerbd = sh->sh_upperbd = val;
sh->sh_nrofentries = 1; sh->sh_nrofentries = 1;
} }
else { else { /* second etc. case entry; put ce into proper place */
/* second etc. case entry */
/* find the proper place to put ce into the list */
register struct case_entry *c1 = sh->sh_entries, *c2 = 0; register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
if (val < sh->sh_lowerbd) if (val < sh->sh_lowerbd)
@ -164,37 +155,34 @@ code_case(expr)
else else
if (val > sh->sh_upperbd) if (val > sh->sh_upperbd)
sh->sh_upperbd = val; sh->sh_upperbd = val;
while (c1 && c1->ce_value < ce->ce_value) { while (c1 && c1->ce_value < ce->ce_value) {
c2 = c1; c2 = c1;
c1 = c1->next; c1 = c1->next;
} }
/* At this point three cases are possible: /* At this point three cases are possible:
1: c1 != 0 && c2 != 0: 1: c1 != 0 && c2 != 0: insert ce somewhere in the middle
insert ce somewhere in the middle 2: c1 != 0 && c2 == 0: insert ce right after the head
2: c1 != 0 && c2 == 0: 3: c1 == 0 && c2 != 0: append ce to last element
insert ce right after the head
3: c1 == 0 && c2 != 0:
append ce to last element
The case c1 == 0 && c2 == 0 cannot occur, since The case c1 == 0 && c2 == 0 cannot occur, since
the list is guaranteed not to be empty. the list is guaranteed to be non-empty.
*/ */
if (c1) { if (c1) {
if (c1->ce_value == ce->ce_value) { if (c1->ce_value == ce->ce_value) {
error("multiple case entry for value %ld", error("multiple case entry for value %ld",
ce->ce_value); ce->ce_value);
free_case_entry(ce); free_case_entry(ce);
return; return;
} }
if (c2) { if (c2) {
ce->next = c2->next; ce->next = c2->next;
c2->next = ce; c2->next = ce;
} }
else { else {
ce->next = sh->sh_entries; ce->next = sh->sh_entries;
sh->sh_entries = ce; sh->sh_entries = ce;
} }
} }
else { else {
ASSERT(c2); ASSERT(c2);
ce->next = (struct case_entry *) 0; ce->next = (struct case_entry *) 0;
c2->next = ce; c2->next = ce;
@ -207,13 +195,11 @@ code_default()
{ {
register struct switch_hdr *sh = switch_stack; register struct switch_hdr *sh = switch_stack;
if (sh == 0) { if (sh == 0)
error("default not in switch"); error("default not in switch");
return; else
} if (sh->sh_default != 0)
if (sh->sh_default != 0) {
error("multiple entry for default in switch"); error("multiple entry for default in switch");
return; else
} C_df_ilb(sh->sh_default = text_label());
C_df_ilb(sh->sh_default = text_label());
} }