Skip to content

Commit

Permalink
Add align argument to pointerref and -set intrinsics.
Browse files Browse the repository at this point in the history
  • Loading branch information
maleadt authored and mfasi committed Sep 5, 2016
1 parent c0d9e22 commit a8ca0ef
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 44 deletions.
4 changes: 2 additions & 2 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,8 @@ type CoreSTDOUT <: IO end
type CoreSTDERR <: IO end
const STDOUT = CoreSTDOUT()
const STDERR = CoreSTDERR()
io_pointer(::CoreSTDOUT) = Intrinsics.pointerref(Intrinsics.cglobal(:jl_uv_stdout, Ptr{Void}), 1)
io_pointer(::CoreSTDERR) = Intrinsics.pointerref(Intrinsics.cglobal(:jl_uv_stderr, Ptr{Void}), 1)
io_pointer(::CoreSTDOUT) = Intrinsics.pointerref(Intrinsics.cglobal(:jl_uv_stdout, Ptr{Void}), 1, 1)
io_pointer(::CoreSTDERR) = Intrinsics.pointerref(Intrinsics.cglobal(:jl_uv_stderr, Ptr{Void}), 1, 1)

unsafe_write(io::IO, x::Ptr{UInt8}, nb::UInt) =
(ccall(:jl_uv_puts, Void, (Ptr{Void}, Ptr{UInt8}, UInt), io_pointer(io), x, nb); nb)
Expand Down
6 changes: 3 additions & 3 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,12 @@ add_tfunc(Core._expr, 1, IInf, (args...)->Expr)
add_tfunc(applicable, 1, IInf, (f, args...)->Bool)
add_tfunc(Core.Intrinsics.arraylen, 1, 1, x->Int)
add_tfunc(arraysize, 2, 2, (a,d)->Int)
add_tfunc(pointerref, 2, 2,
function (a,i)
add_tfunc(pointerref, 3, 3,
function (a,i,align)
a = widenconst(a)
isa(a,DataType) && a<:Ptr && isa(a.parameters[1],Union{Type,TypeVar}) ? a.parameters[1] : Any
end)
add_tfunc(pointerset, 3, 3, (a,v,i)->a)
add_tfunc(pointerset, 4, 4, (a,v,i,align)->a)

function typeof_tfunc(t::ANY)
if isa(t,Const)
Expand Down
8 changes: 3 additions & 5 deletions base/pointer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,9 @@ end
unsafe_wrap{N,I<:Integer}(Atype::Type, p::Ptr, dims::NTuple{N,I}, own::Bool=false) =
unsafe_wrap(Atype, p, convert(Tuple{Vararg{Int}}, dims), own)

unsafe_load(p::Ptr,i::Integer) = pointerref(p, Int(i))
unsafe_load(p::Ptr) = unsafe_load(p, 1)
unsafe_store!(p::Ptr{Any}, x::ANY, i::Integer) = pointerset(p, x, Int(i))
unsafe_store!{T}(p::Ptr{T}, x, i::Integer) = pointerset(p, convert(T,x), Int(i))
unsafe_store!{T}(p::Ptr{T}, x) = pointerset(p, convert(T,x), 1)
unsafe_load(p::Ptr, i::Integer=1) = pointerref(p, Int(i), 1)
unsafe_store!(p::Ptr{Any}, x::ANY, i::Integer=1) = pointerset(p, x, Int(i), 1)
unsafe_store!{T}(p::Ptr{T}, x, i::Integer=1) = pointerset(p, convert(T,x), Int(i), 1)

# unsafe pointer to string conversions (don't make a copy, unlike unsafe_string)
# (Cstring versions are in c.jl)
Expand Down
9 changes: 7 additions & 2 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ static Function *jlcall_frame_func;

static std::vector<Type *> two_pvalue_llvmt;
static std::vector<Type *> three_pvalue_llvmt;
static std::vector<Type *> four_pvalue_llvmt;

static std::map<jl_fptr_t, Function*> builtin_func_map;

Expand Down Expand Up @@ -5125,6 +5126,10 @@ static void init_julia_llvm_env(Module *m)
three_pvalue_llvmt.push_back(T_pjlvalue);
three_pvalue_llvmt.push_back(T_pjlvalue);
three_pvalue_llvmt.push_back(T_pjlvalue);
four_pvalue_llvmt.push_back(T_pjlvalue);
four_pvalue_llvmt.push_back(T_pjlvalue);
four_pvalue_llvmt.push_back(T_pjlvalue);
four_pvalue_llvmt.push_back(T_pjlvalue);
V_null = Constant::getNullValue(T_pjlvalue);

std::vector<Type*> ftargs(0);
Expand Down Expand Up @@ -5363,11 +5368,11 @@ static void init_julia_llvm_env(Module *m)
"jl_get_binding_or_error", m);
add_named_global(jlgetbindingorerror_func, &jl_get_binding_or_error);

