Skip to content

Commit

Permalink
basic C interface, supporting int and float types
Browse files Browse the repository at this point in the history
adding dlopen and dlsym functions, Pointer{T} julia type
  • Loading branch information
JeffBezanson committed May 14, 2010
1 parent d50bc5d commit 18f4562
Show file tree
Hide file tree
Showing 7 changed files with 377 additions and 20 deletions.
4 changes: 2 additions & 2 deletions 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)
Expand All @@ -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)
Expand Down
34 changes: 34 additions & 0 deletions alloc.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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");
Expand Down
61 changes: 54 additions & 7 deletions builtins.c
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)));
}
146 changes: 146 additions & 0 deletions dlload.c
@@ -0,0 +1,146 @@
#include <stdlib.h>
#include <string.h>

#ifdef WIN32
#include <malloc.h>
#include <windows.h>
#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 <unistd.h>
#include <dlfcn.h>
#define GET_FUNCTION_FROM_MODULE dlsym
#define CLOSE_MODULE dlclose
typedef void * module_handle_t;
#define EXTENSION ".so"

#elif defined(MACOSX) || defined(MACINTEL)
#include <unistd.h>
#include <dlfcn.h>
#define GET_FUNCTION_FROM_MODULE dlsym
#define CLOSE_MODULE dlclose
typedef void * module_handle_t;
#define EXTENSION ".bundle"

#endif

#ifdef BOEHM_GC
#include <gc.h>
#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;
}
7 changes: 6 additions & 1 deletion interpreter.c
Expand Up @@ -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*));
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 18f4562

Please sign in to comment.