// 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) { Type *t = v->getType(); if (t == jl_pvalue_llvmt) return v; if (t == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); if (t == T_int1) return julia_bool(v); jl_value_t *jt = julia_type_of(v); jl_bits_type_t *jb = (jl_bits_type_t*)jt; if (jb == jl_int8_type) return builder.CreateCall(box_int8_func, builder.CreateSExt(v, T_int32)); if (jb == jl_int16_type) return builder.CreateCall(box_int16_func, v); if (jb == jl_int32_type) return builder.CreateCall(box_int32_func, v); if (jb == jl_int64_type) return builder.CreateCall(box_int64_func, v); if (jb == jl_float32_type) return builder.CreateCall(box_float32_func, v); //if (jb == jl_float64_type) return builder.CreateCall(box_float64_func, v); if (jb == jl_float64_type) { // manually inline alloc & init of Float64 box. cheap, I know. #ifdef __LP64__ Value *newv = builder.CreateCall(jlalloc2w_func); #else Value *newv = builder.CreateCall(jlalloc3w_func); #endif return init_bits_value(newv, jt, t, v); } if (jb == jl_uint8_type) return builder.CreateCall(box_uint8_func, builder.CreateZExt(v, T_int32)); if (jb == jl_uint16_type) return builder.CreateCall(box_uint16_func, v); if (jb == jl_uint32_type) return builder.CreateCall(box_uint32_func, v); if (jb == jl_uint64_type) return builder.CreateCall(box_uint64_func, v); if (jb == jl_char_type) return builder.CreateCall(box_char_func, v); // TODO: skip the call for constant arguments if (jl_is_bits_type(jt)) { if (v->getType()->isPointerTy()) { v = builder.CreatePtrToInt(v, T_size); } int nb = jl_bitstype_nbits(jt); if (nb == 8) return builder.CreateCall2(box8_func, literal_pointer_val(jt), v); if (nb == 16) return builder.CreateCall2(box16_func, literal_pointer_val(jt), v); if (nb == 32) return builder.CreateCall2(box32_func, literal_pointer_val(jt), v); if (nb == 64) return builder.CreateCall2(box64_func, literal_pointer_val(jt), v); size_t sz = sizeof(void*) + (nb+7)/8; Value *newv = builder.CreateCall(jlallocobj_func, ConstantInt::get(T_size, sz)); // TODO: make sure this is rooted. I think it is. return init_bits_value(newv, jt, t, v); } assert("Don't know how to box this type" && false); return NULL; }
// allocate a box where the type might not be known at compile time static Value *allocate_box_dynamic(Value *jlty, int nb, Value *v) { if (v->getType()->isPointerTy()) { v = builder.CreatePtrToInt(v, T_size); } size_t sz = sizeof(void*) + (nb+7)/8; Value *newv = builder.CreateCall(jlallocobj_func, ConstantInt::get(T_size, sz)); // TODO: make sure this is rooted. I think it is. return init_bits_value(newv, jlty, v->getType(), v); }
// 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, jl_value_t *jt) { Type *t = v->getType(); if (t == jl_pvalue_llvmt) return v; if (t == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); if (t == T_int1) return julia_bool(v); if (jt == NULL) jt = julia_type_of(v); jl_datatype_t *jb = (jl_datatype_t*)jt; assert(jl_is_datatype(jb)); if (jb == jl_int8_type) return builder.CreateCall(box_int8_func, builder.CreateSExt(v, T_int32)); if (jb == jl_int16_type) return builder.CreateCall(box_int16_func, v); if (jb == jl_int32_type) return builder.CreateCall(box_int32_func, v); if (jb == jl_int64_type) return builder.CreateCall(box_int64_func, v); if (jb == jl_float32_type) return builder.CreateCall(box_float32_func, v); //if (jb == jl_float64_type) return builder.CreateCall(box_float64_func, v); if (jb == jl_float64_type) { // manually inline alloc & init of Float64 box. cheap, I know. #ifdef _P64 Value *newv = builder.CreateCall(jlalloc2w_func); #else Value *newv = builder.CreateCall(jlalloc3w_func); #endif return init_bits_value(newv, literal_pointer_val(jt), t, v); } if (jb == jl_uint8_type) return builder.CreateCall(box_uint8_func, builder.CreateZExt(v, T_int32)); if (jb == jl_uint16_type) return builder.CreateCall(box_uint16_func, v); if (jb == jl_uint32_type) return builder.CreateCall(box_uint32_func, v); if (jb == jl_uint64_type) return builder.CreateCall(box_uint64_func, v); if (jb == jl_char_type) return builder.CreateCall(box_char_func, v); // TODO: skip the call for constant arguments if (!jl_isbits(jt)) { assert("Don't know how to box this type" && false); return NULL; } if (!jb->abstract && jb->size == 0) { if (jb->instance == NULL) jl_new_struct_uninit(jb); assert(jb->instance != NULL); return literal_pointer_val(jb->instance); } return allocate_box_dynamic(literal_pointer_val(jt),jl_datatype_size(jt),v); }