diff --git a/src/ccall.cpp b/src/ccall.cpp index 4e4ee59dbdcc7..367b9fd015533 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -715,7 +715,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) builder.CreateCall2(jlputs_func, builder.CreateGEP(stringConst(msg.str()), ArrayRef(zeros)), - literal_pointer_val(JL_STDERR)); + literal_pointer_val(JL_STDERR,T_pint8)); } // emit arguments diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 4725c604870ee..5bea3e6791b48 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -48,14 +48,83 @@ static Value *literal_pointer_val(void *p, Type *t) #endif } -static Value *literal_pointer_val(jl_value_t *p) +static std::map jl_value_to_llvm; + +DLLEXPORT extern "C" const char *jl_get_llvm_gv(jl_value_t *p) +{ + std::map::iterator it; + it = jl_value_to_llvm.find(p); + if (it == jl_value_to_llvm.end()) + return NULL; + return it->second->getName().data(); +} + +static Value *julia_to_gv(const char *cname, jl_value_t *addr) { - return literal_pointer_val(p, jl_pvalue_llvmt); + std::map::iterator it; + it = jl_value_to_llvm.find(addr); + if (it != jl_value_to_llvm.end()) + return builder.CreateLoad(it->second); + GlobalValue *gv = new GlobalVariable(*jl_Module, jl_pvalue_llvmt, + false, GlobalVariable::ExternalLinkage, + ConstantPointerNull::get((PointerType*)jl_pvalue_llvmt), cname); + jl_value_t **p = (jl_value_t**)jl_ExecutionEngine->getPointerToGlobal(gv); + *p = addr; + jl_value_to_llvm[addr] = gv; + return builder.CreateLoad(gv); } -static Value *literal_pointer_val(void *p) +static Value *julia_to_gv(jl_value_t *addr) { - return literal_pointer_val(p, T_pint8); + return julia_to_gv("jl_global#", addr); +} + +static Value *julia_to_gv(jl_sym_t *name, jl_module_t *mod, jl_value_t *addr) { + size_t len = strlen(name->name)+1; + jl_module_t *parent = mod, *prev = NULL; + while (parent != NULL && parent != prev) { + len += strlen(parent->name->name)+1; + prev = parent; + parent = parent->parent; + } + char *fullname = (char*)alloca(len); + len -= strlen(name->name)+1; + strcpy(fullname+len,name->name); + parent = mod; + prev = NULL; + while (parent != NULL && parent != prev) { + size_t part = strlen(parent->name->name)+1; + strcpy(fullname+len-part,parent->name->name); + fullname[len-1] = '.'; + len -= part; + prev = parent; + parent = parent->parent; + } + return julia_to_gv(fullname, addr); +} +static Value *julia_to_gv(jl_datatype_t *addr) { + return julia_to_gv(addr->name->name, addr->name->module, (jl_value_t*)addr); +} +static Value *julia_to_gv(jl_lambda_info_t *linfo, jl_value_t *addr) { + if (linfo != NULL) + return julia_to_gv(linfo->name, linfo->module, addr); + return julia_to_gv(addr); +} +static Value *julia_to_gv(jl_function_t *addr) { + return julia_to_gv(addr->linfo, (jl_value_t*)addr); +} + +static Value *literal_pointer_val(jl_value_t *p) +{ + if (p == NULL) + return literal_pointer_val((void*)NULL, jl_pvalue_llvmt); + if (jl_is_datatype(p)) + return julia_to_gv((jl_datatype_t*)p); + if (jl_is_func(p)) + return julia_to_gv((jl_function_t*)p); + if (jl_is_lambda_info(p)) + return julia_to_gv((jl_lambda_info_t*)p, p); + return julia_to_gv(p); } // --- mapping between julia and llvm types --- @@ -846,3 +915,5 @@ static void emit_cpointercheck(Value *x, const std::string &msg, ctx->f->getBasicBlockList().push_back(passBB); builder.SetInsertPoint(passBB); } + + diff --git a/src/codegen.cpp b/src/codegen.cpp index 5204cfd44dca3..705e849789a6f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1373,8 +1373,8 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, #else builder.CreateStore(literal_pointer_val((jl_value_t*)jl_tuple_type), emit_nthptr_addr(tup, (size_t)0)); - builder.CreateStore(literal_pointer_val((jl_value_t*)nargs), - emit_nthptr_addr(tup, (size_t)1)); + builder.CreateStore(ConstantInt::get(T_size, nargs), + builder.CreateBitCast(emit_nthptr_addr(tup, (size_t)1), T_psize)); #endif #ifdef OVERLAP_TUPLE_LEN size_t offs = 1; @@ -1733,7 +1733,7 @@ static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, if (assign || b==NULL) b = jl_get_binding_wr(m, s); if (pbnd) *pbnd = b; - return literal_pointer_val(&b->value, jl_ppvalue_llvmt); + return emit_nthptr_addr(literal_pointer_val((jl_value_t*)b), offsetof(jl_binding_t,value)/sizeof(size_t)); } // yields a jl_value_t** giving the binding location of a variable @@ -1853,7 +1853,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) if (bnd) { rval = boxed(emit_expr(r, ctx, true)); builder.CreateCall2(jlcheckassign_func, - literal_pointer_val((void*)bnd), + literal_pointer_val((jl_value_t*)bnd), rval); } else { @@ -1956,7 +1956,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, jl_binding_t *b = jl_get_binding(mod, var); if (b == NULL) b = jl_get_binding_wr(mod, var); - Value *bp = literal_pointer_val(&b->value, jl_ppvalue_llvmt); + Value *bp = emit_nthptr_addr(literal_pointer_val((jl_value_t*)b), offsetof(jl_binding_t,value)/sizeof(size_t)); if ((b->constp && b->value!=NULL) || (etype!=(jl_value_t*)jl_any_type && !jl_subtype((jl_value_t*)jl_undef_type, etype, 0))) { @@ -2063,7 +2063,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, else { if (is_global((jl_sym_t*)mn, ctx)) { bnd = jl_get_binding_for_method_def(ctx->module, (jl_sym_t*)mn); - bp = literal_pointer_val(&bnd->value, jl_ppvalue_llvmt); + bp = emit_nthptr_addr(literal_pointer_val((jl_value_t*)bnd), offsetof(jl_binding_t,value)/sizeof(size_t)); } else { bp = var_binding_pointer((jl_sym_t*)mn, &bnd, false, ctx); @@ -2075,7 +2075,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, make_gcroot(a2, ctx); Value *a3 = boxed(emit_expr(args[3], ctx)); make_gcroot(a3, ctx); - Value *mdargs[6] = { name, bp, literal_pointer_val((void*)bnd), + Value *mdargs[6] = { name, bp, literal_pointer_val((jl_value_t*)bnd), a1, a2, a3 }; ctx->argDepth = last_depth; return builder.CreateCall(jlmethod_func, ArrayRef(&mdargs[0], 6)); @@ -2086,7 +2086,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, (void)var_binding_pointer(sym, &bnd, true, ctx); if (bnd) { builder.CreateCall(jldeclareconst_func, - literal_pointer_val((void*)bnd)); + literal_pointer_val((jl_value_t*)bnd)); } } @@ -3198,7 +3198,7 @@ static void init_julia_llvm_env(Module *m) (void*)&jl_type_error_rt); std::vector args_2ptrs(0); - args_2ptrs.push_back(T_pint8); + args_2ptrs.push_back(jl_pvalue_llvmt); args_2ptrs.push_back(jl_pvalue_llvmt); jlcheckassign_func = Function::Create(FunctionType::get(T_void, args_2ptrs, false), @@ -3208,7 +3208,7 @@ static void init_julia_llvm_env(Module *m) (void*)&jl_checked_assignment); std::vector args_1ptr(0); - args_1ptr.push_back(T_pint8); + args_1ptr.push_back(jl_pvalue_llvmt); jldeclareconst_func = Function::Create(FunctionType::get(T_void, args_1ptr, false), Function::ExternalLinkage, @@ -3251,7 +3251,7 @@ static void init_julia_llvm_env(Module *m) std::vector mdargs(0); mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_ppvalue_llvmt); - mdargs.push_back(T_pint8); + mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); diff --git a/src/dump.c b/src/dump.c index ac722c2bf9748..98678a511468c 100644 --- a/src/dump.c +++ b/src/dump.c @@ -350,49 +350,58 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) *(int64_t*)data >= S32_MIN && *(int64_t*)data <= S32_MAX) { writetag(s, (jl_value_t*)SmallInt64_tag); write_int32(s, (int32_t)*(int64_t*)data); - return; } - if (t == jl_int32_type) { + else if (t == jl_int32_type) { writetag(s, (jl_value_t*)Int32_tag); write_int32(s, (int32_t)*(int32_t*)data); - return; } - if ((jl_value_t*)t == jl_idtable_type) - writetag(s, (jl_value_t*)IdTable_tag); - else - writetag(s, (jl_value_t*)jl_datatype_type); - jl_serialize_value(s, t); - size_t nf = jl_tuple_len(t->names); - if (nf == 0 && jl_datatype_size(t)>0) { - if (t->name == jl_pointer_type->name) { - write_int32(s, 0); + else { + if ((jl_value_t*)t == jl_idtable_type) + writetag(s, (jl_value_t*)IdTable_tag); + else + writetag(s, (jl_value_t*)jl_datatype_type); + jl_serialize_value(s, t); + size_t nf = jl_tuple_len(t->names); + if (nf == 0 && jl_datatype_size(t)>0) { + if (t->name == jl_pointer_type->name) { + write_int32(s, 0); #ifdef _P64 - write_int32(s, 0); + write_int32(s, 0); #endif + } + else { + ios_write(s, data, jl_datatype_size(t)); + } } else { - ios_write(s, data, jl_datatype_size(t)); - } - } - else { - if ((jl_value_t*)t == jl_idtable_type) { - jl_array_t *data = (jl_array_t*)jl_get_nth_field(v, 0); - jl_value_t **d = (jl_value_t**)data->data; - for(size_t i=0; i < jl_array_len(data); i+=2) { - if (d[i+1] != NULL) { - jl_serialize_value(s, d[i+1]); - jl_serialize_value(s, d[i]); + if ((jl_value_t*)t == jl_idtable_type) { + jl_array_t *data = (jl_array_t*)jl_get_nth_field(v, 0); + jl_value_t **d = (jl_value_t**)data->data; + for(size_t i=0; i < jl_array_len(data); i+=2) { + if (d[i+1] != NULL) { + jl_serialize_value(s, d[i+1]); + jl_serialize_value(s, d[i]); + } } + jl_serialize_value(s, NULL); } - jl_serialize_value(s, NULL); - } - else { - for(size_t i=0; i < nf; i++) { - jl_serialize_value(s, jl_get_nth_field(v, i)); + else { + for(size_t i=0; i < nf; i++) { + jl_serialize_value(s, jl_get_nth_field(v, i)); + } } } } } + const char *gvname = jl_get_llvm_gv(v); + if (gvname != NULL) { + int32_t gvname_len = strlen(gvname); + write_int32(s, gvname_len); + ios_write(s, gvname, gvname_len); + } + else { + write_int32(s, 0); + } } // --- deserialize --- @@ -470,7 +479,8 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos) } jl_array_t *jl_eqtable_put(jl_array_t *h, void *key, void *val); - +#include +static jl_value_t *jl_deserialize_value_(ios_t *s, int pos, jl_value_t *vtag); static jl_value_t *jl_deserialize_value(ios_t *s) { int pos = ios_pos(s); @@ -495,7 +505,24 @@ static jl_value_t *jl_deserialize_value(ios_t *s) if (tag >= VALUE_TAGS) { return vtag; } - + else if (vtag == (jl_value_t*)LiteralVal_tag) { + return jl_cellref(tree_literal_values, read_uint16(s)); + } + jl_value_t *v = jl_deserialize_value_(s, pos, vtag); + int32_t gvname_len = read_int32(s); + if (gvname_len > 0) { + char *gvname = alloca(gvname_len+1); + memset(gvname, 0, gvname_len+1); + ios_read(s, gvname, gvname_len); + gvname[gvname_len] = 0; + const char *old = jl_get_llvm_gv(v); + if (!old || strcmp(old,gvname)) { + //*((jl_value_t**)jl_dlsym_e((uv_lib_t*)sysimg_handle, const_cast(cname))) = addr; + } + } + return v; +} +static jl_value_t *jl_deserialize_value_(ios_t *s, int pos, jl_value_t *vtag) { int usetable = (tree_literal_values == NULL); size_t i; @@ -564,9 +591,6 @@ static jl_value_t *jl_deserialize_value(ios_t *s) } return (jl_value_t*)e; } - else if (vtag == (jl_value_t*)LiteralVal_tag) { - return jl_cellref(tree_literal_values, read_uint16(s)); - } else if (vtag == (jl_value_t*)jl_tvar_type) { jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_value_t*)jl_tvar_type, 4); if (usetable) diff --git a/src/julia.h b/src/julia.h index 44d161ac306d0..0d468ba313a71 100644 --- a/src/julia.h +++ b/src/julia.h @@ -249,10 +249,9 @@ typedef struct { } jl_weakref_t; typedef struct { - // not first-class + JL_DATA_TYPE jl_sym_t *name; jl_value_t *value; - jl_value_t *type; struct _jl_module_t *owner; // for individual imported bindings unsigned constp:1; unsigned exportp:1; @@ -874,6 +873,7 @@ void jl_init_serializer(void); DLLEXPORT void jl_save_system_image(char *fname); DLLEXPORT void jl_restore_system_image(char *fname); +DLLEXPORT const char *jl_get_llvm_gv(jl_value_t *p); // front end interface DLLEXPORT jl_value_t *jl_parse_input_line(const char *str); diff --git a/test/file.jl b/test/file.jl index d2107f7b98138..064b0a07b5970 100644 --- a/test/file.jl +++ b/test/file.jl @@ -93,7 +93,6 @@ function test_monitor(slval) close(fm) end -# Commented out the tests below due to issues 3015, 3016 and 3020 test_timeout(0.1) test_timeout(1) test_touch(0.1)