@@ -1548,19 +1548,24 @@ static void emit_error(jl_codectx_t &ctx, const Twine &txt)
15481548}
15491549
15501550// DO NOT PASS IN A CONST CONDITION!
1551- static void error_unless (jl_codectx_t &ctx, Value *cond, const Twine &msg)
1551+ static void error_unless (jl_codectx_t &ctx, Function *F, Value *cond, const Twine &msg)
15521552{
15531553 ++EmittedConditionalErrors;
15541554 BasicBlock *failBB = BasicBlock::Create (ctx.builder .getContext (), " fail" , ctx.f );
15551555 BasicBlock *passBB = BasicBlock::Create (ctx.builder .getContext (), " pass" );
15561556 ctx.builder .CreateCondBr (cond, passBB, failBB);
15571557 ctx.builder .SetInsertPoint (failBB);
1558- just_emit_error (ctx, prepare_call (jlerror_func) , msg);
1558+ just_emit_error (ctx, F , msg);
15591559 ctx.builder .CreateUnreachable ();
15601560 passBB->insertInto (ctx.f );
15611561 ctx.builder .SetInsertPoint (passBB);
15621562}
15631563
1564+ static void error_unless (jl_codectx_t &ctx, Value *cond, const Twine &msg)
1565+ {
1566+ error_unless (ctx, prepare_call (jlerror_func), cond, msg);
1567+ }
1568+
15641569static void raise_exception (jl_codectx_t &ctx, Value *exc,
15651570 BasicBlock *contBB=nullptr )
15661571{
@@ -4427,6 +4432,107 @@ static int compare_cgparams(const jl_cgparams_t *a, const jl_cgparams_t *b)
44274432}
44284433#endif
44294434
4435+ static jl_cgval_t emit_memorynew (jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval_t nel, jl_genericmemory_t *inst)
4436+ {
4437+ emit_typecheck (ctx, nel, (jl_value_t *)jl_long_type, " memorynew" );
4438+ nel = update_julia_type (ctx, nel, (jl_value_t *)jl_long_type);
4439+ if (nel.typ == jl_bottom_type)
4440+ return jl_cgval_t ();
4441+
4442+ const jl_datatype_layout_t *layout = ((jl_datatype_t *)typ)->layout ;
4443+ assert (((jl_datatype_t *)typ)->has_concrete_subtype && layout != NULL );
4444+ size_t elsz = layout->size ;
4445+ int isboxed = layout->flags .arrayelem_isboxed ;
4446+ int isunion = layout->flags .arrayelem_isunion ;
4447+ int zi = ((jl_datatype_t *)typ)->zeroinit ;
4448+ if (isboxed)
4449+ elsz = sizeof (void *);
4450+
4451+ auto ptls = get_current_ptls (ctx);
4452+ auto T_size = ctx.types ().T_size ;
4453+ auto int8t = getInt8Ty (ctx.builder .getContext ());
4454+ BasicBlock *emptymemBB, *nonemptymemBB, *retvalBB;
4455+ emptymemBB = BasicBlock::Create (ctx.builder .getContext (), " emptymem" );
4456+ nonemptymemBB = BasicBlock::Create (ctx.builder .getContext (), " nonemptymem" );
4457+ retvalBB = BasicBlock::Create (ctx.builder .getContext (), " retval" );
4458+ auto nel_unboxed = emit_unbox (ctx, ctx.types ().T_size , nel, (jl_value_t *)jl_long_type);
4459+ Value *memorynew_empty = ctx.builder .CreateICmpEQ (nel_unboxed, ConstantInt::get (T_size, 0 ));
4460+ setName (ctx.emission_context , memorynew_empty, " memorynew_empty" );
4461+ ctx.builder .CreateCondBr (memorynew_empty, emptymemBB, nonemptymemBB);
4462+ // if nel == 0
4463+ emptymemBB->insertInto (ctx.f );
4464+ ctx.builder .SetInsertPoint (emptymemBB);
4465+ auto emptyalloc = track_pjlvalue (ctx, literal_pointer_val (ctx, (jl_value_t *)inst));
4466+ ctx.builder .CreateBr (retvalBB);
4467+ nonemptymemBB->insertInto (ctx.f );
4468+ ctx.builder .SetInsertPoint (nonemptymemBB);
4469+ // else actually allocate mem
4470+ auto arg_typename = [&] JL_NOTSAFEPOINT {
4471+ std::string type_str;
4472+ auto eltype = jl_tparam1 (typ);
4473+ if (jl_is_datatype (eltype))
4474+ type_str = jl_symbol_name (((jl_datatype_t *)eltype)->name ->name );
4475+ else if (jl_is_uniontype (eltype))
4476+ type_str = " Union" ;
4477+ else
4478+ type_str = " <unknown type>" ;
4479+ return " Memory{" + type_str + " }[]" ;
4480+ };
4481+ auto cg_typ = literal_pointer_val (ctx, (jl_value_t *) typ);
4482+ auto cg_elsz = ConstantInt::get (T_size, elsz);
4483+
4484+ FunctionCallee intr = Intrinsic::getDeclaration (jl_Module, Intrinsic::smul_with_overflow, ArrayRef<Type*>(T_size));
4485+ // compute nbytes with possible overflow
4486+ Value *prod_with_overflow = ctx.builder .CreateCall (intr, {nel_unboxed, cg_elsz});
4487+ Value *nbytes = ctx.builder .CreateExtractValue (prod_with_overflow, 0 );
4488+ Value *overflow = ctx.builder .CreateExtractValue (prod_with_overflow, 1 );
4489+ if (isunion) {
4490+ // if isunion, we need to allocate the union selector bytes as well
4491+ intr = Intrinsic::getDeclaration (jl_Module, Intrinsic::sadd_with_overflow, ArrayRef<Type*>(T_size));
4492+ Value *add_with_overflow = ctx.builder .CreateCall (intr, {nel_unboxed, nbytes});
4493+ nbytes = ctx.builder .CreateExtractValue (add_with_overflow, 0 );
4494+ Value *overflow1 = ctx.builder .CreateExtractValue (add_with_overflow, 1 );
4495+ overflow = ctx.builder .CreateOr (overflow, overflow1);
4496+ }
4497+ Value *negnel = ctx.builder .CreateICmpSLT (nel_unboxed, ConstantInt::get (T_size, 0 ));
4498+ overflow = ctx.builder .CreateOr (overflow, negnel);
4499+ auto cg_typemax_int = ConstantInt::get (T_size, (((size_t )-1 )>>1 )-1 );
4500+ Value *tobignel = ctx.builder .CreateICmpSLT (cg_typemax_int, elsz == 0 ? nel_unboxed: nbytes);
4501+ overflow = ctx.builder .CreateOr (overflow, tobignel);
4502+ Value *notoverflow = ctx.builder .CreateNot (overflow);
4503+ error_unless (ctx, prepare_call (jlargumenterror_func), notoverflow, " invalid GenericMemory size: the number of elements is either negative or too large for system address width" );
4504+ // actually allocate
4505+ auto call = prepare_call (jl_alloc_genericmemory_unchecked_func);
4506+ Value *alloc = ctx.builder .CreateCall (call, { ptls, nbytes, cg_typ});
4507+ // set length (jl_alloc_genericmemory_unchecked_func doesn't have it)
4508+ Value *decay_alloc = decay_derived (ctx, alloc);
4509+ Value *len_field = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 0 );
4510+ auto len_store = ctx.builder .CreateAlignedStore (nel_unboxed, len_field, Align (sizeof (void *)));
4511+ auto aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memorylen );
4512+ aliasinfo.decorateInst (len_store);
4513+ // This avoids the length store from being deleted which is illegal
4514+ ctx.builder .CreateFence (AtomicOrdering::Release, SyncScope::SingleThread);
4515+ // zeroinit pointers and unions
4516+ if (zi) {
4517+ Value *memory_ptr = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 1 );
4518+ auto *load = ctx.builder .CreateAlignedLoad (ctx.types ().T_ptr , memory_ptr, Align (sizeof (void *)));
4519+ aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
4520+ aliasinfo.decorateInst (load);
4521+ ctx.builder .CreateMemSet (load, ConstantInt::get (int8t, 0 ), nbytes, Align (sizeof (void *)));
4522+ }
4523+
4524+ setName (ctx.emission_context , alloc, arg_typename);
4525+ ctx.builder .CreateBr (retvalBB);
4526+ nonemptymemBB = ctx.builder .GetInsertBlock ();
4527+ // phi node to choose which side of branch
4528+ retvalBB->insertInto (ctx.f );
4529+ ctx.builder .SetInsertPoint (retvalBB);
4530+ auto phi = ctx.builder .CreatePHI (ctx.types ().T_prjlvalue , 2 );
4531+ phi->addIncoming (emptyalloc, emptymemBB);
4532+ phi->addIncoming (alloc, nonemptymemBB);
4533+ return mark_julia_type (ctx, phi, true , typ);
4534+ }
4535+
44304536static jl_cgval_t _emit_memoryref (jl_codectx_t &ctx, Value *mem, Value *data, const jl_datatype_layout_t *layout, jl_value_t *typ)
44314537{
44324538 // jl_cgval_t argv[] = {
0 commit comments