shithub: scc

Download patch

ref: fb8177349e9d26b8f2ded4fb54128d56c2f9c179
parent: 8e3aa834b79499d2a5f4d81cc9644e82d7228ad8
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Apr 1 08:42:43 EDT 2022

cc2/qbe: Use explicit tables in cast()

Cast() was using the information implicit in the AS* macro definitions
and this was a bit obscure. This form uses a table that makes more
obvious how it works and it is independent of the encoding of the AS*
macros.

--- a/src/cmd/cc/cc2/target/qbe/cgen.c
+++ b/src/cmd/cc/cc2/target/qbe/cgen.c
@@ -7,6 +7,11 @@
 #include "arch.h"
 #include "../../cc2.h"
 
+#define I1BYTES 0
+#define I2BYTES 1
+#define I4BYTES 2
+#define I8BYTES 3
+
 static unsigned char opasmw[][2] = {
 	[OADD] = {ASADDW, ASADDW},
 	[OSUB] = {ASSUBW, ASSUBW},
@@ -76,6 +81,42 @@
 	{opasms, opasmd},
 };
 
+static unsigned char i2i_conv[4][4][2] = {
+	[I1BYTES] = {
+		[I4BYTES] = {ASEXTBW, ASUEXTBW},
+		[I8BYTES] = {ASEXTBL, ASUEXTBL},
+	},
+	[I2BYTES] = {
+		[I4BYTES] = {ASEXTHW, ASUEXTHW},
+		[I8BYTES] = {ASEXTHL, ASUEXTHL},
+	},
+	[I4BYTES] = {
+		[I8BYTES] = {ASEXTWL, ASUEXTWL},
+	}
+};
+
+static unsigned char f2i_conv[4][4][2] = {
+	[I4BYTES] = {
+		[I4BYTES] = {ASSTOW, ASSTOUW},
+		[I8BYTES] = {ASSTOL, ASDTOUL},
+	},
+	[I8BYTES] = {
+		[I4BYTES] = {ASDTOW, ASDTOUW},
+		[I8BYTES] = {ASDTOL, ASDTOUL},
+	}
+};
+
+static unsigned char i2f_conv[4][4][2] = {
+	[I4BYTES] = {
+		[I4BYTES] = {ASSWTOS, ASUWTOS},
+		[I8BYTES] = {ASSWTOD, ASUWTOD},
+	},
+	[I8BYTES] = {
+		[I4BYTES] = {ASSLTOS, ASULTOS},
+		[I8BYTES] = {ASSLTOD, ASULTOD},
+	}
+};
+
 extern Type int32type, uint32type, ptrtype;
 
 /*
@@ -169,6 +210,21 @@
 	return complex(np);
 }
 
+static int
+bytes2idx(int nbytes)
+{
+	if (nbytes== 1)
+		return I1BYTES;
+	else if (nbytes == 2)
+		return I2BYTES;
+	else if (nbytes == 4)
+		return I4BYTES;
+	else if (nbytes == 8)
+		return I8BYTES;
+	else
+		abort();
+}
+
 static Node *
 load(Type *tp, Node *np)
 {
@@ -215,77 +271,42 @@
 {
 	Type *ts;
 	Node *tmp;
-	int op, d_isint, s_isint;
+	int op, d_isint, s_isint, sidx, didx;
 
 	ts = &np->type;
 	d_isint = (td->flags & INTF) != 0;
 	s_isint = (ts->flags & INTF) != 0;
 
+	sidx = bytes2idx(ts->size);
+	didx = bytes2idx(td->size);
+
 	if (d_isint && s_isint) {
+		/* conversion from int to int */
 		if (td->size <= ts->size) {
 			np->type = *td;
 			return np;
 		}
-
+		assert(ts->size == 1 || ts->size == 2 || ts->size == 4);
 		assert(td->size == 4 || td->size == 8);
-		switch (ts->size) {
-		case 1:
-			op = (td->size == 4) ? ASEXTBW : ASEXTBL;
-			break;
-		case 2:
-			op = (td->size == 4) ? ASEXTHW : ASEXTHL;
-			break;
-		case 4:
-			op = ASEXTWL;
-			break;
-		default:
-			abort();
-		}
-		/*
-		 * unsigned version of operations are always +1 the
-		 * signed version
-		 */
-		op += (ts->flags & SIGNF) == 0;
+		op = i2i_conv[sidx][didx] [ (ts->flags & SIGNF) == 0];
 	} else if (d_isint) {
 		/* conversion from float to int */
-		switch (ts->size) {
-		case 4:
-			op = (td->size == 8) ? ASSTOL : ASSTOW;
-			break;
-		case 8:
-			op = (td->size == 8) ? ASDTOL : ASDTOW;
-			break;
-		default:
-			abort();
-		}
-		/*
-		 * unsigned version of operations are always +1 the
-		 * signed version
-		 */
-		op += (td->flags & SIGNF) == 0;
+		assert(ts->size == 4 || ts->size == 8);
+		assert(td->size == 4 || td->size == 8);
+		op = f2i_conv[sidx][didx] [ (ts->flags & SIGNF) == 0];
 	} else if (s_isint) {
 		/* conversion from int to float */
-		switch (ts->size) {
-		case 1:
-		case 2:
+		if (ts->size == 1 || ts->size == 2) {
 			ts = (ts->flags&SIGNF) ? &int32type : &uint32type;
 			np = cast(ts, np);
-		case 4:
-			op = (td->size == 8) ? ASSWTOD : ASSWTOS;
-			break;
-		case 8:
-			op = (td->size == 8) ? ASSLTOD : ASSLTOS;
-			break;
-		default:
-			abort();
 		}
-		/*
-		 * unsigned version of operations are always +1 the
-		 * signed version
-		 */
-		op += (ts->flags & SIGNF) == 0;
+		assert(ts->size == 4 || ts->size == 8);
+		assert(td->size == 4 || td->size == 8);
+		op = i2f_conv[sidx][didx] [ (ts->flags & SIGNF) == 0];
 	} else {
 		/* conversion from float to float */
+		assert(ts->size == 4 || ts->size == 8);
+		assert(td->size == 4 || td->size == 8);
 		op = (td->size == 4) ? ASEXTS : ASTRUNCD;
 	}