@@ -3321,7 +3321,7 @@ static Value *emit_genericmemoryptr(jl_codectx_t &ctx, Value *mem, const jl_data
3321
3321
LoadInst *LI = ctx.builder .CreateAlignedLoad (PPT, addr, Align (sizeof (char *)));
3322
3322
LI->setOrdering (AtomicOrdering::NotAtomic);
3323
3323
LI->setMetadata (LLVMContext::MD_nonnull, MDNode::get (ctx.builder .getContext (), None));
3324
- jl_aliasinfo_t aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_const );
3324
+ jl_aliasinfo_t aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
3325
3325
aliasinfo.decorateInst (LI);
3326
3326
Value *ptr = LI;
3327
3327
if (AS) {
@@ -3347,7 +3347,7 @@ static Value *emit_genericmemoryowner(jl_codectx_t &ctx, Value *t)
3347
3347
return emit_guarded_test (ctx, foreign, t, [&] {
3348
3348
addr = ctx.builder .CreateConstInBoundsGEP1_32 (ctx.types ().T_jlgenericmemory , m, 1 );
3349
3349
LoadInst *owner = ctx.builder .CreateAlignedLoad (ctx.types ().T_prjlvalue , addr, Align (sizeof (void *)));
3350
- jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_const );
3350
+ jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
3351
3351
ai.decorateInst (owner);
3352
3352
return ctx.builder .CreateSelect (ctx.builder .CreateIsNull (owner), t, owner);
3353
3353
});
@@ -4432,6 +4432,105 @@ static int compare_cgparams(const jl_cgparams_t *a, const jl_cgparams_t *b)
4432
4432
}
4433
4433
#endif
4434
4434
4435
+ static auto *emit_genericmemory_unchecked (jl_codectx_t &ctx, Value *cg_nbytes, Value *cg_typ)
4436
+ {
4437
+ auto ptls = get_current_ptls (ctx);
4438
+ auto call = prepare_call (jl_alloc_genericmemory_unchecked_func);
4439
+ auto *alloc = ctx.builder .CreateCall (call, { ptls, cg_nbytes, cg_typ});
4440
+ alloc->setAttributes (call->getAttributes ());
4441
+ alloc->addRetAttr (Attribute::getWithAlignment (alloc->getContext (), Align (JL_HEAP_ALIGNMENT)));
4442
+ call->addRetAttr (Attribute::getWithDereferenceableBytes (call->getContext (), sizeof (jl_genericmemory_t )));
4443
+ return alloc;
4444
+ }
4445
+
4446
+ static void emit_memory_zeroinit_and_stores (jl_codectx_t &ctx, jl_datatype_t *typ, Value* alloc, Value* nbytes, Value* nel, int zi)
4447
+ {
4448
+ auto arg_typename = [&] JL_NOTSAFEPOINT {
4449
+ std::string type_str;
4450
+ auto eltype = jl_tparam1 (typ);
4451
+ if (jl_is_datatype (eltype))
4452
+ type_str = jl_symbol_name (((jl_datatype_t *)eltype)->name ->name );
4453
+ else if (jl_is_uniontype (eltype))
4454
+ type_str = " Union" ;
4455
+ else
4456
+ type_str = " <unknown type>" ;
4457
+ return " Memory{" + type_str + " }[]" ;
4458
+ };
4459
+ setName (ctx.emission_context , alloc, arg_typename);
4460
+ // set length (jl_alloc_genericmemory_unchecked_func doesn't have it)
4461
+ Value *decay_alloc = decay_derived (ctx, alloc);
4462
+ Value *len_field = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 0 );
4463
+ auto len_store = ctx.builder .CreateAlignedStore (nel, len_field, Align (sizeof (void *)));
4464
+ auto aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memorylen );
4465
+ aliasinfo.decorateInst (len_store);
4466
+ // This avoids the length store from being deleted which is illegal
4467
+ ctx.builder .CreateFence (AtomicOrdering::Release, SyncScope::SingleThread);
4468
+ // zeroinit pointers and unions
4469
+ if (zi) {
4470
+ Value *memory_ptr = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 1 );
4471
+ auto *load = ctx.builder .CreateAlignedLoad (ctx.types ().T_ptr , memory_ptr, Align (sizeof (void *)));
4472
+ aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
4473
+ aliasinfo.decorateInst (load);
4474
+ auto int8t = getInt8Ty (ctx.builder .getContext ());
4475
+ ctx.builder .CreateMemSet (load, ConstantInt::get (int8t, 0 ), nbytes, Align (sizeof (void *)));
4476
+ }
4477
+ return ;
4478
+ }
4479
+
4480
+
4481
+ static jl_cgval_t emit_const_len_memorynew (jl_codectx_t &ctx, jl_datatype_t *typ, size_t nel, jl_genericmemory_t *inst)
4482
+ {
4483
+ if (nel == 0 ) {
4484
+ Value *empty_alloc = track_pjlvalue (ctx, literal_pointer_val (ctx, (jl_value_t *)inst));
4485
+ return mark_julia_type (ctx, empty_alloc, true , typ);
4486
+ }
4487
+ const jl_datatype_layout_t *layout = ((jl_datatype_t *)typ)->layout ;
4488
+ assert (((jl_datatype_t *)typ)->has_concrete_subtype && layout != NULL );
4489
+ size_t elsz = layout->size ;
4490
+ int isboxed = layout->flags .arrayelem_isboxed ;
4491
+ int isunion = layout->flags .arrayelem_isunion ;
4492
+ int zi = ((jl_datatype_t *)typ)->zeroinit ;
4493
+ if (isboxed)
4494
+ elsz = sizeof (void *);
4495
+ size_t nbytes;
4496
+ bool overflow = __builtin_mul_overflow (nel, elsz, &nbytes);
4497
+ if (isunion) {
4498
+ // an extra byte for each isbits union memory element, stored at m->ptr + m->length
4499
+ overflow |= __builtin_add_overflow (nbytes, nel, &nbytes);
4500
+ }
4501
+ // overflow if signed size is too big or nel is too big (the latter matters iff elsz==0)
4502
+ ssize_t tmp=1 ;
4503
+ overflow |= __builtin_add_overflow (nel, 1 , &tmp) || __builtin_add_overflow (nbytes, 1 , &tmp);
4504
+ if (overflow)
4505
+ emit_error (ctx, prepare_call (jlargumenterror_func), " invalid GenericMemory size: the number of elements is either negative or too large for system address width" );
4506
+
4507
+ auto T_size = ctx.types ().T_size ;
4508
+ auto cg_typ = literal_pointer_val (ctx, (jl_value_t *) typ);
4509
+ auto cg_nbytes = ConstantInt::get (T_size, nbytes);
4510
+ auto cg_nel = ConstantInt::get (T_size, nel);
4511
+ size_t tot = nbytes + LLT_ALIGN (sizeof (jl_genericmemory_t ),JL_SMALL_BYTE_ALIGNMENT);
4512
+ // if allocation fits within GC pools
4513
+ int pooled = tot <= GC_MAX_SZCLASS;
4514
+ Value *alloc, *decay_alloc, *memory_ptr;
4515
+ jl_aliasinfo_t aliasinfo;
4516
+ if (pooled) {
4517
+ alloc = emit_allocobj (ctx, tot, cg_typ, false , JL_SMALL_BYTE_ALIGNMENT);
4518
+ decay_alloc = decay_derived (ctx, alloc);
4519
+ memory_ptr = ctx.builder .CreateStructGEP (ctx.types ().T_jlgenericmemory , decay_alloc, 1 );
4520
+ setName (ctx.emission_context , memory_ptr, " memory_ptr" );
4521
+ auto objref = emit_pointer_from_objref (ctx, alloc);
4522
+ Value *memory_data = emit_ptrgep (ctx, objref, JL_SMALL_BYTE_ALIGNMENT);
4523
+ auto *store = ctx.builder .CreateAlignedStore (memory_data, memory_ptr, Align (sizeof (void *)));
4524
+ aliasinfo = jl_aliasinfo_t::fromTBAA (ctx, ctx.tbaa ().tbaa_memoryptr );
4525
+ aliasinfo.decorateInst (store);
4526
+ setName (ctx.emission_context , memory_data, " memory_data" );
4527
+ } else { // just use the dynamic length version since the malloc will be slow anyway
4528
+ alloc = emit_genericmemory_unchecked (ctx, cg_nbytes, cg_typ);
4529
+ }
4530
+ emit_memory_zeroinit_and_stores (ctx, typ, alloc, cg_nbytes, cg_nel, zi);
4531
+ return mark_julia_type (ctx, alloc, true , typ);
4532
+ }
4533
+
4435
4534
static jl_cgval_t emit_memorynew (jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval_t nel, jl_genericmemory_t *inst)
4436
4535
{
4437
4536
emit_typecheck (ctx, nel, (jl_value_t *)jl_long_type, " memorynew" );
@@ -4448,9 +4547,7 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval
4448
4547
if (isboxed)
4449
4548
elsz = sizeof (void *);
4450
4549
4451
- auto ptls = get_current_ptls (ctx);
4452
4550
auto T_size = ctx.types ().T_size ;
4453
- auto int8t = getInt8Ty (ctx.builder .getContext ());
4454
4551
BasicBlock *emptymemBB, *nonemptymemBB, *retvalBB;
4455
4552
emptymemBB = BasicBlock::Create (ctx.builder .getContext (), " emptymem" );
4456
4553
nonemptymemBB = BasicBlock::Create (ctx.builder .getContext (), " nonemptymem" );
@@ -4466,18 +4563,7 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval
4466
4563
ctx.builder .CreateBr (retvalBB);
4467
4564
nonemptymemBB->insertInto (ctx.f );
4468
4565
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
- };
4566
+
4481
4567
auto cg_typ = literal_pointer_val (ctx, (jl_value_t *) typ);
4482
4568
auto cg_elsz = ConstantInt::get (T_size, elsz);
4483
4569
@@ -4501,27 +4587,10 @@ static jl_cgval_t emit_memorynew(jl_codectx_t &ctx, jl_datatype_t *typ, jl_cgval
4501
4587
overflow = ctx.builder .CreateOr (overflow, tobignel);
4502
4588
Value *notoverflow = ctx.builder .CreateNot (overflow);
4503
4589
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
- }
4590
+ // actually allocate the memory
4523
4591
4524
- setName (ctx.emission_context , alloc, arg_typename);
4592
+ Value *alloc = emit_genericmemory_unchecked (ctx, nbytes, cg_typ);
4593
+ emit_memory_zeroinit_and_stores (ctx, typ, alloc, nbytes, nel_unboxed, zi);
4525
4594
ctx.builder .CreateBr (retvalBB);
4526
4595
nonemptymemBB = ctx.builder .GetInsertBlock ();
4527
4596
// phi node to choose which side of branch
0 commit comments