diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-25 15:33:13 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-25 15:33:13 -0500 |
commit | 9df83e399d7691bb20cc9d42ddb70619908aeeca (patch) | |
tree | 1a31320443ff024d14e401656f4f90ca747b7e41 | |
parent | 27acf3754529988de9d43ba0abb8e5b3bbb3da31 (diff) |
passing structs to foreign functions
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | foreign.c | 46 | ||||
-rw-r--r-- | instance_table.c | 1 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | parse.c | 26 | ||||
-rw-r--r-- | test.c | 7 | ||||
-rw-r--r-- | test.toc | 15 | ||||
-rw-r--r-- | toc.c | 2 | ||||
-rw-r--r-- | tokenizer.c | 5 | ||||
-rw-r--r-- | types.c | 2 |
11 files changed, 81 insertions, 27 deletions
@@ -13,3 +13,4 @@ tags compatibility std/*.c std/*.o +*.so
\ No newline at end of file @@ -6,7 +6,6 @@ static bool types_block(Typer *tr, Block *b); static bool types_decl(Typer *tr, Declaration *d); static bool type_resolve(Typer *tr, Type *t, Location where); -static size_t compiler_sizeof(Type *t); static bool eval_block(Evaluator *ev, Block *b, Type *t, Value *v); static bool eval_expr(Evaluator *ev, Expression *e, Value *v); static bool block_enter(Block *b, Statement *stmts, U16 flags); @@ -60,7 +59,6 @@ static size_t compiler_sizeof_builtin(BuiltinType b) { return 0; } -static size_t compiler_alignof(Type *t); /* finds offsets and size */ static void eval_struct_find_offsets(StructDef *s) { if (!(s->flags & STRUCT_DEF_FOUND_OFFSETS)) { @@ -144,6 +144,42 @@ static bool arg_list_start(av_alist *arg_list, void (*fn)(), Value *return_val, break; } break; + case TYPE_STRUCT: { + size_t struct_size = compiler_sizeof(return_type); + StructDef *struc = return_type->struc; + return_val->struc = err_calloc(1, struct_size); + bool splittable; + /* hopefully this is right! */ + if (struct_size <= sizeof(long)) { + splittable = true; + } else if (struct_size > 2*sizeof(long)) { + splittable = false; + } else if (arr_len(struc->fields) > 4) { + splittable = false; + } else { + /* NOTE: this warning is not because splittable is being computed incorrectly! it doesn't handle it right with *either* splittable = 0 or splittable = 1 */ + warn_print(where, "Dynamically calling function which returns a struct. avcall seems to not handle structs of size ~2*sizeof(long) correctly."); + splittable = true; + size_t word_size = sizeof(__avword); + arr_foreach(struc->fields, Field, f) { + if (f->offset / word_size != (f->offset + compiler_sizeof(&f->type) - 1) / word_size) { + splittable = false; + break; + } + } + } + _av_start_struct(*arg_list, fn, struct_size, splittable, return_val->struc); + } break; + case TYPE_SLICE: +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + av_start_struct(*arg_list, fn, Slice, av_word_splittable_2(I64, void *), &return_val->slice); +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + break; case TYPE_EXPR: assert(0); return false; @@ -215,6 +251,12 @@ static bool arg_list_add(av_alist *arg_list, Value *val, Type *type, Location wh break; } break; + case TYPE_SLICE: + av_struct(*arg_list, Slice, val->slice); + break; + case TYPE_STRUCT: + _av_struct(*arg_list, compiler_sizeof(type), compiler_alignof(type), val->struc); + break; case TYPE_EXPR: assert(0); return false; @@ -269,9 +311,7 @@ static bool foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *fn_type, Val } av_call(arg_list); - (void)fn_type; (void)args; - - + (void)fn_type; (void)args; return true; } diff --git a/instance_table.c b/instance_table.c index fe667b8..f67b901 100644 --- a/instance_table.c +++ b/instance_table.c @@ -18,7 +18,6 @@ */ static void *val_get_ptr(Value *v, Type *t); static U64 val_hash(Value v, Type *t); -static size_t compiler_sizeof(Type *t); static bool val_eq(Value u, Value v, Type *t); static bool type_eq(Type *t1, Type *t2); @@ -18,7 +18,6 @@ /* TODO: -passing structs to foreign functions each=>for #builtin("sizeof(int)") etc. @@ -414,7 +414,7 @@ static bool parse_args(Parser *p, Argument **args) { while (1) { if (t->token->kind == TOKEN_EOF) { tokr_err(t, "Expected argument list to continue."); - info_print(token_location(start), "This is where the argument list starts."); + info_print(token_location(p->file, start), "This is where the argument list starts."); return false; } Argument *arg = parser_arr_add(p, args); @@ -1211,7 +1211,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { if (!parse_expr(p, ea->range.step, step_end)) return false; if (!token_is_kw(step_end, KW_DOTDOT)) { - err_print(token_location(step_end), "Expected .. to follow step in for statement."); + err_print(token_location(p->file, step_end), "Expected .. to follow step in for statement."); return false; } } else { @@ -1231,7 +1231,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { } } } else { - err_print(token_location(first_end), "Expected { or .. to follow expression in for statement."); + err_print(token_location(p->file, first_end), "Expected { or .. to follow expression in for statement."); return false; } @@ -1530,7 +1530,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { case KW_AMPERSAND: case KW_EXCLAMATION: case KW_DEL: - err_print(token_location(lowest_precedence_op), "Unary operator '%s' being used as a binary operator!", kw_to_str(lowest_precedence_op->kw)); + err_print(token_location(p->file, lowest_precedence_op), "Unary operator '%s' being used as a binary operator!", kw_to_str(lowest_precedence_op->kw)); return false; default: assert(0); return false; } @@ -1643,7 +1643,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { } iend = expr_find_end(p, EXPR_CAN_END_WITH_COLON); if (iend->kind != TOKEN_KW) { - err_print(token_location(iend), "Expected ] or : after index."); + err_print(token_location(p->file, iend), "Expected ] or : after index."); return false; } switch (iend->kw) { @@ -1679,7 +1679,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { s->to = parser_new_expr(p); Token *to_end = expr_find_end(p, 0); if (!token_is_kw(to_end, KW_RSQUARE)) { - err_print(token_location(iend), "Expected ] at end of slice."); + err_print(token_location(p->file, iend), "Expected ] at end of slice."); return false; } if (!parse_expr(p, s->to, to_end)) @@ -1687,7 +1687,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { } } break; default: - err_print(token_location(iend), "Expected ] or : after index."); + err_print(token_location(p->file, iend), "Expected ] or : after index."); return false; } ++t->token; /* move past ] */ @@ -1737,7 +1737,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { ++t->token; Token *arg_end = expr_find_end(p, 0); if (!token_is_kw(arg_end, KW_RPAREN)) { - err_print(token_location(arg_end), "Expected ) at end of #%s directive.", directives[t->token->direct]); + err_print(token_location(p->file, arg_end), "Expected ) at end of #%s directive.", directives[t->token->direct]); return false; } if (!parse_expr(p, single_arg, arg_end)) @@ -1858,7 +1858,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla } d->type = type; if (type.kind == TYPE_TUPLE && arr_len(d->type.tuple) != arr_len(d->idents)) { - err_print(d->where, "Expected to have %lu things declared in declaration, but got %lu.", (unsigned long)arr_len(d->type.tuple), (unsigned long)arr_len(d->idents)); + err_print(type.where, "Expected to have %lu things declared in declaration, but got %lu.", (unsigned long)arr_len(d->type.tuple), (unsigned long)arr_len(d->idents)); goto ret_false; } } @@ -1876,8 +1876,8 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla ++t->token; if (token_is_direct(t->token, DIRECT_FOREIGN)) { if (!(d->flags & DECL_ANNOTATES_TYPE)) { - err_print(d->where, "Foreign declaration must have a type."); - return false; + tokr_err(t, "Foreign declaration must have a type."); + goto ret_false; } d->flags |= DECL_FOREIGN; /* foreign name */ @@ -1910,7 +1910,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla /* inferred expression */ d->flags |= DECL_INFER; if (arr_len(d->idents) > 1) { - err_print(d->where, "Inferred declarations can only have one identifier. Please separate this declaration."); + tokr_err(t, "Inferred declarations can only have one identifier. Please separate this declaration."); goto ret_false; } if (!(d->flags & DECL_IS_CONST)) { @@ -2020,7 +2020,7 @@ static bool parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { return false; } if (!token_is_kw(end, KW_SEMICOLON)) { - err_print(token_location(end), "Expected ';' at end of return statement."); + err_print(token_location(p->file, end), "Expected ';' at end of return statement."); t->token = end->kind == TOKEN_EOF ? end : end + 1; return false; } @@ -0,0 +1,7 @@ +typedef struct Point { + long x, y; +} Point; + +long p(Point x) { + return x.x + x.y; +} @@ -1,8 +1,15 @@ -addmul ::= fn (x::=0, y:=0) -add := x+y, mul := x*y { - a : []char = x; +Point ::= struct { + x, y : int; +}; + +p :: fn(Point) int = #foreign "p", "./test.so"; + +mkpoint ::= fn(x:int,y:int) p : Point { + p.x = x; + p.y = y; }; main ::= fn() { - addmul(6,7); + point ::= mkpoint(-3,-5); + total ::= p(point); };
\ No newline at end of file @@ -78,6 +78,8 @@ static inline bool type_is_slicechar(Type *t) { #include "location.c" #include "err.c" #include "blockarr.c" +static size_t compiler_alignof(Type *t); +static size_t compiler_sizeof(Type *t); #include "instance_table.c" #include "copy.c" #include "binfile.c" diff --git a/tokenizer.c b/tokenizer.c index 9466ad8..39b7f06 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -176,10 +176,11 @@ static int tokr_esc_seq(Tokenizer *t) { } -static Location token_location(Token *t) { +static Location token_location(File *file, Token *t) { Location loc; loc.start = t; loc.end = t + 1; + loc.file = file; return loc; } @@ -231,7 +232,7 @@ static void tokr_err_( #endif va_list args; va_start(args, fmt); - err_vprint(token_location(t->token), fmt, args); + err_vprint(token_location(t->file, t->token), fmt, args); va_end(args); } @@ -822,7 +822,7 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) { } /* TODO: this should really be at the closing brace, and not the function declaration */ char *expected = type_to_str(ret_type); - err_print(token_location(f->body.where.end), "No return value in function which returns %s.", expected); + err_print(token_location(f->body.where.file, f->body.where.end), "No return value in function which returns %s.", expected); free(expected); info_print(f->where, "Function was declared here:"); success = false; |