mescc: Tinycc support: pointer arithmetic with pointer-variable.

* 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.
This commit is contained in:
Jan Nieuwenhuizen 2017-08-26 10:16:53 +02:00
parent 8649f7a923
commit 69073e1954
3 changed files with 66 additions and 26 deletions

View 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])

View file

@ -792,6 +792,7 @@
((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))
@ -799,11 +800,12 @@
((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)))
@ -822,6 +824,7 @@
((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))
@ -829,11 +832,15 @@
((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)))
@ -923,6 +930,7 @@
(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))
@ -930,23 +938,27 @@
((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)))

View 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;
}