From 989bfdbd25f2b95fded68df9e49caff51b5b96f6 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Sun, 27 Aug 2017 11:23:45 +0200 Subject: [PATCH] mescc: Tinycc support: array of struct of any size. * module/language/c99/compiler.mes (accu*value): New function (expr->accu*): Use it to support array of struct of any size. * scaffold/tests/7l-struct-any-size-array.c: Test it. * make.scm (add-scaffold-test): Build it. --- make.scm | 3 +- module/language/c99/compiler.mes | 77 ++++++++----------- scaffold/tests/7l-struct-any-size-array.c | 92 +++++++++++++++++++++++ 3 files changed, 127 insertions(+), 45 deletions(-) create mode 100644 scaffold/tests/7l-struct-any-size-array.c diff --git a/make.scm b/make.scm index 3a9bcac4..3f7fd50b 100755 --- a/make.scm +++ b/make.scm @@ -170,7 +170,8 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$ "7h-struct-assign" "7i-struct-struct" "7j-strtoull" - "7k-for-each-elem")) + "7k-for-each-elem" + "7l-struct-any-size-array")) (add-target (group "check-scaffold-tests/7" #:dependencies (filter (target-prefix? "check-scaffold/tests/7") %targets))) diff --git a/module/language/c99/compiler.mes b/module/language/c99/compiler.mes index 99c430e7..6e70c86a 100644 --- a/module/language/c99/compiler.mes +++ b/module/language/c99/compiler.mes @@ -1075,6 +1075,24 @@ (let ((source (with-output-to-string (lambda () (pretty-print-c99 o))))) (make-comment (string-join (string-split source #\newline) " ")))) +(define (accu*value info value) + (append-text info (wrap-as (case value + ((1) (i386:accu->base)) + ((2) (i386:accu+accu)) + ((3) (append (i386:accu->base) + (i386:accu+accu) + (i386:accu+base))) + ((4) (i386:accu-shl 2)) + ((8) (append (i386:accu+accu) + (i386:accu-shl 2))) + ((12) (append (i386:accu->base) + (i386:accu+accu) + (i386:accu+base) + (i386:accu-shl 2))) + ((16) (i386:accu-shl 4)) + (else (append (i386:value->base value) + (i386:accu*base))))))) + (define (expr->accu* info) (lambda (o) (pmatch o @@ -1087,21 +1105,13 @@ ;; foo[bar] ((array-ref ,index (p-expr (ident ,array))) - (let* ((info ((expr->accu info) index)) - (type (ident->type info array)) + (let* ((type (ident->type info array)) (ptr (ident->pointer info array)) (size (if (or (= ptr 1) (= ptr -1)) (ast-type->size info type) - 4))) - (append-text info (append (wrap-as (append (i386:accu->base) - (case size - ((1) '()) - ((2) (i386:accu+accu)) - (else (append (if (<= size 4) '() - (i386:accu+accu)) - (if (<= size 8) '() - (i386:accu+base)) - (i386:accu-shl 2)))))) - ((ident->base info) array) + 4)) + (info ((expr->accu info) index)) + (info (accu*value info size))) + (append-text info (append ((ident->base info) array) (wrap-as (i386:accu+base)))))) ;; bar.foo.i @@ -1193,16 +1203,9 @@ (ptr (field-pointer info type0 field0)) (size (if (or (= ptr -1) (= ptr 1)) (ast-type->size info type1) - 4))) - (append-text info (append (wrap-as (append (i386:accu->base) - (if (eq? size 1) '() - (append - (if (<= size 4) '() - (i386:accu+accu)) - (if (<= size 8) '() - (i386:accu+base)) - (i386:accu-shl 2))))) - (wrap-as (i386:push-accu)) + 4)) + (info (accu*value info size))) + (append-text info (append (wrap-as (i386:push-accu)) ((ident->accu info) struct0) (wrap-as (append (i386:accu+value offset) (i386:pop-base) @@ -1221,16 +1224,9 @@ (ptr (field-pointer info type0 field0)) (size (if (or (= ptr -1) (= ptr 1)) (ast-type->size info type1) - 4))) - (append-text info (append (wrap-as (append (i386:accu->base) - (if (eq? size 1) '() - (append - (if (<= size 4) '() - (i386:accu+accu)) - (if (<= size 8) '() - (i386:accu+base)) - (i386:accu-shl 2))))) - (wrap-as (i386:push-accu)) + 4)) + (info (accu*value info size))) + (append-text info (append (wrap-as (i386:push-accu)) ((ident->accu info) struct0) (wrap-as (append (i386:accu+value offset) (i386:pop-base) @@ -1244,14 +1240,7 @@ (ptr (expr->pointer info array)) (size (if (= ptr 1) (expr->size info array) 4)) - (info (append-text info (wrap-as (append (i386:accu->base) - (if (eq? size 1) '() - (append - (if (<= size 4) '() - (i386:accu+accu)) - (if (<= size 8) '() - (i386:accu+base)) - (i386:accu-shl 2))))))) + (info (accu*value info size)) (info ((expr->base info) array))) (append-text info (wrap-as (i386:accu+base))))) @@ -1337,14 +1326,14 @@ (define (field:size o) (pmatch o ((struct . ,fields) (apply + (map field:size fields))) - ((union . ,fields) 4) ;; FIXME + ((union . ,fields) (apply max (map field:size fields))) ((,name ,type ,size ,pointer) size) - (_ 4))) + (_ (error (format #f "field:size: ~s\n" o))))) (define (field:type o) (pmatch o ((,name ,type ,size ,pointer) type) - (_ (error "field:type:" o)))) + (_ (error (format #f "field:type: ~s\n" o))))) (define (get-type types o) (let ((t (assoc-ref types o))) diff --git a/scaffold/tests/7l-struct-any-size-array.c b/scaffold/tests/7l-struct-any-size-array.c new file mode 100644 index 00000000..08bfa1c6 --- /dev/null +++ b/scaffold/tests/7l-struct-any-size-array.c @@ -0,0 +1,92 @@ +/* -*-comment-start: "//";comment-end:""-*- + * Mes --- Maxwell Equations of Software + * Copyright © 2017 Jan Nieuwenhuizen + * + * This file is part of Mes. + * + * Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mes. If not, see . + */ + +#include "30-test.i" + +#if __MESC__ +#define __attribute__(x) +#endif + +struct foo13 +{ + int a; + int b; + int c; + char d; +} __attribute__ ((packed)); + +; + +struct foo16 +{ + int a; + int b; + int c; + int d; +}; + +struct foo13 tab14[3]; +struct foo16 tab16[3]; + +int +test () +{ + unsigned char *p; + + tab14[1].a = -1; + tab14[1].b = -1; + tab14[1].c = -1; + tab14[1].d = -1; + + p = &tab14; + for (int i = 0; i < sizeof (struct foo13) * 2; i++) + { + if (i < 10) eputs (" "); eputs (itoa (i)); eputs (": "); + eputs (itoa (p[i])); + eputs ("\n"); + } + + for (int i = 0; i < sizeof (struct foo13); i++) + if (p[i] != 0) return 1 + i; + + for (int i = sizeof (struct foo13); i < 2 * sizeof (struct foo13); i++) + if (p[i] != 255) return 1 + i; + + tab16[1].a = -1; + tab16[1].b = -1; + tab16[1].c = -1; + tab16[1].d = -1; + + p = &tab16; + for (int i = 0; i < sizeof (struct foo16) * 2; i++) + { + if (i < 10) eputs (" "); eputs (itoa (i)); eputs (": "); + eputs (itoa (p[i])); + eputs ("\n"); + } + + for (int i = 0; i < sizeof (struct foo16); i++) + if (p[i] != 0) return 1 + i; + + for (int i = sizeof (struct foo16); i < 2 * sizeof (struct foo16); i++) + if (p[i] != 255) return 1 + i; + + return 0; +}