mescc: Tinycc support: pointer arithmetic.

* module/language/c99/compiler.mes (ident->size, expr->size): New function.
  (expr->accu): Use them for ++,--,add, sub.
  (i386:type-alist): Set void size to 1.
* scaffold/tests/71-struct-array.c (test):
* scaffold/tests/76-pointer-arithmetic.c: Test it.
* make.scm (add-scaffold-test): Build it.
This commit is contained in:
Jan Nieuwenhuizen 2017-07-28 10:40:30 +02:00
parent ce980c8239
commit c7547dfd52
4 changed files with 145 additions and 16 deletions

View file

@ -155,7 +155,8 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$
"72-typedef-struct-def" "72-typedef-struct-def"
"73-union" "73-union"
"74-multi-line-string" "74-multi-line-string"
"75-struct-union")) "75-struct-union"
"76-pointer-arithmetic"))
(add-target (group "check-scaffold-tests/7" #:dependencies (filter (target-prefix? "check-scaffold/tests/7") %targets))) (add-target (group "check-scaffold-tests/7" #:dependencies (filter (target-prefix? "check-scaffold/tests/7") %targets)))

View file

@ -697,27 +697,46 @@
((post-inc (p-expr (ident ,name))) ((post-inc (p-expr (ident ,name)))
(let* ((type (ident->type info name)) (let* ((type (ident->type info name))
(ptr (ident->pointer info name)) (ptr (ident->pointer info name))
(size (if (> ptr 1) 4 1))) (size (cond ((= ptr 1) (ident->size info name))
((> ptr 1) 4)
(else 1))))
(append-text info (append ((ident->accu info) name) (append-text info (append ((ident->accu info) name)
((ident-add info) name size))))) ((ident-add info) name size)))))
((post-dec (p-expr (ident ,name))) ((post-dec (p-expr (ident ,name)))
(append-text info (append ((ident->accu info) name) (let* ((type (ident->type info name))
((ident-add info) name -1)))) (ptr (ident->pointer info name))
(size (cond ((= ptr 1) (ident->size info name))
((> ptr 1) 4)
(else 1))))
(append-text info (append ((ident->accu info) name)
((ident-add info) name (- size))))))
((pre-inc (p-expr (ident ,name))) ((pre-inc (p-expr (ident ,name)))
(append-text info (append ((ident-add info) name 1) (let* ((type (ident->type info name))
((ident->accu info) name)))) (ptr (ident->pointer info name))
(size (cond ((= ptr 1) (ident->size info name))
((> ptr 1) 4)
(else 1))))
(append-text info (append ((ident-add info) name size)
((ident->accu info) name)))))
((pre-dec (p-expr (ident ,name))) ((pre-dec (p-expr (ident ,name)))
(append-text info (append ((ident-add info) name -1) (let* ((type (ident->type info name))
((ident->accu info) name)))) (ptr (ident->pointer info name))
(size (cond ((= ptr 1) (ident->size info name))
((> ptr 1) 4)
(else 1))))
(append-text info (append ((ident-add info) name (- size))
((ident->accu info) name)))))
((post-inc ,expr) ((post-inc ,expr)
(let* ((info (append ((expr->accu info) expr))) (let* ((info (append ((expr->accu info) expr)))
(info (append-text info (wrap-as (i386:push-accu)))) (info (append-text info (wrap-as (i386:push-accu))))
(ptr (expr->pointer info expr)) (ptr (expr->pointer info expr))
(size (if (> ptr 0) 4 1)) (size (cond ((= ptr 1) (expr->size info expr))
((> ptr 1) 4)
(else 1)))
(info ((expr-add info) expr size)) (info ((expr-add info) expr size))
(info (append-text info (wrap-as (i386:pop-accu))))) (info (append-text info (wrap-as (i386:pop-accu)))))
info)) info))
@ -726,27 +745,70 @@
(let* ((info (append ((expr->accu info) expr))) (let* ((info (append ((expr->accu info) expr)))
(info (append-text info (wrap-as (i386:push-accu)))) (info (append-text info (wrap-as (i386:push-accu))))
(ptr (expr->pointer info expr)) (ptr (expr->pointer info expr))
(size (if (> ptr 0) 4 1)) (size (cond ((= ptr 1) (expr->size info expr))
((> ptr 1) 4)
(else 1)))
(info ((expr-add info) expr (- size))) (info ((expr-add info) expr (- size)))
(info (append-text info (wrap-as (i386:pop-accu))))) (info (append-text info (wrap-as (i386:pop-accu)))))
info)) info))
((pre-inc ,expr) ((pre-inc ,expr)
(let* ((ptr (expr->pointer info expr)) (let* ((ptr (expr->pointer info expr))
(size (if (> ptr 0) 4 1)) (size (cond ((= ptr 1) (expr->size info expr))
((> ptr 1) 4)
(else 1)))
(info ((expr-add info) expr size)) (info ((expr-add info) expr size))
(info (append ((expr->accu info) expr)))) (info (append ((expr->accu info) expr))))
info)) info))
((pre-dec ,expr) ((pre-dec ,expr)
(let* ((ptr (expr->pointer info expr)) (let* ((ptr (expr->pointer info expr))
(size (if (> ptr 0) 4 1)) (size (cond ((= ptr 1) (expr->size info expr))
((> ptr 1) 4)
(else 1)))
(info ((expr-add info) expr (- size))) (info ((expr-add info) expr (- size)))
(info (append ((expr->accu info) expr)))) (info (append ((expr->accu info) expr))))
info)) info))
((add ,a ,b) ((binop->accu info) a b (i386:accu+base))) ((add ,a (p-expr (fixed ,value)))
((sub ,a ,b) ((binop->accu info) a b (i386:accu-base))) (let* ((ptr (expr->pointer info a))
(size (cond ((= ptr 1) (expr->size info a))
((> ptr 1) 4)
(else 1)))
(info ((expr->accu info) a))
(value (cstring->number value))
(value (* size value)))
(append-text info (wrap-as (i386:accu+value value)))))
((add ,a ,b)
(let* ((ptr (expr->pointer info a))
(size (cond ((= ptr 1) (expr->size info a))
((> ptr 1) 4)
(else 1))))
(if (not (= size 1))
(warn (format #f "TODO: pointer arithmetic: ~s\n" o))))
((binop->accu info) a b (i386:accu+base)))
((sub ,a (p-expr (fixed ,value)))
(let* ((ptr (expr->pointer info a))
(size (cond ((= ptr 1) (expr->size info a))
((> ptr 1) 4)
(else 1)))
(info ((expr->accu info) a))
(value (cstring->number value))
(value (* size value)))
(stderr "sub[~s]: ~s + ~s\n" size a value)
(append-text info (wrap-as (i386:accu+value (- value))))))
((sub ,a ,b)
(let* ((ptr (expr->pointer info a))
(size (cond ((= ptr 1) (expr->size info a))
((> ptr 1) 4)
(else 1))))
(if (not (= size 1))
(warn (format #f "TODO: pointer arithmetic: ~s\n" o))))
((binop->accu info) a b (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)
(let ((info ((ast->info info) expr))) (let ((info ((ast->info info) expr)))
@ -1119,7 +1181,7 @@
("long" . ,(make-type 'builtin 4 0 #f)) ("long" . ,(make-type 'builtin 4 0 #f))
("long long" . ,(make-type 'builtin 8 0 #f)) ("long long" . ,(make-type 'builtin 8 0 #f))
("long long int" . ,(make-type 'builtin 8 0 #f)) ("long long int" . ,(make-type 'builtin 8 0 #f))
("void" . ,(make-type 'builtin 4 0 #f)) ("void" . ,(make-type 'builtin 1 0 #f))
;; FIXME sign ;; FIXME sign
("unsigned char" . ,(make-type 'builtin 1 0 #f)) ("unsigned char" . ,(make-type 'builtin 1 0 #f))
("unsigned short" . ,(make-type 'builtin 2 0 #f)) ("unsigned short" . ,(make-type 'builtin 2 0 #f))
@ -1493,6 +1555,7 @@
(define (ident->decl info o) (define (ident->decl info o)
(or (assoc-ref (.locals info) o) (or (assoc-ref (.locals info) o)
(assoc-ref (.globals info) o) (assoc-ref (.globals info) o)
(assoc-ref (.constants info) o)
(begin (begin
(stderr "NO IDENT: ~a\n" o) (stderr "NO IDENT: ~a\n" o)
(assoc-ref (.functions info) o)))) (assoc-ref (.functions info) o))))
@ -1501,19 +1564,33 @@
(let ((type (ident->decl info o))) (let ((type (ident->decl info o)))
(cond ((global? type) (global:type type)) (cond ((global? type) (global:type type))
((local? type) (local:type type)) ((local? type) (local:type type))
((assoc-ref (.constants info) o) "int")
(else (stderr "ident->type ~s => ~s\n" o type) (else (stderr "ident->type ~s => ~s\n" o type)
(car type))))) (car type)))))
(define (ident->pointer info o) (define (ident->pointer info o)
(let ((local (assoc-ref (.locals info) o))) (let ((local (assoc-ref (.locals info) o)))
(if local (local:pointer local) (if local (local:pointer local)
(or (and=> (ident->decl info o) global:pointer) 0)))) (let ((global (assoc-ref (.globals info) o)))
(if global
(global:pointer (ident->decl info o))
0)))))
(define (ident->size info o)
(let* ((type (ident->type info o))
(xtype (ast-type->type info type)))
(type:size xtype)))
(define (expr->pointer info o) (define (expr->pointer info o)
(pmatch o (pmatch o
((p-expr (ident ,name)) (ident->pointer info name)) ((p-expr (ident ,name)) (ident->pointer info name))
(_ (stderr "expr->pointer: unsupported: ~s\n" o) 0))) (_ (stderr "expr->pointer: unsupported: ~s\n" o) 0)))
(define (expr->size info o)
(pmatch o
((p-expr (ident ,name)) (ident->size info name))
(_ (stderr "expr->size: unsupported: ~s\n" o) 4)))
(define (p-expr->type info o) (define (p-expr->type info o)
(pmatch o (pmatch o
((p-expr (ident ,name)) (ident->type info name)) ((p-expr (ident ,name)) (ident->type info name))

View file

@ -58,6 +58,10 @@ test ()
printf ("eentje: %d\n", f.bar[0]); printf ("eentje: %d\n", f.bar[0]);
printf ("tweetje: %d\n", f.bar[1]); printf ("tweetje: %d\n", f.bar[1]);
int *pf = &f;
if (*pf != 0x22) return 1;
if (*(pf + 1) != 0x34) return 2;
struct foo *g = &f; struct foo *g = &f;
printf ("punter eentje: %d\n", g->bar[0]); printf ("punter eentje: %d\n", g->bar[0]);
printf ("punter tweetje: %d\n", g->bar[1]); printf ("punter tweetje: %d\n", g->bar[1]);

View file

@ -0,0 +1,47 @@
/* -*-comment-start: "//";comment-end:""-*-
* Mes --- Maxwell Equations of Software
* Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of Mes.
*
* Mes is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* Mes is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mes. If not, see <http://www.gnu.org/licenses/>.
*/
#include "30-test.i"
int
test ()
{
char *pc = 0;
void *pv = 0;
int *pi = 0;
char **ppc = 0;
void **ppv = 0;
int **ppi = 0;
if (++pc != 1) return 1;
if (++pv != 1) return 2;
if (++pi != 4) return 3;
if (++ppc != 4) return 4;
if (++ppv != 4) return 5;
if (++ppi != 4) return 6;
if (pc + 1 != 2) return 7;
if (pv + 1 != 2) return 8;
if (pi + 1 != 8) return 9;
if (ppc + 1 != 8) return 10;
if (ppv + 1 != 8) return 11;
if (ppi + 1 != 8) return 12;
return 0;
}