mescc: Tinycc support: pointer arithmetic with variable.

* 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.
This commit is contained in:
Jan Nieuwenhuizen 2017-08-23 07:08:16 +02:00
parent 1e23dbaf17
commit 0875ce655a
2 changed files with 71 additions and 9 deletions

View file

@ -799,28 +799,42 @@
((and struct? (= ptr -2)) 4) ((and struct? (= ptr -2)) 4)
((and struct? (= ptr 2)) 4) ((and struct? (= ptr 2)) 4)
(else 1)))) (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))) ((sub ,a (p-expr (fixed ,value)))
(let* ((ptr (expr->pointer info a)) (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)) (size (cond ((= ptr 1) (expr->size info a))
((> ptr 1) 4) ((> ptr 1) 4)
((and struct? (= ptr -2)) 4)
((and struct? (= ptr 2)) 4)
(else 1))) (else 1)))
(info ((expr->accu info) a)) (info ((expr->accu info) a))
(value (cstring->number value)) (value (cstring->number value))
(value (* size 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)))))) (append-text info (wrap-as (i386:accu+value (- value))))))
((sub ,a ,b) ((sub ,a ,b)
(let* ((ptr (expr->pointer info a)) (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)) (size (cond ((= ptr 1) (expr->size info a))
((> ptr 1) 4) ((> ptr 1) 4)
((and struct? (= ptr -2)) 4)
((and struct? (= ptr 2)) 4)
(else 1)))) (else 1))))
(if (not (= size 1)) (if (= size 1) ((binop->accu info) a b (i386:accu-base))
(warn (format #f "TODO: pointer arithmetic: ~s\n" o)))) (let* ((info ((expr->accu info) b))
((binop->accu info) a b (i386:accu-base))) (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-and ,a ,b) ((binop->accu info) a b (i386:accu-and-base)))
((bitwise-not ,expr) ((bitwise-not ,expr)
@ -908,7 +922,18 @@
(let* ((info (append-text info (ast->comment o))) (let* ((info (append-text info (ast->comment o)))
(info ((expr->accu info) b)) (info ((expr->accu info) b))
(info (if (equal? op "=") info (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 ((expr->accu info) a))
(info (append-text info (wrap-as (i386:pop-base))))) (info (append-text info (wrap-as (i386:pop-base)))))
(append-text info (cond ((equal? op "+=") (wrap-as (i386:accu+base))) (append-text info (cond ((equal? op "+=") (wrap-as (i386:accu+base)))

View file

@ -23,6 +23,12 @@
char *list[2] = {"foo\n", "bar\n"}; char *list[2] = {"foo\n", "bar\n"};
struct foo {
int a;
int b;
int c;
};
int int
test () test ()
{ {
@ -49,10 +55,41 @@ test ()
char **p = list; char **p = list;
++*p; ++*p;
eputs (*p); eputs (*p);
if (strcmp (*p, "oo\n")) return 1; if (strcmp (*p, "oo\n")) return 13;
--*p; --*p;
eputs (*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; return 0;
} }