Skip to content

Commit 4a5e85d

Browse files
vtjnashquinnj
authored andcommitted
fix codegen bugs, simplify type representations
anonymize all types, remove special representation for Ptr, fix Constant generation for types containing split-union fields
1 parent 1cf7f28 commit 4a5e85d

10 files changed

+386
-367
lines changed

base/atomics.jl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -345,28 +345,31 @@ for typ in atomictypes
345345
irt = Base.libllvm_version >= v"3.6" ? "$ilt, $ilt*" : "$ilt*"
346346
@eval getindex(x::Atomic{$typ}) =
347347
llvmcall($"""
348-
%rv = load atomic $rt %0 acquire, align $(alignment(typ))
348+
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
349+
%rv = load atomic $rt %ptr acquire, align $(alignment(typ))
349350
ret $lt %rv
350351
""", $typ, Tuple{Ptr{$typ}}, unsafe_convert(Ptr{$typ}, x))
351352
@eval setindex!(x::Atomic{$typ}, v::$typ) =
352353
llvmcall($"""
353-
store atomic $lt %1, $lt* %0 release, align $(alignment(typ))
354+
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
355+
store atomic $lt %1, $lt* %ptr release, align $(alignment(typ))
354356
ret void
355-
""", Void, Tuple{Ptr{$typ},$typ}, unsafe_convert(Ptr{$typ}, x), v)
357+
""", Void, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v)
356358

357359
# Note: atomic_cas! succeeded (i.e. it stored "new") if and only if the result is "cmp"
358360
if typ <: Integer
359361
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
360362
llvmcall($"""
361-
%rs = cmpxchg $lt* %0, $lt %1, $lt %2 acq_rel acquire
363+
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
364+
%rs = cmpxchg $lt* %ptr, $lt %1, $lt %2 acq_rel acquire
362365
%rv = extractvalue { $lt, i1 } %rs, 0
363366
ret $lt %rv
364367
""", $typ, Tuple{Ptr{$typ},$typ,$typ},
365368
unsafe_convert(Ptr{$typ}, x), cmp, new)
366369
else
367370
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
368371
llvmcall($"""
369-
%iptr = bitcast $lt* %0 to $ilt*
372+
%iptr = inttoptr i$WORD_SIZE %0 to $ilt*
370373
%icmp = bitcast $lt %1 to $ilt
371374
%inew = bitcast $lt %2 to $ilt
372375
%irs = cmpxchg $ilt* %iptr, $ilt %icmp, $ilt %inew acq_rel acquire
@@ -387,14 +390,15 @@ for typ in atomictypes
387390
if typ <: Integer
388391
@eval $fn(x::Atomic{$typ}, v::$typ) =
389392
llvmcall($"""
390-
%rv = atomicrmw $rmw $lt* %0, $lt %1 acq_rel
393+
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
394+
%rv = atomicrmw $rmw $lt* %ptr, $lt %1 acq_rel
391395
ret $lt %rv
392396
""", $typ, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v)
393397
else
394398
rmwop == :xchg || continue
395399
@eval $fn(x::Atomic{$typ}, v::$typ) =
396400
llvmcall($"""
397-
%iptr = bitcast $lt* %0 to $ilt*
401+
%iptr = inttoptr i$WORD_SIZE %0 to $ilt*
398402
%ival = bitcast $lt %1 to $ilt
399403
%irv = atomicrmw $rmw $ilt* %iptr, $ilt %ival acq_rel
400404
%rv = bitcast $ilt %irv to $lt

base/fastmath.jl

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -296,34 +296,18 @@ asin_fast(x::FloatTypes) = asin(x)
296296

297297
# explicit implementations
298298

299-
# FIXME: Change to `ccall((:sincos, libm))` when `Ref` calling convention can be
300-
# stack allocated.
301299
@inline function sincos_fast(v::Float64)
302-
return Base.llvmcall("""
303-
%f = bitcast i8 *%1 to void (double, double *, double *)*
304-
%ps = alloca double
305-
%pc = alloca double
306-
call void %f(double %0, double *%ps, double *%pc)
307-
%s = load double, double* %ps
308-
%c = load double, double* %pc
309-
%res0 = insertvalue [2 x double] undef, double %s, 0
310-
%res = insertvalue [2 x double] %res0, double %c, 1
311-
ret [2 x double] %res
312-
""", Tuple{Float64,Float64}, Tuple{Float64,Ptr{Void}}, v, cglobal((:sincos, libm)))
300+
s = Ref{Cdouble}()
301+
c = Ref{Cdouble}()
302+
ccall((:sincos, libm), Void, (Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), v, s, c)
303+
return (s[], c[])
313304
end
314305

315306
@inline function sincos_fast(v::Float32)
316-
return Base.llvmcall("""
317-
%f = bitcast i8 *%1 to void (float, float *, float *)*
318-
%ps = alloca float
319-
%pc = alloca float
320-
call void %f(float %0, float *%ps, float *%pc)
321-
%s = load float, float* %ps
322-
%c = load float, float* %pc
323-
%res0 = insertvalue [2 x float] undef, float %s, 0
324-
%res = insertvalue [2 x float] %res0, float %c, 1
325-
ret [2 x float] %res
326-
""", Tuple{Float32,Float32}, Tuple{Float32,Ptr{Void}}, v, cglobal((:sincosf, libm)))
307+
s = Ref{Cfloat}()
308+
c = Ref{Cfloat}()
309+
ccall((:sincosf, libm), Void, (Cfloat, Ptr{Cfloat}, Ptr{Cfloat}), v, s, c)
310+
return (s[], c[])
327311
end
328312

329313
@inline function sincos_fast(v::Float16)

src/ccall.cpp

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ static Value *runtime_sym_lookup(
182182
PHINode *p = irbuilder.CreatePHI(T_pvoidfunc, 2);
183183
p->addIncoming(llvmf_orig, enter_bb);
184184
p->addIncoming(llvmf, dlsym_lookup);
185-
return irbuilder.CreatePointerCast(p, funcptype);
185+
return irbuilder.CreateBitCast(p, funcptype);
186186
}
187187

188188
static Value *runtime_sym_lookup(
@@ -534,7 +534,7 @@ static Value *julia_to_address(
534534
{
535535
assert(jl_is_datatype(jlto) && julia_struct_has_layout((jl_datatype_t*)jlto, jlto_env));
536536

537-
if (!jl_is_cpointer_type(jlto) || !to->isPointerTy()) {
537+
if (!jl_is_cpointer_type(jlto) || to != T_size) {
538538
emit_error(ctx, "ccall: & on argument was not matched by Ptr{T} argument type");
539539
return UndefValue::get(to);
540540
}
@@ -547,19 +547,18 @@ static Value *julia_to_address(
547547
ety = jl_tparam0(jlto);
548548
typeassert_input(ctx, jvinfo, ety, jlto_env, argn, true);
549549
}
550-
assert(to->isPointerTy());
551550

552551
if (jvinfo.isboxed) {
553552
if (!jl_is_abstracttype(ety)) {
554553
if (jl_is_mutable_datatype(ety)) {
555554
// no copy, just reference the data field
556-
return data_pointer(ctx, jvinfo, to);
555+
return ctx.builder.CreateBitCast(emit_pointer_from_objref(ctx, data_pointer(ctx, jvinfo)), to);
557556
}
558-
else if (jl_is_immutable_datatype(ety) && jlto != (jl_value_t*)jl_voidpointer_type) {
557+
else if (jl_is_immutable_datatype(ety) && jlto != (jl_value_t*)jl_voidpointer_type) { // anything declared `struct`, except Ptr{Void}
559558
// yes copy
560559
Value *nbytes;
561560
AllocaInst *ai;
562-
if (jl_is_leaf_type(ety) || jl_is_primitivetype(ety)) {
561+
if (((jl_datatype_t*)ety)->layout) {
563562
int nb = jl_datatype_size(ety);
564563
nbytes = ConstantInt::get(T_int32, nb);
565564
ai = emit_static_alloca(ctx, T_int8, nb);
@@ -571,7 +570,7 @@ static Value *julia_to_address(
571570
}
572571
ai->setAlignment(16);
573572
ctx.builder.CreateMemCpy(ai, data_pointer(ctx, jvinfo, T_pint8), nbytes, sizeof(void*)); // minimum gc-alignment in julia is pointer size
574-
return emit_bitcast(ctx, ai, to);
573+
return ctx.builder.CreatePtrToInt(ai, to);
575574
}
576575
}
577576
// emit maybe copy
@@ -583,14 +582,14 @@ static Value *julia_to_address(
583582
Value *ismutable = emit_datatype_mutabl(ctx, jvt);
584583
ctx.builder.CreateCondBr(ismutable, mutableBB, immutableBB);
585584
ctx.builder.SetInsertPoint(mutableBB);
586-
Value *p1 = data_pointer(ctx, jvinfo, to);
585+
Value *p1 = ctx.builder.CreateBitCast(emit_pointer_from_objref(ctx, data_pointer(ctx, jvinfo)), to);
587586
ctx.builder.CreateBr(afterBB);
588587
ctx.builder.SetInsertPoint(immutableBB);
589588
Value *nbytes = emit_datatype_size(ctx, jvt);
590589
AllocaInst *ai = ctx.builder.CreateAlloca(T_int8, nbytes);
591590
ai->setAlignment(16);
592591
ctx.builder.CreateMemCpy(ai, data_pointer(ctx, jvinfo, T_pint8), nbytes, sizeof(void*)); // minimum gc-alignment in julia is pointer size
593-
Value *p2 = emit_bitcast(ctx, ai, to);
592+
Value *p2 = ctx.builder.CreatePtrToInt(ai, to);
594593
ctx.builder.CreateBr(afterBB);
595594
ctx.builder.SetInsertPoint(afterBB);
596595
PHINode *p = ctx.builder.CreatePHI(to, 2);
@@ -612,9 +611,7 @@ static Value *julia_to_address(
612611
(uint64_t)jl_datatype_size(ety),
613612
(uint64_t)jl_datatype_align(ety));
614613
}
615-
if (slot->getType() != to)
616-
slot = emit_bitcast(ctx, slot, to);
617-
return slot;
614+
return ctx.builder.CreatePtrToInt(slot, to);
618615
}
619616

620617

@@ -781,22 +778,21 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
781778
rt = (jl_value_t*)jl_voidpointer_type;
782779
}
783780
Type *lrt = julia_type_to_llvm(rt);
784-
if (lrt == NULL)
785-
lrt = T_pint8;
786781

787782
interpret_symbol_arg(ctx, sym, args[1], "cglobal", false);
788783

789784
if (sym.jl_ptr != NULL) {
790-
res = ctx.builder.CreateIntToPtr(sym.jl_ptr, lrt);
785+
res = ctx.builder.CreateBitCast(sym.jl_ptr, lrt);
791786
}
792787
else if (sym.fptr != NULL) {
793-
res = literal_static_pointer_val(ctx, (void*)(uintptr_t)sym.fptr, lrt);
788+
res = ConstantInt::get(lrt, (uint64_t)sym.fptr);
794789
if (imaging_mode)
795790
jl_printf(JL_STDERR,"WARNING: literal address used in cglobal for %s; code cannot be statically compiled\n", sym.f_name);
796791
}
797792
else {
798793
if (imaging_mode) {
799-
res = runtime_sym_lookup(ctx, (PointerType*)lrt, sym.f_lib, sym.f_name, ctx.f);
794+
res = runtime_sym_lookup(ctx, cast<PointerType>(T_pint8), sym.f_lib, sym.f_name, ctx.f);
795+
res = ctx.builder.CreatePtrToInt(res, lrt);
800796
}
801797
else {
802798
void *symaddr = jl_dlsym_e(jl_get_library(sym.f_lib), sym.f_name);
@@ -815,7 +811,7 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
815811
}
816812
// since we aren't saving this code, there's no sense in
817813
// putting anything complicated here: just JIT the address of the cglobal
818-
res = literal_static_pointer_val(ctx, symaddr, lrt);
814+
res = ConstantInt::get(lrt, (uint64_t)symaddr);
819815
}
820816
}
821817

@@ -1590,17 +1586,17 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
15901586

15911587
// some special functions
15921588
if (is_libjulia_func(jl_array_ptr)) {
1593-
assert(lrt->isPointerTy());
1589+
assert(lrt == T_size);
15941590
assert(!isVa && !llvmcall && nargt == 1);
15951591
assert(!addressOf.at(0));
15961592
const jl_cgval_t &ary = argv[0];
15971593
jl_value_t *aryex = ccallarg(0);
15981594
JL_GC_POP();
1599-
return mark_or_box_ccall_result(ctx, emit_bitcast(ctx, emit_arrayptr(ctx, ary, aryex), lrt),
1595+
return mark_or_box_ccall_result(ctx, ctx.builder.CreatePtrToInt(emit_arrayptr(ctx, ary, aryex), lrt),
16001596
retboxed, rt, unionall, static_rt);
16011597
}
16021598
else if (is_libjulia_func(jl_value_ptr)) {
1603-
assert(lrt->isPointerTy());
1599+
assert(retboxed ? lrt == T_prjlvalue : lrt == T_size);
16041600
assert(!isVa && !llvmcall && nargt == 1);
16051601
jl_value_t *tti = jl_svecref(at, 0);
16061602
Value *ary;
@@ -1612,7 +1608,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16121608
}
16131609
else if (jl_is_abstract_ref_type(tti)) {
16141610
tti = (jl_value_t*)jl_voidpointer_type;
1615-
largty = T_pint8;
1611+
largty = T_size;
16161612
isboxed = false;
16171613
}
16181614
else {
@@ -1628,13 +1624,16 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16281624
if (!retboxed) {
16291625
return mark_or_box_ccall_result(
16301626
ctx,
1631-
emit_bitcast(ctx, emit_pointer_from_objref(ctx,
1632-
emit_bitcast(ctx, ary, T_prjlvalue)), lrt),
1627+
emit_pointer_from_objref(ctx,
1628+
emit_bitcast(ctx, ary, T_prjlvalue)),
16331629
retboxed, rt, unionall, static_rt);
1634-
} else {
1630+
}
1631+
else {
16351632
return mark_or_box_ccall_result(
16361633
ctx,
1637-
maybe_decay_untracked(emit_bitcast(ctx, ary, lrt)),
1634+
ctx.builder.CreateAddrSpaceCast(
1635+
ctx.builder.CreateIntToPtr(ary, T_pjlvalue),
1636+
T_prjlvalue), // TODO: this addrspace cast is invalid (implies that the value is rooted elsewhere)
16381637
retboxed, rt, unionall, static_rt);
16391638
}
16401639
}
@@ -1694,11 +1693,11 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16941693
return ghostValue(jl_void_type);
16951694
}
16961695
else if (_is_libjulia_func((uintptr_t)ptls_getter, "jl_get_ptls_states")) {
1697-
assert(lrt == T_pint8);
1696+
assert(lrt == T_size);
16981697
assert(!isVa && !llvmcall && nargt == 0);
16991698
JL_GC_POP();
17001699
return mark_or_box_ccall_result(ctx,
1701-
emit_bitcast(ctx, ctx.ptlsStates, lrt),
1700+
ctx.builder.CreatePtrToInt(ctx.ptlsStates, lrt),
17021701
retboxed, rt, unionall, static_rt);
17031702
}
17041703
else if (is_libjulia_func(jl_threadid)) {
@@ -1771,6 +1770,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17711770
}
17721771
else if (is_libjulia_func(jl_function_ptr)) {
17731772
assert(!isVa && !llvmcall && nargt == 3);
1773+
assert(lrt == T_size);
17741774
jl_value_t *f = argv[0].constant;
17751775
jl_value_t *frt = argv[1].constant;
17761776
if (!frt) {
@@ -1797,11 +1797,10 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17971797
llvmf = NULL;
17981798
}
17991799
if (llvmf) {
1800-
llvmf = prepare_call(llvmf);
18011800
JL_GC_POP();
18021801
JL_GC_POP();
1803-
return mark_or_box_ccall_result(ctx, emit_bitcast(ctx, llvmf, lrt),
1804-
retboxed, rt, unionall, static_rt);
1802+
Value *fptr = ctx.builder.CreatePtrToInt(prepare_call(llvmf), lrt);
1803+
return mark_or_box_ccall_result(ctx, fptr, retboxed, rt, unionall, static_rt);
18051804
}
18061805
}
18071806
JL_GC_POP();
@@ -1833,10 +1832,10 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
18331832
}
18341833
}
18351834
else if (is_libjulia_func(jl_string_ptr)) {
1836-
assert(lrt == T_pint8);
1835+
assert(lrt == T_size);
18371836
assert(!isVa && !llvmcall && nargt == 1 && !addressOf.at(0));
1838-
auto obj = emit_pointer_from_objref(ctx, boxed(ctx, argv[0]));
1839-
auto strp = ctx.builder.CreateConstGEP1_32(emit_bitcast(ctx, obj, T_pint8), sizeof(void*));
1837+
Value *obj = emit_pointer_from_objref(ctx, boxed(ctx, argv[0]));
1838+
Value *strp = ctx.builder.CreateAdd(obj, ConstantInt::get(T_size, sizeof(void*)));
18401839
JL_GC_POP();
18411840
return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
18421841
}
@@ -1939,9 +1938,6 @@ jl_cgval_t function_sig_t::emit_a_ccall(
19391938
if (isa<UndefValue>(v)) {
19401939
return jl_cgval_t();
19411940
}
1942-
// A bit of a hack, but we're trying to get rid of this feature
1943-
// anyway.
1944-
v = emit_bitcast(ctx, emit_pointer_from_objref(ctx, v), pargty);
19451941
assert((!toboxed && !byRef) || isa<UndefValue>(v));
19461942
}
19471943

0 commit comments

Comments
 (0)