From cb1a634e495c6f2e3ebd90f25235c6f7d2d639b7 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sun, 3 May 2020 12:37:28 -0400 Subject: turns out __cdecl is only for 32-bit. now everything works except for 64-bit arguments --- .gitignore | 7 ++ eval.c | 4 +- foreign_msvc.c | 276 ---------------------------------------------------- foreign_msvc32.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ test.toc | 22 ++++- toc.c | 2 +- types.c | 2 +- 7 files changed, 318 insertions(+), 282 deletions(-) delete mode 100644 foreign_msvc.c create mode 100644 foreign_msvc32.c diff --git a/.gitignore b/.gitignore index 5b905a2..3b26d1a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,10 @@ std/*.o *.so README.html docs/*.html +*.dll +*.exp +*.lib +*.pdb +*.ilk +*.obj +*.exe diff --git a/eval.c b/eval.c index 01f7625..4b7dc40 100644 --- a/eval.c +++ b/eval.c @@ -211,7 +211,7 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { } break; case TYPE_ARR: { fprintf(f, "["); /* @TODO: change? when array initializers are added */ - size_t n = t->arr.n; + size_t n = (size_t)t->arr.n; if (n > 5) n = 5; for (size_t i = 0; i < n; ++i) { if (i) fprintf(f, ", "); @@ -1002,7 +1002,7 @@ static Value val_zero(Type *t) { val.struc = err_calloc(1, compiler_sizeof(t)); break; case TYPE_ARR: - val.arr = err_calloc(t->arr.n, compiler_sizeof(t->arr.of)); + val.arr = err_calloc((size_t)t->arr.n, compiler_sizeof(t->arr.of)); break; default: break; diff --git a/foreign_msvc.c b/foreign_msvc.c deleted file mode 100644 index f78f275..0000000 --- a/foreign_msvc.c +++ /dev/null @@ -1,276 +0,0 @@ -/* -this code is not standard-compliant in the slightest, and a bit dubious, -but I don't think there's any other way that doesn't involve inline assembly -*/ - -#include - -typedef size_t Word; - -typedef struct { - HMODULE handle; -} Library; - - -static Status val_to_word(Value v, Type *t, Location where, Word *w) { - switch (t->kind) { - case TYPE_BUILTIN: - switch (t->builtin) { - case BUILTIN_I8: *w = (Word)v.i8; break; - case BUILTIN_I16: *w = (Word)v.i16; break; - case BUILTIN_I32: *w = (Word)v.i32; break; - case BUILTIN_I64: *w = (Word)v.i64; break; - case BUILTIN_U8: *w = (Word)v.u8; break; - case BUILTIN_U16: *w = (Word)v.u16; break; - case BUILTIN_U32: *w = (Word)v.u32; break; - case BUILTIN_U64: *w = (Word)v.u64; break; - case BUILTIN_F32: *w = (Word)*(uint32_t *)&v.f32; break; - case BUILTIN_F64: *w = (Word)*(uint64_t *)&v.f64; break; - case BUILTIN_CHAR: *w = (Word)v.charv; break; - case BUILTIN_BOOL: *w = (Word)v.boolv; break; - case BUILTIN_TYPE: - case BUILTIN_VARARGS: - case BUILTIN_NMS: - case BUILTIN_VOID: - goto unsupported; - } - break; - case TYPE_PTR: - *w = (Word)v.ptr; break; - default: - unsupported: { - /* @TODO(eventually) */ - char *s = type_to_str(t); - err_print(where, "#foreign functions can't take arguments of type %s at compile time on Windows.", s); - free(s); - return false; - } - } - return true; -} - - -/* -because of the way the MSVC "cdecl" calling convention works, the only things that affect the way a function is called are -the number of arguments and whether the function returns an integer (or pointer), floating-point number, -or struct (struct return values are not supported yet). - -this means we can get away with these twenty functions--GCC passes most arguments in registers, so there would need to be -a lot more functions to support different combinations of integer and floating-point arguments (since they use different -registers) -*/ - -/* call function with 0 arguments, returning some sort of integer (or pointer) */ -static Word msvc_call0i(FnPtr fn, Word *w) { - (void)w; - return ((Word(*)(void))fn)(); -} -static Word msvc_call1i(FnPtr fn, Word *w) { - return ((Word(*)(Word))fn)(w[0]); -} -static Word msvc_call2i(FnPtr fn, Word *w) { - return ((Word(*)(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 Word msvc_call4i(FnPtr fn, Word *w) { - return ((Word(*)(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 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 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 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 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 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 Word (*const msvc_calli[11])(FnPtr fn, Word *w) = { - msvc_call0i, - msvc_call1i, - msvc_call2i, - msvc_call3i, - msvc_call4i, - msvc_call5i, - msvc_call6i, - msvc_call7i, - msvc_call8i, - msvc_call9i, - msvc_call10i -}; - - -/* call function with 0 arguments, returning a float or double */ -static double msvc_call0f(FnPtr fn, Word *w) { - (void)w; - return ((double(*)(void))fn)(); -} -static double msvc_call1f(FnPtr fn, Word *w) { - return ((double(*)(Word))fn)(w[0]); -} -static double msvc_call2f(FnPtr fn, Word *w) { - return ((double(*)(Word, Word))fn)(w[0], w[1]); -} -static double msvc_call3f(FnPtr fn, Word *w) { - return ((double(*)(Word, Word, Word))fn)(w[0], w[1], w[2]); -} -static double msvc_call4f(FnPtr fn, Word *w) { - return ((double(*)(Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3]); -} -static double msvc_call5f(FnPtr fn, Word *w) { - return ((double(*)(Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4]); -} -static double msvc_call6f(FnPtr fn, Word *w) { - return ((double(*)(Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5]); -} -static double msvc_call7f(FnPtr fn, Word *w) { - return ((double(*)(Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6]); -} -static double msvc_call8f(FnPtr fn, Word *w) { - return ((double(*)(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 double msvc_call9f(FnPtr fn, Word *w) { - return ((double(*)(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 double msvc_call10f(FnPtr fn, Word *w) { - return ((double(*)(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 double (*const msvc_callf[11])(FnPtr fn, Word *w) = { - msvc_call0f, - msvc_call1f, - msvc_call2f, - msvc_call3f, - msvc_call4f, - msvc_call5f, - msvc_call6f, - msvc_call7f, - msvc_call8f, - msvc_call9f, - msvc_call10f -}; - -static Status foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *ret_type, Type *arg_types, size_t arg_types_stride, Value *args, size_t nargs, Location call_where, Value *ret) { - possibly_static_assert(sizeof(double) == 8); - possibly_static_assert(sizeof(float) == 4); - FnPtr fn_ptr = fn->foreign.fn_ptr; - if (!fn_ptr) { - assert(fn->flags & FN_EXPR_FOREIGN); - char const *libname = fn->foreign.lib; - if (!libname) { - err_print(call_where, "Attempt to call function at compile time which does not have an associated library."); - info_print(fn->where, "Function was declared here."); - return false; - } - Library *lib = str_hash_table_get(&ffmgr->libs_loaded, libname, strlen(libname)); - if (!lib) { - HMODULE handle = LoadLibraryA(libname); - if (!handle) { - DWORD err = GetLastError(); - err_print(call_where, "Could not open dynamic library %s (error code %ld).", libname, err); - return false; - } - lib = str_hash_table_insert(&ffmgr->libs_loaded, libname, strlen(libname)); - lib->handle = handle; - } - const char *name = fn->foreign.name; - fn_ptr = (FnPtr)GetProcAddress(lib->handle, name); - if (!fn_ptr) { - err_print(call_where, "Could not get function %s from dynamic library.", name); - return false; - } - fn->foreign.fn_ptr = fn_ptr; - } - Word words[10]; - char *type = (char *)arg_types; - for (size_t i = 0; i < nargs; ++i) { - val_to_word(args[i], (Type *)type, call_where, &words[i]); - type += arg_types_stride; - } - bool is_float = false; - switch (ret_type->kind) { - case TYPE_BUILTIN: - switch (ret_type->builtin) { - case BUILTIN_I8: - case BUILTIN_I16: - case BUILTIN_I32: - case BUILTIN_I64: - case BUILTIN_U8: - case BUILTIN_U16: - case BUILTIN_U32: - case BUILTIN_U64: - case BUILTIN_BOOL: - case BUILTIN_CHAR: - case BUILTIN_VOID: - break; - case BUILTIN_F32: - case BUILTIN_F64: - is_float = true; - break; - default: - goto unsupported; - } - break; - case TYPE_PTR: - break; - default: - unsupported: { - char *s = type_to_str(ret_type); - /* @TODO(eventually) */ - err_print(call_where, "You can't call functions which return type %s at compile time on Windows.", s); - free(s); - return false; - } - } - - 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); - assert(ret_type->kind == TYPE_BUILTIN); - if (ret_type->builtin == BUILTIN_F32) { - U64 lower_bits = (U32)*(U64 *)&d; - ret->f32 = *(float *)&lower_bits; - } else { - assert(ret_type->builtin == BUILTIN_F64); - ret->f64 = d; - } - } else { - Word w = msvc_calli[nargs](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; - default: assert(0); break; - } - break; - case TYPE_PTR: - ret->ptr = (void *)w; - break; - default: assert(0); break; - } - } - return true; -} diff --git a/foreign_msvc32.c b/foreign_msvc32.c new file mode 100644 index 0000000..d1b38e0 --- /dev/null +++ b/foreign_msvc32.c @@ -0,0 +1,287 @@ +/* +this code is not standard-compliant in the slightest, and a bit dubious, +but I don't think there's any other way that doesn't involve inline assembly +*/ + +#include + +typedef size_t Word; + +#if SIZE_MAX != U32_MAX +/* +@TODO +x64 has its own calling convention +*/ +#error "Calling #foreign functitons at compile time only works on 32-bit Windows, not 64-bit." +#endif + +typedef struct { + HMODULE handle; +} Library; + +/* f64s take 2 words */ +static Status val_to_words(Value v, Type *t, Location where, Word *w) { + switch (t->kind) { + case TYPE_BUILTIN: + switch (t->builtin) { + case BUILTIN_I8: *w = (Word)v.i8; break; + case BUILTIN_I16: *w = (Word)v.i16; break; + case BUILTIN_I32: *w = (Word)v.i32; break; + case BUILTIN_U8: *w = (Word)v.u8; break; + case BUILTIN_U16: *w = (Word)v.u16; break; + case BUILTIN_U32: *w = (Word)v.u32; break; + case BUILTIN_F32: *w = (Word)*(U32 *)&v.f32; break; + case BUILTIN_I64: + case BUILTIN_U64: + case BUILTIN_F64: { + Word *ws = (Word *)&v; + w[0] = ws[0]; + w[1] = ws[1]; + } break; + case BUILTIN_CHAR: *w = (Word)v.charv; break; + case BUILTIN_BOOL: *w = (Word)v.boolv; break; + case BUILTIN_TYPE: + case BUILTIN_VARARGS: + case BUILTIN_NMS: + case BUILTIN_VOID: + goto unsupported; + } + break; + case TYPE_PTR: + *w = (Word)v.ptr; break; + default: + unsupported: { + /* @TODO(eventually) */ + char *s = type_to_str(t); + err_print(where, "#foreign functions can't take arguments of type %s at compile time on Windows.", s); + free(s); + return false; + } + } + return true; +} + + +/* +because of the way the MSVC "cdecl" calling convention works, the only things that affect the way a function is called are +the number of arguments and whether the function returns an integer (or pointer), floating-point number, +or struct (struct return values are not supported yet). + +this means we can get away with these twenty functions--GCC/MSVC x64 pass most arguments in registers, so there would need to be +a lot more functions to support different combinations of integer and floating-point arguments (since they use different +registers) +*/ + +/* call function with 0 arguments, returning some sort of integer (or pointer) */ +static Word msvc_call0i(FnPtr fn, Word *w) { + (void)w; + return ((Word(*)(void))fn)(); +} +static Word msvc_call1i(FnPtr fn, Word *w) { + return ((Word(*)(Word))fn)(w[0]); +} +static Word msvc_call2i(FnPtr fn, Word *w) { + return ((Word(*)(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 Word msvc_call4i(FnPtr fn, Word *w) { + return ((Word(*)(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 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 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 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 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 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 Word (*const msvc_calli[11])(FnPtr fn, Word *w) = { + msvc_call0i, + msvc_call1i, + msvc_call2i, + msvc_call3i, + msvc_call4i, + msvc_call5i, + msvc_call6i, + msvc_call7i, + msvc_call8i, + msvc_call9i, + msvc_call10i +}; + + +/* call function with 0 arguments, returning a float or double */ +static double msvc_call0f(FnPtr fn, Word *w) { + (void)w; + return ((double(*)(void))fn)(); +} +static double msvc_call1f(FnPtr fn, Word *w) { + return ((double(*)(Word))fn)(w[0]); +} +static double msvc_call2f(FnPtr fn, Word *w) { + return ((double(*)(Word, Word))fn)(w[0], w[1]); +} +static double msvc_call3f(FnPtr fn, Word *w) { + return ((double(*)(Word, Word, Word))fn)(w[0], w[1], w[2]); +} +static double msvc_call4f(FnPtr fn, Word *w) { + return ((double(*)(Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3]); +} +static double msvc_call5f(FnPtr fn, Word *w) { + return ((double(*)(Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4]); +} +static double msvc_call6f(FnPtr fn, Word *w) { + return ((double(*)(Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5]); +} +static double msvc_call7f(FnPtr fn, Word *w) { + return ((double(*)(Word, Word, Word, Word, Word, Word, Word))fn)(w[0], w[1], w[2], w[3], w[4], w[5], w[6]); +} +static double msvc_call8f(FnPtr fn, Word *w) { + return ((double(*)(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 double msvc_call9f(FnPtr fn, Word *w) { + return ((double(*)(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 double msvc_call10f(FnPtr fn, Word *w) { + return ((double(*)(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 double (*const msvc_callf[11])(FnPtr fn, Word *w) = { + msvc_call0f, + msvc_call1f, + msvc_call2f, + msvc_call3f, + msvc_call4f, + msvc_call5f, + msvc_call6f, + msvc_call7f, + msvc_call8f, + msvc_call9f, + msvc_call10f +}; + +static Status foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *ret_type, Type *arg_types, size_t arg_types_stride, Value *args, size_t nargs, Location call_where, Value *ret) { + possibly_static_assert(sizeof(double) == 8); + possibly_static_assert(sizeof(float) == 4); + FnPtr fn_ptr = fn->foreign.fn_ptr; + if (!fn_ptr) { + assert(fn->flags & FN_EXPR_FOREIGN); + char const *libname = fn->foreign.lib; + if (!libname) { + err_print(call_where, "Attempt to call function at compile time which does not have an associated library."); + info_print(fn->where, "Function was declared here."); + return false; + } + Library *lib = str_hash_table_get(&ffmgr->libs_loaded, libname, strlen(libname)); + if (!lib) { + HMODULE handle = LoadLibraryA(libname); + if (!handle) { + DWORD err = GetLastError(); + err_print(call_where, "Could not open dynamic library %s (error code %ld).", libname, err); + return false; + } + lib = str_hash_table_insert(&ffmgr->libs_loaded, libname, strlen(libname)); + lib->handle = handle; + } + const char *name = fn->foreign.name; + fn_ptr = (FnPtr)GetProcAddress(lib->handle, name); + if (!fn_ptr) { + err_print(call_where, "Could not get function %s from dynamic library.", name); + return false; + } + fn->foreign.fn_ptr = fn_ptr; + } + Word words[10]; + char *type = (char *)arg_types; + for (size_t i = 0; i < nargs; ++i) { + val_to_words(args[i], (Type *)type, call_where, &words[i]); + type += arg_types_stride; + } + bool is_float = false; + switch (ret_type->kind) { + case TYPE_BUILTIN: + switch (ret_type->builtin) { + case BUILTIN_I8: + case BUILTIN_I16: + case BUILTIN_I32: + case BUILTIN_I64: + case BUILTIN_U8: + case BUILTIN_U16: + case BUILTIN_U32: + case BUILTIN_U64: + case BUILTIN_BOOL: + case BUILTIN_CHAR: + case BUILTIN_VOID: + break; + case BUILTIN_F32: + case BUILTIN_F64: + is_float = true; + break; + default: + goto unsupported; + } + break; + case TYPE_PTR: + break; + default: + unsupported: { + char *s = type_to_str(ret_type); + /* @TODO(eventually) */ + err_print(call_where, "You can't call functions which return type %s at compile time on Windows.", s); + free(s); + return false; + } + } + + 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); + assert(ret_type->kind == TYPE_BUILTIN); + if (ret_type->builtin == BUILTIN_F32) { + ret->f32 = (F32)d; /* turns out functions just always return doubles */ + } else { + assert(ret_type->builtin == BUILTIN_F64); + ret->f64 = d; + } + } else { + Word w = msvc_calli[nargs](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; + default: assert(0); break; + } + break; + case TYPE_PTR: + ret->ptr = (void *)w; + break; + default: assert(0); break; + } + } + return true; +} diff --git a/test.toc b/test.toc index 44917ac..f9d135c 100644 --- a/test.toc +++ b/test.toc @@ -1,3 +1,5 @@ +/* + stdc ::= "msvcrt.dll"; printf ::= #foreign("printf",stdc) fn (#C &"char const", #C ..) #C int; puti ::= fn(i: i32) i32 { @@ -5,9 +7,25 @@ puti ::= fn(i: i32) i32 { printf(&fmt[0], i) as i32 } // BUG: puti(puti(x)) -sqrtf ::= #foreign("sqrt",stdc) fn(f64) f64; +//sqrt ::= #foreign("sqrt",stdc) fn(f64) f64; +sqrtf ::= #foreign("sinf",stdc) fn(f32) f32; +/* +putf ::= fn(f: f64) i32 { + fmt := "number: %f\n\0"; + printf(&fmt[0], f) as i32 +} +*/ main ::= fn() { - f ::= sqrtf(2.0); + sqrtf(3.1); } 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/toc.c b/toc.c index bebb9b1..7069205 100644 --- a/toc.c +++ b/toc.c @@ -135,7 +135,7 @@ static Location token_location(File *file, Token *t); #if COMPILE_TIME_FOREIGN_FN_SUPPORT #if defined _MSC_VER && !defined COMPILE_TIME_FOREIGN_FN_AVCALL -#include "foreign_msvc.c" +#include "foreign_msvc32.c" #else #include "foreign_avcall.c" #endif diff --git a/types.c b/types.c index 1001e07..7dbfff6 100644 --- a/types.c +++ b/types.c @@ -264,7 +264,7 @@ static size_t compiler_sizeof(Type *t) { case TYPE_PTR: return sizeof v.ptr; case TYPE_ARR: - return t->arr.n * compiler_sizeof(t->arr.of); + return (size_t)t->arr.n * compiler_sizeof(t->arr.of); case TYPE_TUPLE: return sizeof v.tuple; case TYPE_SLICE: -- cgit v1.2.3