static inline jl_value_t *jl_iintrinsic_2(jl_value_t *a, jl_value_t *b, const char *name, char (*getsign)(void*, unsigned), jl_value_t* (*lambda2)(jl_value_t*, void*, void*, unsigned, unsigned, void*), void *list, int cvtb) { jl_value_t *ty = jl_typeof(a); jl_value_t *tyb = jl_typeof(b); if (tyb != ty) { if (!cvtb) jl_errorf("%s: types of a and b must match", name); if (!jl_is_bitstype(tyb)) jl_errorf("%s: b is not a bitstypes", name); } if (!jl_is_bitstype(ty)) jl_errorf("%s: a is not a bitstypes", name); void *pa = jl_data_ptr(a), *pb = jl_data_ptr(b); unsigned sz = jl_datatype_size(ty); unsigned sz2 = next_power_of_two(sz); unsigned szb = jl_datatype_size(tyb); if (sz2 > sz) { /* round type up to the appropriate c-type and set/clear the unused bits */ void *pa2 = alloca(sz2); memcpy(pa2, pa, sz); memset((char*)pa2 + sz, getsign(pa, sz), sz2 - sz); pa = pa2; } if (sz2 > szb) { /* round type up to the appropriate c-type and set/clear/truncate the unused bits */ void *pb2 = alloca(sz2); memcpy(pb2, pb, szb); memset((char*)pb2 + szb, getsign(pb, sz), sz2 - szb); pb = pb2; } jl_value_t *newv = lambda2(ty, pa, pb, sz, sz2, list); return newv; }
// See comment above for an explanation of NOINLINE. static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt) { size_t nf = jl_datatype_nfields(dt); for (size_t f=0; f < nf; f++) { size_t offs = jl_field_offset(dt, f); char *ao = (char*)jl_data_ptr(a) + offs; char *bo = (char*)jl_data_ptr(b) + offs; int eq; if (jl_field_isptr(dt, f)) { jl_value_t *af = *(jl_value_t**)ao; jl_value_t *bf = *(jl_value_t**)bo; if (af == bf) eq = 1; else if (af==NULL || bf==NULL) eq = 0; else eq = jl_egal(af, bf); } else { jl_datatype_t *ft = (jl_datatype_t*)jl_field_type(dt, f); if (!ft->layout->haspadding) { eq = bits_equal(ao, bo, jl_field_size(dt, f)); } else { assert(jl_datatype_nfields(ft) > 0); eq = compare_fields((jl_value_t*)ao, (jl_value_t*)bo, ft); } } if (!eq) return 0; } return 1; }
JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b) { // warning: a,b may NOT have been gc-rooted by the caller if (a == b) return 1; jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(a); if (dt != (jl_datatype_t*)jl_typeof(b)) return 0; if (dt == jl_simplevector_type) return compare_svec((jl_svec_t*)a, (jl_svec_t*)b); if (dt == jl_datatype_type) { jl_datatype_t *dta = (jl_datatype_t*)a; jl_datatype_t *dtb = (jl_datatype_t*)b; return dta->name == dtb->name && compare_svec(dta->parameters, dtb->parameters); } if (dt == jl_string_type) { size_t l = jl_string_len(a); if (jl_string_len(b) != l) return 0; return !memcmp(jl_string_data(a), jl_string_data(b), l); } if (dt->mutabl) return 0; size_t sz = jl_datatype_size(dt); if (sz == 0) return 1; size_t nf = jl_datatype_nfields(dt); if (nf == 0) return bits_equal(jl_data_ptr(a), jl_data_ptr(b), sz); if (dt == jl_unionall_type) return egal_types(a, b, NULL); return compare_fields(a, b, dt); }
static inline jl_value_t *jl_iintrinsic_1(jl_value_t *ty, jl_value_t *a, const char *name, char (*getsign)(void*, unsigned), jl_value_t *(*lambda1)(jl_value_t*, void*, unsigned, unsigned, const void*), const void *list) { if (!jl_is_bitstype(jl_typeof(a))) jl_errorf("%s: value is not a bitstype", name); if (!jl_is_bitstype(ty)) jl_errorf("%s: type is not a bitstype", name); void *pa = jl_data_ptr(a); unsigned isize = jl_datatype_size(jl_typeof(a)); unsigned isize2 = next_power_of_two(isize); unsigned osize = jl_datatype_size(ty); unsigned osize2 = next_power_of_two(osize); if (isize2 > osize2) osize2 = isize2; if (osize2 > isize || isize2 > isize) { /* if needed, round type up to a real c-type and set/clear the unused bits */ void *pa2; pa2 = alloca(osize2); /* TODO: this memcpy assumes little-endian, * for big-endian, need to align the copy to the other end */ \ memcpy(pa2, pa, isize); memset((char*)pa2 + isize, getsign(pa, isize), osize2 - isize); pa = pa2; } jl_value_t *newv = lambda1(ty, pa, osize, osize2, list); if (ty == (jl_value_t*)jl_bool_type) return *(uint8_t*)jl_data_ptr(newv) & 1 ? jl_true : jl_false; return newv; }
static inline jl_value_t *jl_intrinsiclambda_2(jl_value_t *ty, void *pa, void *pb, unsigned sz, unsigned sz2, void *voidlist) { jl_value_t *newv = newstruct((jl_datatype_t*)ty); intrinsic_2_t op = select_intrinsic_2(sz2, (intrinsic_2_t*)voidlist); op(sz * host_char_bit, pa, pb, jl_data_ptr(newv)); if (ty == (jl_value_t*)jl_bool_type) return *(uint8_t*)jl_data_ptr(newv) & 1 ? jl_true : jl_false; return newv; }
static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) { if (tv == (jl_value_t*)jl_sym_type) return ((jl_sym_t*)v)->hash; if (tv == (jl_value_t*)jl_simplevector_type) return hash_svec((jl_svec_t*)v); jl_datatype_t *dt = (jl_datatype_t*)tv; if (dt == jl_datatype_type) { jl_datatype_t *dtv = (jl_datatype_t*)v; // `name->wrapper` is cacheable even though it contains TypeVars // that don't have stable IDs. //if (jl_egal(dtv->name->wrapper, v)) // return bitmix(~dtv->name->hash, 0xaa5566aa); return bitmix(~dtv->name->hash, hash_svec(dtv->parameters)); } if (dt == jl_typename_type) return ((jl_typename_t*)v)->hash; #ifdef _P64 if (v == jl_ANY_flag) return 0x31c472f68ee30bddULL; #else if (v == jl_ANY_flag) return 0x8ee30bdd; #endif if (dt == jl_string_type) { #ifdef _P64 return memhash_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); #else return memhash32_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); #endif } if (dt->mutabl) return inthash((uintptr_t)v); size_t sz = jl_datatype_size(tv); uintptr_t h = jl_object_id(tv); if (sz == 0) return ~h; size_t nf = jl_datatype_nfields(dt); if (nf == 0) { return bits_hash(jl_data_ptr(v), sz) ^ h; } for (size_t f=0; f < nf; f++) { size_t offs = jl_field_offset(dt, f); char *vo = (char*)jl_data_ptr(v) + offs; uintptr_t u; if (jl_field_isptr(dt, f)) { jl_value_t *f = *(jl_value_t**)vo; u = f==NULL ? 0 : jl_object_id(f); } else { jl_datatype_t *fieldtype = (jl_datatype_t*)jl_field_type(dt, f); assert(jl_is_datatype(fieldtype) && !fieldtype->abstract && !fieldtype->mutabl); if (fieldtype->layout->haspadding) u = jl_object_id_((jl_value_t*)fieldtype, (jl_value_t*)vo); else u = bits_hash(vo, jl_field_size(dt, f)); } h = bitmix(h, u); } return h; }
static inline jl_value_t *jl_intrinsiclambda_2(jl_value_t *ty, void *pa, void *pb, unsigned sz, unsigned sz2, const void *voidlist) { jl_ptls_t ptls = jl_get_ptls_states(); jl_value_t *newv = jl_gc_alloc(ptls, ((jl_datatype_t*)ty)->size, ty); intrinsic_2_t op = select_intrinsic_2(sz2, (const intrinsic_2_t*)voidlist); op(sz * host_char_bit, pa, pb, jl_data_ptr(newv)); if (ty == (jl_value_t*)jl_bool_type) return *(uint8_t*)jl_data_ptr(newv) & 1 ? jl_true : jl_false; return newv; }
static inline jl_value_t *jl_intrinsiclambda_checked(jl_value_t *ty, void *pa, void *pb, unsigned sz, unsigned sz2, void *voidlist) { jl_value_t *newv = newstruct((jl_datatype_t*)ty); intrinsic_checked_t op = select_intrinsic_checked(sz2, (intrinsic_checked_t*)voidlist); int ovflw = op(sz * host_char_bit, pa, pb, jl_data_ptr(newv)); if (ovflw) jl_throw(jl_overflow_exception); if (ty == (jl_value_t*)jl_bool_type) return *(uint8_t*)jl_data_ptr(newv) & 1 ? jl_true : jl_false; return newv; }
int jl_egal(jl_value_t *a, jl_value_t *b) { if (a == b) return 1; jl_value_t *ta = (jl_value_t*)jl_typeof(a); if (ta != (jl_value_t*)jl_typeof(b)) return 0; if (jl_is_tuple(a)) { size_t l = jl_tuple_len(a); if (l != jl_tuple_len(b)) return 0; for(size_t i=0; i < l; i++) { if (!jl_egal(jl_tupleref(a,i),jl_tupleref(b,i))) return 0; } return 1; } jl_datatype_t *dt = (jl_datatype_t*)ta; if (dt == jl_datatype_type) { jl_datatype_t *dta = (jl_datatype_t*)a; jl_datatype_t *dtb = (jl_datatype_t*)b; return dta->name == dtb->name && jl_egal((jl_value_t*)dta->parameters, (jl_value_t*)dtb->parameters); } if (dt->mutabl) return 0; size_t sz = dt->size; if (sz == 0) return 1; size_t nf = jl_tuple_len(dt->names); if (nf == 0) { return bits_equal(jl_data_ptr(a), jl_data_ptr(b), sz); } for (size_t f=0; f < nf; f++) { size_t offs = dt->fields[f].offset; char *ao = (char*)jl_data_ptr(a) + offs; char *bo = (char*)jl_data_ptr(b) + offs; int eq; if (dt->fields[f].isptr) { jl_value_t *af = *(jl_value_t**)ao; jl_value_t *bf = *(jl_value_t**)bo; if (af == bf) eq = 1; else if (af==NULL || bf==NULL) eq = 0; else eq = jl_egal(af, bf); } else { eq = bits_equal(ao, bo, dt->fields[f].size); } if (!eq) return 0; } return 1; }
// run time version of bitcast intrinsic JL_DLLEXPORT jl_value_t *jl_bitcast(jl_value_t *ty, jl_value_t *v) { JL_TYPECHK(bitcast, datatype, ty); if (!jl_is_concrete_type(ty) || !jl_is_primitivetype(ty)) jl_error("bitcast: target type not a leaf primitive type"); if (!jl_is_primitivetype(jl_typeof(v))) jl_error("bitcast: value not a primitive type"); if (jl_datatype_size(jl_typeof(v)) != jl_datatype_size(ty)) jl_error("bitcast: argument size does not match size of target type"); if (ty == jl_typeof(v)) return v; if (ty == (jl_value_t*)jl_bool_type) return *(uint8_t*)jl_data_ptr(v) & 1 ? jl_true : jl_false; return jl_new_bits(ty, jl_data_ptr(v)); }
// run time version of box/unbox intrinsic JL_DLLEXPORT jl_value_t *jl_reinterpret(jl_value_t *ty, jl_value_t *v) { JL_TYPECHK(reinterpret, datatype, ty); if (!jl_is_leaf_type(ty) || !jl_is_bitstype(ty)) jl_error("reinterpret: target type not a leaf bitstype"); if (!jl_is_bitstype(jl_typeof(v))) jl_error("reinterpret: value not a bitstype"); if (jl_datatype_size(jl_typeof(v)) != jl_datatype_size(ty)) jl_error("reinterpret: argument size does not match size of target type"); if (ty == jl_typeof(v)) return v; if (ty == (jl_value_t*)jl_bool_type) return *(uint8_t*)jl_data_ptr(v) & 1 ? jl_true : jl_false; return jl_new_bits(ty, jl_data_ptr(v)); }
static inline jl_value_t *jl_intrinsiclambda_u1(jl_value_t *ty, void *pa, unsigned osize, unsigned osize2, void *voidlist) { jl_value_t *newv = newstruct((jl_datatype_t*)ty); intrinsic_u1_t op = select_intrinsic_u1(osize2, (intrinsic_u1_t*)voidlist); unsigned cnt = op(osize * host_char_bit, pa); // TODO: the following memset/memcpy assumes little-endian // for big-endian, need to copy from the other end of cnt if (osize > sizeof(unsigned)) { // perform zext, if needed memset((char*)jl_data_ptr(newv) + sizeof(unsigned), 0, osize - sizeof(unsigned)); osize = sizeof(unsigned); } memcpy(jl_data_ptr(newv), &cnt, osize); return newv; }
// this is a run-time function // warning: cannot allocate memory except using alloc_temp_arg_space extern "C" DLLEXPORT void *jl_value_to_pointer(jl_value_t *jt, jl_value_t *v, int argn, int addressof) { jl_value_t *jvt = (jl_value_t*)jl_typeof(v); if (addressof) { if (jvt == jt) { if (jl_is_bitstype(jvt)) { size_t osz = jl_datatype_size(jt); return alloc_temp_arg_copy(jl_data_ptr(v), osz); } else if (!jl_is_tuple(jvt) && jl_is_leaf_type(jvt) && !jl_is_array_type(jvt)) { return v + 1; } } goto value_to_pointer_error; } else { if (jl_is_cpointer_type(jvt) && jl_tparam0(jvt) == jt) { return (void*)jl_unbox_voidpointer(v); } } if (((jl_value_t*)jl_uint8_type == jt || (jl_value_t*)jl_int8_type == jt) && jl_is_byte_string(v)) { return jl_string_data(v); } if (jl_is_array_type(jvt)) { if (jl_tparam0(jl_typeof(v)) == jt || jt==(jl_value_t*)jl_bottom_type) return ((jl_array_t*)v)->data; if (jl_is_cpointer_type(jt)) { jl_array_t *ar = (jl_array_t*)v; void **temp=(void**)alloc_temp_arg_space((1+jl_array_len(ar))*sizeof(void*)); size_t i; for(i=0; i < jl_array_len(ar); i++) { temp[i] = jl_value_to_pointer(jl_tparam0(jt), jl_arrayref(ar, i), argn, 0); } temp[i] = 0; return temp; } } value_to_pointer_error: std::map<int, std::string>::iterator it = argNumberStrings.find(argn); if (it == argNumberStrings.end()) { std::stringstream msg; msg << "argument "; msg << argn; argNumberStrings[argn] = msg.str(); it = argNumberStrings.find(argn); } jl_value_t *targ=NULL, *pty=NULL; JL_GC_PUSH2(&targ, &pty); targ = (jl_value_t*)jl_tuple1(jt); pty = (jl_value_t*)jl_apply_type((jl_value_t*)jl_pointer_type, (jl_tuple_t*)targ); jl_type_error_rt("ccall", (*it).second.c_str(), pty, v); // doesn't return return (jl_value_t*)jl_null; }
static inline jl_value_t *jl_intrinsiclambda_ty1(jl_value_t *ty, void *pa, unsigned osize, unsigned osize2, void *voidlist) { jl_value_t *newv = newstruct((jl_datatype_t*)ty); intrinsic_1_t op = select_intrinsic_1(osize2, (intrinsic_1_t*)voidlist); op(osize * host_char_bit, pa, jl_data_ptr(newv)); return newv; }
JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na) { jl_ptls_t ptls = jl_get_ptls_states(); if (type->instance != NULL) return type->instance; size_t nf = jl_datatype_nfields(type); jl_value_t *jv = jl_gc_alloc(ptls, jl_datatype_size(type), type); JL_GC_PUSH1(&jv); for (size_t i = 0; i < na; i++) { jl_value_t *ft = jl_field_type(type, i); if (!jl_isa(args[i], ft)) jl_type_error("new", ft, args[i]); jl_set_nth_field(jv, i, args[i]); } for(size_t i=na; i < nf; i++) { if (jl_field_isptr(type, i)) { *(jl_value_t**)((char*)jl_data_ptr(jv)+jl_field_offset(type,i)) = NULL; } else { jl_value_t *ft = jl_field_type(type, i); if (jl_is_uniontype(ft)) { uint8_t *psel = &((uint8_t *)jv)[jl_field_offset(type, i) + jl_field_size(type, i) - 1]; *psel = 0; } } } JL_GC_POP(); return jv; }
void *td_jl_get_dataptr(void *v) { if (jl_is_array(v)) return jl_array_data(v); if (jl_is_byte_string(v)) return jl_string_data(v); return jl_data_ptr(v); }
static inline jl_value_t *jl_intrinsiclambda_ty1(jl_value_t *ty, void *pa, unsigned osize, unsigned osize2, const void *voidlist) { jl_ptls_t ptls = jl_get_ptls_states(); jl_value_t *newv = jl_gc_alloc(ptls, ((jl_datatype_t*)ty)->size, ty); intrinsic_1_t op = select_intrinsic_1(osize2, (const intrinsic_1_t*)voidlist); op(osize * host_char_bit, pa, jl_data_ptr(newv)); return newv; }
JL_DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type) { if (type->instance != NULL) return type->instance; jl_value_t *jv = newstruct(type); if (type->size > 0) memset(jl_data_ptr(jv), 0, type->size); return jv; }
DLLEXPORT void jl_show_any(jl_value_t *str, jl_value_t *v) { uv_stream_t *s = ((uv_stream_t**)str)[1]; // fallback for printing some other builtin types if (jl_is_tuple(v)) { jl_show_tuple(str, (jl_tuple_t*)v, '(', ')', 1); } else if (jl_is_type(v)) { show_type(str, v); } else if (jl_is_func(v)) { show_function(s, v); } else if (jl_typeis(v,jl_intrinsic_type)) { JL_PRINTF(s, "# intrinsic function %d", *(uint32_t*)jl_data_ptr(v)); } else { jl_value_t *t = (jl_value_t*)jl_typeof(v); assert(jl_is_datatype(t)); jl_datatype_t *dt = (jl_datatype_t*)t; show_type(str, t); JL_PUTC('(', s); if (jl_tuple_len(dt->names)>0 || dt->size==0) { size_t i; size_t n = jl_tuple_len(dt->names); for(i=0; i < n; i++) { jl_value_t *fval = jl_get_nth_field(v, i); if (fval == NULL) JL_PUTS("#undef", s); else jl_show(str, fval); if (i < n-1) JL_PUTC(',', s); } } else { size_t nb = jl_datatype_size(dt); char *data = (char*)jl_data_ptr(v); JL_PUTS("0x", s); for(int i=nb-1; i >= 0; --i) jl_printf(s, "%02hhx", data[i]); } JL_PUTC(')', s); } }
JL_DLLEXPORT jl_value_t *jl_box_char(uint32_t x) { jl_ptls_t ptls = jl_get_ptls_states(); if (0 < (int32_t)x) return boxed_char_cache[x >> 24]; jl_value_t *v = jl_gc_alloc(ptls, sizeof(void*), jl_char_type); *(uint32_t*)jl_data_ptr(v) = x; return v; }
JL_DLLEXPORT jl_value_t *jl_check_top_bit(jl_value_t *a) { jl_value_t *ty = jl_typeof(a); if (!jl_is_bitstype(ty)) jl_error("check_top_bit: value is not a bitstype"); if (signbitbyte(jl_data_ptr(a), jl_datatype_size(ty))) jl_throw(jl_inexact_exception); return a; }
DLLEXPORT uptrint_t jl_object_id(jl_value_t *v) { if (jl_is_symbol(v)) return ((jl_sym_t*)v)->hash; jl_value_t *tv = (jl_value_t*)jl_typeof(v); if (tv == (jl_value_t*)jl_tuple_type) { uptrint_t h = 0; size_t l = jl_tuple_len(v); for(size_t i = 0; i < l; i++) { uptrint_t u = jl_object_id(jl_tupleref(v,i)); h = bitmix(h, u); } return h; } jl_datatype_t *dt = (jl_datatype_t*)tv; if (dt == jl_datatype_type) { jl_datatype_t *dtv = (jl_datatype_t*)v; uptrint_t h = inthash((uptrint_t)tv); return bitmix(bitmix(h, jl_object_id((jl_value_t*)dtv->name)), jl_object_id((jl_value_t*)dtv->parameters)); } if (dt->mutabl) return inthash((uptrint_t)v); size_t sz = jl_datatype_size(tv); uptrint_t h = inthash((uptrint_t)tv); if (sz == 0) return ~h; size_t nf = jl_tuple_len(dt->names); if (nf == 0) { return bits_hash(jl_data_ptr(v), sz) ^ h; } for (size_t f=0; f < nf; f++) { size_t offs = dt->fields[f].offset; char *vo = (char*)jl_data_ptr(v) + offs; uptrint_t u; if (dt->fields[f].isptr) { jl_value_t *f = *(jl_value_t**)vo; u = f==NULL ? 0 : jl_object_id(f); } else { u = bits_hash(vo, dt->fields[f].size); } h = bitmix(h, u); } return h; }
static inline jl_value_t *jl_intrinsic_cvt(jl_value_t *ty, jl_value_t *a, const char *name, intrinsic_cvt_t op, intrinsic_cvt_check_t check_op) { jl_value_t *aty = jl_typeof(a); if (!jl_is_bitstype(aty)) jl_errorf("%s: value is not a bitstype", name); if (!jl_is_bitstype(ty)) jl_errorf("%s: type is not a bitstype", name); void *pa = jl_data_ptr(a); unsigned isize = jl_datatype_size(aty); unsigned osize = jl_datatype_size(ty); if (check_op && check_op(isize, osize, pa)) jl_throw(jl_inexact_exception); jl_value_t *newv = newstruct((jl_datatype_t*)ty); op(aty == (jl_value_t*)jl_bool_type ? 1 : isize * host_char_bit, pa, osize * host_char_bit, jl_data_ptr(newv)); if (ty == (jl_value_t*)jl_bool_type) return *(uint8_t*)jl_data_ptr(newv) & 1 ? jl_true : jl_false; return newv; }
JL_DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type) { jl_ptls_t ptls = jl_get_ptls_states(); if (type->instance != NULL) return type->instance; size_t size = type->size; jl_value_t *jv = jl_gc_alloc(ptls, size, type); if (size > 0) memset(jl_data_ptr(jv), 0, size); return jv; }
static void to_td_val(td_val_t *out, jl_value_t *v) { td_tag_t tag = jl_type_to_td(jl_typeof(v)); if (tag < TD_UTF8) { out->tag = tag; memcpy(&out->object, jl_data_ptr(v), td_type_size(tag)); } else { out->owner = td_env_julia(NULL, NULL); out->object = v; } }
// Note that this function updates len static jl_value_t *jl_new_bits_internal(jl_value_t *dt, void *data, size_t *len) { assert(jl_is_datatype(dt)); jl_datatype_t *bt = (jl_datatype_t*)dt; size_t nb = jl_datatype_size(bt); if (nb == 0) return jl_new_struct_uninit(bt); *len = LLT_ALIGN(*len, bt->alignment); data = (char*)data + (*len); *len += nb; if (bt == jl_uint8_type) return jl_box_uint8(*(uint8_t*)data); if (bt == jl_int64_type) return jl_box_int64(*(int64_t*)data); if (bt == jl_bool_type) return (*(int8_t*)data) ? jl_true:jl_false; if (bt == jl_int32_type) return jl_box_int32(*(int32_t*)data); if (bt == jl_float64_type) return jl_box_float64(*(double*)data); jl_value_t *v = (jl_value_t*)newobj((jl_value_t*)bt, NWORDS(nb)); switch (nb) { case 1: *(int8_t*) jl_data_ptr(v) = *(int8_t*)data; break; case 2: *(int16_t*) jl_data_ptr(v) = *(int16_t*)data; break; case 4: *(int32_t*) jl_data_ptr(v) = *(int32_t*)data; break; case 8: *(int64_t*) jl_data_ptr(v) = *(int64_t*)data; break; case 16: *(bits128_t*)jl_data_ptr(v) = *(bits128_t*)data; break; default: memcpy(jl_data_ptr(v), data, nb); } return v; }
// See comment above for an explanation of NOINLINE. static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt) { size_t f, nf = jl_datatype_nfields(dt); for (f = 0; f < nf; f++) { size_t offs = jl_field_offset(dt, f); char *ao = (char*)jl_data_ptr(a) + offs; char *bo = (char*)jl_data_ptr(b) + offs; if (jl_field_isptr(dt, f)) { jl_value_t *af = *(jl_value_t**)ao; jl_value_t *bf = *(jl_value_t**)bo; if (af != bf) { if (af == NULL || bf == NULL) return 0; if (!jl_egal(af, bf)) return 0; } } else { jl_datatype_t *ft = (jl_datatype_t*)jl_field_type(dt, f); if (jl_is_uniontype(ft)) { uint8_t asel = ((uint8_t*)ao)[jl_field_size(dt, f) - 1]; uint8_t bsel = ((uint8_t*)bo)[jl_field_size(dt, f) - 1]; if (asel != bsel) return 0; ft = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)ft, asel); } if (!ft->layout->haspadding) { if (!bits_equal(ao, bo, ft->size)) return 0; } else { assert(jl_datatype_nfields(ft) > 0); if (!compare_fields((jl_value_t*)ao, (jl_value_t*)bo, ft)) return 0; } } } return 1; }
DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na) { if (type->instance != NULL) return type->instance; size_t nf = jl_datatype_nfields(type); jl_value_t *jv = newstruct(type); for(size_t i=0; i < na; i++) { jl_set_nth_field(jv, i, args[i]); } for(size_t i=na; i < nf; i++) { if (type->fields[i].isptr) *(jl_value_t**)((char*)jl_data_ptr(jv)+jl_field_offset(type,i)) = NULL; } return jv; }
static inline jl_value_t *jl_fintrinsic_1(jl_value_t *ty, jl_value_t *a, const char *name, fintrinsic_op1 *floatop, fintrinsic_op1 *doubleop) { if (!jl_is_bitstype(jl_typeof(a))) jl_errorf("%s: value is not a bitstype", name); if (!jl_is_bitstype(ty)) jl_errorf("%s: type is not a bitstype", name); jl_value_t *newv = newstruct((jl_datatype_t*)ty); void *pa = jl_data_ptr(a), *pr = jl_data_ptr(newv); unsigned sz = jl_datatype_size(jl_typeof(a)); unsigned sz2 = jl_datatype_size(ty); switch (sz) { /* choose the right size c-type operation based on the input */ case 4: floatop(sz2 * host_char_bit, pa, pr); break; case 8: doubleop(sz2 * host_char_bit, pa, pr); break; default: jl_errorf("%s: runtime floating point intrinsics are not implemented for bit sizes other than 32 and 64", name); } return newv; }
JL_DLLEXPORT jl_value_t *jl_powi_llvm(jl_value_t *a, jl_value_t *b) { jl_value_t *ty = jl_typeof(a); if (!jl_is_bitstype(ty)) jl_error("powi_llvm: a is not a bitstype"); if (!jl_is_bitstype(jl_typeof(b)) || jl_datatype_size(jl_typeof(b)) != 4) jl_error("powi_llvm: b is not a 32-bit bitstype"); jl_value_t *newv = newstruct((jl_datatype_t*)ty); void *pa = jl_data_ptr(a), *pr = jl_data_ptr(newv); int sz = jl_datatype_size(ty); switch (sz) { /* choose the right size c-type operation */ case 4: *(float*)pr = powf(*(float*)pa, (float)jl_unbox_int32(b)); break; case 8: *(double*)pr = pow(*(double*)pa, (double)jl_unbox_int32(b)); break; default: jl_error("powi_llvm: runtime floating point intrinsics are not implemented for bit sizes other than 32 and 64"); } return newv; }