diff --git a/src/cgutils.cpp b/src/cgutils.cpp index a87a217f9b067..cce8408b1e11f 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -4505,23 +4505,23 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval auto T_size = ctx.types().T_size; auto int8t = getInt8Ty(ctx.builder.getContext()); - auto ptls = get_current_ptls(ctx); - BasicBlock *emptymemBB, *defaultBB, *retvalBB; + BasicBlock *emptymemBB, *nonemptymemBB, *retvalBB; emptymemBB = BasicBlock::Create(ctx.builder.getContext(), "emptymem"); - defaultBB = BasicBlock::Create(ctx.builder.getContext(), "default"); + nonemptymemBB = BasicBlock::Create(ctx.builder.getContext(), "nonemptymem"); retvalBB = BasicBlock::Create(ctx.builder.getContext(), "retval"); auto nel_unboxed = emit_unbox(ctx, ctx.types().T_size, nel, (jl_value_t*)jl_long_type); Value *memorynew_empty = ctx.builder.CreateICmpEQ(nel_unboxed, ConstantInt::get(T_size, 0)); setName(ctx.emission_context, memorynew_empty, "memorynew_empty"); - ctx.builder.CreateCondBr(memorynew_empty, emptymemBB, defaultBB); + ctx.builder.CreateCondBr(memorynew_empty, emptymemBB, nonemptymemBB); // if nel == 0 emptymemBB->insertInto(ctx.f); ctx.builder.SetInsertPoint(emptymemBB); - auto emptyalloc =literal_pointer_val(ctx, (jl_value_t*)inst); + auto emptyalloc = literal_pointer_val(ctx, (jl_value_t*)inst); ctx.builder.CreateBr(retvalBB); - defaultBB->insertInto(ctx.f); - ctx.builder.SetInsertPoint(defaultBB); + nonemptymemBB->insertInto(ctx.f); + ctx.builder.SetInsertPoint(nonemptymemBB); // else actually allocate mem + auto ptls = get_current_ptls(ctx); auto arg_typename = [&] JL_NOTSAFEPOINT { std::string type_str; auto eltype = jl_tparam1(typ); @@ -4537,10 +4537,12 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval auto cg_elsz = ConstantInt::get(T_size, elsz); FunctionCallee intr = Intrinsic::getDeclaration(jl_Module, Intrinsic::smul_with_overflow, ArrayRef(T_size)); + // compute nbytes with possible overflow Value *prod_with_overflow = ctx.builder.CreateCall(intr, {nel_unboxed, cg_elsz}); Value *nbytes = ctx.builder.CreateExtractValue(prod_with_overflow, 0); Value *overflow = ctx.builder.CreateExtractValue(prod_with_overflow, 1); if (isunion) { + // if isunion, we need to allocate the union selector bytes as well intr = Intrinsic::getDeclaration(jl_Module, Intrinsic::sadd_with_overflow, ArrayRef(T_size)); Value *add_with_overflow = ctx.builder.CreateCall(intr, {nel_unboxed, nbytes}); nbytes = ctx.builder.CreateExtractValue(add_with_overflow, 0); @@ -4549,13 +4551,18 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval } Value *notoverflow = ctx.builder.CreateNot(overflow); error_unless(ctx, notoverflow, "invalid GenericMemory size: too large for system address width"); - + // actually allocate (TODO: optimize alloc for fixed sizes) auto alloc = ctx.builder.CreateCall(prepare_call(jl_alloc_genericmemory_unchecked_func), { ptls, nbytes, cg_typ}); + // set length (jl_alloc_genericmemory_unchecked_func doesn't have it) auto len_field = ctx.builder.CreateStructGEP(ctx.types().T_jlgenericmemory, alloc, 0); ctx.builder.CreateStore(nel_unboxed, len_field); + // zeroinit pointers and unions if (zi) { auto data_field = ctx.builder.CreateStructGEP(ctx.types().T_jlgenericmemory, alloc, 1); - ctx.builder.CreateMemSet(data_field, ConstantInt::get(int8t, 0), nbytes, Align(sizeof(void*))); + jl_value_t *ety = jl_tparam1(typ); + Type *elty = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, ety); + auto data = ctx.builder.CreateInBoundsGEP(elty, data_field, 0); + ctx.builder.CreateMemSet(data, ConstantInt::get(int8t, 0), nbytes, Align(sizeof(void*))); } setName(ctx.emission_context, alloc, arg_typename); @@ -4565,8 +4572,8 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval ctx.builder.SetInsertPoint(retvalBB); auto phi = ctx.builder.CreatePHI(ctx.types().T_prjlvalue, 2); phi->addIncoming(emptyalloc, emptymemBB); - phi->addIncoming(alloc, defaultBB); - //ctx.f->print(dbgs(), NULL); + phi->addIncoming(alloc, nonemptymemBB); + ctx.f->print(dbgs(), NULL); return mark_julia_type(ctx, phi, true, typ); }