summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-01-25 15:33:13 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-01-25 15:33:13 -0500
commit9df83e399d7691bb20cc9d42ddb70619908aeeca (patch)
tree1a31320443ff024d14e401656f4f90ca747b7e41
parent27acf3754529988de9d43ba0abb8e5b3bbb3da31 (diff)
passing structs to foreign functions
-rw-r--r--.gitignore1
-rw-r--r--eval.c2
-rw-r--r--foreign.c46
-rw-r--r--instance_table.c1
-rw-r--r--main.c1
-rw-r--r--parse.c26
-rw-r--r--test.c7
-rw-r--r--test.toc15
-rw-r--r--toc.c2
-rw-r--r--tokenizer.c5
-rw-r--r--types.c2
11 files changed, 81 insertions, 27 deletions
diff --git a/.gitignore b/.gitignore
index 3326907..9c61414 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@ tags
compatibility
std/*.c
std/*.o
+*.so \ No newline at end of file
diff --git a/eval.c b/eval.c
index 6ff8d8a..7b2474c 100644
--- a/eval.c
+++ b/eval.c
@@ -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)) {
diff --git a/foreign.c b/foreign.c
index e669f8a..a5b63e7 100644
--- a/foreign.c
+++ b/foreign.c
@@ -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);
diff --git a/main.c b/main.c
index 0d6bf11..61bbf87 100644
--- a/main.c
+++ b/main.c
@@ -18,7 +18,6 @@
/*
TODO:
-passing structs to foreign functions
each=>for
#builtin("sizeof(int)") etc.
diff --git a/parse.c b/parse.c
index f0b79f9..461d877 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
}
diff --git a/test.c b/test.c
new file mode 100644
index 0000000..e774509
--- /dev/null
+++ b/test.c
@@ -0,0 +1,7 @@
+typedef struct Point {
+ long x, y;
+} Point;
+
+long p(Point x) {
+ return x.x + x.y;
+}
diff --git a/test.toc b/test.toc
index 666a9d1..786bd03 100644
--- a/test.toc
+++ b/test.toc
@@ -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
diff --git a/toc.c b/toc.c
index fc5945f..57c67b5 100644
--- a/toc.c
+++ b/toc.c
@@ -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);
}
diff --git a/types.c b/types.c
index 7a18c72..98d1958 100644
--- a/types.c
+++ b/types.c
@@ -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;