From 18f456233b280f2b5649c033c1977133c73bfd88 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 14 May 2010 01:39:57 -0400 Subject: [PATCH] basic C interface, supporting int and float types adding dlopen and dlsym functions, Pointer{T} julia type --- Makefile | 4 +- alloc.c | 34 ++++++++++++ builtins.c | 61 ++++++++++++++++++--- dlload.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ interpreter.c | 7 ++- intrinsics.cpp | 130 ++++++++++++++++++++++++++++++++++++++++--- julia.h | 15 ++++- 7 files changed, 377 insertions(+), 20 deletions(-) create mode 100644 dlload.c diff --git a/Makefile b/Makefile index 4576b22d779c9..f2630ba15f9ee 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ NAME = julia -SRCS = jltypes gf ast repl builtins module codegen interpreter alloc +SRCS = jltypes gf ast repl builtins module codegen interpreter alloc dlload OBJS = $(SRCS:%=%.o) DOBJS = $(SRCS:%=%.do) EXENAME = $(NAME) @@ -12,7 +12,7 @@ include ./Make.inc.$(shell uname) FLAGS = -falign-functions -Wall -Wno-strict-aliasing -I$(FLISPDIR) -I$(LLTDIR) $(HFILEDIRS:%=-I%) $(LIBDIRS:%=-L%) $(CFLAGS) -D___LIBRARY $(CONFIG) -I$(shell llvm-config --includedir) LIBFILES = $(FLISP) $(LLT) -LIBS = $(LIBFILES) -lutil -ldl -lm -lgc $(shell llvm-config --ldflags --libs core engine jit interpreter bitreader) -lreadline $(OSLIBS) +LIBS = $(LIBFILES) -lutil -ldl -lm -lgc $(shell llvm-config --ldflags --libs core engine jit interpreter bitreader) -lreadline $(OSLIBS) -Wl,--export-dynamic DEBUGFLAGS = -ggdb3 -DDEBUG $(FLAGS) SHIPFLAGS = -O3 -DNDEBUG $(FLAGS) diff --git a/alloc.c b/alloc.c index 35661bad2e2e4..b618db20d55fe 100644 --- a/alloc.c +++ b/alloc.c @@ -34,6 +34,10 @@ jl_bits_type_t *jl_intrinsic_type; jl_struct_type_t *jl_methtable_type; jl_struct_type_t *jl_lambda_info_type; +jl_typector_t *jl_pointer_typector; +jl_bits_type_t *jl_pointer_void_type; +jl_bits_type_t *jl_pointer_uint8_type; + jl_sym_t *call_sym; jl_sym_t *dots_sym; jl_sym_t *dollar_sym; jl_sym_t *quote_sym; jl_sym_t *tuple_sym; jl_sym_t *top_sym; @@ -461,6 +465,19 @@ UNBOX_FUNC(bool, int8_t) UNBOX_FUNC(float32, float) UNBOX_FUNC(float64, double) +jl_value_t *jl_box_pointer(jl_bits_type_t *ty, void *p) +{ + jl_value_t *v = newobj((jl_type_t*)ty, 1); + *(void**)jl_bits_data(v) = p; + return v; +} + +void *jl_unbox_pointer(jl_value_t *v) +{ + assert(jl_is_cpointer(v)); + return *(void**)jl_bits_data(v); +} + // array constructors --------------------------------------------------------- jl_array_t *jl_new_array(jl_type_t *atype, jl_value_t **dimargs, size_t ndims) @@ -608,6 +625,23 @@ void jl_init_builtin_types() jl_intrinsic_type = jl_new_bitstype((jl_value_t*)jl_symbol("IntrinsicFunction"), jl_any_type, jl_null, 32); + tv = jl_typevars(1, "T"); + jl_bits_type_t *cptrbits = + jl_new_bitstype((jl_value_t*)jl_symbol("Pointer"), jl_any_type, tv, +#ifdef BITS64 + 64 +#else + 32 +#endif + ); + jl_pointer_typector = jl_new_type_ctor(tv, (jl_type_t*)cptrbits); + jl_pointer_void_type = + (jl_bits_type_t*)jl_apply_type_ctor(jl_pointer_typector, + jl_tuple(1, jl_bottom_type)); + jl_pointer_uint8_type = + (jl_bits_type_t*)jl_apply_type_ctor(jl_pointer_typector, + jl_tuple(1, jl_uint8_type)); + call_sym = jl_symbol("call"); quote_sym = jl_symbol("quote"); top_sym = jl_symbol("top"); diff --git a/builtins.c b/builtins.c index 9edcb366c58b9..a3ce931314961 100644 --- a/builtins.c +++ b/builtins.c @@ -78,7 +78,7 @@ jl_expr_t *jl_exprn(jl_sym_t *head, size_t n) ex->type = (jl_type_t*)jl_expr_type; ex->head = head; ex->args = jl_alloc_tuple(n); - ex->etype = jl_any_type; + ex->etype = (jl_type_t*)jl_any_type; return ex; } @@ -206,7 +206,7 @@ void jl_load(const char *fname) else { //jl_toplevel_eval(form); jl_lambda_info_t *lam = (jl_lambda_info_t*)jl_exprarg(form,0); - (void)jl_interpret_toplevel_expr(lam); + (void)jl_interpret_toplevel_thunk(lam); } } } @@ -222,13 +222,11 @@ void jl_load(const char *fname) JL_CALLABLE(jl_f_load) { JL_NARGS(load, 1, 1); - if (jl_typeof(args[0]) == jl_array_uint8_type) { - char *fname = (char*)((jl_array_t*)args[0])->data; - jl_load(fname); - } - else { + if (jl_typeof(args[0]) != jl_array_uint8_type) { jl_error("load: expected string"); } + char *fname = (char*)((jl_array_t*)args[0])->data; + jl_load(fname); return (jl_value_t*)jl_null; } @@ -700,6 +698,22 @@ INT_PRINT_FUNC(uint,32) INT_PRINT_FUNC(int,64) INT_PRINT_FUNC(uint,64) +JL_CALLABLE(jl_f_print_pointer) +{ + ios_t *s = current_output_stream; + void *ptr = *(void**)jl_bits_data(args[0]); + if (jl_typeis(args[0],jl_pointer_void_type)) + ios_printf(s, "Pointer{Void}"); + else + jl_print((jl_value_t*)jl_typeof(args[0])); +#ifdef BITS64 + ios_printf(s, " @0x%016x", (uptrint_t)ptr); +#else + ios_printf(s, " @0x%08x", (uptrint_t)ptr); +#endif + return (jl_value_t*)jl_null; +} + JL_CALLABLE(jl_f_print_symbol) { ios_t *s = current_output_stream; @@ -1036,6 +1050,31 @@ JL_CALLABLE(jl_f_invoke) return jl_apply(ml->func, &args[2], nargs-2); } +// --- c interface --- + +JL_CALLABLE(jl_f_dlopen) +{ + JL_NARGS(dlopen, 1, 1); + if (jl_typeof(args[0]) != jl_array_uint8_type) { + jl_error("dlopen: expected string"); + } + char *fname = (char*)((jl_array_t*)args[0])->data; + return jl_box_pointer(jl_pointer_void_type, + jl_load_dynamic_library(fname)); +} + +JL_CALLABLE(jl_f_dlsym) +{ + JL_NARGS(dlsym, 2, 2); + JL_TYPECHK(dlsym, cpointer, args[0]); + if (jl_typeof(args[1]) != jl_array_uint8_type) { + jl_error("dlsym: expected string"); + } + void *hnd = jl_unbox_pointer(args[0]); + char *sym = (char*)((jl_array_t*)args[1])->data; + return jl_box_pointer(jl_pointer_void_type, jl_dlsym(hnd, sym)); +} + // --- init --- static void add_builtin_method1(jl_function_t *gf, jl_type_t *t, jl_fptr_t f) @@ -1074,6 +1113,7 @@ void jl_init_builtins() add_builtin_method1(jl_print_gf, (jl_type_t*)jl_int64_type, jl_f_print_int64); add_builtin_method1(jl_print_gf, (jl_type_t*)jl_uint64_type, jl_f_print_uint64); add_builtin_method1(jl_print_gf, (jl_type_t*)jl_bool_type, jl_f_print_bool); + add_builtin_method1(jl_print_gf, (jl_type_t*)jl_unconstrained_type(jl_pointer_typector), jl_f_print_pointer); current_output_stream = ios_stdout; @@ -1095,6 +1135,8 @@ void jl_init_builtins() add_builtin_func("time_thunk", jl_f_time_thunk); add_builtin_func("method_exists", jl_f_methodexists); add_builtin_func("invoke", jl_f_invoke); + add_builtin_func("dlopen", jl_f_dlopen); + add_builtin_func("dlsym", jl_f_dlsym); add_builtin("convert", (jl_value_t*)jl_convert_gf); add_builtin("print", (jl_value_t*)jl_print_gf); add_builtin("identity", (jl_value_t*)jl_identity_func); @@ -1123,6 +1165,7 @@ void jl_init_builtins() // builtin types add_builtin("Any", (jl_value_t*)jl_any_type); add_builtin("Bottom", (jl_value_t*)jl_bottom_type); + add_builtin("Void", (jl_value_t*)jl_bottom_type); add_builtin("TypeVar", (jl_value_t*)jl_tvar_type); add_builtin("Tuple", (jl_value_t*)jl_tuple_type); add_builtin("NTuple", (jl_value_t*)jl_ntuple_type); @@ -1152,10 +1195,14 @@ void jl_init_builtins() add_builtin("Expr", (jl_value_t*)jl_new_type_ctor(jl_null, (jl_type_t*)jl_expr_type)); + add_builtin("Pointer", (jl_value_t*)jl_pointer_typector); add_builtin("BitsKind", (jl_value_t*)jl_bits_kind); add_builtin("StructKind", (jl_value_t*)jl_struct_kind); add_builtin("FuncKind", (jl_value_t*)jl_func_kind); add_builtin("TagKind", (jl_value_t*)jl_tag_kind); add_builtin("UnionKind", (jl_value_t*)jl_union_kind); + + add_builtin("JuliaDLHandle", jl_box_pointer(jl_pointer_void_type, + jl_load_dynamic_library(NULL))); } diff --git a/dlload.c b/dlload.c new file mode 100644 index 0000000000000..dee9374b6d512 --- /dev/null +++ b/dlload.c @@ -0,0 +1,146 @@ +#include +#include + +#ifdef WIN32 +#include +#include +#undef TRUE +#undef FALSE +#undef VOID +#define GET_FUNCTION_FROM_MODULE GetProcAddress +#define CLOSE_MODULE FreeLibrary +typedef HINSTANCE module_handle_t; +#define EXTENSION ".dll" + +#elif defined(LINUX) +#include +#include +#define GET_FUNCTION_FROM_MODULE dlsym +#define CLOSE_MODULE dlclose +typedef void * module_handle_t; +#define EXTENSION ".so" + +#elif defined(MACOSX) || defined(MACINTEL) +#include +#include +#define GET_FUNCTION_FROM_MODULE dlsym +#define CLOSE_MODULE dlclose +typedef void * module_handle_t; +#define EXTENSION ".bundle" + +#endif + +#ifdef BOEHM_GC +#include +#endif +#include "llt.h" +#include "julia.h" + +#define PATHBUF 512 + +#ifdef WIN32 +#define STDCALL __stdcall +#else +#define STDCALL +#endif + +extern char *julia_home; + +void *jl_load_dynamic_library(char *fname) +{ + module_handle_t handle; + char *modname; + char path[PATHBUF]; + path[0] = '\0'; +#ifdef WIN32 + LPVOID lpMsgBuf; + DWORD dw; +#endif + + modname = fname; +#ifndef WIN32 + if (modname == NULL) { + return (void*)dlopen(NULL, RTLD_NOW); + } + char *cwd; + + /* first, try load from current directory */ + if (modname[0] != '/') { + cwd = getcwd(path, PATHBUF); + if (cwd == NULL) + return NULL; + strncat(path, "/", PATHBUF-1-strlen(path)); + strncat(path, modname, PATHBUF-1-strlen(path)); + + handle = dlopen(path, RTLD_NOW); + if (handle == NULL) { + /* try julia home */ + if (julia_home) { + strncpy(path, julia_home, PATHBUF-1); + strncat(path, "/", PATHBUF-1-strlen(path)); + strncat(path, modname, PATHBUF-1-strlen(path)); + handle = dlopen(path, RTLD_NOW); + } + if (handle == NULL) { + //ios_printf(ios_stderr, "%s\n", dlerror()); + /* try loading from standard library path */ + handle = dlopen(modname, RTLD_NOW); + if (handle == NULL) { + ios_printf(ios_stderr, "%s\n", dlerror()); + jl_errorf("could not load module %s", fname); + } + } + } + } + else { + handle = dlopen(modname, RTLD_NOW); + if (handle == NULL) { + ios_printf(ios_stderr, "%s\n", dlerror()); + jl_errorf("could not load module %s", fname); + } + } +#else + if (modname == NULL) { + return (void*)GetModuleHandle(NULL); + } + handle = LoadLibrary(modname); + if (handle == NULL) { + if (julia_home) { + strncpy(path, julia_home, PATHBUF-1); + strncat(path, "\\", PATHBUF-1-strlen(path)); + strncat(path, modname, PATHBUF-1-strlen(path)); + handle = LoadLibrary(path); + } + if (handle == NULL) { + dw = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + jl_errorf("could not load module %s: (%d) %s", fname, dw, + lpMsgBuf); + } + } +#endif + + return (void*)handle; +} + +void *jl_dlsym(void *handle, char *symbol) +{ +#ifndef WIN32 + (void)dlerror(); + void *ptr = dlsym(handle, symbol); + char *msg = dlerror(); + if (msg != NULL) { + jl_errorf("dlsym: %s", msg); + } + return ptr; +#else + void *ptr = GET_FUNCTION_FROM_MODULE(handle, symbol); +#endif + return ptr; +} diff --git a/interpreter.c b/interpreter.c index 0ed33e7a8f8f3..41ef1028c9826 100644 --- a/interpreter.c +++ b/interpreter.c @@ -16,6 +16,11 @@ static jl_value_t *eval(jl_value_t *e); +jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e) +{ + return eval(e); +} + static jl_value_t *do_call(jl_function_t *f, jl_value_t **args, size_t nargs) { jl_value_t **argv = alloca(nargs * sizeof(jl_value_t*)); @@ -81,7 +86,7 @@ static int label_idx(jl_value_t *tgt, jl_tuple_t *stmts) return j; } -jl_value_t *jl_interpret_toplevel_expr(jl_lambda_info_t *lam) +jl_value_t *jl_interpret_toplevel_thunk(jl_lambda_info_t *lam) { jl_expr_t *ast = (jl_expr_t*)lam->ast; jl_tuple_t *stmts = jl_lam_body(ast); diff --git a/intrinsics.cpp b/intrinsics.cpp index 2381239d92beb..fb091d3093dcd 100644 --- a/intrinsics.cpp +++ b/intrinsics.cpp @@ -20,6 +20,8 @@ namespace JL_I { fptrunc32, fpext64, // functions sqrt_float, powi_float, sin_float, cos_float, pow_float, + // c interface + ccall, }; }; @@ -35,6 +37,7 @@ static Function *box_int64_func; static Function *box_uint64_func; static Function *box_float32_func; static Function *box_float64_func; +static Function *box_pointer_func; /* low-level intrinsics design: @@ -63,12 +66,51 @@ static Value *mark_unsigned(Value *v) return x; } +static const Type *julia_type_to_llvm(jl_value_t *jt) +{ + if (jt == (jl_value_t*)jl_int8_type || jt == (jl_value_t*)jl_uint8_type) return T_int8; + if (jt == (jl_value_t*)jl_int16_type || jt == (jl_value_t*)jl_uint16_type) return T_int16; + if (jt == (jl_value_t*)jl_int32_type || jt == (jl_value_t*)jl_uint32_type) return T_int32; + if (jt == (jl_value_t*)jl_int64_type || jt == (jl_value_t*)jl_uint64_type) return T_int64; + if (jt == (jl_value_t*)jl_float32_type) return T_float32; + if (jt == (jl_value_t*)jl_float64_type) return T_float64; + if (jt == (jl_value_t*)jl_bottom_type) return T_void; + if (jl_is_bits_type(jt) && jl_is_cpointer_type(jt)) { + const Type *lt = julia_type_to_llvm(jl_tparam0(jt)); + return PointerType::get(lt, 0); + } + jl_errorf("cannot convert type %s to a native type", + jl_print_to_string(jt)); + return NULL; +} + +static jl_value_t *llvm_type_to_julia(const Type *t) +{ + if (t == T_int8) return (jl_value_t*)jl_int8_type; + if (t == T_int16) return (jl_value_t*)jl_int16_type; + if (t == T_int32) return (jl_value_t*)jl_int32_type; + if (t == T_int64) return (jl_value_t*)jl_int64_type; + if (t == T_float32) return (jl_value_t*)jl_float32_type; + if (t == T_float64) return (jl_value_t*)jl_float64_type; + if (t == T_void) return (jl_value_t*)jl_bottom_type; + if (t->isPointerTy()) { + jl_value_t *elty = llvm_type_to_julia(t->getContainedType(0)); + return (jl_value_t*)jl_apply_type_ctor(jl_pointer_typector, + jl_tuple(1, elty)); + } + jl_errorf("cannot convert type %s to a julia type", + t->getDescription().c_str()); + return NULL; +} + // this is used to wrap values for generic contexts, where a // dynamically-typed value is required (e.g. argument to unknown function). // if it's already a pointer it's left alone. static Value *boxed(Value *v) { const Type *t = v->getType(); + if (t == jl_pvalue_llvmt) + return v; if (is_unsigned(v)) { if (t == T_int8) return builder.CreateCall(box_uint8_func, v); if (t == T_int16) return builder.CreateCall(box_uint16_func, v); @@ -83,7 +125,68 @@ static Value *boxed(Value *v) if (t == T_float32) return builder.CreateCall(box_float32_func, v); if (t == T_float64) return builder.CreateCall(box_float64_func, v); } - return v; + if (t->isPointerTy()) { + jl_value_t *jt = llvm_type_to_julia(t); + return builder.CreateCall2(box_pointer_func, + literal_pointer_val(jt), v); + } + assert("Don't know how to box this type" && false); +} + +static Value *bitstype_pointer(Value *x) +{ + return builder.CreateGEP(builder.CreateBitCast(x, jl_ppvalue_llvmt), + ConstantInt::get(T_int32, 1)); +} + +static Value *julia_to_native(const Type *ty, jl_value_t *jt, Value *jv, + int argn, jl_codectx_t *ctx) +{ + std::stringstream msg; + msg << "ccall: expected "; + msg << std::string(jl_print_to_string(jt)); + msg << " as argument "; + msg << argn; + emit_typecheck(jv, jt, msg.str(), ctx); + Value *p; + p = bitstype_pointer(jv); + return builder.CreateLoad(builder.CreateBitCast(p,PointerType::get(ty,0)), + false); +} + +// ccall(pointer, rettype, (argtypes...), args...) +static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) +{ + JL_NARGSV(ccall, 3); + jl_value_t *ptr = jl_interpret_toplevel_expr(args[1]); + jl_value_t *rt = jl_interpret_toplevel_expr(args[2]); + jl_value_t *at = jl_interpret_toplevel_expr(args[3]); + JL_TYPECHK(ccall, cpointer, ptr); + JL_TYPECHK(ccall, type, rt); + JL_TYPECHK(ccall, tuple, at); + JL_TYPECHK(ccall, type, at); + jl_tuple_t *tt = (jl_tuple_t*)at; + if (tt->length != nargs-3) + jl_error("ccall: wrong number of arguments to C function"); + void *fptr = *(void**)jl_bits_data(ptr); + std::vector fargt(0); + const Type *lrt = julia_type_to_llvm(rt); + size_t i; + for(i=0; i < tt->length; i++) { + fargt.push_back(julia_type_to_llvm(jl_tupleref(tt,i))); + } + Function *llvmf = + Function::Create(FunctionType::get(lrt, fargt, false), + Function::ExternalLinkage, + "ccall_", jl_Module); + jl_ExecutionEngine->addGlobalMapping(llvmf, fptr); + std::vector argvals(0); + for(i=4; i < nargs+1; i++) { + Value *arg = emit_expr(args[i], ctx, true); + argvals.push_back(julia_to_native(fargt[i-4], jl_tupleref(tt,i-4), + arg, i-3, ctx)); + } + return builder.CreateCall(llvmf, argvals.begin(), argvals.end()); } // convert int type to same-size float type @@ -108,6 +211,7 @@ static Value *FP(Value *v) static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, jl_codectx_t *ctx) { + if (f == ccall) return emit_ccall(args, nargs, ctx); if (nargs < 1) jl_error("invalid intrinsic call"); Value *x = emit_expr(args[1], ctx, true); const Type *t = x->getType(); @@ -146,20 +250,16 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, if (t != T_float64) x = builder.CreateBitCast(x, T_float64); return x; HANDLE(unbox8,1) - p = builder.CreateGEP(builder.CreateBitCast(x, jl_ppvalue_llvmt), - ConstantInt::get(T_int32, 1)); + p = bitstype_pointer(x); return builder.CreateLoad(builder.CreateBitCast(p,T_pint8),false); HANDLE(unbox16,1) - p = builder.CreateGEP(builder.CreateBitCast(x, jl_ppvalue_llvmt), - ConstantInt::get(T_int32, 1)); + p = bitstype_pointer(x); return builder.CreateLoad(builder.CreateBitCast(p,T_pint16),false); HANDLE(unbox32,1) - p = builder.CreateGEP(builder.CreateBitCast(x, jl_ppvalue_llvmt), - ConstantInt::get(T_int32, 1)); + p = bitstype_pointer(x); return builder.CreateLoad(builder.CreateBitCast(p,T_pint32),false); HANDLE(unbox64,1) - p = builder.CreateGEP(builder.CreateBitCast(x, jl_ppvalue_llvmt), - ConstantInt::get(T_int32, 1)); + p = bitstype_pointer(x); return builder.CreateLoad(builder.CreateBitCast(p,T_pint64),false); HANDLE(neg_int,1) return builder.CreateSub(ConstantInt::get(t, 0), x); @@ -355,10 +455,22 @@ extern "C" void jl_init_intrinsic_functions() ADD_I(fptrunc32); ADD_I(fpext64); ADD_I(sqrt_float); ADD_I(powi_float); ADD_I(pow_float); ADD_I(sin_float); ADD_I(cos_float); + ADD_I(ccall); BOX_F(int8); BOX_F(uint8); BOX_F(int16); BOX_F(uint16); BOX_F(int32); BOX_F(uint32); BOX_F(int64); BOX_F(uint64); BOX_F(float32); BOX_F(float64); + + std::vector boxpointerargs(0); + boxpointerargs.push_back(jl_pvalue_llvmt); + boxpointerargs.push_back(T_pint8); + box_pointer_func = + Function::Create(FunctionType::get(jl_pvalue_llvmt, + boxpointerargs, false), + Function::ExternalLinkage, "jl_box_pointer", + jl_Module); + jl_ExecutionEngine->addGlobalMapping(box_pointer_func, + (void*)&jl_box_pointer); } diff --git a/julia.h b/julia.h index 0e11a44e96172..986472cca3b2a 100644 --- a/julia.h +++ b/julia.h @@ -211,6 +211,10 @@ extern jl_bits_type_t *jl_uint64_type; extern jl_bits_type_t *jl_float32_type; extern jl_bits_type_t *jl_float64_type; +extern jl_typector_t *jl_pointer_typector; +extern jl_bits_type_t *jl_pointer_void_type; +extern jl_bits_type_t *jl_pointer_uint8_type; + extern jl_type_t *jl_array_uint8_type; extern jl_type_t *jl_array_any_type; extern jl_struct_type_t *jl_expr_type; @@ -300,6 +304,8 @@ extern jl_sym_t *closure_ref_sym; #define jl_is_function(v) (jl_is_func_type(jl_typeof(v))) #define jl_is_array(v) (((jl_tag_type_t*)jl_typeof(v))->name==jl_array_typename) #define jl_is_box(v) (((jl_tag_type_t*)jl_typeof(v))->name==jl_box_typename) +#define jl_is_cpointer_type(v) (((jl_tag_type_t*)(v))->name==jl_pointer_void_type->name) +#define jl_is_cpointer(v) jl_is_cpointer_type(jl_typeof(v)) #define jl_is_gf(f) (((jl_function_t*)(f))->fptr==jl_apply_generic) #define jl_gf_mtable(f) ((jl_methtable_t*)jl_t0(((jl_function_t*)(f))->env)) @@ -388,6 +394,8 @@ int64_t jl_unbox_int64(jl_value_t *v); uint64_t jl_unbox_uint64(jl_value_t *v); float jl_unbox_float32(jl_value_t *v); double jl_unbox_float64(jl_value_t *v); +jl_value_t *jl_box_pointer(jl_bits_type_t *ty, void *p); +void *jl_unbox_pointer(jl_value_t *v); // exceptions void jl_error(const char *str); @@ -429,11 +437,16 @@ jl_module_t *jl_add_module(jl_module_t *m, jl_module_t *child); jl_module_t *jl_get_module(jl_module_t *m, jl_sym_t *name); jl_module_t *jl_import_module(jl_module_t *to, jl_module_t *from); +// external libraries +void *jl_load_dynamic_library(char *fname); +void *jl_dlsym(void *handle, char *symbol); + // compiler void jl_compile(jl_lambda_info_t *li); jl_value_t *jl_toplevel_eval(jl_value_t *ast); void jl_load(const char *fname); -jl_value_t *jl_interpret_toplevel_expr(jl_lambda_info_t *lam); +jl_value_t *jl_interpret_toplevel_thunk(jl_lambda_info_t *lam); +jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e); void jl_print_method_table(jl_function_t *gf); jl_function_t *jl_instantiate_method(jl_function_t *f, jl_tuple_t *sp);