Przeglądaj źródła

revised the administration of Value expressions

erikb 38 lat temu
rodzic
commit
53af3f399a

+ 2 - 2
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

+ 24 - 6
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);

+ 3 - 0
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 */

+ 11 - 16
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;
 
-				/*	&<var> indicates that <var> cannot
-					be used as register anymore
+				/*	&<var> indicates that <var>
+					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!",

+ 37 - 1
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);
 	}
 }
 

+ 9 - 0
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

+ 4 - 1
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,

+ 15 - 5
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:
 	{

+ 123 - 117
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;
-		}
 	}
 }
 

+ 12 - 3
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

+ 14 - 3
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

+ 9 - 35
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)<<shift)|
 					(f&~(mask<<shift))
 		*/
-		if (leftop->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);
 	}
 }

+ 53 - 103
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)

+ 1 - 3
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;