mescc: Tinycc support: fixes for foo->bar[baz].
authorJan Nieuwenhuizen <janneke@gnu.org>
Sat, 5 Aug 2017 17:10:00 +0000 (19:10 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Sat, 5 Aug 2017 17:10:00 +0000 (19:10 +0200)
* module/language/c99/compiler.mes (expr->accu, expr->accu*): fixes
  for foo->bar[baz].
  (expr->pointer): Support i-sel.
  (p-expr->type): Support add, sub, de-ref, ref-to.
* scaffold/tests/7f-struct-pointer-arithmetic.c: Test it.
* make.scm (add-scaffold-test): Build it.

make.scm
module/language/c99/compiler.mes
scaffold/tests/7f-struct-pointer-arithmetic.c [new file with mode: 0644]

index b4752f5325c9cf038c6937bae312a243d82d3c4b..5fe89b626464df07ac0d0656427c67bd567e9944 100755 (executable)
--- a/make.scm
+++ b/make.scm
@@ -164,7 +164,8 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$
    "7b-struct-int-array"
    "7c-dynarray"
    "7d-cast-char"
-   "7e-struct-array-access"))
+   "7e-struct-array-access"
+   "7f-struct-pointer-arithmetic"))
 
 (add-target (group "check-scaffold-tests/7" #:dependencies (filter (target-prefix? "check-scaffold/tests/7") %targets)))
 
index 73a94488ba50f467cd3a65facf155a2dfd7eb679..a9209d2432e3f3fbe4eda8093126099e84a54ed6 100644 (file)
 
         ((add ,a (p-expr (fixed ,value)))
          (let* ((ptr (expr->pointer info a))
-                (size (cond ((= ptr 1)  (expr->size info a))
+                (type0 (p-expr->type info a))
+                (struct? (memq (type:type (ast-type->type info type0)) '(struct union)))
+                (size (cond ((= ptr 1) (expr->size info a))
                             ((> ptr 1) 4)
+                            ((and struct? (= ptr -2)) 4)
                             (else 1)))
                 (info ((expr->accu info) a))
                 (value (cstring->number value))
                 (value (* size value)))
+           (stderr "ptr=~s\n" ptr)
+           (stderr "  size=~s\n" size)
+           (stderr "  struct?=~s\n" struct?)
+           (if (not (= size 1))
+               (warn (format #f "TODO: pointer arithmetic: ~s\n" o)))
            (append-text info (wrap-as (i386:accu+value value)))))
 
         ((add ,a ,b)
          (let* ((ptr (expr->pointer info a))
                 (size (cond ((= ptr 1) (expr->size info a))
                             ((> ptr 1) 4)
+                            ((and struct? (= ptr -2)) 4)
                             (else 1))))
            (if (not (= size 1))
                (warn (format #f "TODO: pointer arithmetic: ~s\n" o))))
                 (info ((expr->accu info) a))
                 (value (cstring->number value))
                 (value (* size value)))
+           (if (not (= size 1))
+               (warn (format #f "TODO: pointer arithmetic: ~s\n" o)))
            (append-text info (wrap-as (i386:accu+value (- value))))))
 
         ((sub ,a ,b)
               (type1 (field-type info type0 field0))
               (offset (field-offset info type0 field0))
               (info ((expr->accu info) index))
+              (struct? (memq (type:type (ast-type->type info type0)) '(struct union)))
               (ptr (field-pointer info type0 field0))
               (size (if (= ptr -1) (ast-type->size info type1)
                         4)))
+         (stderr "ACCU* o=~s\n" o)
+         (stderr "   ptr=~s\n" ptr)
+         (stderr "   size=~s\n" size)
          (append-text info (append (wrap-as (append (i386:accu->base)
                                                     (if (eq? size 1) '()
                                                         (append
                                                          (i386:accu-shl 2)))))
                                    (wrap-as (i386:push-accu))
                                    ((ident-address->accu info) struct0)
+                                   (if (and struct? (= ptr -2)) (wrap-as (i386:mem->accu)) '())
                                    (wrap-as (append (i386:accu+value offset)
                                                     (i386:pop-base)
                                                     (i386:accu+base)))))))
               (type1 (field-type info type0 field0))
               (offset (field-offset info type0 field0))
               (info ((expr->accu info) index))
+              (struct? (memq (type:type (ast-type->type info type0)) '(struct union)))
               (ptr (field-pointer info type0 field0))
               (size (if (= ptr -1) (ast-type->size info type1)
                         4)))
                                                          (i386:accu-shl 2)))))
                                    (wrap-as (i386:push-accu))
                                    ((ident->accu info) struct0)
+                                   (if (and struct? (= ptr -2)) (wrap-as (i386:mem->accu)) '())
                                    (wrap-as (append (i386:accu+value offset)
                                                     (i386:pop-base)
                                                     (i386:accu+base)))))))
     ((pre-dec ,a) (expr->pointer info a))
     ((post-inc ,a) (expr->pointer info a))
     ((post-dec ,a) (expr->pointer info a))
+    ((d-sel (ident ,field) (p-expr (ident ,struct)))
+     (let ((type (ident->type info struct)))
+       (field-pointer info type field)))
+    ((i-sel (ident ,field) (p-expr (ident ,struct)))
+     (let ((type (ident->type info struct)))
+       (field-pointer info type field)))
     ((cast (type-name ,type (abs-declr ,pointer)) (p-expr (ident ,name)))
      (let* ((type (ast-type->type info type))
             (pointer0 (type:pointer type))
      (let* ((type0 (ident->type info array))
             (type0 (if (pair? type0) type0 `("tag" ,type0))))
        (field-type info type0 field)))
+    ((de-ref ,expr) (p-expr->type info expr))
+    ((ref-to ,expr) (p-expr->type info expr))
+    ((add ,a ,b)
+     (p-expr->type info a))
+    ((sub ,a ,b)
+     (p-expr->type info a))
     (_ (error "p-expr->type: unsupported: " o))))
 
 (define (local-var? o) ;; formals < 0, locals > 0
diff --git a/scaffold/tests/7f-struct-pointer-arithmetic.c b/scaffold/tests/7f-struct-pointer-arithmetic.c
new file mode 100644 (file)
index 0000000..1a1e763
--- /dev/null
@@ -0,0 +1,65 @@
+/* -*-comment-start: "//";comment-end:""-*-
+ * Mes --- Maxwell Equations of Software
+ * Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "30-test.i"
+
+#include <mlibc.h>
+#include <stdio.h>
+
+struct foo;
+
+struct foo {
+    struct foo **foo;
+};
+  
+struct foo g_foo[2];
+
+int
+test ()
+{
+  struct foo foo;
+  foo.foo = g_foo;
+  void *p;
+  void *q;
+  
+  p = &foo.foo[0];
+  q = foo.foo;
+  eputs ("f:"); eputs (itoa (foo.foo)); eputs ("\n");
+  eputs ("p:"); eputs (itoa (p)); eputs ("\n");
+  eputs ("q:"); eputs (itoa (q)); eputs ("\n");
+  if (q != p) return 1;
+
+  p = &foo.foo[1];
+  q = foo.foo + 1;
+  eputs ("f:"); eputs (itoa (foo.foo)); eputs ("\n");
+  eputs ("p:"); eputs (itoa (p)); eputs ("\n");
+  eputs ("q:"); eputs (itoa (q)); eputs ("\n");
+  if (q != p) return 2;
+
+  struct foo *pfoo = &foo;
+  p = &pfoo->foo[1];
+  q = pfoo->foo + 1;
+  eputs ("f:"); eputs (itoa (pfoo->foo)); eputs ("\n");
+  eputs ("p:"); eputs (itoa (p)); eputs ("\n");
+  eputs ("q:"); eputs (itoa (q)); eputs ("\n");
+  if (q != p) return 3;
+
+  return 0;
+}