Skip to content

Commit

Permalink
fix issues with passing Ptr{Void}& to ccall
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash committed Jan 24, 2015
1 parent b3c574c commit 41a370e
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 13 deletions.
36 changes: 24 additions & 12 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,41 +269,53 @@ static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv,
// no copy, just reference the data field
return builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), ty); // skip type tag field
}
else if (jl_is_immutable_datatype(ety)) {
else if (jl_is_immutable_datatype(ety) && jt != (jl_value_t*)jl_voidpointer_type) {

This comment has been minimized.

Copy link
@JeffBezanson

JeffBezanson Jan 24, 2015

Member

Why is voidpointer_type a special case here?

This comment has been minimized.

Copy link
@vtjnash

vtjnash Jan 25, 2015

Author Member

in ccall(:a, B, (Ptr{Void},), &c), we expect to pass a pointer to the data of c (see also 41a370e#diff-be60d844ffde1319a02946d17c472e46R262)

without this, the code thinks it is passing a &Void(). while valid, that is not correct for all uses. (see also https://github.com/JuliaLang/julia/blob/master/base/base.jl#L56).

this is used in https://github.com/JuliaLang/julia/blob/master/base/libc.jl#L31, for example

This comment has been minimized.

Copy link
@JeffBezanson

JeffBezanson Jan 25, 2015

Member

That's right, thanks for reminding me.

This comment has been minimized.

Copy link
@vtjnash

vtjnash Jan 25, 2015

Author Member

as i mentioned in the PR, I want to eliminate & entirely. but the first step here is to make a transitional form that supports more flexible behavior, without breaking the existing code

// yes copy
Value *nbytes;
if (jl_is_leaf_type(ety))
nbytes = ConstantInt::get(T_int32, jl_datatype_size(ety));
else
nbytes = emit_nthptr_recast(emit_typeof(jv), offsetof(jl_datatype_t,size)/sizeof(char*), tbaa_datatype, T_int32);
nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad(
builder.CreateGEP(builder.CreatePointerCast(emit_typeof(jv), T_pint32),
ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/4)),
false));
*needStackRestore = true;
AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes);
ai->setAlignment(128); //bits = 16 bytes
ai->setAlignment(16);
builder.CreateMemCpy(ai, builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), T_pint8), nbytes, 1);
return builder.CreateBitCast(ai, ty);
}
// emit maybe copy
*needStackRestore = true;
Value *jvt = emit_typeof(jv);
Value *p;
BasicBlock *mutableBB = BasicBlock::Create(getGlobalContext(),"is-mutable",ctx->f);
BasicBlock *immutableBB = BasicBlock::Create(getGlobalContext(),"is-immutable",ctx->f);
BasicBlock *afterBB = BasicBlock::Create(getGlobalContext(),"after",ctx->f);
Value *ismutable = builder.CreateTrunc(emit_nthptr_recast(
jvt, offsetof(jl_datatype_t,mutabl)/sizeof(char*), tbaa_datatype, T_int8), T_int1);
Value *ismutable = builder.CreateTrunc(
tbaa_decorate(tbaa_datatype, builder.CreateLoad(
builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint8),
ConstantInt::get(T_size, offsetof(jl_datatype_t,mutabl))),
false)),
T_int1);
builder.CreateCondBr(ismutable, mutableBB, immutableBB);
builder.SetInsertPoint(mutableBB);
p = builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), ty); // skip type tag field
Value *p1 = builder.CreatePointerCast(emit_nthptr_addr(jv, (size_t)1), ty); // skip type tag field
builder.CreateBr(afterBB);
builder.SetInsertPoint(immutableBB);
Value *nbytes = emit_nthptr_recast(jvt, offsetof(jl_datatype_t,size)/sizeof(char*), tbaa_datatype, T_int32);
Value *nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad(
builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint32),
ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/4)),
false));
AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes);
ai->setAlignment(128); //bits = 16 bytes
builder.CreateMemCpy(ai, builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), T_pint8), nbytes, 1);
p = ai;
ai->setAlignment(16);
builder.CreateMemCpy(ai, builder.CreatePointerCast(emit_nthptr_addr(jv, (size_t)1), T_pint8), nbytes, 1);
Value *p2 = builder.CreatePointerCast(ai, ty);
builder.CreateBr(afterBB);
builder.SetInsertPoint(afterBB);
return builder.CreateBitCast(p, ty);
PHINode *p = builder.CreatePHI(ty, 2);
p->addIncoming(p1, mutableBB);
p->addIncoming(p2, immutableBB);
return p;
}
if (addressOf)
jl_error("ccall: unexpected & on argument"); // the only "safe" thing to emit here is the expected struct
Expand Down
2 changes: 1 addition & 1 deletion src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4030,7 +4030,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle)
builder.CreateAlloca(T_int8,
ConstantInt::get(T_int32,
sizeof(jl_handler_t)));
handlr->setAlignment(128); // bits == 16 bytes
handlr->setAlignment(16);
handlers[labl] = handlr;
}
}
Expand Down

0 comments on commit 41a370e

Please sign in to comment.