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)
(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)
@ -908,7 +922,18 @@
(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)))

View file

@ -23,6 +23,12 @@
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;
}