From 66c571d2172bc7a099ac85665bc15769aa33209e Mon Sep 17 00:00:00 2001 From: erikb Date: Wed, 2 Apr 1986 08:37:17 +0000 Subject: [PATCH] revised the administration of Value expressions --- lang/cem/cemcom/Makefile.erik | 4 +- lang/cem/cemcom/arith.c | 30 ++++- lang/cem/cemcom/ch7.c | 3 + lang/cem/cemcom/ch7mon.c | 27 ++-- lang/cem/cemcom/code.c | 38 +++++- lang/cem/cemcom/code.str | 9 ++ lang/cem/cemcom/cstoper.c | 5 +- lang/cem/cemcom/dumpidf.c | 20 ++- lang/cem/cemcom/eval.c | 240 +++++++++++++++++----------------- lang/cem/cemcom/expr.c | 15 ++- lang/cem/cemcom/expr.str | 17 ++- lang/cem/cemcom/field.c | 44 ++----- lang/cem/cemcom/ival.c | 156 ++++++++-------------- lang/cem/cemcom/switch.c | 4 +- 14 files changed, 317 insertions(+), 295 deletions(-) diff --git a/lang/cem/cemcom/Makefile.erik b/lang/cem/cemcom/Makefile.erik index 8acb5b6e9..dff19db64 100644 --- a/lang/cem/cemcom/Makefile.erik +++ b/lang/cem/cemcom/Makefile.erik @@ -190,10 +190,10 @@ idf.o: LLlex.h Lpars.h align.h alloc.h arith.h assert.h botch_free.h debug.h dec declarator.o: Lpars.h alloc.h arith.h botch_free.h declar.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h type.h decspecs.o: Lpars.h arith.h decspecs.h def.h level.h nobitfield.h spec_arith.h type.h struct.o: LLlex.h Lpars.h align.h arith.h assert.h botch_free.h debug.h def.h field.h idf.h level.h nobitfield.h nopp.h sizes.h spec_arith.h stack.h storage.h struct.h type.h -expr.o: LLlex.h Lpars.h alloc.h arith.h botch_free.h declar.h decspecs.h def.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h type.h +expr.o: LLlex.h Lpars.h alloc.h arith.h botch_free.h declar.h decspecs.h def.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h storage.h type.h level.h ch7.o: Lpars.h arith.h assert.h debug.h def.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h struct.h type.h ch7bin.o: Lpars.h arith.h botch_free.h expr.h idf.h label.h nobitfield.h nopp.h spec_arith.h storage.h struct.h type.h -cstoper.o: Lpars.h arith.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h target_sizes.h type.h +cstoper.o: Lpars.h arith.h expr.h idf.h label.h nobitfield.h nopp.h sizes.h spec_arith.h target_sizes.h type.h assert.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 diff --git a/lang/cem/cemcom/arith.c b/lang/cem/cemcom/arith.c index 629fbac00..61bdb6efb 100644 --- a/lang/cem/cemcom/arith.c +++ b/lang/cem/cemcom/arith.c @@ -257,18 +257,16 @@ float2float(expp, tp) */ fp_used = 1; - if (is_fp_cst(*expp)) { + if (is_fp_cst(*expp)) (*expp)->ex_type = tp; - } - else { + else *expp = arith2arith(tp, FLOAT2FLOAT, *expp); - } } array2pointer(expp) struct expr **expp; { - /* The expression, which must be an array, it is converted + /* The expression, which must be an array, is converted to a pointer. */ (*expp)->ex_type = @@ -278,13 +276,29 @@ array2pointer(expp) function2pointer(expp) struct expr **expp; { - /* The expression, which must be a function, it is converted + /* The expression, which must be a function, is converted to a pointer to the function. */ (*expp)->ex_type = construct_type(POINTER, (*expp)->ex_type, (arith)0); } +string2pointer(expp) + struct expr **expp; +{ + /* The expression, which must be a string constant, is converted + to a pointer to the string-containing area. + */ + struct expr *ex = *expp; + label lbl = data_label(); + + code_string(ex->SG_VALUE, ex->SG_LEN, lbl); + ex->ex_class = Value; + ex->VL_CLASS = Label; + ex->VL_LBL = lbl; + ex->VL_VALUE = (arith)0; +} + opnd2integral(expp, oper) struct expr **expp; int oper; @@ -421,6 +435,10 @@ any2opnd(expp, oper) case ARRAY: array2pointer(expp); break; + case POINTER: + if ((*expp)->ex_class == String) + string2pointer(expp); + break; #ifndef NOBITFIELD case FIELD: field2arith(expp); diff --git a/lang/cem/cemcom/ch7.c b/lang/cem/cemcom/ch7.c index 0f39bcfd9..ab173731d 100644 --- a/lang/cem/cemcom/ch7.c +++ b/lang/cem/cemcom/ch7.c @@ -109,6 +109,7 @@ ch7sel(expp, oper, idf) struct oper *op = &((*expp)->ex_object.ex_oper); if (op->op_oper == '.' || op->op_oper == ARROW) { + ASSERT(is_cp_cst(op->op_right)); op->op_right->VL_VALUE += sd->sd_offset; (*expp)->ex_type = sd->sd_type; if ((*expp)->ex_type == error_type) @@ -188,6 +189,8 @@ ch7cast(expp, oper, tp) function2pointer(expp); if ((*expp)->ex_type->tp_fund == ARRAY) array2pointer(expp); + if ((*expp)->ex_class == String) + string2pointer(expp); oldtp = (*expp)->ex_type; if (oldtp == tp) {} /* life is easy */ diff --git a/lang/cem/cemcom/ch7mon.c b/lang/cem/cemcom/ch7mon.c index f18969f3f..b99925a1f 100644 --- a/lang/cem/cemcom/ch7mon.c +++ b/lang/cem/cemcom/ch7mon.c @@ -46,13 +46,11 @@ ch7mon(oper, expp) } break; case '&': - if ((*expp)->ex_type->tp_fund == ARRAY) { + if ((*expp)->ex_type->tp_fund == ARRAY) array2pointer(expp); - } else - if ((*expp)->ex_type->tp_fund == FUNCTION) { + if ((*expp)->ex_type->tp_fund == FUNCTION) function2pointer(expp); - } else #ifndef NOBITFIELD if ((*expp)->ex_type->tp_fund == FIELD) { @@ -65,12 +63,15 @@ ch7mon(oper, expp) } else { /* assume that enums are already filtered out */ - if ((*expp)->ex_class == Value && (*expp)->VL_IDF) { + if ( (*expp)->ex_class == Value + && (*expp)->VL_CLASS == Name + ) { register struct def *def = (*expp)->VL_IDF->id_def; - /* & indicates that cannot - be used as register anymore + /* & indicates that + cannot be used as register + anymore */ if (def->df_sc == REGISTER) { expr_error(*expp, @@ -98,11 +99,7 @@ ch7mon(oper, expp) any2arith(expp, oper); if (is_cp_cst(*expp)) { arith o1 = (*expp)->VL_VALUE; - if (oper == '-') - o1 = -o1; - else - o1 = ~o1; - (*expp)->VL_VALUE = o1; + (*expp)->VL_VALUE = (oper == '-') ? -o1 : ~o1; } else if (is_fp_cst(*expp)) @@ -118,9 +115,7 @@ ch7mon(oper, expp) any2arith(expp, oper); opnd2test(expp, '!'); if (is_cp_cst(*expp)) { - arith o1 = (*expp)->VL_VALUE; - o1 = !o1; - (*expp)->VL_VALUE = o1; + (*expp)->VL_VALUE = !((*expp)->VL_VALUE); (*expp)->ex_type = int_type; } else @@ -133,7 +128,7 @@ ch7mon(oper, expp) break; case SIZEOF: if ( (*expp)->ex_class == Value - && (*expp)->VL_IDF + && (*expp)->VL_CLASS == Name && (*expp)->VL_IDF->id_def->df_formal_array ) warning("sizeof formal array %s is sizeof pointer!", diff --git a/lang/cem/cemcom/code.c b/lang/cem/cemcom/code.c index 689daaa98..098924f7a 100644 --- a/lang/cem/cemcom/code.c +++ b/lang/cem/cemcom/code.c @@ -59,11 +59,41 @@ famous_first_words() C_ms_emx(word_size, pointer_size); } +static struct string_cst *str_list = 0; + +code_string(val, len, dlb) + char *val; + int len; + label dlb; +{ + struct string_cst *sc = new_string_cst(); + + C_ina_dlb(dlb); + sc->next = str_list; + str_list = sc; + sc->sc_value = val; + sc->sc_len = len; + sc->sc_dlb = dlb; +} + +def_strings(sc) + register struct string_cst *sc; +{ + if (sc) { + def_strings(sc->next); + C_df_dlb(sc->sc_dlb); + C_con_scon(sc->sc_value, sc->sc_len); + free_string_cst(sc); + } +} + end_code() { /* end_code() performs the actions to be taken when closing the output stream. */ + def_strings(str_list); + str_list = 0; C_ms_src((arith)(LineNumber - 2), FileName); C_close(); } @@ -351,6 +381,7 @@ loc_init(expr, id) */ register struct type *tp = id->id_def->df_type; + ASSERT(id->id_def->df_sc != STATIC); /* automatic aggregates cannot be initialised. */ switch (tp->tp_fund) { case ARRAY: @@ -374,9 +405,14 @@ loc_init(expr, id) } } else { /* not embraced */ + struct value vl; + ch7cast(&expr, '=', tp); EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); - store_val(id, tp, (arith) 0); + vl.vl_class = Name; + vl.vl_data.vl_idf = id; + vl.vl_value = (arith)0; + store_val(&vl, tp); } } diff --git a/lang/cem/cemcom/code.str b/lang/cem/cemcom/code.str index 11a00cb68..2f2399ce1 100644 --- a/lang/cem/cemcom/code.str +++ b/lang/cem/cemcom/code.str @@ -9,6 +9,15 @@ struct stat_block { /* ALLOCDEF "stat_block" */ +struct string_cst { /* storing string constants */ + struct string_cst *next; + char *sc_value; + int sc_len; + label sc_dlb; +}; + +/* ALLOCDEF "string_cst" */ + #define LVAL 0 #define RVAL 1 #define FALSE 0 diff --git a/lang/cem/cemcom/cstoper.c b/lang/cem/cemcom/cstoper.c index 9b4e09eb4..1d31a1b28 100644 --- a/lang/cem/cemcom/cstoper.c +++ b/lang/cem/cemcom/cstoper.c @@ -10,6 +10,7 @@ #include "expr.h" #include "sizes.h" #include "Lpars.h" +#include "assert.h" long mach_long_sign; /* sign bit of the machine long */ int mach_long_size; /* size of long on this machine == sizeof(long) */ @@ -21,13 +22,14 @@ cstbin(expp, oper, expr) struct expr **expp, *expr; { /* The operation oper is performed on the constant - expressions *expp and expr, and the result restored in + expressions *expp(ld) and expr(ct), and the result restored in *expp. */ arith o1 = (*expp)->VL_VALUE; arith o2 = expr->VL_VALUE; int uns = (*expp)->ex_type->tp_unsigned; + ASSERT(is_ld_cst(*expp) && is_cp_cst(expr)); switch (oper) { case '*': o1 *= o2; @@ -190,6 +192,7 @@ cut_size(expr) int uns = expr->ex_type->tp_unsigned; int size = (int) expr->ex_type->tp_size; + ASSERT(expr->ex_class == Value); if (uns) { if (o1 & ~full_mask[size]) expr_warning(expr, diff --git a/lang/cem/cemcom/dumpidf.c b/lang/cem/cemcom/dumpidf.c index 1c20e88b5..cd7e46948 100644 --- a/lang/cem/cemcom/dumpidf.c +++ b/lang/cem/cemcom/dumpidf.c @@ -331,14 +331,24 @@ p1_expr(lvl, expr) expr->ex_class == Type ? "Type" : "UNKNOWN CLASS" ); switch (expr->ex_class) { - struct value *v; struct oper *o; case Value: - v = &expr->ex_object.ex_value; - if (v->vl_idf) - printf("%s + ", v->vl_idf->id_text); + switch (expr->VL_CLASS) { + case Const: + printf("(Const) "); + break; + case Name: + printf("(Name) %s + ", expr->VL_IDF->id_text); + break; + case Label: + printf("(Label) .%lu + ", expr->VL_LBL); + break; + default: + printf("(Unknown) "); + break; + } printf(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n", - v->vl_value); + expr->VL_VALUE); break; case String: { diff --git a/lang/cem/cemcom/eval.c b/lang/cem/cemcom/eval.c index 636e42877..b0f5f40c5 100644 --- a/lang/cem/cemcom/eval.c +++ b/lang/cem/cemcom/eval.c @@ -80,22 +80,17 @@ EVAL(expr, val, code, true_label, false_label) register gencode = (code == TRUE); switch (expr->ex_class) { - case Value: /* just a simple value */ if (gencode) load_val(expr, val); break; - case String: /* a string constant */ + expr_warning(expr, "(DEBUG) value-class 'String' seen"); if (gencode) { - label datlab = data_label(); - - C_df_dlb(datlab); - C_con_scon(expr->SG_VALUE, (arith)expr->SG_LEN); - C_lae_dlb(datlab, (arith)0); + string2pointer(&expr); + C_lae_dlb(expr->VL_LBL, expr->VL_VALUE); } break; - case Float: /* a floating constant */ if (gencode) { label datlab = data_label(); @@ -106,7 +101,6 @@ EVAL(expr, val, code, true_label, false_label) C_loi(expr->ex_type->tp_size); } break; - case Oper: /* compound expression */ { register int oper = expr->OP_OPER; @@ -116,7 +110,6 @@ EVAL(expr, val, code, true_label, false_label) if (tp->tp_fund == ERRONEOUS) /* stop immediately */ break; - switch (oper) { case '+': /* We have the following possibilities : @@ -366,8 +359,10 @@ EVAL(expr, val, code, true_label, false_label) store_block(tp->tp_size, tp->tp_align); } else - store_val(leftop->VL_IDF, leftop->ex_type, - leftop->VL_VALUE); + store_val( + &(leftop->ex_object.ex_value), + leftop->ex_type + ); break; case PLUSAB: case MINAB: @@ -410,8 +405,10 @@ EVAL(expr, val, code, true_label, false_label) assop(tp, oper); if (gencode) C_dup(roundup(tp->tp_size)); - store_val(leftop->VL_IDF, leftop->ex_type, - leftop->VL_VALUE); + store_val( + &(leftop->ex_object.ex_value), + leftop->ex_type + ); } break; case '(': @@ -433,7 +430,9 @@ EVAL(expr, val, code, true_label, false_label) EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); ParSize += ATW(expr->ex_type->tp_size); } - if (leftop->ex_class == Value && leftop->VL_IDF != 0) { + if ( leftop->ex_class == Value + && leftop->VL_CLASS == Name + ) { /* just an example: main() { (*((int (*)())0))(); } */ @@ -466,11 +465,13 @@ EVAL(expr, val, code, true_label, false_label) } case '.': EVAL(leftop, LVAL, code, NO_LABEL, NO_LABEL); + ASSERT(is_cp_cst(rightop)); if (gencode) C_adp(rightop->VL_VALUE); break; case ARROW: EVAL(leftop, RVAL, code, NO_LABEL, NO_LABEL); + ASSERT(is_cp_cst(rightop)); if (gencode) C_adp(rightop->VL_VALUE); break; @@ -532,8 +533,10 @@ EVAL(expr, val, code, true_label, false_label) free_tmp_var(old_offset); } else - store_val(leftop->VL_IDF, leftop->ex_type, - leftop->VL_VALUE); + store_val( + &(leftop->ex_object.ex_value), + leftop->ex_type + ); break; } case '?': /* must be followed by ':' */ @@ -841,62 +844,70 @@ free_tmp_var(oldoffset) - into an automatic local variable - into a local static variable - absolute addressing - When the destination is described by an (lvalue) expression, the call - is "store_val(ex->VL_IDF, ex->ex_type, ex->VL_VALUE)" */ -store_val(id, tp, offs) - register struct idf *id; +store_val(vl, tp) + register struct value *vl; struct type *tp; - arith offs; { arith size = tp->tp_size; int tpalign = tp->tp_align; + int al_on_word; + register int inword; + register int indword; + arith val = vl->vl_value; + + if (vl->vl_class == Const) { /* absolute addressing */ + load_cst(val, pointer_size); + store_block(size, tpalign); + return; + } - if (id) { + al_on_word = (tpalign % word_align == 0); + if (!(inword = (size == word_size && al_on_word))) + indword = (size == dword_size && al_on_word); + + if (vl->vl_class == Name) { + register struct idf *id = vl->vl_data.vl_idf; register struct def *df = id->id_def; - int al_on_word = (tpalign % word_align == 0); - register inword = (size == word_size && al_on_word); - register indword = (size == dword_size && al_on_word); if (df->df_level == L_GLOBAL) { if (inword) - C_ste_dnam(id->id_text, offs); + C_ste_dnam(id->id_text, val); else if (indword) - C_sde_dnam(id->id_text, offs); + C_sde_dnam(id->id_text, val); else { - C_lae_dnam(id->id_text, offs); - store_block(size, tpalign); - } - } - else - if (df->df_sc == STATIC) { - if (inword) - C_ste_dlb((label)df->df_address, offs); - else - if (indword) - C_sde_dlb((label)df->df_address, offs); - else { - C_lae_dlb((label)df->df_address, offs); + C_lae_dnam(id->id_text, val); store_block(size, tpalign); } } else { + ASSERT(df->df_sc != STATIC); if (inword) - C_stl(df->df_address + offs); + C_stl(df->df_address + val); else if (indword) - C_sdl(df->df_address + offs); + C_sdl(df->df_address + val); else { - C_lal(df->df_address + offs); + C_lal(df->df_address + val); store_block(size, tpalign); df->df_register = REG_NONE; } } } - else { /* absolute addressing */ - load_cst(offs, pointer_size); - store_block(size, tpalign); + else { + label dlb = vl->vl_data.vl_lbl; + + ASSERT(vl->vl_class == Label); + if (inword) + C_ste_dlb(dlb, val); + else + if (indword) + C_sde_dlb(dlb, val); + else { + C_lae_dlb(dlb, val); + store_block(size, tpalign); + } } } @@ -914,101 +925,96 @@ load_val(expr, val) struct expr *expr; /* expression containing the value */ int val; /* generate either LVAL or RVAL */ { - register struct idf *id; register struct type *tp = expr->ex_type; - register struct def *df; - register rvalue = (val == RVAL && expr->ex_lvalue != 0); - register arith exval = expr->VL_VALUE; + register int rvalue = (val == RVAL && expr->ex_lvalue != 0); register arith size = tp->tp_size; - register tpalign = tp->tp_align; - register al_on_word = (tpalign % word_align == 0); + register int tpalign = tp->tp_align; + register int al_on_word; + register int inword, indword; + register arith val = expr->VL_VALUE; - if ((id = expr->VL_IDF) == 0) { - /* Note: enum constants are also dealt with here */ - if (rvalue) { - /* absolute addressing - */ - load_cst(exval, pointer_size); + if (expr->VL_CLASS == Const) { + if (rvalue) { /* absolute addressing */ + load_cst(val, pointer_size); load_block(size, tpalign); } else /* integer, unsigned, long, enum etc */ - load_cst(exval, size); + load_cst(val, size); + return; } - else - if ((df = id->id_def)->df_type->tp_fund == FUNCTION) - /* the previous statement tried to catch a function - identifier, which may be cast to a pointer to a - function. - ASSERT(!(rvalue)); ??? - */ - C_lpi(id->id_text); - else - if (df->df_level == L_GLOBAL) { + if (rvalue) { + al_on_word = (tpalign % word_align == 0); + if (!(inword = (size == word_size && al_on_word))) + indword = (size == dword_size && al_on_word); + } + if (expr->VL_CLASS == Label) { if (rvalue) { - if (size == word_size && al_on_word) - C_loe_dnam(id->id_text, exval); + if (inword) + C_loe_dlb(expr->VL_LBL, val); else - if (size == dword_size && al_on_word) - C_lde_dnam(id->id_text, exval); + if (indword) + C_lde_dlb(expr->VL_LBL, val); else { - C_lae_dnam(id->id_text, exval); + C_lae_dlb(expr->VL_LBL, val); load_block(size, tpalign); } } else { - C_lae_dnam(id->id_text, (arith)0); - C_adp(exval); + C_lae_dlb(expr->VL_LBL, (arith)0); + C_adp(val); } } - else - if (df->df_sc == STATIC) { - if (rvalue) { - if (size == word_size && al_on_word) - C_loe_dlb((label)df->df_address, exval); - else - if (size == dword_size && al_on_word) - C_lde_dlb((label)df->df_address, exval); + else { + register struct idf *id = expr->VL_IDF; + register struct def *df; + + ASSERT(expr->VL_CLASS == Name); + if ((df = id->id_def)->df_type->tp_fund == FUNCTION) + /* the previous statement tried to catch a function + identifier, which may be cast to a pointer to a + function. + ASSERT(!(rvalue)); ??? + */ + C_lpi(id->id_text); + else + if (df->df_level == L_GLOBAL) { + if (rvalue) { + if (inword) + C_loe_dnam(id->id_text, val); + else + if (indword) + C_lde_dnam(id->id_text, val); + else { + C_lae_dnam(id->id_text, val); + load_block(size, tpalign); + } + } else { - C_lae_dlb((label)df->df_address, exval); - load_block(size, tpalign); + C_lae_dnam(id->id_text, (arith)0); + C_adp(val); } - } else { - C_lae_dlb((label)df->df_address, (arith)0); - C_adp(exval); - } - } - else { - if (rvalue) { - if (size == word_size && al_on_word) - C_lol(df->df_address + exval); - else - if (size == dword_size && al_on_word) - C_ldl(df->df_address + exval); + ASSERT(df->df_sc != STATIC); + if (rvalue) { + if (inword) + C_lol(df->df_address + val); + else + if (indword) + C_ldl(df->df_address + val); + else { + C_lal(df->df_address + val); + load_block(size, tpalign); + df->df_register = REG_NONE; + } + } else { - C_lal(df->df_address + exval); - load_block(size, tpalign); + C_lal(df->df_address); + C_adp(val); df->df_register = REG_NONE; } } - else { - /* following code may be used when - comparing addresses as in the following - example: - f() { - int a[10], *i; - for (i = &a[0]; i < &a[10]; i++) ...; - } - We don't accept the contents of a[10] to - be legitimate, so the RVAL of it may - contain a big mess. - */ - C_lal(df->df_address); - C_adp(exval); - df->df_register = REG_NONE; - } } } diff --git a/lang/cem/cemcom/expr.c b/lang/cem/cemcom/expr.c index ba07d30ca..0a8629e94 100644 --- a/lang/cem/cemcom/expr.c +++ b/lang/cem/cemcom/expr.c @@ -15,6 +15,7 @@ #include "declar.h" #include "storage.h" #include "sizes.h" +#include "level.h" extern char *symbol2str(); extern char options[]; @@ -184,10 +185,17 @@ idf2expr(expr) ) ? 0 : 1; expr->ex_class = Value; if (def->df_sc == ENUM) { - expr->VL_IDF = 0; + expr->VL_CLASS = Const; expr->VL_VALUE = def->df_address; } - else { + else + if (def->df_sc == STATIC && def->df_level >= L_LOCAL) { + expr->VL_CLASS = Label; + expr->VL_LBL = def->df_address; + expr->VL_VALUE = (arith)0; + } + else { + expr->VL_CLASS = Name; expr->VL_IDF = idf; expr->VL_VALUE = (arith)0; } @@ -246,6 +254,7 @@ intexpr(ivalue, fund) crash("(intexpr) bad fund %s\n", symbol2str(fund)); } expr->ex_class = Value; + expr->VL_CLASS = Const; expr->VL_VALUE = ivalue; cut_size(expr); @@ -421,7 +430,7 @@ is_cp_cst(expr) /* An expression is a `compile-time constant' if it is a load-time constant, and the idf is not there. */ - return is_ld_cst(expr) && expr->VL_IDF == 0; + return is_ld_cst(expr) && expr->VL_CLASS == Const; } int diff --git a/lang/cem/cemcom/expr.str b/lang/cem/cemcom/expr.str index 2531672db..1d6275862 100644 --- a/lang/cem/cemcom/expr.str +++ b/lang/cem/cemcom/expr.str @@ -5,9 +5,18 @@ a union of various goodies, we define them first; so be patient. */ +/* classes of value */ +#define Const 1 +#define Name 2 +#define Label 3 + struct value { - struct idf *vl_idf; /* idf of an external name or 0 */ - arith vl_value; /* constant, or offset if idf != 0 */ + int vl_class; /* Const, Name or Label */ + arith vl_value; /* constant value or offset */ + union { + struct idf *vl_idf; /* external name */ + label vl_lbl; /* compiler-generated label */ + } vl_data; }; struct string { @@ -53,8 +62,10 @@ struct expr { }; /* some abbreviated selections */ +#define VL_CLASS ex_object.ex_value.vl_class #define VL_VALUE ex_object.ex_value.vl_value -#define VL_IDF ex_object.ex_value.vl_idf +#define VL_IDF ex_object.ex_value.vl_data.vl_idf +#define VL_LBL ex_object.ex_value.vl_data.vl_lbl #define SG_VALUE ex_object.ex_string.sg_value #define SG_LEN ex_object.ex_string.sg_len #define SG_DATLAB ex_object.ex_string.sg_datlab diff --git a/lang/cem/cemcom/field.c b/lang/cem/cemcom/field.c index bc0b76d27..6245ac86f 100644 --- a/lang/cem/cemcom/field.c +++ b/lang/cem/cemcom/field.c @@ -47,7 +47,6 @@ eval_field(expr, code) ASSERT(leftop->ex_type->tp_fund == FIELD); ASSERT(asize == word_size); /* make sure that C_loc() is legal */ - leftop->ex_type = atype; /* this is cheating but it works... */ /* Note that op is either an assignment operator or an increment/ @@ -60,26 +59,21 @@ eval_field(expr, code) conversion(tp, atype); C_loc(fd->fd_mask); C_and(asize); - if (code == TRUE) { + if (code == TRUE) C_dup(asize); - } C_loc((arith)fd->fd_shift); - if (atype->tp_unsigned) C_slu(asize); else C_sli(asize); - C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize)))); - if (leftop->ex_depth == 0) { /* simple case */ load_val(leftop, RVAL); C_and(asize); C_ior(asize); store_val( - leftop->VL_IDF, - leftop->ex_type, - leftop->VL_VALUE + &(leftop->ex_object.ex_value), + leftop->ex_type ); } else { /* complex case */ @@ -98,13 +92,11 @@ eval_field(expr, code) } } else { /* treat ++F as F += 1 and --F as F -= 1 */ - /* F op= e: f = (((((f>>shift)&mask) op e)&mask)<ex_depth == 0) { /* simple case */ + if (leftop->ex_depth == 0) /* simple case */ load_val(leftop, RVAL); - } else { /* complex case */ tmpvar = tmp_pointer_var(&old_offset); EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL); @@ -113,26 +105,18 @@ eval_field(expr, code) C_sti(pointer_size); C_loi(asize); } - C_loc((arith)fd->fd_shift); - if (atype->tp_unsigned) C_sru(asize); else C_sri(asize); - C_loc(fd->fd_mask); C_and(asize); - - if (code == TRUE && (op == POSTINCR || op == POSTDECR)) { + if (code == TRUE && (op == POSTINCR || op == POSTDECR)) C_dup(asize); - } - EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL); conversion(tp, atype); - - /* generate the code for the operator - */ + /* generate code for the operator */ if (op == PLUSPLUS || op == POSTINCR) assop(atype, PLUSAB); else @@ -140,31 +124,23 @@ eval_field(expr, code) assop(atype, MINAB); else assop(atype, op); - C_loc(fd->fd_mask); C_and(asize); - - if (code == TRUE && op != POSTINCR && op != POSTDECR) { + if (code == TRUE && op != POSTINCR && op != POSTDECR) C_dup(asize); - } - C_loc((arith)fd->fd_shift); - if (atype->tp_unsigned) C_slu(asize); else C_sli(asize); - C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize)))); - if (leftop->ex_depth == 0) { load_val(leftop, RVAL); C_and(asize); C_ior(asize); store_val( - leftop->VL_IDF, - leftop->ex_type, - leftop->VL_VALUE + &(leftop->ex_object.ex_value), + leftop->ex_type ); } else { @@ -179,7 +155,6 @@ eval_field(expr, code) free_tmp_var(old_offset); } } - if (code == TRUE) { /* Take care that the effective value stored in the bit field (i.e. the value that is got on @@ -193,7 +168,6 @@ eval_field(expr, code) C_loc(shift); C_sri(asize); } - conversion(atype, tp); } } diff --git a/lang/cem/cemcom/ival.c b/lang/cem/cemcom/ival.c index 8e921e964..ff52c496b 100644 --- a/lang/cem/cemcom/ival.c +++ b/lang/cem/cemcom/ival.c @@ -27,7 +27,6 @@ char *symbol2str(); char *long2str(); struct expr *do_array(), *do_struct(), *IVAL(); -struct expr *strings = 0; /* list of string constants within initialiser */ /* do_ival() performs the initialisation of a global variable of type tp with the initialisation expression expr by calling IVAL(). @@ -39,33 +38,8 @@ do_ival(tpp, expr) { if (IVAL(tpp, expr) != 0) too_many_initialisers(expr); - - /* The following loop declares the string constants - used in the initialisation. - The code for these string constants may not appear in - the code of the initialisation because a data label - in EM causes the current initialisation to be completed. - E.g. char *s[] = {"hello", "world"}; - */ - while (strings != 0) { - C_df_dlb(strings->SG_DATLAB); - C_con_scon(strings->SG_VALUE, (arith)strings->SG_LEN); - strings = strings->next; - } -} - - -/* store_string() collects the string constants appearing in an - initialisation. -*/ -store_string(expr) - struct expr *expr; -{ - expr->next = strings; - strings = expr; } - /* IVAL() recursively guides the initialisation expression through the different routines for the different types of initialisation: - array initialisation @@ -89,18 +63,14 @@ IVAL(tpp, expr) /* array initialisation */ if (valid_type(tp->tp_up, "array element") == 0) return 0; - if (ISCOMMA(expr)) { - /* list of initialisation expressions */ + if (ISCOMMA(expr)) /* list of initialisation expressions */ return do_array(expr, tpp); - } - /* There might be an initialisation of a string - like char s[] = "I am a string" - */ + /* catch initialisations like char s[] = "I am a string" */ if (tp->tp_up->tp_fund == CHAR && expr->ex_class == String) init_string(tpp, expr); else /* " int i[24] = 12;" */ check_and_pad(expr, tpp); - return 0; /* nothing left */ + break; case STRUCT: /* struct initialisation */ if (valid_type(tp, "struct") == 0) @@ -109,12 +79,12 @@ IVAL(tpp, expr) return do_struct(expr, tp); /* "struct foo f = 12;" */ check_and_pad(expr, tpp); - return 0; + break; case UNION: error("union initialisation not allowed"); - return 0; + break; case ERRONEOUS: - return 0; + break; default: /* fundamental type */ if (ISCOMMA(expr)) { /* " int i = {12};" */ if (IVAL(tpp, expr->OP_LEFT) != 0) @@ -127,9 +97,9 @@ IVAL(tpp, expr) } /* "int i = 12;" */ check_ival(expr, tp); - return 0; + break; } - /* NOTREACHED */ + return 0; } /* do_array() initialises the members of an array described @@ -451,20 +421,18 @@ check_ival(expr, type) case LONG: case ENUM: ch7cast(&expr, '=', type); - if (!is_cp_cst(expr)) { + if (is_cp_cst(expr)) + con_int(expr); + else illegal_init_cst(expr); - break; - } - con_int(expr); break; #ifndef NOBITFIELD case FIELD: ch7cast(&expr, '=', type->tp_up); - if (!is_cp_cst(expr)) { + if (is_cp_cst(expr)) + put_bf(type, expr->VL_VALUE); + else illegal_init_cst(expr); - break; - } - put_bf(type, expr->VL_VALUE); break; #endif NOBITFIELD case FLOAT: @@ -475,14 +443,13 @@ check_ival(expr, type) else if (expr->ex_class == Oper && expr->OP_OPER == INT2FLOAT) { expr = expr->OP_RIGHT; - if (!is_cp_cst(expr)) { + if (is_cp_cst(expr)) + C_con_fcon( + long2str((long)expr->VL_VALUE, 10), + type->tp_size + ); + else illegal_init_cst(expr); - break; - } - C_con_fcon( - long2str((long)expr->VL_VALUE, 10), - type->tp_size - ); } else illegal_init_cst(expr); @@ -493,55 +460,35 @@ check_ival(expr, type) case Oper: illegal_init_cst(expr); break; - case String: /* char *s = "...." */ - { - label datlab = data_label(); - - C_ina_dlb(datlab); - C_con_dlb(datlab, (arith)0); - expr->SG_DATLAB = datlab; - store_string(expr); - break; - } case Value: { - struct value *vl = &(expr->ex_object.ex_value); - struct idf *idf = vl->vl_idf; - ASSERT(expr->ex_type->tp_fund == POINTER); if (expr->ex_type->tp_up->tp_fund == FUNCTION) { - if (idf) - C_con_pnam(idf->id_text); + if (expr->VL_CLASS == Name) + C_con_pnam(expr->VL_IDF->id_text); else /* int (*func)() = 0 */ con_int(expr); } else - if (idf) { - register struct def *def = idf->id_def; - - if (def->df_level >= L_LOCAL) { - if (def->df_sc != STATIC) - /* Eg. int a; - static int *p = &a; - */ - expr_error(expr, - "illegal initialisation" - ); - else - C_con_dlb( - (label)def->df_address, - vl->vl_value - ); - } + if (expr->VL_CLASS == Name) { + register struct idf *id = expr->VL_IDF; + + if (id ->id_def->df_level >= L_LOCAL) + expr_error(expr, + "illegal initialisation"); else - C_con_dnam(idf->id_text, vl->vl_value); + C_con_dnam(id->id_text, expr->VL_VALUE); } + else + if (expr->VL_CLASS == Label) + C_con_dlb(expr->VL_LBL, expr->VL_VALUE); else con_int(expr); break; } + case String: default: - crash("(check_ival) illegal initialisation expression"); + crash("(check_ival) illegal value class"); } break; case ERRONEOUS: @@ -565,6 +512,7 @@ init_string(tpp, expr) char *s = expr->SG_VALUE; arith ntopad; + ASSERT(expr->ex_class == String); length = expr->SG_LEN; if (tp->tp_size == (arith)-1) { /* set the dimension */ @@ -604,21 +552,22 @@ put_bf(tp, val) static arith offset = (arith)-1; register struct field *fd = tp->tp_field; register struct sdef *sd = fd->fd_sdef; - static struct expr expr; + static struct expr exp; ASSERT(sd); if (offset == (arith)-1) { /* first bitfield in this field */ offset = sd->sd_offset; - expr.ex_type = tp->tp_up; - expr.ex_class = Value; + exp.ex_type = tp->tp_up; + exp.ex_class = Value; + exp.VL_CLASS = Const; } if (val != 0) /* insert the value into "field" */ field |= (val & fd->fd_mask) << fd->fd_shift; if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) { /* the selector was the last stored at this address */ - expr.VL_VALUE = field; - con_int(&expr); + exp.VL_VALUE = field; + con_int(&exp); field = (arith)0; offset = (arith)-1; } @@ -654,27 +603,28 @@ valid_type(tp, str) return 1; } -con_int(expr) - register struct expr *expr; +con_int(ex) + register struct expr *ex; { - register struct type *tp = expr->ex_type; + register struct type *tp = ex->ex_type; + ASSERT(is_cp_cst(ex)); if (tp->tp_unsigned) - C_con_ucon(long2str((long)expr->VL_VALUE, -10), tp->tp_size); + C_con_ucon(long2str((long)ex->VL_VALUE, -10), tp->tp_size); else - C_con_icon(long2str((long)expr->VL_VALUE, 10), tp->tp_size); + C_con_icon(long2str((long)ex->VL_VALUE, 10), tp->tp_size); } -illegal_init_cst(expr) - struct expr *expr; +illegal_init_cst(ex) + struct expr *ex; { - expr_error(expr, "illegal initialisation constant"); + expr_error(ex, "illegal initialisation constant"); } -too_many_initialisers(expr) - struct expr *expr; +too_many_initialisers(ex) + struct expr *ex; { - expr_error(expr, "too many initialisers"); + expr_error(ex, "too many initialisers"); } aggregate_type(tp) diff --git a/lang/cem/cemcom/switch.c b/lang/cem/cemcom/switch.c index 28db313f8..3999206f7 100644 --- a/lang/cem/cemcom/switch.c +++ b/lang/cem/cemcom/switch.c @@ -124,6 +124,7 @@ code_case(expr) register struct case_entry *ce; register struct switch_hdr *sh = switch_stack; + ASSERT(is_cp_cst(expr)); if (sh == 0) { error("case statement not in switch"); return; @@ -133,14 +134,11 @@ code_case(expr) /* is probably 0 anyway */ return; } - expr->ex_type = sh->sh_type; cut_size(expr); - ce = new_case_entry(); C_df_ilb(ce->ce_label = text_label()); ce->ce_value = val = expr->VL_VALUE; - if (sh->sh_entries == 0) { /* first case entry */ ce->next = (struct case_entry *) 0; -- 2.34.1