Browse Source

Bug fix: INC/DEC evaluated argument twice(!)

ceriel 32 years ago
parent
commit
81ec28ccb9
1 changed files with 52 additions and 5 deletions
  1. 52 5
      lang/m2/comp/code.c

+ 52 - 5
lang/m2/comp/code.c

@@ -474,6 +474,23 @@ addu(sz)
 	C_adu((arith)sz);
 }
 
+static int
+complex_lhs(nd)
+	register t_node *nd;
+{
+	switch(nd->nd_class) {
+	case Value:
+	case Name:
+	case Set:
+	case Def:
+		return 0;
+	case Select:
+		return complex_lhs(nd->nd_NEXT);
+	default:
+		return 1;
+	}
+}
+
 CodeStd(nd)
 	t_node *nd;
 {
@@ -545,10 +562,19 @@ CodeStd(nd)
 	case S_DEC:
 	case S_INC: {
 		register arith size;
+		int compl = complex_lhs(left);
+		arith tmp = 0;
 
 		size = left->nd_type->tp_size;
 		if ((int) size < (int) word_size) size = word_size;
-		CodePExpr(left);
+		if (compl) {
+			tmp = NewPtr();
+			CodeDAddress(left, 1);
+			STL(tmp, pointer_size);
+			LOL(tmp, pointer_size);
+			C_loi(left->nd_type->tp_size);
+		}
+		else CodePExpr(left);
 		CodeCoercion(left->nd_type, tp);
 		if (arg) {
 			CodePExpr(arg->nd_LEFT);
@@ -570,7 +596,12 @@ CodeStd(nd)
 			RangeCheck(left->nd_type, tp->tp_fund == T_INTEGER ?
 						int_type : card_type);
 		}
-		CodeDStore(left);
+		if (compl) {
+			LOL(tmp, pointer_size);
+			C_sti(left->nd_type->tp_size);
+			FreePtr(tmp);
+		}
+		else CodeDStore(left);
 		break;
 		}
 
@@ -579,8 +610,18 @@ CodeStd(nd)
 		break;
 
 	case S_INCL:
-	case S_EXCL:
-		CodePExpr(left);
+	case S_EXCL: {
+		int compl = complex_lhs(left);
+		arith tmp = 0;
+
+		if (compl) {
+			tmp = NewPtr();
+			CodeDAddress(left, 1);
+			STL(tmp, pointer_size);
+			LOL(tmp, pointer_size);
+			C_loi(left->nd_type->tp_size);
+		}
+		else CodePExpr(left);
 		CodePExpr(arg->nd_LEFT);
 		C_loc(tp->set_low);
 		C_sbi(word_size);
@@ -592,8 +633,14 @@ CodeStd(nd)
 			C_com(tp->tp_size);
 			C_and(tp->tp_size);
 		}
-		CodeDStore(left);
+		if (compl) {
+			LOL(tmp, pointer_size);
+			C_sti(left->nd_type->tp_size);
+			FreePtr(tmp);
+		}
+		else CodeDStore(left);
 		break;
+		}
 
 	default:
 		crash("(CodeStd)");