jlpref_func = Function::Create(FunctionType::get(T_pjlvalue, two_pvalue_llvmt, false),
jlpref_func = Function::Create(FunctionType::get(T_pjlvalue, three_pvalue_llvmt, false),
Function::ExternalLinkage,
"jl_pointerref", m);

jlpset_func = Function::Create(FunctionType::get(T_pjlvalue, three_pvalue_llvmt, false),
jlpset_func = Function::Create(FunctionType::get(T_pjlvalue, four_pvalue_llvmt, false),
Function::ExternalLinkage,
"jl_pointerset", m);

Expand Down
64 changes: 39 additions & 25 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ static void jl_init_intrinsic_functions_codegen(Module *m)
std::vector<Type *> args3(0); \
args3.push_back(T_pjlvalue); \
args3.push_back(T_pjlvalue); \
args3.push_back(T_pjlvalue);
args3.push_back(T_pjlvalue); \
std::vector<Type *> args4(0); \
args4.push_back(T_pjlvalue); \
args4.push_back(T_pjlvalue); \
args4.push_back(T_pjlvalue); \
args4.push_back(T_pjlvalue);

#define ADD_I(name, nargs) do { \
Function *func = Function::Create(FunctionType::get(T_pjlvalue, args##nargs, false), \
Expand Down Expand Up @@ -723,14 +728,15 @@ static jl_cgval_t emit_checked_fptoui(jl_value_t *targ, jl_value_t *x, jl_codect
return mark_julia_type(ans, false, jlto, ctx);
}

static jl_cgval_t emit_runtime_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx)
static jl_cgval_t emit_runtime_pointerref(jl_value_t *e, jl_value_t *i, jl_value_t *align, jl_codectx_t *ctx)
{
jl_cgval_t parg = emit_expr(e, ctx);
Value *iarg = boxed(emit_expr(i, ctx), ctx);
Value *alignarg = boxed(emit_expr(align, ctx), ctx);
#ifdef LLVM37
Value *ret = builder.CreateCall(prepare_call(jlpref_func), { boxed(parg, ctx), iarg });
Value *ret = builder.CreateCall(prepare_call(jlpref_func), { boxed(parg, ctx), iarg, alignarg });
#else
Value *ret = builder.CreateCall2(prepare_call(jlpref_func), boxed(parg, ctx), iarg);
Value *ret = builder.CreateCall3(prepare_call(jlpref_func), boxed(parg, ctx), iarg, alignarg);
#endif
jl_value_t *ety;
if (jl_is_cpointer_type(parg.typ)) {
Expand All @@ -742,28 +748,32 @@ static jl_cgval_t emit_runtime_pointerref(jl_value_t *e, jl_value_t *i, jl_codec
return mark_julia_type(ret, true, ety, ctx);
}

static jl_cgval_t emit_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ctx)
static jl_cgval_t emit_pointerref(jl_value_t *e, jl_value_t *i, jl_value_t *align, jl_codectx_t *ctx)
{
jl_value_t *aty = expr_type(e, ctx);
if (!jl_is_cpointer_type(aty))
return emit_runtime_pointerref(e, i, ctx);
return emit_runtime_pointerref(e, i, align, ctx);
//jl_error("pointerref: expected pointer type as first argument");
jl_value_t *ety = jl_tparam0(aty);
if (jl_is_typevar(ety))
return emit_runtime_pointerref(e, i, ctx);
return emit_runtime_pointerref(e, i, align, ctx);
//jl_error("pointerref: invalid pointer");
if (expr_type(i, ctx) != (jl_value_t*)jl_long_type)
return emit_runtime_pointerref(e, i, ctx);
return emit_runtime_pointerref(e, i, align, ctx);
//jl_error("pointerref: invalid index type");
jl_cgval_t align_val = emit_expr(align, ctx);
if (align_val.constant == NULL || !jl_is_long(align_val.constant))
return emit_runtime_pointerref(e, i, align, ctx);
//jl_error("pointerref: invalid or non-statically evaluatable alignment")
Value *thePtr = auto_unbox(e,ctx);
Value *idx = emit_unbox(T_size, emit_expr(i, ctx), (jl_value_t*)jl_long_type);
Value *im1 = builder.CreateSub(idx, ConstantInt::get(T_size, 1));
if (!jl_isbits(ety)) {
if (ety == (jl_value_t*)jl_any_type)
return mark_julia_type(
builder.CreateLoad(builder.CreateGEP(
builder.CreateAlignedLoad(builder.CreateGEP(
emit_bitcast(thePtr, T_ppjlvalue),
im1)),
im1), jl_unbox_long(align_val.constant)),
true,
ety, ctx);
if (!jl_is_structtype(ety) || jl_is_array_type(ety) || !jl_is_leaf_type(ety)) {
Expand All @@ -781,33 +791,33 @@ static jl_cgval_t emit_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t *ct
thePtr, size, 1)->getCalledValue());
return mark_julia_type(strct, true, ety, ctx);
}
// TODO: alignment?
return typed_load(thePtr, im1, ety, ctx, tbaa_data, 1);
return typed_load(thePtr, im1, ety, ctx, tbaa_data, jl_unbox_long(align_val.constant));
}

static jl_cgval_t emit_runtime_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_codectx_t *ctx)
static jl_cgval_t emit_runtime_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_value_t *align, jl_codectx_t *ctx)
{
jl_cgval_t parg = emit_expr(e, ctx);
Value *iarg = boxed(emit_expr(i, ctx), ctx);
Value *xarg = boxed(emit_expr(x, ctx), ctx);
Value *iarg = boxed(emit_expr(i, ctx), ctx);
Value *alignarg = boxed(emit_expr(align, ctx), ctx);
#ifdef LLVM37
builder.CreateCall(prepare_call(jlpset_func), { boxed(parg, ctx), xarg, iarg });
builder.CreateCall(prepare_call(jlpset_func), { boxed(parg, ctx), xarg, iarg, alignarg });
#else
builder.CreateCall3(prepare_call(jlpset_func), boxed(parg, ctx), xarg, iarg);
builder.CreateCall3(prepare_call(jlpset_func), boxed(parg, ctx), xarg, iarg, alignarg);
#endif
return parg;
}

// e[i] = x
static jl_cgval_t emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_codectx_t *ctx)
static jl_cgval_t emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, jl_value_t *align, jl_codectx_t *ctx)
{
jl_value_t *aty = expr_type(e, ctx);
if (!jl_is_cpointer_type(aty))
return emit_runtime_pointerset(e, x, i, ctx);
return emit_runtime_pointerset(e, x, i, align, ctx);
//jl_error("pointerset: expected pointer type as first argument");
jl_value_t *ety = jl_tparam0(aty);
if (jl_is_typevar(ety))
return emit_runtime_pointerset(e, x, i, ctx);
return emit_runtime_pointerset(e, x, i, align, ctx);
//jl_error("pointerset: invalid pointer");
jl_value_t *xty = expr_type(x, ctx);
jl_cgval_t val;
Expand All @@ -818,8 +828,12 @@ static jl_cgval_t emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, j
emit_typecheck(val, ety, "pointerset: type mismatch in assign", ctx);
}
if (expr_type(i, ctx) != (jl_value_t*)jl_long_type)
return emit_runtime_pointerset(e, x, i, ctx);
return emit_runtime_pointerset(e, x, i, align, ctx);
//jl_error("pointerset: invalid index type");
jl_cgval_t align_val = emit_expr(align, ctx);
if (align_val.constant == NULL || !jl_is_long(align_val.constant))
return emit_runtime_pointerset(e, x, i, align, ctx);
//jl_error("pointerset: invalid or non-statically evaluatable alignment")
Value *idx = emit_unbox(T_size, emit_expr(i, ctx),(jl_value_t*)jl_long_type);
Value *im1 = builder.CreateSub(idx, ConstantInt::get(T_size, 1));
Value *thePtr = auto_unbox(e,ctx);
Expand All @@ -836,14 +850,14 @@ static jl_cgval_t emit_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t *i, j
im1 = builder.CreateMul(im1, ConstantInt::get(T_size,
LLT_ALIGN(size, ((jl_datatype_t*)ety)->layout->alignment)));
prepare_call(builder.CreateMemCpy(builder.CreateGEP(emit_bitcast(thePtr, T_pint8), im1),
data_pointer(val, ctx, T_pint8), size, 1)->getCalledValue());
data_pointer(val, ctx, T_pint8), size, jl_unbox_long(align_val.constant))->getCalledValue());
}
else {
if (!emitted) {
val = emit_expr(x, ctx);
}
// TODO: alignment?
typed_store(thePtr, im1, val, ety, ctx, tbaa_data, NULL, 1);
assert(jl_is_datatype(ety));
typed_store(thePtr, im1, val, ety, ctx, tbaa_data, NULL, jl_unbox_long(align_val.constant));
}
return mark_julia_type(thePtr, false, aty, ctx);
}
Expand Down Expand Up @@ -959,9 +973,9 @@ static jl_cgval_t emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
return mark_julia_type(r, true, (jl_value_t*)jl_any_type, ctx);
#else
case pointerref:
return emit_pointerref(args[1], args[2], ctx);
return emit_pointerref(args[1], args[2], args[3], ctx);
case pointerset:
return emit_pointerset(args[1], args[2], args[3], ctx);
return emit_pointerset(args[1], args[2], args[3], args[4], ctx);
case box:
return generic_box(args[1], args[2], ctx);
case unbox:
Expand Down
4 changes: 2 additions & 2 deletions src/intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@
ADD_I(powi_llvm, 2) \
ALIAS(sqrt_llvm_fast, sqrt_llvm) \
/* pointer access */ \
ADD_I(pointerref, 2) \
ADD_I(pointerset, 3) \
ADD_I(pointerref, 3) \
ADD_I(pointerset, 4) \
/* c interface */ \
ALIAS(ccall, ccall) \
ALIAS(cglobal, cglobal) \
Expand Down
4 changes: 2 additions & 2 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,8 @@ extern JL_DLLEXPORT jl_value_t *jl_segv_exception;
const char *jl_intrinsic_name(int f);

