summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2022-03-08 15:49:01 +0100
committerQuentin Carbonneaux <quentin@c9x.me>2022-03-08 15:57:06 +0100
commit9060981c10c21834596d5677a2c9ccc56809eb64 (patch)
tree2fe18c42b4c435a15612abdc4ce836d5860cdfa2
parent349794f3e4f11e4cc34a501ba935a2a305229738 (diff)
downloadroux-9060981c10c21834596d5677a2c9ccc56809eb64.tar.gz
flag types defined as unions
The risc-v abi needs to know if a
type is defined as a union or not.

We cannot use nunion to obtain this
information because the risc-v abi
made the unfortunate decision of
treating

	union { int i; }

differently from

	int i;

So, instead, I introduce a single
bit flag 'isunion'.
-rw-r--r--all.h3
-rw-r--r--amd64/sysv.c2
-rw-r--r--arm64/abi.c2
-rw-r--r--parse.c10
-rw-r--r--rv64/abi.c2
5 files changed, 11 insertions, 8 deletions
diff --git a/all.h b/all.h
index a62b19b..f806c5b 100644
--- a/all.h
+++ b/all.h
@@ -357,7 +357,8 @@ struct Fn {
 
 struct Typ {
 	char name[NString];
-	int dark;
+	char isdark;
+	char isunion;
 	int align;
 	uint64_t size;
 	uint nunion;
diff --git a/amd64/sysv.c b/amd64/sysv.c
index 7287f41..e9f3d6b 100644
--- a/amd64/sysv.c
+++ b/amd64/sysv.c
@@ -77,7 +77,7 @@ typclass(AClass *a, Typ *t)
 	a->size = sz;
 	a->align = t->align;
 
-	if (t->dark || sz > 16 || sz == 0) {
+	if (t->isdark || sz > 16 || sz == 0) {
 		/* large or unaligned structures are
 		 * required to be passed in memory
 		 */
diff --git a/arm64/abi.c b/arm64/abi.c
index f127576..6ed393d 100644
--- a/arm64/abi.c
+++ b/arm64/abi.c
@@ -94,7 +94,7 @@ typclass(Class *c, Typ *t, int *gp, int *fp)
 	if (t->align > 4)
 		err("alignments larger than 16 are not supported");
 
-	if (t->dark || sz > 16 || sz == 0) {
+	if (t->isdark || sz > 16 || sz == 0) {
 		/* large structs are replaced by a
 		 * pointer to some caller-allocated
 		 * memory */
diff --git a/parse.c b/parse.c
index c9638fd..70c291b 100644
--- a/parse.c
+++ b/parse.c
@@ -925,7 +925,8 @@ parsetyp()
 	 */
 	vgrow(&typ, ntyp+1);
 	ty = &typ[ntyp++];
-	ty->dark = 0;
+	ty->isdark = 0;
+	ty->isunion = 0;
 	ty->align = -1;
 	ty->size = 0;
 	if (nextnl() != Ttyp ||  nextnl() != Teq)
@@ -944,7 +945,7 @@ parsetyp()
 		err("type body must start with {");
 	t = nextnl();
 	if (t == Tint) {
-		ty->dark = 1;
+		ty->isdark = 1;
 		ty->size = tokval.num;
 		if (ty->align == -1)
 			err("dark types need alignment");
@@ -954,7 +955,8 @@ parsetyp()
 	}
 	n = 0;
 	ty->fields = vnew(1, sizeof ty->fields[0], Pheap);
-	if (t == Tlbrace)
+	if (t == Tlbrace) {
+		ty->isunion = 1;
 		do {
 			if (t != Tlbrace)
 				err("invalid union member");
@@ -962,7 +964,7 @@ parsetyp()
 			parsefields(ty->fields[n++], ty, nextnl());
 			t = nextnl();
 		} while (t != Trbrace);
-	else
+	} else
 		parsefields(ty->fields[n++], ty, t);
 	ty->nunion = n;
 }
diff --git a/rv64/abi.c b/rv64/abi.c
index 05deabe..b49057b 100644
--- a/rv64/abi.c
+++ b/rv64/abi.c
@@ -105,7 +105,7 @@ typclass(Class *c, Typ *t, int *gp, int *fp)
 	if (t->align > 4)
 		err("alignments larger than 16 are not supported");
 
-	if (t->dark || sz > 16 || sz == 0) {
+	if (t->isdark || sz > 16 || sz == 0) {
 		/* large structs are replaced by a
 		 * pointer to some caller-allocated
 		 * memory */