Skip to content

Commit 7cf7580

Browse files
committed
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 d96a9a9 commit 7cf7580

10 files changed

+388
-368
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

@@ -1591,17 +1587,17 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
15911587

15921588
// some special functions
15931589
if (is_libjulia_func(jl_array_ptr)) {
1594-
assert(lrt->isPointerTy());
1590+
assert(lrt == T_size);
15951591
assert(!isVa && !llvmcall && nargt == 1);
15961592
assert(!addressOf.at(0));
15971593
const jl_cgval_t &ary = argv[0];
15981594
jl_value_t *aryex = ccallarg(0);
15991595
JL_GC_POP();
1600-
return mark_or_box_ccall_result(ctx, emit_bitcast(ctx, emit_arrayptr(ctx, ary, aryex), lrt),
1596+
return mark_or_box_ccall_result(ctx, ctx.builder.CreatePtrToInt(emit_arrayptr(ctx, ary, aryex), lrt),
16011597
retboxed, rt, unionall, static_rt);
16021598
}
16031599
else if (is_libjulia_func(jl_value_ptr)) {
1604-
assert(lrt->isPointerTy());
1600+
assert(retboxed ? lrt == T_prjlvalue : lrt == T_size);
16051601
assert(!isVa && !llvmcall && nargt == 1);
16061602
jl_value_t *tti = jl_svecref(at, 0);
16071603
Value *ary;
@@ -1613,7 +1609,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16131609
}
16141610
else if (jl_is_abstract_ref_type(tti)) {
16151611
tti = (jl_value_t*)jl_voidpointer_type;
1616-
largty = T_pint8;
1612+
largty = T_size;
16171613
isboxed = false;
16181614
}
16191615
else {
@@ -1629,13 +1625,16 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16291625
if (!retboxed) {
16301626
return mark_or_box_ccall_result(
16311627
ctx,
1632-
emit_bitcast(ctx, emit_pointer_from_objref(ctx,
1633-
emit_bitcast(ctx, ary, T_prjlvalue)), lrt),
1628+
emit_pointer_from_objref(ctx,
1629+
emit_bitcast(ctx, ary, T_prjlvalue)),
16341630
retboxed, rt, unionall, static_rt);
1635-
} else {
1631+
}
1632+
else {
16361633
return mark_or_box_ccall_result(
16371634
ctx,
1638-
maybe_decay_untracked(emit_bitcast(ctx, ary, lrt)),
1635+
ctx.builder.CreateAddrSpaceCast(
1636+
ctx.builder.CreateIntToPtr(ary, T_pjlvalue),
1637+
T_prjlvalue), // TODO: this addrspace cast is invalid (implies that the value is rooted elsewhere)
16391638
retboxed, rt, unionall, static_rt);
16401639
}
16411640
}
@@ -1688,11 +1687,11 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16881687
return ghostValue(jl_void_type);
16891688
}
16901689
else if (_is_libjulia_func((uintptr_t)ptls_getter, "jl_get_ptls_states")) {
1691-
assert(lrt == T_pint8);
1690+
assert(lrt == T_size);
16921691
assert(!isVa && !llvmcall && nargt == 0);
16931692
JL_GC_POP();
16941693
return mark_or_box_ccall_result(ctx,
1695-
emit_bitcast(ctx, ctx.ptlsStates, lrt),
1694+
ctx.builder.CreatePtrToInt(ctx.ptlsStates, lrt),
16961695
retboxed, rt, unionall, static_rt);
16971696
}
16981697
else if (is_libjulia_func(jl_threadid)) {
@@ -1765,6 +1764,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17651764
}
17661765
else if (is_libjulia_func(jl_function_ptr)) {
17671766
assert(!isVa && !llvmcall && nargt == 3);
1767+
assert(lrt == T_size);
17681768
jl_value_t *f = argv[0].constant;
17691769
jl_value_t *frt = argv[1].constant;
17701770
if (!frt) {
@@ -1791,11 +1791,10 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17911791
llvmf = NULL;
17921792
}
17931793
if (llvmf) {
1794-
llvmf = prepare_call(llvmf);
17951794
JL_GC_POP();
17961795
JL_GC_POP();
1797-
return mark_or_box_ccall_result(ctx, emit_bitcast(ctx, llvmf, lrt),
1798-
retboxed, rt, unionall, static_rt);
1796+
Value *fptr = ctx.builder.CreatePtrToInt(prepare_call(llvmf), lrt);
1797+
return mark_or_box_ccall_result(ctx, fptr, retboxed, rt, unionall, static_rt);
17991798
}
18001799
}
18011800
JL_GC_POP();
@@ -1827,10 +1826,10 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
18271826
}
18281827
}
18291828
else if (is_libjulia_func(jl_string_ptr)) {
1830-
assert(lrt == T_pint8);
1829+
assert(lrt == T_size);
18311830
assert(!isVa && !llvmcall && nargt == 1 && !addressOf.at(0));
1832-
auto obj = emit_pointer_from_objref(ctx, boxed(ctx, argv[0]));
1833-
auto strp = ctx.builder.CreateConstGEP1_32(emit_bitcast(ctx, obj, T_pint8), sizeof(void*));
1831+
Value *obj = emit_pointer_from_objref(ctx, boxed(ctx, argv[0]));
1832+
Value *strp = ctx.builder.CreateAdd(obj, ConstantInt::get(T_size, sizeof(void*)));
18341833
JL_GC_POP();
18351834
return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
18361835
}
@@ -1933,9 +1932,6 @@ jl_cgval_t function_sig_t::emit_a_ccall(
19331932
if (isa<UndefValue>(v)) {
19341933
return jl_cgval_t();
19351934
}
1936-
// A bit of a hack, but we're trying to get rid of this feature
1937-
// anyway.
1938-
v = emit_bitcast(ctx, emit_pointer_from_objref(ctx, v), pargty);
19391935
assert((!toboxed && !byRef) || isa<UndefValue>(v));
19401936
}
19411937

0 commit comments

Comments
 (0)