aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2021-10-25 15:00:48 -0700
committerMichael Forney <mforney@mforney.org>2021-10-25 17:01:50 -0700
commit7ffff16e6745c267b77d23a047f6ca5f20ca71e7 (patch)
tree7a7ccd3c8b2a8c2dc72cdf343e50ce7bba245cb7
parent42fc7b33d3987fc394e5c0d5ce7cb606b110296d (diff)
decl: Allow alignment > 16 of globals and struct members
-rw-r--r--decl.c6
-rw-r--r--test/alignas-local.c4
-rw-r--r--test/alignas-local.qbe9
-rw-r--r--test/alignas-member.c4
-rw-r--r--test/alignas-member.qbe1
-rw-r--r--test/alignas.c2
-rw-r--r--test/alignas.qbe2
7 files changed, 24 insertions, 4 deletions
diff --git a/decl.c b/decl.c
index c673463..50fe1c6 100644
--- a/decl.c
+++ b/decl.c
@@ -379,7 +379,7 @@ declspecs(struct scope *s, enum storageclass *sc, enum funcspec *fs, int *align)
*align = other->align;
} else {
i = intconstexpr(s, false);
- if (i & (i - 1) || i > 16)
+ if (i & (i - 1))
error(&tok.loc, "invalid alignment: %d", i);
if (i)
*align = (int)i;
@@ -960,8 +960,10 @@ decl(struct scope *s, struct func *f)
if (init || d->linkage == LINKNONE) {
if (d->linkage != LINKNONE || sc & SCSTATIC)
emitdata(d, init);
- else
+ else if (d->align <= 16)
funcinit(f, d, init);
+ else
+ error(&tok.loc, "unsupported alignment %d for object with automatic storage duration", d->align);
d->defined = true;
if (d->tentative.next)
listremove(&d->tentative);
diff --git a/test/alignas-local.c b/test/alignas-local.c
new file mode 100644
index 0000000..e1a8667
--- /dev/null
+++ b/test/alignas-local.c
@@ -0,0 +1,4 @@
+int main(void) {
+ _Alignas(16) char x;
+ return (unsigned long)&x % 16;
+}
diff --git a/test/alignas-local.qbe b/test/alignas-local.qbe
new file mode 100644
index 0000000..cff9008
--- /dev/null
+++ b/test/alignas-local.qbe
@@ -0,0 +1,9 @@
+export
+function w $main() {
+@start.1
+ %.1 =l alloc16 1
+@body.2
+ %.2 =l extsw 16
+ %.3 =l urem %.1, %.2
+ ret %.3
+}
diff --git a/test/alignas-member.c b/test/alignas-member.c
new file mode 100644
index 0000000..965e42a
--- /dev/null
+++ b/test/alignas-member.c
@@ -0,0 +1,4 @@
+struct {
+ int x;
+ _Alignas(32) char s[32];
+} s = {123, "abc"};
diff --git a/test/alignas-member.qbe b/test/alignas-member.qbe
new file mode 100644
index 0000000..13aa14f
--- /dev/null
+++ b/test/alignas-member.qbe
@@ -0,0 +1 @@
+export data $s = align 32 { w 123, z 28, b "abc\000", z 28, }
diff --git a/test/alignas.c b/test/alignas.c
index b714d37..a0a7669 100644
--- a/test/alignas.c
+++ b/test/alignas.c
@@ -1 +1 @@
-_Alignas(8) int x;
+_Alignas(32) long x[4] = {1, 2, 3, 4};
diff --git a/test/alignas.qbe b/test/alignas.qbe
index 6dd5505..8758fb2 100644
--- a/test/alignas.qbe
+++ b/test/alignas.qbe
@@ -1 +1 @@
-export data $x = align 8 { z 4 }
+export data $x = align 32 { l 1, l 2, l 3, l 4, }