From 95f107282d63e9c1253a6f14f06b2b2e2c62d566 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Sat, 5 Aug 2017 19:10:00 +0200 Subject: [PATCH] mescc: Tinycc support: fixes for foo->bar[baz]. * module/language/c99/compiler.mes (expr->accu, expr->accu*): fixes for foo->bar[baz]. (expr->pointer): Support i-sel. (p-expr->type): Support add, sub, de-ref, ref-to. * scaffold/tests/7f-struct-pointer-arithmetic.c: Test it. * make.scm (add-scaffold-test): Build it. --- make.scm | 3 +- module/language/c99/compiler.mes | 32 ++++++++- scaffold/tests/7f-struct-pointer-arithmetic.c | 65 +++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 scaffold/tests/7f-struct-pointer-arithmetic.c diff --git a/make.scm b/make.scm index b4752f53..5fe89b62 100755 --- a/make.scm +++ b/make.scm @@ -164,7 +164,8 @@ exec ${GUILE-guile} --no-auto-compile -L . -L guile -C . -C guile -s "$0" ${1+"$ "7b-struct-int-array" "7c-dynarray" "7d-cast-char" - "7e-struct-array-access")) + "7e-struct-array-access" + "7f-struct-pointer-arithmetic")) (add-target (group "check-scaffold-tests/7" #:dependencies (filter (target-prefix? "check-scaffold/tests/7") %targets))) diff --git a/module/language/c99/compiler.mes b/module/language/c99/compiler.mes index 73a94488..a9209d24 100644 --- a/module/language/c99/compiler.mes +++ b/module/language/c99/compiler.mes @@ -812,18 +812,27 @@ ((add ,a (p-expr (fixed ,value))) (let* ((ptr (expr->pointer info a)) - (size (cond ((= ptr 1) (expr->size 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) (else 1))) (info ((expr->accu info) a)) (value (cstring->number value)) (value (* size value))) + (stderr "ptr=~s\n" ptr) + (stderr " size=~s\n" size) + (stderr " struct?=~s\n" struct?) + (if (not (= size 1)) + (warn (format #f "TODO: pointer arithmetic: ~s\n" o))) (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) + ((and struct? (= ptr -2)) 4) (else 1)))) (if (not (= size 1)) (warn (format #f "TODO: pointer arithmetic: ~s\n" o)))) @@ -837,6 +846,8 @@ (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) @@ -1137,9 +1148,13 @@ (type1 (field-type info type0 field0)) (offset (field-offset info type0 field0)) (info ((expr->accu info) index)) + (struct? (memq (type:type (ast-type->type info type0)) '(struct union))) (ptr (field-pointer info type0 field0)) (size (if (= ptr -1) (ast-type->size info type1) 4))) + (stderr "ACCU* o=~s\n" o) + (stderr " ptr=~s\n" ptr) + (stderr " size=~s\n" size) (append-text info (append (wrap-as (append (i386:accu->base) (if (eq? size 1) '() (append @@ -1150,6 +1165,7 @@ (i386:accu-shl 2))))) (wrap-as (i386:push-accu)) ((ident-address->accu info) struct0) + (if (and struct? (= ptr -2)) (wrap-as (i386:mem->accu)) '()) (wrap-as (append (i386:accu+value offset) (i386:pop-base) (i386:accu+base))))))) @@ -1160,6 +1176,7 @@ (type1 (field-type info type0 field0)) (offset (field-offset info type0 field0)) (info ((expr->accu info) index)) + (struct? (memq (type:type (ast-type->type info type0)) '(struct union))) (ptr (field-pointer info type0 field0)) (size (if (= ptr -1) (ast-type->size info type1) 4))) @@ -1173,6 +1190,7 @@ (i386:accu-shl 2))))) (wrap-as (i386:push-accu)) ((ident->accu info) struct0) + (if (and struct? (= ptr -2)) (wrap-as (i386:mem->accu)) '()) (wrap-as (append (i386:accu+value offset) (i386:pop-base) (i386:accu+base))))))) @@ -1663,6 +1681,12 @@ ((pre-dec ,a) (expr->pointer info a)) ((post-inc ,a) (expr->pointer info a)) ((post-dec ,a) (expr->pointer info a)) + ((d-sel (ident ,field) (p-expr (ident ,struct))) + (let ((type (ident->type info struct))) + (field-pointer info type field))) + ((i-sel (ident ,field) (p-expr (ident ,struct))) + (let ((type (ident->type info struct))) + (field-pointer info type field))) ((cast (type-name ,type (abs-declr ,pointer)) (p-expr (ident ,name))) (let* ((type (ast-type->type info type)) (pointer0 (type:pointer type)) @@ -1701,6 +1725,12 @@ (let* ((type0 (ident->type info array)) (type0 (if (pair? type0) type0 `("tag" ,type0)))) (field-type info type0 field))) + ((de-ref ,expr) (p-expr->type info expr)) + ((ref-to ,expr) (p-expr->type info expr)) + ((add ,a ,b) + (p-expr->type info a)) + ((sub ,a ,b) + (p-expr->type info a)) (_ (error "p-expr->type: unsupported: " o)))) (define (local-var? o) ;; formals < 0, locals > 0 diff --git a/scaffold/tests/7f-struct-pointer-arithmetic.c b/scaffold/tests/7f-struct-pointer-arithmetic.c new file mode 100644 index 00000000..1a1e763c --- /dev/null +++ b/scaffold/tests/7f-struct-pointer-arithmetic.c @@ -0,0 +1,65 @@ +/* -*-comment-start: "//";comment-end:""-*- + * Mes --- Maxwell Equations of Software + * Copyright © 2017 Jan Nieuwenhuizen + * + * 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 . + */ + +#include "30-test.i" + +#include +#include + +struct foo; + +struct foo { + struct foo **foo; +}; + +struct foo g_foo[2]; + +int +test () +{ + struct foo foo; + foo.foo = g_foo; + void *p; + void *q; + + p = &foo.foo[0]; + q = foo.foo; + eputs ("f:"); eputs (itoa (foo.foo)); eputs ("\n"); + eputs ("p:"); eputs (itoa (p)); eputs ("\n"); + eputs ("q:"); eputs (itoa (q)); eputs ("\n"); + if (q != p) return 1; + + p = &foo.foo[1]; + q = foo.foo + 1; + eputs ("f:"); eputs (itoa (foo.foo)); eputs ("\n"); + eputs ("p:"); eputs (itoa (p)); eputs ("\n"); + eputs ("q:"); eputs (itoa (q)); eputs ("\n"); + if (q != p) return 2; + + struct foo *pfoo = &foo; + p = &pfoo->foo[1]; + q = pfoo->foo + 1; + eputs ("f:"); eputs (itoa (pfoo->foo)); eputs ("\n"); + eputs ("p:"); eputs (itoa (p)); eputs ("\n"); + eputs ("q:"); eputs (itoa (q)); eputs ("\n"); + if (q != p) return 3; + + return 0; +}