mescc: Tinycc support: byte and word struct fields.
authorJan Nieuwenhuizen <janneke@gnu.org>
Sun, 6 Aug 2017 10:27:16 +0000 (12:27 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Sun, 6 Aug 2017 10:27:16 +0000 (12:27 +0200)
* stage0/x86.M1 (mov____%al,0x8(%edx)):
  (mov____%ax,(%edx)):
  (mov____%ax,0x32(%edx)):
  (mov____%ax,0x8(%edx)):
  (movzbl_0x32(%eax),%eax):
  (movzbl_0x8(%eax),%eax):
  (movzwl_0x32(%eax),%eax):
  (movzwl_0x8(%eax),%eax): New define.
* module/mes/as-i386.mes (i386:word-accu->base-mem):
  (i386:byte-accu->base-mem+n):
  (i386:word-accu->base-mem+n):
  (i386:byte-mem+n->accu):
  (i386:word-mem+n->accu): New function.
* module/mes/as-i386.scm: Export them.
* module/language/c99/compiler.mes (struct-field): Use actual size for
  simple types (WAS: 4).
  (decl->info):
  (expr->accu): Respect byte and word struct field sizes.
* scaffold/tests/7g-struct-byte-word-field.c: Test it.
* make.scm (add-scaffold-test): Build it.

make.scm
module/language/c99/compiler.mes
module/mes/as-i386.mes
module/mes/as-i386.scm
scaffold/tests/7g-struct-byte-word-field.c [new file with mode: 0644]
stage0/x86.M1

index 5fe89b626464df07ac0d0656427c67bd567e9944..04b05f20400183e4198ce4ee0cd5af3ccddc30fc 100755 (executable)
--- a/make.scm
+++ b/make.scm
@@ -165,7 +165,8 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$
    "7c-dynarray"
    "7d-cast-char"
    "7e-struct-array-access"
-   "7f-struct-pointer-arithmetic"))
+   "7f-struct-pointer-arithmetic"
+   "7g-struct-byte-word-field"))
 
 (add-target (group "check-scaffold-tests/7" #:dependencies (filter (target-prefix? "check-scaffold/tests/7") %targets)))
 
index 9da74f3cd75d6404fca72eadb2e3b074bd12c77f..bd7f914abc4dfbcde056b9745485b4a62ea85440 100644 (file)
         ((d-sel (ident ,field) (p-expr (ident ,struct)))
          (let* ((type (ident->type info struct))
                 (offset (field-offset info type field))
-                (ptr (field-pointer info type field)))
+                (ptr (field-pointer info type field))
+                (size (if (= ptr 0) (field-size info type field)
+                          4)))
          (if (= ptr -1)
              (append-text info (append ((ident->accu info) struct)
                                        (wrap-as (i386:accu+value offset))))
              (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))))
-         (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 (wrap-as (i386:mem+n->accu offset)))))
+                                       (case size
+                                         ((1) (wrap-as (i386:byte-mem+n->accu offset)))
+                                         ((2) (wrap-as (i386:word-mem+n->accu offset)))
+                                         (else (wrap-as (i386:mem+n->accu offset)))))))))
 
         ((i-sel (ident ,field) (p-expr (ident ,struct)))
          (let* ((type (ident->type info struct))
                 (offset (field-offset info type field))
-                (ptr (field-pointer info type field)))
+                (ptr (field-pointer info type field))
+                (size (if (= ptr 0) (field-size info type field)
+                          4)))
            (if (= ptr -1)
                (append-text info (append ((ident-address->accu info) struct)
                                          (wrap-as (i386:mem->accu))
                                          (wrap-as (i386:accu+value offset))))
                (append-text info (append ((ident-address->accu info) struct)
                                          (wrap-as (i386:mem->accu))
-                                         (wrap-as (i386:mem+n->accu offset)))))))
+                                         (case size
+                                         ((1) (wrap-as (i386:byte-mem+n->accu offset)))
+                                         ((2) (wrap-as (i386:word-mem+n->accu offset)))
+                                         (else (wrap-as (i386:mem+n->accu offset)))))))))
+
+        ((d-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 (wrap-as (i386:mem+n->accu offset)))))
 
         ((i-sel (ident ,field) (de-ref (p-expr (ident ,array))))
          (let* ((type (ident->type info array))
                   (comp-declr-list (comp-declr (ident ,name))))
        (list name `("tag" ,type) 4 0))
       ((comp-decl (decl-spec-list (type-spec (fixed-type ,type))) (comp-declr-list (comp-declr (ident ,name))))
-       (list name type 4 0))
+       (list name type (ast-type->size info type) 0))
       ((comp-decl (decl-spec-list (type-spec (typename ,type))) (comp-declr-list (comp-declr (ident ,name))))
-       (list name type 4 0))
+       (list name type (ast-type->size info type) 0))
       ((comp-decl (decl-spec-list (type-spec (typename ,type))) (comp-declr-list (comp-declr (ptr-declr (pointer (pointer)) (ident ,name)))))
        (list name type 4 2))
       ((comp-decl (decl-spec-list (type-spec (fixed-type ,type))) (comp-declr-list (comp-declr (ftn-declr (scope (ptr-declr (pointer) (ident ,name))) (param-list . ,param-list)))))
         ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name))))
          (clone info #:types (cons (cons name (or (get-type types type) `(typedef ,type))) types)))
 
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (typename ,type))) (init-declr-list (init-declr (array-of (ident ,name) ,value))))
+         (let* ((type (get-type types type))
+                (value (p-expr->number info value))
+                (size (* value 4))
+                (pointer -1)
+                (type (make-type 'array size pointer type)))
+           (clone info #:types (cons (cons name type) types))))
+
+        ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-ref (ident ,type)))) (init-declr-list (init-declr (ptr-declr ,pointer (ident ,name)))))
+         (let* ((pointer (expr->pointer info pointer))
+                (type (or (get-type types type) `(typedef ,type)))
+                (size 4)
+                (type (make-type 'typedef size pointer type)))
+           (clone info #:types (cons (cons name type) types))))
+
         ((decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-def ,field-list))) (init-declr-list (init-declr (ident ,name))))
          ((decl->info info) `(decl (decl-spec-list (stor-spec (typedef)) (type-spec (struct-def (ident ,name) ,field-list))) (init-declr-list (init-declr (ident ,name))))))
 
                  (let loop ((fields fields) (initzers initzers) (info info))
                    (if (null? fields) info
                        (let ((offset (field-offset info type (field:name (car fields))))
+                             (size (field:size (car fields)))
                              (initzer (if (null? initzers) '(p-expr (fixed "0")) (car initzers))))
                          (loop (cdr fields) (if (null? initzers) '() (cdr initzers))
                                (clone info #:text
                                        ((ident->accu info) name)
                                        (wrap-as (append (i386:accu->base)))
                                        (.text ((expr->accu empty) initzer))
-                                       (wrap-as (i386:accu->base-mem+n offset)))))))))
+                                       (wrap-as (case size
+                                                  ((1) (i386:byte-accu->base-mem+n offset))
+                                                  ((2) (i386:word-accu->base-mem+n offset))
+                                                  (else (i386:accu->base-mem+n offset)))))))))))
                (let* ((initzer-globals (filter identity (append-map (initzer->globals globals) initzers)))
                       (global-names (map car globals))
                       (initzer-globals (filter (lambda (g) (and g (not (member (car g) global-names)))) initzer-globals))
index 38a619802eb72fc368236201dbaa89db1033fa44..0a94de23ceef104f8cc863552cb0404aff5416c5 100644 (file)
 (define (i386:byte-accu->base-mem)
   '(("mov____%al,(%edx)")))             ; mov    %al,(%edx)
 
+(define (i386:word-accu->base-mem)
+  '(("mov____%ax,(%edx)")))             ; mov    %ax,(%edx)
+
 (define (i386:accu->base-mem+n n)
   (or n (error "invalid value: accu->base-mem+n: " n))
   `(,(if (< (abs n) #x80) `("mov____%eax,0x8(%edx)" (#:immediate1 ,n))
          `("mov____%eax,0x32(%edx)" (#:immediate ,n)))))
 
+(define (i386:byte-accu->base-mem+n n)
+  (or n (error "invalid value: accu->base-mem+n: " n))
+  `(,(if (< (abs n) #x80) `("mov____%al,0x8(%edx)" (#:immediate1 ,n))
+         `("mov____%al,0x32(%edx)" (#:immediate ,n)))))
+
+(define (i386:word-accu->base-mem+n n)
+  (or n (error "invalid value: accu->base-mem+n: " n))
+  `(,(if (< (abs n) #x80) `("mov____%ax,0x8(%edx)" (#:immediate1 ,n))
+         `("mov____%ax,0x32(%edx)" (#:immediate ,n)))))
+
 (define (i386:accu->label label)
   `(("mov____%eax,0x32" (#:address ,label)))) ; mov    %eax,0x<label>
 
   `(,(if (< (abs n) #x80) `("mov____0x8(%eax),%eax" (#:immediate1 ,n))
          `("mov____0x32(%eax),%eax" (#:immediate ,n)))))
 
+(define (i386:byte-mem+n->accu n)
+  `(,(if (< (abs n) #x80) `("movzbl_0x8(%eax),%eax" (#:immediate1 ,n))
+         `("movzbl_0x32(%eax),%eax" (#:immediate ,n)))))
+
+(define (i386:word-mem+n->accu n)
+  `(,(if (< (abs n) #x80) `("movzwl_0x8(%eax),%eax" (#:immediate1 ,n))
+         `("movzwl_xb0x32(%eax),%eax" (#:immediate ,n)))))
+
 (define (i386:base-mem+n->accu v)
   (or v (error "invalid value: base-mem+n->accu: " v))
   `(("add___%edx,%eax")
index 12bec49c07e1a8eb529e33b36f80b44bacf7d879..d1cc0f3ce8a78625951c701c14ceeb11c2c22603 100644 (file)
             i386:accu+value
             i386:accu->base
             i386:accu->base-mem
+            i386:byte-accu->base-mem
+            i386:word-accu->base-mem
             i386:accu->base-mem+n
+            i386:byte-accu->base-mem+n
+            i386:word-accu->base-mem+n
             i386:accu->label
             i386:accu->local
             i386:accu-and-base
             i386:local-ptr->base
             i386:local-test
             i386:mem+n->accu
+            i386:byte-mem+n->accu
+            i386:word-mem+n->accu
             i386:mem->accu
             i386:mem->base
             i386:nop
diff --git a/scaffold/tests/7g-struct-byte-word-field.c b/scaffold/tests/7g-struct-byte-word-field.c
new file mode 100644 (file)
index 0000000..707391a
--- /dev/null
@@ -0,0 +1,56 @@
+/* -*-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 <inttypes.h>
+#include <string.h>
+
+struct option {
+  char const *name;
+  uint8_t index;
+  uint16_t flags;
+  int barf;
+};
+
+int
+test ()
+{
+  struct option h = {"help", 0, 10, 1};
+  struct option o = {"output", 1, 11, 1};
+  struct option v = {"version", 0, 0, 1};
+
+  if (strcmp (h.name, "help")) return 1;
+  if (h.index != 0) return 2;
+  if (h.flags != 10) return 3;
+
+  struct option *p = &o;
+  if (strcmp (p->name, "output")) return 4;
+  if (p->index != 1) return 5;
+  if (p->flags != 11) return 6;
+
+  p = &v;
+  v.index = 2;
+  p->flags = 12;
+  if (v.index != 2) return 7;
+  if (v.flags != 12) return 8;
+
+  return 0;
+}
index 549b242ffadc780e9776827b6338003410601425..3d28954db27b99319f04cde2fab46746d7df221c 100644 (file)
@@ -74,6 +74,10 @@ DEFINE mov____$i32,0x32 c705
 DEFINE mov____$i32,0x8(%eax) c740
 DEFINE mov____$i32,0x8(%ebp) c745
 DEFINE mov____%al,(%edx) 8802
+DEFINE mov____%al,0x8(%edx) 8842
+DEFINE mov____%ax,(%edx) 668902
+DEFINE mov____%ax,0x32(%edx) 668982
+DEFINE mov____%ax,0x8(%edx) 668942
 DEFINE mov____%dl,(%eax) 8810
 DEFINE mov____%dl,0x8(%eax) 8850
 DEFINE mov____%eax,%ebx 89c3
@@ -120,9 +124,13 @@ DEFINE movzbl_%dl,%edx 0fb6d2
 DEFINE movzbl_(%eax),%eax 0fb600
 DEFINE movzbl_(%eax),%edx 0fb610
 DEFINE movzbl_(%edx),%edx 0fb612
+DEFINE movzbl_0x32(%eax),%eax 0fb680
 DEFINE movzbl_0x32(%ebp),%eax 0fb685
+DEFINE movzbl_0x8(%eax),%eax 0fb640
 DEFINE movzbl_0x8(%ebp),%eax 0fb645
 DEFINE movzbl_0x8(%ebp),%edx 0fb655
+DEFINE movzwl_0x32(%eax),%eax 0fb780
+DEFINE movzwl_0x8(%eax),%eax 0fb740
 DEFINE mul____%edx f7e2
 DEFINE nop 90
 DEFINE not____%eax f7d0