mescc: Tinycc support: pointer arithmetic with pointer-variable.
authorJan Nieuwenhuizen <janneke@gnu.org>
Sat, 26 Aug 2017 08:16:53 +0000 (10:16 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Sat, 26 Aug 2017 08:16:53 +0000 (10:16 +0200)
* module/language/c99/compiler.mes (expr->accu): pointer arithmetic with pointer-variable.
* scaffold/tests/76-pointer-arithmetic.c (test): Test it.
* mlibc/include/stdarg.h (va_start): Update for fixed pointer arithmetic.

mlibc/include/stdarg.h
module/language/c99/compiler.mes
scaffold/tests/76-pointer-arithmetic.c

index fa5a63327c4bfe3ae41c830cc8af4e7287f1d7d2..211ec36f2e63e402bf073f316af295b79ea42f7f 100644 (file)
@@ -35,7 +35,7 @@ typedef char* va_list;
 #define va_start(ap, last) (void)((ap) = (char*)(&(last) + 1))
 #else // !__GNUC__
 typedef int va_list;
-#define va_start(ap, last) (void)((ap) = (char*)(&(last) + 4))
+#define va_start(ap, last) (void)((ap) = (char*)(&(last) + 1))
 #endif // !__GNUC__
 
 #define va_arg(ap, type) (type)(((int*)((ap) = ((ap) + 4)))[-1])
index c64429b7d2eac60e130211f70797b0aee363d29a..99c430e7cf8f0d89ce252d22edba7521250b0ad6 100644 (file)
 
         ((add ,a ,b)
          (let* ((ptr (expr->pointer info a))
+                (ptr-b (expr->pointer info b))
                 (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))
                             ((and struct? (= ptr -2)) 4)
                             ((and struct? (= ptr 2)) 4)
                             (else 1))))
-           (if (= size 1) ((binop->accu info) a b (i386:accu+base))
+           (if (or (= 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)))
+                      (info (append-text info (wrap-as (append (i386:value->base size)
+                                                               (i386:accu*base)
+                                                               (i386:accu->base)))))
+                      (info ((expr->accu info) a)))
                  (append-text info (wrap-as (i386:accu+base)))))))
 
         ((sub ,a (p-expr (fixed ,value)))
 
         ((sub ,a ,b)
          (let* ((ptr (expr->pointer info a))
+                (ptr-b (expr->pointer info b))
                 (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))
                             ((and struct? (= ptr -2)) 4)
                             ((and struct? (= ptr 2)) 4)
                             (else 1))))
