mescc: Tinycc support: struct.struct.
authorJan Nieuwenhuizen <janneke@gnu.org>
Tue, 18 Jul 2017 18:22:44 +0000 (20:22 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Wed, 26 Jul 2017 09:36:08 +0000 (11:36 +0200)
* module/language/c99/compiler.mes (expr->accu): Support &*,
  bar.foo.i, p->foo.i, p->pf->i (*pp)->foo.i, [slightly modified] offsetof.
* scaffold/tests/72-typedef-struct-def.c (test): Test them.

module/language/c99/compiler.mes
scaffold/tests/72-typedef-struct-def.c

index 2a73fa84035f757a1dc00861288666afb77a28e3..70f0e0c0d257c05964dba0480afb49c3689f25a1 100644 (file)
         ((initzer ,initzer)
          ((expr->accu info) initzer))
 
+        ;; offsetoff
+        ((ref-to (i-sel (ident ,field) (cast (type-name (decl-spec-list ,struct) (abs-declr (pointer))) (p-expr (fixed ,base)))))
+         (let* ((type (decl->ast-type struct))
+                (offset (field-offset info type field))
+                (base (cstring->number base)))
+           (append-text info (wrap-as (i386:value->accu (+ base offset))))))
+
         ;; &foo
         ((ref-to (p-expr (ident ,name)))
          (append-text info ((ident-address->accu info) name)))
 
-        ;; &f.field
-        ((ref-to (d-sel (ident ,field) (p-expr (ident ,array))))
-         (let* ((type (ident->type info array))
-                (offset (field-offset info type field))
-                (text (.text info)))
-           (append-text info (append ((ident->accu info) array)
-                                     (wrap-as (i386:accu+n offset))))))
+        ;; &*foo
+        ((ref-to (de-ref ,expr))
+         ((expr->accu info) expr))
 
-        ;; &a[x];
-        ((ref-to (array-ref ,index (p-expr (ident ,array))))
-         ((expr->accu* info) `(array-ref ,index (p-expr (ident ,array)))))
+        ((ref-to ,expr)
+         ((expr->accu* info) expr))
 
         ((sizeof-expr (p-expr (ident ,name)))
          (let* ((type (ident->type info name))
          (let ((size (ast-type->size info type)))
            (append-text info (wrap-as (i386:value->accu size)))))
 
-        ((sizeof-type (type-name (decl-spec-list (type-spec (fixed-type ,type))) (abs-declr (pointer))))
+        ((sizeof-type (type-name (decl-spec-list ,type) (abs-declr (pointer))))
          (let ((size 4))
            (append-text info (wrap-as (i386:value->accu size)))))
 
          (let ((info ((expr->accu* info) o)))
            (append-text info (wrap-as (i386:mem->accu)))))
 
+        ;; bar.f.i
+        ((d-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0))))
+         (let ((info ((expr->accu* info) o)))
+           (append-text info (wrap-as (i386:mem->accu)))))
+
+        ;; bar.poo->i
+        ((i-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0))))
+         (let ((info ((expr->accu* info) o)))
+           (append-text info (wrap-as (i386:mem->accu)))))
+
+        ;; bar->foo.i
+        ((d-sel (ident ,field1) (i-sel (ident ,field0) (p-expr (ident ,struct0))))
+         (let ((info ((expr->accu* info) o)))
+           (append-text info (wrap-as (i386:mem->accu)))))
+
+        ;;(i-sel (ident "i") (i-sel (ident "p") (p-expr (ident "p"))))
+        ((i-sel (ident ,field1) (i-sel (ident ,field0) (p-expr (ident ,struct0))))
+         (let ((info ((expr->accu* info) o)))
+           (append-text info (wrap-as (i386:mem->accu)))))
+
+        ;; (*pp)->bar.foo
+        ((d-sel (ident ,field1) (i-sel (ident ,field0) (de-ref (p-expr (ident ,struct0)))))
+         (let ((info ((expr->accu* info) o)))
+           (append-text info (wrap-as (i386:mem->accu)))))
+
         ;; f.field
-        ((d-sel (ident ,field) (p-expr (ident ,array)))
-         (let* ((type (ident->type info array))
-                (offset (field-offset info type field))
-                (text (.text info)))
-           (append-text info (append ((ident->accu info) array)
+        ((d-sel (ident ,field) (p-expr (ident ,struct)))
+         (let* ((type (ident->type info struct))
+                (offset (field-offset info type field)))
+           (append-text info (append ((ident->accu info) struct)
                                      (wrap-as (i386:mem+n->accu offset))))))
 
         ((d-sel (ident ,field) (array-ref ,index (p-expr (ident ,array))))
 
         ((i-sel (ident ,field) (p-expr (ident ,array)))
          (let* ((type (ident->type info array))
-                (offset (field-offset info type field))
-                (text (.text info)))
+                (offset (field-offset info type field)))
            (append-text info (append ((ident-address->accu info) array)
                                      (wrap-as (i386:mem->accu))
                                      (wrap-as (i386:mem+n->accu offset))))))
 
         ((i-sel (ident ,field) (de-ref (p-expr (ident ,array))))
          (let* ((type (ident->type info array))
-                (offset (field-offset info type field))
-                (text (.text info)))
+                (offset (field-offset info type field)))
            (append-text info (append ((ident-address->accu info) array)
                                      (wrap-as (i386:mem->accu))
                                      (wrap-as (i386:mem->accu))
                                      (wrap-as (i386:mem+n->accu offset))))))
 
+        ;;foo[index]->bar
+        ((i-sel (ident ,field) (array-ref ,index ,array))
+         (let ((info ((expr->accu* info) o)))
+           (append-text info (wrap-as (i386:mem->accu)))))
+
         ((de-ref (p-expr (ident ,name)))
          (let* ((type (ident->type info name))
                 (ptr (ident->pointer info name))
                                                     ((equal? op "/=") (wrap-as (i386:accu/base)))
                                                     ((equal? op "%=") (wrap-as (i386:accu%base)))
                                                     ((equal? op "|=") (wrap-as (i386:accu-or-base)))
+                                                    ((equal? op "&=") (wrap-as (i386:accu-and-base)))
                                                     (else (error "mescc: op ~a not supported: ~a\n" op o))))))))
            (pmatch a
              ((p-expr (ident ,name)) (append-text info ((accu->ident info) name)))
              ((d-sel (ident ,field) ,p-expr)
               (let* ((type (p-expr->type info p-expr))
-                     (offset (field-offset info type field))
+                     (offset (field-offset info (if (pair? type) type `("struct" ,type)) field))
                      (info (append-text info (wrap-as (i386:push-accu))))
                      (info ((expr->accu* info) a))
                      (info (append-text info (wrap-as (i386:pop-base)))))
                           4)))
                 (append-text info (append (wrap-as (i386:accu->base))
                                           ((base->ident-address info) name)))))