JL_DLLEXPORT jl_value_t *jl_reinterpret(jl_value_t *ty, jl_value_t *v);
JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i);
JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *i);
JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i, jl_value_t *align);
JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *align, jl_value_t *i);

JL_DLLEXPORT jl_value_t *jl_neg_int(jl_value_t *a);
JL_DLLEXPORT jl_value_t *jl_add_int(jl_value_t *a, jl_value_t *b);
Expand Down
10 changes: 7 additions & 3 deletions src/runtime_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ JL_DLLEXPORT jl_value_t *jl_reinterpret(jl_value_t *ty, jl_value_t *v)
}

// run time version of pointerref intrinsic (warning: i is not rooted)
JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i)
JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i, jl_value_t *align)
{
JL_TYPECHK(pointerref, pointer, p);
JL_TYPECHK(pointerref, long, i);
JL_TYPECHK(pointerref, long, i)
JL_TYPECHK(pointerref, long, align);
// TODO: alignment
jl_value_t *ety = jl_tparam0(jl_typeof(p));
if (ety == (jl_value_t*)jl_any_type) {
jl_value_t **pp = (jl_value_t**)(jl_unbox_long(p) + (jl_unbox_long(i)-1)*sizeof(void*));
Expand All @@ -51,10 +53,12 @@ JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i)
}

// run time version of pointerset intrinsic (warning: x is not gc-rooted)
JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *i)
JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *i, jl_value_t *align)
{
JL_TYPECHK(pointerset, pointer, p);
JL_TYPECHK(pointerset, long, i);
JL_TYPECHK(pointerref, long, align);
// TODO: alignment
jl_value_t *ety = jl_tparam0(jl_typeof(p));
if (ety == (jl_value_t*)jl_any_type) {
jl_value_t **pp = (jl_value_t**)(jl_unbox_long(p) + (jl_unbox_long(i)-1)*sizeof(void*));
Expand Down

0 comments on commit a8ca0ef

Please sign in to comment.