From edb6bbcd9c8d60714fd66d13f37bd7e5530a4440 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Sun, 30 Jul 2017 18:04:25 +0200 Subject: [PATCH] mescc: Tinycc support: field size of foo.bar[baz], foo->bar[baz]. Inspired by a patch from rain1 for foo->bar[baz]. * module/language/c99/compiler.mes (expr->accu): (expr->accu*): Consider field size for foo.bar[baz]. * scaffold/tests/7a-struct-char-array.c: Test it. * make.scm (add-scaffold-test): Build it. --- make.scm | 3 +- module/language/c99/compiler.mes | 76 ++++++++++++++++-------- scaffold/tests/7a-struct-char-array.c | 83 +++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 26 deletions(-) create mode 100644 scaffold/tests/7a-struct-char-array.c diff --git a/make.scm b/make.scm index 354e38e3..65c0710e 100755 --- a/make.scm +++ b/make.scm @@ -159,7 +159,8 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$ "76-pointer-arithmetic" "77-pointer-assign" "78-union-struct" - "79-int-array")) + "79-int-array" + "7a-struct-char-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 604571e8..b3b46409 100644 --- a/module/language/c99/compiler.mes +++ b/module/language/c99/compiler.mes @@ -565,14 +565,22 @@ (else '()))))))) ;; foo.bar[baz]) - ((array-ref ,index (d-sel (ident ,field) (p-expr (ident ,struct)))) - (let ((info ((expr->accu* info) o))) - (append-text info (wrap-as (i386:mem->accu))))) + ((array-ref ,index (d-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((info ((expr->accu* info) o)) + (type0 (ident->type info struct0)) + (type1 (field-type info type0 field0)) + (size (ast-type->size info type1))) + (append-text info (wrap-as (if (= size 1) (i386:byte-mem->accu) + (i386:mem->accu)))))) ;; foo->bar[baz]) - ((array-ref ,index (i-sel (ident ,field) (p-expr (ident ,struct)))) - (let ((info ((expr->accu* info) o))) - (append-text info (wrap-as (i386:mem->accu))))) + ((array-ref ,index (i-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((info ((expr->accu* info) o)) + (type0 (ident->type info struct0)) + (type1 (field-type info type0 field0)) + (size (ast-type->size info type1))) + (append-text info (wrap-as (if (= size 1) (i386:byte-mem->accu) + (i386:mem->accu)))))) ;; [baz] ((array-ref ,index ,array) @@ -1110,29 +1118,47 @@ (wrap-as (i386:accu+value offset))))))) ;; foo.bar[baz] - ((array-ref ,index (d-sel (ident ,field) (p-expr (ident ,struct)))) - (let* ((type (ident->type info struct)) - (offset (field-offset info type field)) - (info ((expr->accu info) index))) - (append-text info (append (wrap-as (append (i386:accu-shl 2) ;; FIXME: assume size=4 - (i386:push-accu))) - ((ident-address->accu info) struct) + ((array-ref ,index (d-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((type0 (ident->type info struct0)) + (type1 (field-type info type0 field0)) + (offset (field-offset info type0 field0)) + (info ((expr->accu info) index)) + (size (ast-type->size info type1))) + (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)))) + (i386:push-accu)) + ((ident-address->accu info) struct0) (wrap-as (append (i386:accu+value offset) (i386:pop-base) (i386:accu+base))))))) ;; foo->bar[baz] - ((array-ref ,index (i-sel (ident ,field) (p-expr (ident ,struct)))) - (let* ((type (ident->type info struct)) - (offset (field-offset info type field)) - (info ((expr->accu info) index))) - (append-text info (append (wrap-as (append (i386:accu-shl 2) ;; FIXME: assume size=4 - (i386:push-accu))) - ((ident->accu info) struct) + ((array-ref ,index (i-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((type0 (ident->type info struct0)) + (type1 (field-type info type0 field0)) + (offset (field-offset info type0 field0)) + (info ((expr->accu info) index)) + (size (ast-type->size info type1))) + (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)))) + (i386:push-accu)) + ((ident->accu info) struct0) (wrap-as (append (i386:accu+value offset) (i386:pop-base) (i386:accu+base))))))) - + ((array-ref ,index ,array) (let* ((info ((expr->accu info) index)) (size 4) ;; FIXME @@ -1891,7 +1917,7 @@ (let* ((local (car (add-local locals name type -1))) (count (p-expr->number info count)) (size (ast-type->size info type)) - (local (make-local-entry name type -1 (+ (local:id (cdr local)) -1 (quotient (+ (* count size) 3) 4)))) + (local (make-local-entry name type -1 (+ (local:id (cdr local)) -1 (quotient (+ (* count size) 3) 4)))) (locals (cons local locals)) (info (clone info #:locals locals))) info) @@ -1909,7 +1935,7 @@ (let* ((local (car (add-local locals name type -1))) (count (p-expr->number info count)) (size 4) - (local (make-local-entry name type -2 (+ (local:id (cdr local)) -1 (quotient (+ (* count size) 3) 4)))) + (local (make-local-entry name type -2 (+ (local:id (cdr local)) -1 (quotient (+ (* count size) 3) 4)))) (locals (cons local locals)) (info (clone info #:locals locals))) info) @@ -2142,7 +2168,7 @@ ((decl (decl-spec-list (stor-spec (typedef)) ,type) ,name) (format (current-error-port) "SKIP: typedef=~s\n" o) - info) + info) ((decl (@ ,at)) (format (current-error-port) "SKIP: at=~s\n" o) @@ -2183,7 +2209,7 @@ ((expr-stmt) info) ((compd-stmt (block-item-list . ,statements)) ((ast-list->info info) statements)) - + ((expr-stmt (fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list))) (if (equal? name "asm") (let ((arg0 (cadr (cadar expr-list)))) (append-text info (wrap-as (asm->m1 arg0)))) diff --git a/scaffold/tests/7a-struct-char-array.c b/scaffold/tests/7a-struct-char-array.c new file mode 100644 index 00000000..ef5e11e5 --- /dev/null +++ b/scaffold/tests/7a-struct-char-array.c @@ -0,0 +1,83 @@ +/* -*-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" + +struct file { + unsigned char buffer[1]; +}; + +int fill0; +int fill1; +int fill2; +int fill3; +int fill4; + +struct file file; + +int fill5; +int fill6; +int fill7; +int fill8; +int fill9; + +void * +memcpy (void *dest, void const *src, int n) +{ + char* p = dest; + char* q = src; + while (n--) *p++ = *q++; + return dest; +} + +#if __MESC__ +char * +strcpy (char *dest, char const *src) +{ + char *p = dest; + while (*src) *p++ = *src++; + *p = 0; + return dest; +} +#endif + +int +test () +{ + struct file *pfile = &file; + strcpy (file.buffer, "0123456789\n"); + eputs (file.buffer); + char *p = pfile->buffer; + if (p[4] != '4') return 1; + if (file.buffer[4] != '4') return 2; + if (pfile->buffer[4] != '4') return 3; + + memcpy (pfile->buffer + 4, " ", 1); + + strcpy (file.buffer, "0123456789\n"); + eputs (file.buffer); + p[4] = 'A'; + eputs (file.buffer); + if (p[4] != 'A') return 4; + if (file.buffer[4] != 'A') return 5; + if (pfile->buffer[4] != 'A') return 6; + + return 0; +}