diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-05-03 13:51:54 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-05-03 13:51:54 -0400 |
commit | 3fcabe8edbe4213ab1d5a65c584ee332c1b26baf (patch) | |
tree | cd5d3e36a153d5c35a7a29d8fe4d4e1431cb9076 | |
parent | cb1a634e495c6f2e3ebd90f25235c6f7d2d639b7 (diff) |
64-bit #foreign arguments
-rw-r--r-- | foreign_msvc32.c | 90 | ||||
-rw-r--r-- | test.toc | 25 | ||||
-rw-r--r-- | tokenizer.c | 4 |
3 files changed, 55 insertions, 64 deletions
diff --git a/foreign_msvc32.c b/foreign_msvc32.c index d1b38e0..8ab61a2 100644 --- a/foreign_msvc32.c +++ b/foreign_msvc32.c @@ -73,41 +73,41 @@ registers) */ /* call function with 0 arguments, returning some sort of integer (or pointer) */ -static Word msvc_call0i(FnPtr fn, Word *w) { +static U64 msvc_call0i(FnPtr fn, Word *w) { (void)w; - return ((Word(*)(void))fn)(); + return ((U64(*)(void))fn)(); } -static Word msvc_call1i(FnPtr fn, Word *w) { - return ((Word(*)(Word))fn)(w[0]); +static U64 msvc_call1i(FnPtr fn, Word *w) { + return ((U64(*)(Word))fn)(w[0]); } -static Word msvc_call2i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word))fn)(w[0], w[1]); +static U64 msvc_call2i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word))fn)(w[0], w[1]); } -static Word msvc_call3i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word, Word))fn)(w[0], w[1], w[2]); +static U64 msvc_call3i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word, Word))fn)(w[0], w[1], w[2]); } -static Word msvc_call4i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3]); +static U64 msvc_call4i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3]); } -static Word msvc_call5i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4]); +static U64 msvc_call5i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4]); } -static Word msvc_call6i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5]); +static U64 msvc_call6i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5]); } -static Word msvc_call7i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6]); +static U64 msvc_call7i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6]); } -static Word msvc_call8i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]); +static U64 msvc_call8i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]); } -static Word msvc_call9i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word, Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7], w[8]); +static U64 msvc_call9i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word, Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7], w[8]); } -static Word msvc_call10i(FnPtr fn, Word *w) { - return ((Word(*)(Word, Word, Word, Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7], w[8], w[9]); +static U64 msvc_call10i(FnPtr fn, Word *w) { + return ((U64(*)(Word, Word, Word, Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7], w[8], w[9]); } -static Word (*const msvc_calli[11])(FnPtr fn, Word *w) = { +static U64 (*const msvc_calli[11])(FnPtr fn, Word *w) = { msvc_call0i, msvc_call1i, msvc_call2i, @@ -203,11 +203,20 @@ static Status foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *ret_type, fn->foreign.fn_ptr = fn_ptr; } Word words[10]; + Word *word = words; char *type = (char *)arg_types; for (size_t i = 0; i < nargs; ++i) { - val_to_words(args[i], (Type *)type, call_where, &words[i]); + int arg_words = compiler_sizeof((Type *)type) == 8 ? 2 : 1; + if (word + arg_words > words + 10) { + err_print(call_where, "You can only call functions with up to 40 bytes of arguments on 32-bit Windows."); + return false; + } + if (!val_to_words(args[i], (Type *)type, call_where, word)) + return false; type += arg_types_stride; + word += arg_words; } + size_t nwords = (size_t)(word - words); bool is_float = false; switch (ret_type->kind) { case TYPE_BUILTIN: @@ -244,13 +253,8 @@ static Status foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *ret_type, } } - if (nargs > 10) { - err_print(call_where, "You can only call functions with up to 10 arguments on Windows at compile time. This call has %ld.", (long)nargs); - return false; - } - if (is_float) { - double d = msvc_callf[nargs](fn_ptr, words); + double d = msvc_callf[nwords](fn_ptr, words); assert(ret_type->kind == TYPE_BUILTIN); if (ret_type->builtin == BUILTIN_F32) { ret->f32 = (F32)d; /* turns out functions just always return doubles */ @@ -259,26 +263,26 @@ static Status foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *ret_type, ret->f64 = d; } } else { - Word w = msvc_calli[nargs](fn_ptr, words); + U64 r = msvc_calli[nwords](fn_ptr, words); switch (ret_type->kind) { case TYPE_BUILTIN: switch (ret_type->builtin) { - case BUILTIN_I8: ret->i8 = (I8)w; break; - case BUILTIN_I16: ret->i16 = (I16)w; break; - case BUILTIN_I32: ret->i32 = (I32)w; break; - case BUILTIN_I64: ret->i64 = (I64)w; break; - case BUILTIN_U8: ret->u8 = (U8)w; break; - case BUILTIN_U16: ret->u16 = (U16)w; break; - case BUILTIN_U32: ret->u32 = (U32)w; break; - case BUILTIN_U64: ret->u64 = (U64)w; break; - case BUILTIN_BOOL: ret->boolv = (bool)w; break; - case BUILTIN_CHAR: ret->charv = (char)w; break; - case BUILTIN_VOID: (void)w; break; + case BUILTIN_I8: ret->i8 = (I8)r; break; + case BUILTIN_I16: ret->i16 = (I16)r; break; + case BUILTIN_I32: ret->i32 = (I32)r; break; + case BUILTIN_I64: ret->i64 = (I64)r; break; + case BUILTIN_U8: ret->u8 = (U8)r; break; + case BUILTIN_U16: ret->u16 = (U16)r; break; + case BUILTIN_U32: ret->u32 = (U32)r; break; + case BUILTIN_U64: ret->u64 = (U64)r; break; + case BUILTIN_BOOL: ret->boolv = (bool)r; break; + case BUILTIN_CHAR: ret->charv = (char)r; break; + case BUILTIN_VOID: (void)r; break; default: assert(0); break; } break; case TYPE_PTR: - ret->ptr = (void *)w; + ret->ptr = (void *)r; break; default: assert(0); break; } @@ -1,31 +1,18 @@ -/* - stdc ::= "msvcrt.dll"; printf ::= #foreign("printf",stdc) fn (#C &"char const", #C ..) #C int; -puti ::= fn(i: i32) i32 { - fmt := "number: %d\n\0"; +puti ::= fn(i: u64) i32 { + fmt := "number: %llx\n\0"; printf(&fmt[0], i) as i32 } + // BUG: puti(puti(x)) -//sqrt ::= #foreign("sqrt",stdc) fn(f64) f64; -sqrtf ::= #foreign("sinf",stdc) fn(f32) f32; -/* +sqrt ::= #foreign("sqrt",stdc) fn(f64) f64; putf ::= fn(f: f64) i32 { fmt := "number: %f\n\0"; printf(&fmt[0], f) as i32 } -*/ - +foo ::= #foreign("foo", "test.dll") fn(#C unsigned_long_long, #C unsigned_long_long) #C unsigned_long_long; main ::= fn() { - sqrtf(3.1); + puti(foo(0x12345678cafebabe as u64, 0x76543210deadbeef as u64)); } main(); - -*/ - -foo ::= #foreign("foo","test.dll") fn(f32) f32; -printf ::= #foreign("printf", "msvcrt.dll") fn(#C &"const char", #C ..) #C int; - -main ::= fn() { - x ::= foo(2.7); -} diff --git a/tokenizer.c b/tokenizer.c index cdbebd8..d90a4f6 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -401,7 +401,7 @@ static Status tokenize_file(Tokenizer *t, File *file) { n->floatval = (Floating)n->intval; tokr_nextchar(t); continue; - } else if (*t->s == 'e') { + } else if (*t->s == 'e' && base != 16) { tokr_nextchar(t); if (n->kind == NUM_LITERAL_INT) { n->kind = NUM_LITERAL_FLOAT; @@ -436,7 +436,7 @@ static Status tokenize_file(Tokenizer *t, File *file) { if (*t->s >= 'a' && *t->s <= 'f') digit = 10 + *t->s - 'a'; else if (*t->s >= 'A' && *t->s <= 'F') - digit = *t->s - 'A'; + digit = 10 + *t->s - 'A'; } if (digit == -1) { if (*t->s >= '0' && *t->s <= '9') |