static void emit_func_check(Value *x, jl_codectx_t *ctx) { Value *istype1 = builder.CreateICmpEQ(emit_typeof(emit_typeof(x)), literal_pointer_val((jl_value_t*)jl_func_kind)); BasicBlock *elseBB1 = BasicBlock::Create(getGlobalContext(),"a", ctx->f); BasicBlock *mergeBB1 = BasicBlock::Create(getGlobalContext(),"b"); builder.CreateCondBr(istype1, mergeBB1, elseBB1); builder.SetInsertPoint(elseBB1); Value *istype2 = builder.CreateICmpEQ(emit_typeof(x), literal_pointer_val((jl_value_t*)jl_struct_kind)); BasicBlock *elseBB2 = BasicBlock::Create(getGlobalContext(),"a", ctx->f); builder.CreateCondBr(istype2, mergeBB1, elseBB2); builder.SetInsertPoint(elseBB2); emit_type_error(x, (jl_value_t*)jl_function_type, "apply", ctx); builder.CreateBr(mergeBB1); ctx->f->getBasicBlockList().push_back(mergeBB1); builder.SetInsertPoint(mergeBB1); }
static void emit_typecheck(Value *x, jl_value_t *type, const std::string &msg, jl_codectx_t *ctx) { Value *istype = builder.CreateICmpEQ(emit_typeof(x), literal_pointer_val(type)); BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f); BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass"); builder.CreateCondBr(istype, passBB, failBB); builder.SetInsertPoint(failBB); emit_type_error(x, type, msg, ctx); builder.CreateBr(passBB); ctx->f->getBasicBlockList().push_back(passBB); builder.SetInsertPoint(passBB); }
static void emit_cpointercheck(Value *x, const std::string &msg, jl_codectx_t *ctx) { Value *t = emit_typeof(x); emit_typecheck(t, (jl_value_t*)jl_datatype_type, msg, ctx); Value *istype = builder.CreateICmpEQ(emit_nthptr(t, offsetof(jl_datatype_t,name)/sizeof(char*)), literal_pointer_val((jl_value_t*)jl_pointer_type->name)); BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f); BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass"); builder.CreateCondBr(istype, passBB, failBB); builder.SetInsertPoint(failBB); emit_type_error(x, (jl_value_t*)jl_pointer_type, msg, ctx); builder.CreateBr(passBB); ctx->f->getBasicBlockList().push_back(passBB); builder.SetInsertPoint(passBB); }
static void emit_func_check(Value *x, jl_codectx_t *ctx) { Value *xty = emit_typeof(x); Value *isfunc = builder. CreateOr(builder. CreateICmpEQ(xty, literal_pointer_val((jl_value_t*)jl_function_type)), builder. CreateICmpEQ(xty, literal_pointer_val((jl_value_t*)jl_datatype_type))); BasicBlock *elseBB1 = BasicBlock::Create(getGlobalContext(),"notf", ctx->f); BasicBlock *mergeBB1 = BasicBlock::Create(getGlobalContext(),"isf"); builder.CreateCondBr(isfunc, mergeBB1, elseBB1); builder.SetInsertPoint(elseBB1); emit_type_error(x, (jl_value_t*)jl_function_type, "apply", ctx); builder.CreateBr(mergeBB1); ctx->f->getBasicBlockList().push_back(mergeBB1); builder.SetInsertPoint(mergeBB1); }
static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, jl_value_t *aty, bool addressOf, bool byRef, bool inReg, bool needCopy, int argn, jl_codectx_t *ctx, bool *needStackRestore) { Type *vt = jv->getType(); // We're passing any if (ty == jl_pvalue_llvmt) { return boxed(jv,ctx); } if (ty == vt && !addressOf && !byRef) { return jv; } if (vt != jl_pvalue_llvmt) { // argument value is unboxed if (addressOf || (byRef && inReg)) { if (ty->isPointerTy() && ty->getContainedType(0)==vt) { // pass the address of an alloca'd thing, not a box // since those are immutable. *needStackRestore = true; Value *slot = builder.CreateAlloca(vt); builder.CreateStore(jv, slot); return builder.CreateBitCast(slot, ty); } } else if ((vt->isIntegerTy() && ty->isIntegerTy()) || (vt->isFloatingPointTy() && ty->isFloatingPointTy()) || (vt->isPointerTy() && ty->isPointerTy())) { if (vt->getPrimitiveSizeInBits() == ty->getPrimitiveSizeInBits()) { if (!byRef) { return builder.CreateBitCast(jv, ty); } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(ty); builder.CreateStore(jv,builder.CreateBitCast(mem,vt->getPointerTo())); return mem; } } } else if (vt->isStructTy()) { if (!byRef) { return jv; } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(vt); builder.CreateStore(jv,mem); return mem; } } emit_error("ccall: argument type did not match declaration", ctx); } if (jl_is_tuple(jt)) { return emit_unbox(ty,jv,jt); } if (jl_is_cpointer_type(jt) && addressOf) { assert(ty->isPointerTy()); jl_value_t *ety = jl_tparam0(jt); if (aty != ety && ety != (jl_value_t*)jl_any_type && jt != (jl_value_t*)jl_voidpointer_type) { std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, ety, msg.str(), ctx); } if (jl_is_mutable_datatype(ety)) { // no copy, just reference the data field return builder.CreateBitCast(jv, ty); } else if (jl_is_immutable_datatype(ety) && jt != (jl_value_t*)jl_voidpointer_type) { // yes copy Value *nbytes; if (jl_is_leaf_type(ety)) nbytes = ConstantInt::get(T_int32, jl_datatype_size(ety)); else 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)/sizeof(int32_t))), false)); *needStackRestore = true; AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes); ai->setAlignment(16); builder.CreateMemCpy(ai, builder.CreateBitCast(jv, T_pint8), nbytes, 1); return builder.CreateBitCast(ai, ty); } // emit maybe copy *needStackRestore = true; Value *jvt = emit_typeof(jv); 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( 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); Value *p1 = builder.CreatePointerCast(jv, ty); builder.CreateBr(afterBB); builder.SetInsertPoint(immutableBB); Value *nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad( builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint32), ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/sizeof(int32_t))), false)); AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes); ai->setAlignment(16); builder.CreateMemCpy(ai, builder.CreatePointerCast(jv, T_pint8), nbytes, 1); Value *p2 = builder.CreatePointerCast(ai, ty); builder.CreateBr(afterBB); builder.SetInsertPoint(afterBB); 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 assert(jl_is_datatype(jt)); if (aty != jt) { std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, jt, msg.str(), ctx); } Value *p = data_pointer(jv); Value *pjv = builder.CreatePointerCast(p, PointerType::get(ty,0)); if (byRef) { if (!needCopy) { return pjv; } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(ty); builder.CreateMemCpy(mem,pjv,(uint64_t)jl_datatype_size(jt),(uint64_t)((jl_datatype_t*)jt)->alignment); return mem; } } else { return builder.CreateLoad(pjv,false); } }