-           (if (= size 1) ((binop->accu info) a b (i386:accu-base))
+           (if (or (= size 1) (= ptr-b 1)) (let ((info ((binop->accu info) a b (i386:accu-base))))
+                                             (if (not (= ptr-b 1)) info
+                                                 (append-text info (wrap-as (append (i386:value->base size)
+                                                                                    (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)))
+                      (info (append-text info (wrap-as (append (i386:value->base size)
+                                                               (i386:accu*base)
+                                                               (i386:accu->base)))))
+                      (info ((expr->accu info) a)))
                  (append-text info (wrap-as (i386:accu-base)))))))
 
         ((bitwise-and ,a ,b) ((binop->accu info) a b (i386:accu-and-base)))
                 (info ((expr->accu info) b))
                 (info (if (equal? op "=") info
                           (let* ((ptr (expr->pointer info a))
+                                 (ptr-b (expr->pointer info b))
                                  (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))
                                              ((and struct? (= ptr -2)) 4)
                                              ((and struct? (= ptr 2)) 4)
                                              (else 1)))
-                                 (info (if (= size 1) info
+                                 (info (if (or (= size 1) (= ptr-b 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)))
-                                                    ((equal? op "-=") (wrap-as (i386:accu-base)))
-                                                    ((equal? op "*=") (wrap-as (i386:accu*base)))
-                                                    ((equal? op "/=") (wrap-as (i386:accu/base)))
-                                                    ((equal? op "%=") (wrap-as (i386:accu%base)))
-                                                    ((equal? op "&=") (wrap-as (i386:accu-and-base)))
-                                                    ((equal? op "|=") (wrap-as (i386:accu-or-base)))
-                                                    ((equal? op "^=") (wrap-as (i386:accu-xor-base)))
-                                                    ((equal? op ">>=") (wrap-as (i386:accu>>base)))
-                                                    ((equal? op "<<=") (wrap-as (i386:accu<<base)))
-                                                    (else (error (format #f "mescc: op ~a not supported: ~a\n" op o)))))))))
+                                 (info (append-text info (wrap-as (i386:pop-base))))
+                                 (info (append-text info (cond ((equal? op "+=") (wrap-as (i386:accu+base)))
+                                                     ((equal? op "-=") (wrap-as (i386:accu-base)))
+                                                     ((equal? op "*=") (wrap-as (i386:accu*base)))
+                                                     ((equal? op "/=") (wrap-as (i386:accu/base)))
+                                                     ((equal? op "%=") (wrap-as (i386:accu%base)))
+                                                     ((equal? op "&=") (wrap-as (i386:accu-and-base)))
+                                                     ((equal? op "|=") (wrap-as (i386:accu-or-base)))
+                                                     ((equal? op "^=") (wrap-as (i386:accu-xor-base)))
+                                                     ((equal? op ">>=") (wrap-as (i386:accu>>base)))
+                                                     ((equal? op "<<=") (wrap-as (i386:accu<<base)))
+                                                     (else (error (format #f "mescc: op ~a not supported: ~a\n" op o)))))))
+                            (cond ((not (and (= ptr 1) (= ptr-b 1))) info)
+                                  ((equal? op "-=") (append-text info (wrap-as (append (i386:value->base size)
+                                                                                       (i386:accu/base)))))
+                                  (else (error (format #f "invalid operands to binary ~s (have ~s* and ~s*)" op type0 (p-expr->type info b)))))))))
            (pmatch a
              ((p-expr (ident ,name))
               (append-text info ((accu->ident info) name)))
index 39469d43e24f6d8749023ecd160209684b5324d1..712bea03ee8d5f00222cd708414f81039e6a57cb 100644 (file)
@@ -27,6 +27,7 @@ struct foo {
   int a;
   int b;
   int c;
+  unsigned char *d;
 };
 
 int
@@ -64,7 +65,7 @@ test ()
   eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
   pfoo++;
   eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
-  if (pfoo != 12) return 15;
+  if (pfoo != 16) return 15;
 
   pfoo--;
   eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
@@ -72,7 +73,7 @@ test ()
 
   pfoo++;
   eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
-  if (pfoo != 12) return 17;
+  if (pfoo != 16) return 17;
 
   int one = 1;
   int two = 2;
@@ -82,7 +83,7 @@ test ()
 
   pfoo = pfoo + one;
   eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
-  if (pfoo != 12) return 19;
+  if (pfoo != 16) return 19;
 
   pfoo -= one;
   eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
@@ -90,9 +91,36 @@ test ()
 
   pfoo += one;
   eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
-  if (pfoo != 12) return 21;
+  if (pfoo != 16) return 21;
 
   if (&one - 1 != &two) return 22;
 
+  struct foo* sym = 32;
+  int d = 16;
+  int i = sym + 16;
+  eputs ("i="); eputs (itoa (i)); eputs ("\n");
+  if (i != 288) return 23;
+
+  i = sym + d;
+  eputs ("i="); eputs (itoa (i)); eputs ("\n");
+  if (i != 288) return 24;
+
+  i = sym - 16;
+  eputs ("i="); eputs (itoa (i)); eputs ("\n");
+  if (i != -224) return 25;
+
+  i = sym - d;
+  eputs ("i="); eputs (itoa (i)); eputs ("\n");
+  if (i != -224) return 26;
+
+  i = sym - (struct foo*)d;
+  eputs ("i="); eputs (itoa (i)); eputs ("\n");
+  if (i != 1) return 27;
+
+  pfoo = sym + 1;
+  pfoo -= sym;
+  eputs ("pfoo="); eputs (itoa (pfoo)); eputs ("\n");
+  if (pfoo != 1) return 28;
+
   return 0;
 }