mescc: Tinycc support: pointer arithmetic with variable.
authorJan Nieuwenhuizen <janneke@gnu.org>
Wed, 23 Aug 2017 05:08:16 +0000 (07:08 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Wed, 23 Aug 2017 05:08:16 +0000 (07:08 +0200)
* module/language/c99/compiler.mes (expr->accu): Support pointer
  arithmetic with variable: p + i, p - i, p += i, p -= i.
* scaffold/tests/76-pointer-arithmetic.c (test): Test it.

module/language/c99/compiler.mes
scaffold/tests/76-pointer-arithmetic.c

index 12544de5e568011cbba4bfa039497bdb53991c24..cbc7ca9293ac2a40428219816d72ffefea9529e3 100644 (file)
                             ((and struct? (= ptr -2)) 4)
                             ((and struct? (= ptr 2)) 4)
                             (else 1))))
-         ((binop->accu info) a b (i386:accu+base))))
+           (if (= size 1) ((binop->accu info) a b (i386:accu+base))
+               (let* ((info ((expr->accu info) b))
+                      (info (append-text info (wrap-as (i386:value->base size))))
+                      (info (append-text info (wrap-as (i386:accu*base))))
+                      (info ((expr->base info) a)))
+                 (append-text info (wrap-as (i386:accu+base)))))))
 
         ((sub ,a (p-expr (fixed ,value)))
          (let* ((ptr (expr->pointer 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)
+                            ((and struct? (= ptr 2)) 4)
                             (else 1)))
                 (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)
          (let* ((ptr (expr->pointer 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)
+                            ((and struct? (= ptr 2)) 4)
                             (else 1))))
-           (if (not (= size 1))
-               (warn (format #f "TODO: pointer arithmetic: ~s\n" o))))
-         ((binop->accu info) a b (i386:accu-base)))
+           (if (= size 1) ((binop->accu info) a b (i386:accu-base))
+               (let* ((info ((expr->accu info) b))
+                      (info (append-text info (wrap-as (i386:value->base size))))
+                      (info (append-text info (wrap-as (i386:accu*base))))
+                      (info ((expr->base info) a)))
+                 (append-text info (wrap-as (i386:accu-base)))))))
 
         ((bitwise-and ,a ,b) ((binop->accu info) a b (i386:accu-and-base)))
         ((bitwise-not ,expr)
          (let* ((info (append-text info (ast->comment o)))
                 (info ((expr->accu info) b))
                 (info (if (equal? op "=") info
-                          (let* ((info (append-text info (wrap-as (i386:push-accu))))
+                          (let* ((ptr (expr->pointer 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)
+                                             ((and struct? (= ptr 2)) 4)
+                                             (else 1)))
+                                 (info (if (= size 1) info
+                                           (let ((info (append-text info (wrap-as (i386:value->base size)))))
+                                             (append-text info (wrap-as (i386:accu*base))))))
+                                 (info (append-text info (wrap-as (i386:push-accu))))
                                  (info ((expr->accu info) a))
                                  (info (append-text info (wrap-as (i386:pop-base)))))
                             (append-text info (cond ((equal? op "+=") (wrap-as (i386:accu+base)))
index 28b63344b0f1e43773c4d0f34118eb6f461962fe..2edb00a4e3669cc9ea441a85f0a5d6a8e72d108c 100644 (file)
 
 char *list[2] = {"foo\n", "bar\n"};
 
+struct foo {
+  int a;
+  int b;
+  int c;
+};
+
 int
 test ()
 {
@@ -49,10 +55,41 @@ test ()
   char **p = list;
   ++*p;
   eputs (*p);
-  if (strcmp (*p, "oo\n")) return 1;
+  if (strcmp (*p, "oo\n")) return 13;
   --*p;
   eputs (*p);
-  if (strcmp (*p, "foo\n")) return 2;
+  if (strcmp (*p, "foo\n")) return 14;
+
+  struct foo* pfoo = 0;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  pfoo++;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  if (pfoo != 12) return 15;
+
+  pfoo--;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  if (pfoo) return 16;
+
+  pfoo++;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  if (pfoo != 12) return 17;
+
+  int one = 1;
+  pfoo = pfoo - one;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  if (pfoo) return 18;
+
+  pfoo = pfoo + one;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  if (pfoo != 12) return 19;
+
+  pfoo -= one;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  if (pfoo) return 20;
+
+  pfoo += one;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  if (pfoo != 12) return 21;
 
   return 0;
 }