From cccbfe4c61899e13c3ea90f22a36a8576bc46a40 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Tue, 18 Jul 2017 20:22:44 +0200 Subject: [PATCH] mescc: Tinycc support: struct.struct. * module/language/c99/compiler.mes (expr->accu): Support &*, bar.foo.i, p->foo.i, p->pf->i (*pp)->foo.i, [slightly modified] offsetof. * scaffold/tests/72-typedef-struct-def.c (test): Test them. --- module/language/c99/compiler.mes | 216 ++++++++++++++++++++----- scaffold/tests/72-typedef-struct-def.c | 32 +++- 2 files changed, 207 insertions(+), 41 deletions(-) diff --git a/module/language/c99/compiler.mes b/module/language/c99/compiler.mes index 2a73fa84..70f0e0c0 100644 --- a/module/language/c99/compiler.mes +++ b/module/language/c99/compiler.mes @@ -492,21 +492,23 @@ ((initzer ,initzer) ((expr->accu info) initzer)) + ;; offsetoff + ((ref-to (i-sel (ident ,field) (cast (type-name (decl-spec-list ,struct) (abs-declr (pointer))) (p-expr (fixed ,base))))) + (let* ((type (decl->ast-type struct)) + (offset (field-offset info type field)) + (base (cstring->number base))) + (append-text info (wrap-as (i386:value->accu (+ base offset)))))) + ;; &foo ((ref-to (p-expr (ident ,name))) (append-text info ((ident-address->accu info) name))) - ;; &f.field - ((ref-to (d-sel (ident ,field) (p-expr (ident ,array)))) - (let* ((type (ident->type info array)) - (offset (field-offset info type field)) - (text (.text info))) - (append-text info (append ((ident->accu info) array) - (wrap-as (i386:accu+n offset)))))) + ;; &*foo + ((ref-to (de-ref ,expr)) + ((expr->accu info) expr)) - ;; &a[x]; - ((ref-to (array-ref ,index (p-expr (ident ,array)))) - ((expr->accu* info) `(array-ref ,index (p-expr (ident ,array))))) + ((ref-to ,expr) + ((expr->accu* info) expr)) ((sizeof-expr (p-expr (ident ,name))) (let* ((type (ident->type info name)) @@ -537,7 +539,7 @@ (let ((size (ast-type->size info type))) (append-text info (wrap-as (i386:value->accu size))))) - ((sizeof-type (type-name (decl-spec-list (type-spec (fixed-type ,type))) (abs-declr (pointer)))) + ((sizeof-type (type-name (decl-spec-list ,type) (abs-declr (pointer)))) (let ((size 4)) (append-text info (wrap-as (i386:value->accu size))))) @@ -569,12 +571,36 @@ (let ((info ((expr->accu* info) o))) (append-text info (wrap-as (i386:mem->accu))))) + ;; bar.f.i + ((d-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let ((info ((expr->accu* info) o))) + (append-text info (wrap-as (i386:mem->accu))))) + + ;; bar.poo->i + ((i-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let ((info ((expr->accu* info) o))) + (append-text info (wrap-as (i386:mem->accu))))) + + ;; bar->foo.i + ((d-sel (ident ,field1) (i-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let ((info ((expr->accu* info) o))) + (append-text info (wrap-as (i386:mem->accu))))) + + ;;(i-sel (ident "i") (i-sel (ident "p") (p-expr (ident "p")))) + ((i-sel (ident ,field1) (i-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let ((info ((expr->accu* info) o))) + (append-text info (wrap-as (i386:mem->accu))))) + + ;; (*pp)->bar.foo + ((d-sel (ident ,field1) (i-sel (ident ,field0) (de-ref (p-expr (ident ,struct0))))) + (let ((info ((expr->accu* info) o))) + (append-text info (wrap-as (i386:mem->accu))))) + ;; f.field - ((d-sel (ident ,field) (p-expr (ident ,array))) - (let* ((type (ident->type info array)) - (offset (field-offset info type field)) - (text (.text info))) - (append-text info (append ((ident->accu info) array) + ((d-sel (ident ,field) (p-expr (ident ,struct))) + (let* ((type (ident->type info struct)) + (offset (field-offset info type field))) + (append-text info (append ((ident->accu info) struct) (wrap-as (i386:mem+n->accu offset)))))) ((d-sel (ident ,field) (array-ref ,index (p-expr (ident ,array)))) @@ -585,21 +611,24 @@ ((i-sel (ident ,field) (p-expr (ident ,array))) (let* ((type (ident->type info array)) - (offset (field-offset info type field)) - (text (.text info))) + (offset (field-offset info type field))) (append-text info (append ((ident-address->accu info) array) (wrap-as (i386:mem->accu)) (wrap-as (i386:mem+n->accu offset)))))) ((i-sel (ident ,field) (de-ref (p-expr (ident ,array)))) (let* ((type (ident->type info array)) - (offset (field-offset info type field)) - (text (.text info))) + (offset (field-offset info type field))) (append-text info (append ((ident-address->accu info) array) (wrap-as (i386:mem->accu)) (wrap-as (i386:mem->accu)) (wrap-as (i386:mem+n->accu offset)))))) + ;;foo[index]->bar + ((i-sel (ident ,field) (array-ref ,index ,array)) + (let ((info ((expr->accu* info) o))) + (append-text info (wrap-as (i386:mem->accu))))) + ((de-ref (p-expr (ident ,name))) (let* ((type (ident->type info name)) (ptr (ident->pointer info name)) @@ -804,12 +833,13 @@ ((equal? op "/=") (wrap-as (i386:accu/base))) ((equal? op "%=") (wrap-as (i386:accu%base))) ((equal? op "|=") (wrap-as (i386:accu-or-base))) + ((equal? op "&=") (wrap-as (i386:accu-and-base))) (else (error "mescc: op ~a not supported: ~a\n" op o)))))))) (pmatch a ((p-expr (ident ,name)) (append-text info ((accu->ident info) name))) ((d-sel (ident ,field) ,p-expr) (let* ((type (p-expr->type info p-expr)) - (offset (field-offset info type field)) + (offset (field-offset info (if (pair? type) type `("struct" ,type)) field)) (info (append-text info (wrap-as (i386:push-accu)))) (info ((expr->accu* info) a)) (info (append-text info (wrap-as (i386:pop-base))))) @@ -821,6 +851,9 @@ 4))) (append-text info (append (wrap-as (i386:accu->base)) ((base->ident-address info) name))))) + ((de-ref ,expr) + (let ((info ((expr->base info) expr))) + (append-text info (wrap-as (i386:mem->base))))) ;; FIXME: size ((array-ref ,index (d-sel (ident ,field) (p-expr (ident ,struct)))) (let* ((info (append-text info (wrap-as (i386:push-accu)))) (info ((expr->accu* info) a)) @@ -904,6 +937,65 @@ ((ident->base info) array) (wrap-as (i386:accu+base)))))) + ;; bar.foo.i + ((d-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((type0 (ident->type info struct0)) + (type1 (field-type info `("struct" ,type0) field0)) + (offset (+ (field-offset info `("struct" ,type0) field0) + (field-offset info `("struct" ,type1) field1)))) + (append-text info (append ((ident->accu info) struct0) + (wrap-as (i386:accu+value offset)))))) + + ;; bar.poo->i + ((i-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((type0 (ident->type info struct0)) + (type1 (field-type info `("struct" ,type0) field0)) + (offset0 (field-offset info `("struct" ,type0) field0)) + (offset1 (field-offset info `("struct" ,type1) field1))) + (append-text info (append ((ident->accu info) struct0) + (wrap-as (i386:accu+value offset0)) + (wrap-as (i386:mem->accu)) + (wrap-as (i386:accu+value offset1)))))) + + ;; bar->foo.i + ((d-sel (ident ,field1) (i-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((type0 (ident->type info struct0)) + (type1 (field-type info `("struct" ,type0) field0)) + (offset (+ (field-offset info `("struct" ,type0) field0) + (field-offset info `("struct" ,type1) field1)))) + (append-text info (append ((ident-address->accu info) struct0) + (wrap-as (i386:accu+value offset)))))) + + ;; bar->foo.i + ((d-sel (ident ,field1) (d-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((type0 (ident->type info struct0)) + (type1 (field-type info `("struct" ,type0) field0)) + (offset (+ (field-offset info `("struct" ,type0) field0) + (field-offset info `("struct" ,type1) field1)))) + (append-text info (append ((ident->accu info) struct0) + (wrap-as (i386:accu+value offset)))))) + + ;;(i-sel (ident "i") (i-sel (ident "p") (p-expr (ident "p")))) + ((i-sel (ident ,field1) (i-sel (ident ,field0) (p-expr (ident ,struct0)))) + (let* ((type0 (ident->type info struct0)) + (type1 (field-type info `("struct" ,type0) field0)) + (offset0 (field-offset info `("struct" ,type0) field0)) + (offset1 (field-offset info `("struct" ,type1) field1))) + (append-text info (append ((ident->accu info) struct0) + (wrap-as (i386:accu+value offset0)) + (wrap-as (i386:mem->accu)) + (wrap-as (i386:accu+value offset1)))))) + + ;; (*pp)->bar.foo + ((d-sel (ident ,field1) (i-sel (ident ,field0) (de-ref (p-expr (ident ,struct0))))) + (let* ((type0 (ident->type info struct0)) + (type1 (field-type info `("struct" ,type0) field0)) + (offset (+ (field-offset info `("struct" ,type0) field0) + (field-offset info `("struct" ,type1) field1)))) + (append-text info (append ((ident->accu info) struct0) + (wrap-as (i386:mem->accu)) + (wrap-as (i386:accu+value offset)))))) + ;; g_cells[].type ((d-sel (ident ,field) (array-ref ,index (p-expr (ident ,array)))) (let* ((type (ident->type info array)) @@ -911,33 +1003,33 @@ (info ((expr->accu* info) `(array-ref ,index (p-expr (ident ,array)))))) (append-text info (wrap-as (i386:accu+value offset))))) - ((d-sel (ident ,field) (p-expr (ident ,name))) - (let* ((type (ident->type info name)) + ((d-sel (ident ,field) (p-expr (ident ,struct))) + (let* ((type (ident->type info struct)) (offset (field-offset info type field)) (text (.text info))) - (append-text info (append ((ident->accu info) name) + (append-text info (append ((ident->accu info) struct) (wrap-as (i386:accu+value offset)))))) ;; foo.bar[baz] - ((array-ref ,index (d-sel (ident ,field) (p-expr (ident ,name)))) - (let* ((type (ident->type info name)) + ((array-ref ,index (d-sel (ident ,field) (p-expr (ident ,struct)))) + (let* ((type (ident->type info struct)) (offset (field-offset info type field)) (info ((expr->accu info) index))) (append-text info (append (wrap-as (append (i386:accu-shl 2) ;; FIXME: assume size=4 (i386:push-accu))) - ((ident-address->accu info) name) + ((ident-address->accu info) struct) (wrap-as (append (i386:accu+value offset) (i386:pop-base) (i386:accu+base))))))) ;; foo->bar[baz] - ((array-ref ,index (i-sel (ident ,field) (p-expr (ident ,name)))) - (let* ((type (ident->type info name)) + ((array-ref ,index (i-sel (ident ,field) (p-expr (ident ,struct)))) + (let* ((type (ident->type info struct)) (offset (field-offset info type field)) (info ((expr->accu info) index))) (append-text info (append (wrap-as (append (i386:accu-shl 2) ;; FIXME: assume size=4 (i386:push-accu))) - ((ident->accu info) name) + ((ident->accu info) struct) (wrap-as (append (i386:accu+value offset) (i386:pop-base) (i386:accu+base))))))) @@ -958,21 +1050,28 @@ ((i-sel (ident ,field) (p-expr (ident ,array))) (let* ((type (ident->type info array)) - (offset (field-offset info type field)) - (text (.text info))) + (offset (field-offset info type field))) (append-text info (append ((ident-address->accu info) array) (wrap-as (i386:mem->accu)) (wrap-as (i386:accu+value offset)))))) ((i-sel (ident ,field) (de-ref (p-expr (ident ,array)))) (let* ((type (ident->type info array)) - (offset (field-offset info type field)) - (text (.text info))) + (offset (field-offset info type field))) (append-text info (append ((ident-address->accu info) array) (wrap-as (i386:mem->accu)) (wrap-as (i386:mem->accu)) (wrap-as (i386:accu+value offset)))))) + ;;foo[index]->bar + ((i-sel (ident ,field) (array-ref ,index (p-expr (ident ,array)))) + (let* ((type (ident->type info array)) + (offset (field-offset info type field)) + (info ((expr->accu* info) `(array-ref ,index (p-expr (ident ,array)))))) + (append-text info (append (wrap-as (i386:mem->accu)) + (wrap-as (i386:mem->accu)) + (wrap-as (i386:accu+value offset)))))) + (_ (error "expr->accu*: unsupported: " o))))) (define (ident->constant name value) @@ -1005,8 +1104,15 @@ (define (field:size o) (pmatch o ((,name ,type ,size ,pointer) size) + ((,name ,type ,size) size) (_ 4))) +(define (field:type o) + (pmatch o + ((,name ,type ,size ,pointer) type) + ((,name ,type ,size) type) + (_ (error "field:type:" o)))) + (define (get-type types o) (let ((t (assoc-ref types o))) (pmatch t @@ -1026,6 +1132,7 @@ ((union-ref (ident ,type)) (ast-type->type info `("struct" ,type))) ((void) (ast-type->type info "void")) + ((type-spec (typename ,type)) (ast-type->type info type)) (_ (let ((type (get-type (.types info) o))) (if type type (begin @@ -1040,6 +1147,11 @@ (let ((type (ast-type->type info o))) (type:size type))) +(define (field-field info struct field) + (let* ((xtype (ast-type->type info struct)) + (fields (type:description xtype))) + (and=> (member field fields (lambda (a b) (equal? a (car b)))) car))) + (define (field-offset info struct field) (let ((xtype (ast-type->type info struct))) (if (eq? (type:type xtype) 'union) 0 @@ -1050,10 +1162,14 @@ (define (field-size info struct field) (let ((xtype (ast-type->type info struct))) (if (eq? (type:type xtype) 'union) 0 - (let* ((fields (type:description xtype)) - (field (and=> (member field fields (lambda (a b) (equal? a (car b)))) car))) + (let ((field (field-field info struct field))) (field:size field))))) +(define (field-type info struct field) + (let ((xtype (ast-type->type info struct))) + (let ((field (field-field info struct field))) + (field:type field)))) + (define (ast->type o) (pmatch o ((fixed-type ,type) @@ -1239,12 +1355,22 @@ (let ((size 4) (count (cstring->number count))) (list name type (* count size) 0))) - ;; struct InlineFunc **inline_fns; + + ((comp-decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (comp-declr-list (comp-declr (ptr-declr (pointer (pointer)) (ident ,name))))) + (list name type 4)) + ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ptr-declr (pointer (pointer)) (ident ,name))))) (list name type 4)) - ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ptr-declr (pointer) (ident ,name))))) + + ((comp-decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (comp-declr-list (comp-declr (ptr-declr (pointer) (ident ,name))))) (list name type 4)) + ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ptr-declr (pointer) (ident ,name))))) + (list name type 4)) + + ((comp-decl (decl-spec-list (type-spec (struct-ref (ident (,type))))) (comp-declr-list (comp-declr (ident ,name)))) + ((struct-field info) `(comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ident ,name)))))) + ((comp-decl (decl-spec-list (type-spec (struct-ref (ident ,type)))) (comp-declr-list (comp-declr (ident ,name)))) (let ((size (ast-type->size info `("struct" ,type)))) (list name type size 0))) @@ -1275,8 +1401,13 @@ (define (p-expr->type info o) (pmatch o ((p-expr (ident ,name)) (ident->type info name)) - ((array-ref ,index (p-expr (ident ,array))) - (ident->type info array)) + ((array-ref ,index (p-expr (ident ,array))) (ident->type info array)) + ((i-sel (ident ,field) (p-expr (ident ,struct))) + (let ((type0 (ident->type info struct))) + (field-type info `("struct" ,type0) field))) + ((d-sel (ident ,field) (p-expr (ident ,struct))) + (let ((type0 (ident->type info struct))) + (field-type info `("struct" ,type0) field))) (_ (error "p-expr->type: unsupported: " o)))) (define (local-var? o) ;; formals < 0, locals > 0 @@ -1990,6 +2121,11 @@ (let loop ((values (map (initzer->value info) values)) (value 0)) (if (null? values) (int->bv32 value) (loop (cdr values) (logior value (car values)))))) + ((initzer (ref-to (i-sel (ident ,field) (cast (type-name (decl-spec-list ,struct) (abs-declr (pointer))) (p-expr (fixed ,base)))))) + (let* ((type (decl->ast-type struct)) + (offset (field-offset info type field)) + (base (cstring->number base))) + (int->bv32 (+ base offset)))) (() (int->bv32 0)) (_ (error "initzer->data: unsupported: " o))))) diff --git a/scaffold/tests/72-typedef-struct-def.c b/scaffold/tests/72-typedef-struct-def.c index b6565cc7..7ee2a98c 100644 --- a/scaffold/tests/72-typedef-struct-def.c +++ b/scaffold/tests/72-typedef-struct-def.c @@ -29,16 +29,34 @@ typedef struct foo typedef struct { int i; + struct foo f; + struct foo *p; } bar; + +//NYACC +//#define offsetof(type, field) ((size_t) &((type *)0)->field) +#if __MESC__ +#define offsetof(type, field) (&((type *)0)->field) +#else +#define offsetof(type, field) ((size_t)&((type *)0)->field) +#endif + int test () { foo f = {1}; printf ("f.i=%d\n", f.i); - bar b = {1}; + bar b = {1, 2, &f}; printf ("b.i=%d\n", b.i); + + printf ("b.f.i=%d\n", b.f.i); + if (b.f.i != 2) return 1; + + printf ("b.p->i=%d\n", b.p->i); + if (b.p->i != 1) return 1; + bar* p = &b; p->i = 2; printf ("p->i=%d\n", b.i); @@ -49,12 +67,24 @@ test () p->i--; printf ("p->i=%d\n", b.i); + printf ("p->f.i=%d\n", p->f.i); + if (p->f.i != 2) return 1; + + printf ("p->p->i=%d\n", p->p->i); + if (p->p->i != 1) return 1; bar** pp = &p; (*pp)->i = 3; printf ("(*pp)->i=%d\n", b.i); printf ("sizeof i:%d\n", sizeof (p->i)); + if ((sizeof p->i) != 4) return 1; + + printf ("offsetof g=%d\n", (offsetof (bar ,f))); + if ((offsetof (bar ,f)) != 4) return 1; + + printf ("(*pp)->b.i=%d\n", (*pp)->f.i); + if ((*pp)->f.i != 2) return 1; return 0; }