+             ((de-ref ,expr)
+              (let ((info ((expr->base info) expr)))
+                (append-text info (wrap-as (i386:mem->base))))) ;; FIXME: size
              ((array-ref ,index (d-sel (ident ,field) (p-expr (ident ,struct))))
               (let* ((info (append-text info (wrap-as (i386:push-accu))))
                      (info ((expr->accu* info) a))
                                    ((ident->base info) array)
                                    (wrap-as (i386:accu+base))))))
 
+      ;; bar.foo.i
+      ((d-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0))))
+       (let* ((type0 (ident->type info struct0))
+              (type1 (field-type info `("struct" ,type0) field0))
+              (offset (+ (field-offset info `("struct" ,type0) field0)
+                         (field-offset info `("struct" ,type1) field1))))
+         (append-text info (append ((ident->accu info) struct0)
+                                   (wrap-as (i386:accu+value offset))))))
+
+      ;; bar.poo->i
+      ((i-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0))))
+       (let* ((type0 (ident->type info struct0))
+              (type1 (field-type info `("struct" ,type0) field0))
+              (offset0 (field-offset info `("struct" ,type0) field0))
+              (offset1 (field-offset info `("struct" ,type1) field1)))
+         (append-text info (append ((ident->accu info) struct0)
+                                   (wrap-as (i386:accu+value offset0))
+                                   (wrap-as (i386:mem->accu))
+                                   (wrap-as (i386:accu+value offset1))))))
+
+      ;; bar->foo.i
+      ((d-sel (ident ,field1) (i-sel (ident ,field0) (p-expr (ident ,struct0))))
+       (let* ((type0 (ident->type info struct0))
+              (type1 (field-type info `("struct" ,type0) field0))
+              (offset (+ (field-offset info `("struct" ,type0) field0)
+                         (field-offset info `("struct" ,type1) field1))))
+         (append-text info (append ((ident-address->accu info) struct0)
+                                   (wrap-as (i386:accu+value offset))))))
+
+      ;; bar->foo.i
+      ((d-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0))))
+       (let* ((type0 (ident->type info struct0))
+              (type1 (field-type info `("struct" ,type0) field0))
+              (offset (+ (field-offset info `("struct" ,type0) field0)
+                         (field-offset info `("struct" ,type1) field1))))
+         (append-text info (append ((ident->accu info) struct0)
+                                   (wrap-as (i386:accu+value offset))))))
+
+      ;;(i-sel (ident "i") (i-sel (ident "p") (p-expr (ident "p"))))
+      ((i-sel (ident ,field1) (i-sel (ident ,field0) (p-expr (ident ,struct0))))
+       (let* ((type0 (ident->type info struct0))
+              (type1 (field-type info `("struct" ,type0) field0))
+              (offset0 (field-offset info `("struct" ,type0) field0))
+              (offset1 (field-offset info `("struct" ,type1) field1)))
+         (append-text info (append ((ident->accu info) struct0)
+                                   (wrap-as (i386:accu+value offset0))
+                                   (wrap-as (i386:mem->accu))
+                                   (wrap-as (i386:accu+value offset1))))))
+
+      ;; (*pp)->bar.foo
+      ((d-sel (ident ,field1) (i-sel (ident ,field0) (de-ref (p-expr (ident ,struct0)))))
+       (let* ((type0 (ident->type info struct0))
+              (type1 (field-type info `("struct" ,type0) field0))
+              (offset (+ (field-offset info `("struct" ,type0) field0)
+                         (field-offset info `("struct" ,type1) field1))))
+         (append-text info (append ((ident->accu info) struct0)
+                                   (wrap-as (i386:mem->accu))
+                                   (wrap-as (i386:accu+value offset))))))
+
       ;; g_cells[<expr>].type
       ((d-sel (ident ,field) (array-ref ,index (p-expr (ident ,array))))
        (let* ((type (ident->type info array))
               (info ((expr->accu* info) `(array-ref ,index (p-expr (ident ,array))))))
          (append-text info (wrap-as (i386:accu+value offset)))))
 
-      ((d-sel (ident ,field) (p-expr (ident ,name)))
-       (let* ((type (ident->type info name))
+      ((d-sel (ident ,field) (p-expr (ident ,struct)))
+       (let* ((type (ident->type info struct))
               (offset (field-offset info type field))
               (text (.text info)))
-         (append-text info (append ((ident->accu info) name)
+         (append-text info (append ((ident->accu info) struct)
                                    (wrap-as (i386:accu+value offset))))))
 
       ;; foo.bar[baz]
-      ((array-ref ,index (d-sel (ident ,field) (p-expr (ident ,name))))
-       (let* ((type (ident->type info name))
+      ((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) name)
+                                   ((ident-address->accu info) struct)
                                    (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 ,name))))
-       (let* ((type (ident->type info name))
+      ((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) name)
+                                   ((ident->accu info) struct)
                                    (wrap-as (append (i386:accu+value offset)
                                                     (i386:pop-base)
                                                     (i386:accu+base)))))))
 
       ((i-sel (ident ,field) (p-expr (ident ,array)))
        (let* ((type (ident->type info array))
-              (offset (field-offset info type field))
-              (text (.text info)))
+              (offset (field-offset info type field)))
          (append-text info (append ((ident-address->accu info) array)
                                    (wrap-as (i386:mem->accu))
                                    (wrap-as (i386:accu+value offset))))))
 
       ((i-sel (ident ,field) (de-ref (p-expr (ident ,array))))
        (let* ((type (ident->type info array))
-              (offset (field-offset info type field))
-              (text (.text info)))
+              (offset (field-offset info type field)))
          (append-text info (append ((ident-address->accu info) array)
                                    (wrap-as (i386:mem->accu))
                                    (wrap-as (i386:mem->accu))
                                    (wrap-as (i386:accu+value offset))))))
 
+      ;;foo[index]->bar
+      ((i-sel (ident ,field) (array-ref ,index (p-expr (ident ,array))))
+       (let* ((type (ident->type info array))
+              (offset (field-offset info type field))
+              (info ((expr->accu* info) `(array-ref ,index (p-expr (ident ,array))))))
+         (append-text info (append (wrap-as (i386:mem->accu))
+                                   (wrap-as (i386:mem->accu))
+                                   (wrap-as (i386:accu+value offset))))))
+
       (_ (error "expr->accu*: unsupported: " o)))))
 
 (define (ident->constant name value)
 (define (field:size o)
   (pmatch o
     ((,name ,type ,size ,pointer) size)
+    ((,name ,type ,size) size)
     (_ 4)))
 
+(define (field:type o)
+  (pmatch o
+    ((,name ,type ,size ,pointer) type)
+    ((,name ,type ,size) type)
+    (_ (error "field:type:" o))))
+
 (define (get-type types o)
   (let ((t (assoc-ref types o)))
     (pmatch t
     ((union-ref (ident ,type))
      (ast-type->type info `("struct" ,type)))
     ((void) (ast-type->type info "void"))
+    ((type-spec (typename ,type)) (ast-type->type info type))
     (_ (let ((type (get-type (.types info) o)))
          (if type type
              (begin
   (let ((type (ast-type->type info o)))
     (type:size type)))
 
+(define (field-field info struct field)
+  (let* ((xtype (ast-type->type info struct))
+         (fields (type:description xtype)))
+    (and=> (member field fields (lambda (a b) (equal? a (car b)))) car)))
+
 (define (field-offset info struct field)
   (let ((xtype (ast-type->type info struct)))
     (if (eq? (type:type xtype) 'union) 0
 (define (field-size info struct field)
   (let ((xtype (ast-type->type info struct)))
     (if (eq? (type:type xtype) 'union) 0
-        (let* ((fields (type:description xtype))
-               (field (and=> (member field fields (lambda (a b) (equal? a (car b)))) car)))
+        (let ((field (field-field info struct field)))
           (field:size field)))))
 
+(define (field-type info struct field)
+  (let ((xtype (ast-type->type info struct)))
+        (let ((field (field-field info struct field)))
+          (field:type field))))
+
 (define (ast->type o)
   (pmatch o
     ((fixed-type ,type)
        (let ((size 4)
              (count (cstring->number count)))
          (list name type (* count size) 0)))
-      ;; struct InlineFunc **inline_fns;
+
+      ((comp-decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (comp-declr-list (comp-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
+       (list name type 4))
+
       ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
        (list name type 4))
-      ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ptr-declr (pointer) (ident ,name)))))
+
+      ((comp-decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (comp-declr-list (comp-declr (ptr-declr (pointer) (ident ,name)))))
        (list name type 4))
 
+      ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ptr-declr (pointer) (ident ,name)))))
+       (list name type 4))      
+
+      ((comp-decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (comp-declr-list (comp-declr (ident ,name))))
+       ((struct-field info) `(comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ident ,name))))))
+
       ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ident ,name))))
        (let ((size (ast-type->size info `("struct" ,type))))
          (list name type size 0)))
 (define (p-expr->type info o)
   (pmatch o
     ((p-expr (ident ,name)) (ident->type info name))
-    ((array-ref ,index (p-expr (ident ,array)))
-     (ident->type info array))
+    ((array-ref ,index (p-expr (ident ,array))) (ident->type info array))
+    ((i-sel (ident ,field) (p-expr (ident ,struct)))
+     (let ((type0 (ident->type info struct)))
+       (field-type info `("struct" ,type0) field)))
+    ((d-sel (ident ,field) (p-expr (ident ,struct)))
+     (let ((type0 (ident->type info struct)))
+       (field-type info `("struct" ,type0) field)))
     (_ (error "p-expr->type: unsupported: " o))))
 
 (define (local-var? o) ;; formals < 0, locals > 0
        (let loop ((values (map (initzer->value info) values)) (value 0))
          (if (null? values) (int->bv32 value)
              (loop (cdr values) (logior value (car values))))))
+      ((initzer (ref-to (i-sel (ident ,field) (cast (type-name (decl-spec-list ,struct) (abs-declr (pointer))) (p-expr (fixed ,base))))))
+       (let* ((type (decl->ast-type struct))
+              (offset (field-offset info type field))
+              (base (cstring->number base)))
+         (int->bv32 (+ base offset))))
       (() (int->bv32 0))
       (_ (error "initzer->data: unsupported: " o)))))
 
index b6565cc7640426fe633791e1687e714e879597ad..7ee2a98c7c98f61d7f98c483a06b2d35148f14ea 100644 (file)
@@ -29,16 +29,34 @@ typedef struct foo
 typedef struct
 {
   int i;
+  struct foo f;
+  struct foo *p;
 } bar;
 
+
+//NYACC
+//#define offsetof(type, field) ((size_t) &((type *)0)->field)
+#if __MESC__
+#define offsetof(type, field) (&((type *)0)->field)
+#else
+#define offsetof(type, field) ((size_t)&((type *)0)->field)
+#endif
+
 int
 test ()
 {
   foo f = {1};
   printf ("f.i=%d\n", f.i);
 
-  bar b = {1};
+  bar b = {1, 2, &f};
   printf ("b.i=%d\n", b.i);
+
+  printf ("b.f.i=%d\n", b.f.i);
+  if (b.f.i != 2) return 1;
+
+  printf ("b.p->i=%d\n", b.p->i);
+  if (b.p->i != 1) return 1;
+
   bar* p = &b;
   p->i = 2;
   printf ("p->i=%d\n", b.i);
@@ -49,12 +67,24 @@ test ()
   p->i--;
   printf ("p->i=%d\n", b.i);
 
+  printf ("p->f.i=%d\n", p->f.i);
+  if (p->f.i != 2) return 1;
+
+  printf ("p->p->i=%d\n", p->p->i);
+  if (p->p->i != 1) return 1;
 
   bar** pp = &p;
   (*pp)->i = 3;
   printf ("(*pp)->i=%d\n", b.i);
 
   printf ("sizeof i:%d\n", sizeof (p->i));
+  if ((sizeof p->i) != 4) return 1;
+
+  printf ("offsetof g=%d\n", (offsetof (bar ,f)));
+  if ((offsetof (bar ,f)) != 4) return 1;
+
+  printf ("(*pp)->b.i=%d\n", (*pp)->f.i);
+  if ((*pp)->f.i != 2) return 1;
 
   return 0;
 }