Skip to content

Commit ac4227b

Browse files
committed
Switch LLVM codegen of Ptr{T} to an actual pointer type.
1 parent 57efee1 commit ac4227b

File tree

8 files changed

+75
-62
lines changed

8 files changed

+75
-62
lines changed

base/atomics.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,13 +364,13 @@ for typ in atomictypes
364364
irt = "$ilt, $ilt*"
365365
@eval getindex(x::Atomic{$typ}) =
366366
GC.@preserve x llvmcall($"""
367-
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
367+
%ptr = bitcast i8* %0 to $lt*
368368
%rv = load atomic $rt %ptr acquire, align $(gc_alignment(typ))
369369
ret $lt %rv
370370
""", $typ, Tuple{Ptr{$typ}}, unsafe_convert(Ptr{$typ}, x))
371371
@eval setindex!(x::Atomic{$typ}, v::$typ) =
372372
GC.@preserve x llvmcall($"""
373-
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
373+
%ptr = bitcast i8* %0 to $lt*
374374
store atomic $lt %1, $lt* %ptr release, align $(gc_alignment(typ))
375375
ret void
376376
""", Cvoid, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v)
@@ -379,7 +379,7 @@ for typ in atomictypes
379379
if typ <: Integer
380380
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
381381
GC.@preserve x llvmcall($"""
382-
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
382+
%ptr = bitcast i8* %0 to $lt*
383383
%rs = cmpxchg $lt* %ptr, $lt %1, $lt %2 acq_rel acquire
384384
%rv = extractvalue { $lt, i1 } %rs, 0
385385
ret $lt %rv
@@ -388,7 +388,7 @@ for typ in atomictypes
388388
else
389389
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
390390
GC.@preserve x llvmcall($"""
391-
%iptr = inttoptr i$WORD_SIZE %0 to $ilt*
391+
%iptr = bitcast i8* %0 to $ilt*
392392
%icmp = bitcast $lt %1 to $ilt
393393
%inew = bitcast $lt %2 to $ilt
394394
%irs = cmpxchg $ilt* %iptr, $ilt %icmp, $ilt %inew acq_rel acquire
@@ -411,15 +411,15 @@ for typ in atomictypes
411411
if typ <: Integer
412412
@eval $fn(x::Atomic{$typ}, v::$typ) =
413413
GC.@preserve x llvmcall($"""
414-
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
414+
%ptr = bitcast i8* %0 to $lt*
415415
%rv = atomicrmw $rmw $lt* %ptr, $lt %1 acq_rel
416416
ret $lt %rv
417417
""", $typ, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v)
418418
else
419419
rmwop === :xchg || continue
420420
@eval $fn(x::Atomic{$typ}, v::$typ) =
421421
GC.@preserve x llvmcall($"""
422-
%iptr = inttoptr i$WORD_SIZE %0 to $ilt*
422+
%iptr = bitcast i8* %0 to $ilt*
423423
%ival = bitcast $lt %1 to $ilt
424424
%irv = atomicrmw $rmw $ilt* %iptr, $ilt %ival acq_rel
425425
%rv = bitcast $ilt %irv to $lt

base/pointer.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,8 @@ isless(x::Ptr{T}, y::Ptr{T}) where {T} = x < y
313313
<(x::Ptr, y::Ptr) = UInt(x) < UInt(y)
314314
-(x::Ptr, y::Ptr) = UInt(x) - UInt(y)
315315

316-
+(x::Ptr, y::Integer) = oftype(x, add_ptr(UInt(x), (y % UInt) % UInt))
317-
-(x::Ptr, y::Integer) = oftype(x, sub_ptr(UInt(x), (y % UInt) % UInt))
316+
+(x::Ptr, y::Integer) = add_ptr(x, (y % UInt) % UInt)
317+
-(x::Ptr, y::Integer) = sub_ptr(x, (y % UInt) % UInt)
318318
+(x::Integer, y::Ptr) = y + x
319319

320320
unsigned(x::Ptr) = UInt(x)

base/task.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,7 @@ const _state_index = findfirst(==(:_state), fieldnames(Task))
154154
@eval function load_state_acquire(t)
155155
# TODO: Replace this by proper atomic operations when available
156156
@GC.preserve t llvmcall($("""
157-
%ptr = inttoptr i$(Sys.WORD_SIZE) %0 to i8*
158-
%rv = load atomic i8, i8* %ptr acquire, align 8
157+
%rv = load atomic i8, i8* %0 acquire, align 8
159158
ret i8 %rv
160159
"""), UInt8, Tuple{Ptr{UInt8}},
161160
Ptr{UInt8}(pointer_from_objref(t) + fieldoffset(Task, _state_index)))

src/ccall.cpp

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ static void interpret_symbol_arg(jl_codectx_t &ctx, native_sym_arg_t &out, jl_va
616616
emit_cpointercheck(ctx, arg1, errmsg);
617617
}
618618
arg1 = update_julia_type(ctx, arg1, (jl_value_t*)jl_voidpointer_type);
619-
jl_ptr = emit_unbox(ctx, ctx.types().T_size, arg1, (jl_value_t*)jl_voidpointer_type);
619+
jl_ptr = emit_unbox(ctx, ctx.types().T_ptr, arg1, (jl_value_t*)jl_voidpointer_type);
620620
}
621621
else {
622622
out.gcroot = ptr;
@@ -696,7 +696,7 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
696696
else {
697697
rt = (jl_value_t*)jl_voidpointer_type;
698698
}
699-
Type *lrt = ctx.types().T_size;
699+
Type *lrt = ctx.types().T_ptr;
700700
assert(lrt == julia_type_to_llvm(ctx, rt));
701701

702702
interpret_symbol_arg(ctx, sym, args[1], /*ccall=*/false, false);
@@ -723,7 +723,6 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
723723
}
724724
else /*if (ctx.emission_context.imaging) */{
725725
res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f);
726-
res = ctx.builder.CreatePtrToInt(res, lrt);
727726
}
728727
}
729728

@@ -1462,14 +1461,14 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
14621461
(void)isVa; // prevent compiler warning
14631462
if (is_libjulia_func(jl_value_ptr)) {
14641463
++CCALL_STAT(jl_value_ptr);
1465-
assert(retboxed ? lrt == ctx.types().T_prjlvalue : lrt == ctx.types().T_size);
1464+
assert(retboxed ? lrt == ctx.types().T_prjlvalue : lrt == ctx.types().T_ptr);
14661465
assert(!isVa && !llvmcall && nccallargs == 1);
14671466
jl_value_t *tti = jl_svecref(at, 0);
14681467
Type *largty;
14691468
bool isboxed;
14701469
if (jl_is_abstract_ref_type(tti)) {
14711470
tti = (jl_value_t*)jl_voidpointer_type;
1472-
largty = ctx.types().T_size;
1471+
largty = ctx.types().T_ptr;
14731472
isboxed = false;
14741473
}
14751474
else {
@@ -1482,7 +1481,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
14821481
}
14831482
else {
14841483
retval = emit_unbox(ctx, largty, argv[0], tti);
1485-
retval = emit_inttoptr(ctx, retval, ctx.types().T_pjlvalue);
14861484
}
14871485
// retval is now an untracked jl_value_t*
14881486
if (retboxed)
@@ -1561,9 +1559,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
15611559
assert(lrt == ctx.types().T_size);
15621560
assert(!isVa && !llvmcall && nccallargs == 0);
15631561
JL_GC_POP();
1564-
return mark_or_box_ccall_result(ctx,
1565-
ctx.builder.CreatePtrToInt(get_current_ptls(ctx), lrt),
1566-
retboxed, rt, unionall, static_rt);
1562+
return mark_or_box_ccall_result(ctx, get_current_ptls(ctx), retboxed, rt, unionall, static_rt);
15671563
}
15681564
else if (is_libjulia_func(jl_threadid)) {
15691565
++CCALL_STAT(jl_threadid);
@@ -1683,29 +1679,27 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16831679
}
16841680
else if (is_libjulia_func(jl_string_ptr)) {
16851681
++CCALL_STAT(jl_string_ptr);
1686-
assert(lrt == ctx.types().T_size);
1682+
assert(lrt == ctx.types().T_ptr);
16871683
assert(!isVa && !llvmcall && nccallargs == 1);
16881684
auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])),
16891685
ctx.types().T_pprjlvalue);
16901686
// The inbounds gep makes it more clear to LLVM that the resulting value is not
16911687
// a null pointer.
16921688
auto strp = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, obj, 1);
1693-
strp = ctx.builder.CreatePtrToInt(strp, ctx.types().T_size);
16941689
setName(ctx.emission_context, strp, "string_ptr");
16951690
JL_GC_POP();
16961691
return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
16971692
}
16981693
else if (is_libjulia_func(jl_symbol_name)) {
16991694
++CCALL_STAT(jl_symbol_name);
1700-
assert(lrt == ctx.types().T_size);
1695+
assert(lrt == ctx.types().T_ptr);
17011696
assert(!isVa && !llvmcall && nccallargs == 1);
17021697
auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])),
17031698
ctx.types().T_pprjlvalue);
17041699
// The inbounds gep makes it more clear to LLVM that the resulting value is not
17051700
// a null pointer.
17061701
auto strp = ctx.builder.CreateConstInBoundsGEP1_32(
17071702
ctx.types().T_prjlvalue, obj, (sizeof(jl_sym_t) + sizeof(void*) - 1) / sizeof(void*));
1708-
strp = ctx.builder.CreatePtrToInt(strp, ctx.types().T_size);
17091703
setName(ctx.emission_context, strp, "symbol_name");
17101704
JL_GC_POP();
17111705
return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt);
@@ -1750,14 +1744,12 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17501744
const jl_cgval_t &dst = argv[0];
17511745
const jl_cgval_t &src = argv[1];
17521746
const jl_cgval_t &n = argv[2];
1753-
Value *destp = emit_unbox(ctx, ctx.types().T_size, dst, (jl_value_t*)jl_voidpointer_type);
1747+
Value *destp = emit_unbox(ctx, ctx.types().T_ptr, dst, (jl_value_t*)jl_voidpointer_type);
17541748

17551749
ctx.builder.CreateMemCpy(
1756-
emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
1750+
destp,
17571751
MaybeAlign(1),
1758-
emit_inttoptr(ctx,
1759-
emit_unbox(ctx, ctx.types().T_size, src, (jl_value_t*)jl_voidpointer_type),
1760-
getInt8PtrTy(ctx.builder.getContext())),
1752+
emit_unbox(ctx, ctx.types().T_ptr, src, (jl_value_t*)jl_voidpointer_type),
17611753
MaybeAlign(1),
17621754
emit_unbox(ctx, ctx.types().T_size, n, (jl_value_t*)jl_ulong_type),
17631755
false);
@@ -1770,11 +1762,11 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17701762
const jl_cgval_t &dst = argv[0];
17711763
const jl_cgval_t &val = argv[1];
17721764
const jl_cgval_t &n = argv[2];
1773-
Value *destp = emit_unbox(ctx, ctx.types().T_size, dst, (jl_value_t*)jl_voidpointer_type);
1765+
Value *destp = emit_unbox(ctx, ctx.types().T_ptr, dst, (jl_value_t*)jl_voidpointer_type);
17741766
Value *val32 = emit_unbox(ctx, getInt32Ty(ctx.builder.getContext()), val, (jl_value_t*)jl_uint32_type);
17751767
Value *val8 = ctx.builder.CreateTrunc(val32, getInt8Ty(ctx.builder.getContext()), "memset_val");
17761768
ctx.builder.CreateMemSet(
1777-
emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
1769+
destp,
17781770
val8,
17791771
emit_unbox(ctx, ctx.types().T_size, n, (jl_value_t*)jl_ulong_type),
17801772
MaybeAlign(1)
@@ -1788,14 +1780,12 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17881780
const jl_cgval_t &dst = argv[0];
17891781
const jl_cgval_t &src = argv[1];
17901782
const jl_cgval_t &n = argv[2];
1791-
Value *destp = emit_unbox(ctx, ctx.types().T_size, dst, (jl_value_t*)jl_voidpointer_type);
1783+
Value *destp = emit_unbox(ctx, ctx.types().T_ptr, dst, (jl_value_t*)jl_voidpointer_type);
17921784

17931785
ctx.builder.CreateMemMove(
1794-
emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())),
1786+
destp,
17951787
MaybeAlign(0),
1796-
emit_inttoptr(ctx,
1797-
emit_unbox(ctx, ctx.types().T_size, src, (jl_value_t*)jl_voidpointer_type),
1798-
getInt8PtrTy(ctx.builder.getContext())),
1788+
emit_unbox(ctx, ctx.types().T_ptr, src, (jl_value_t*)jl_voidpointer_type),
17991789
MaybeAlign(0),
18001790
emit_unbox(ctx, ctx.types().T_size, n, (jl_value_t*)jl_ulong_type),
18011791
false);
@@ -1999,7 +1989,7 @@ jl_cgval_t function_sig_t::emit_a_ccall(
19991989
++LiteralCCalls;
20001990
null_pointer_check(ctx, symarg.jl_ptr, nullptr);
20011991
Type *funcptype = PointerType::get(functype, 0);
2002-
llvmf = emit_inttoptr(ctx, symarg.jl_ptr, funcptype);
1992+
llvmf = ctx.builder.CreateBitCast(symarg.jl_ptr, funcptype);
20031993
}
20041994
else if (symarg.fptr != NULL) {
20051995
++LiteralCCalls;

src/cgutils.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,8 @@ static Type *bitstype_to_llvm(jl_value_t *bt, LLVMContext &ctxt, bool llvmcall =
690690
return getDoubleTy(ctxt);
691691
if (bt == (jl_value_t*)jl_bfloat16_type)
692692
return getBFloatTy(ctxt);
693+
if (jl_is_cpointer_type(bt))
694+
return PointerType::get(getInt8Ty(ctxt), 0);
693695
if (jl_is_llvmpointer_type(bt)) {
694696
jl_value_t *as_param = jl_tparam1(bt);
695697
int as;

src/codegen.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ extern void _chkstk(void);
283283

284284
// types
285285
struct jl_typecache_t {
286+
Type *T_ptr;
286287
Type *T_size;
287288
Type *T_jlvalue;
288289
Type *T_pjlvalue;
@@ -304,7 +305,7 @@ struct jl_typecache_t {
304305
bool initialized;
305306

306307
jl_typecache_t() :
307-
T_jlvalue(nullptr), T_pjlvalue(nullptr), T_prjlvalue(nullptr),
308+
T_ptr(nullptr), T_jlvalue(nullptr), T_pjlvalue(nullptr), T_prjlvalue(nullptr),
308309
T_ppjlvalue(nullptr), T_pprjlvalue(nullptr),
309310
T_jlgenericmemory(nullptr), T_jlarray(nullptr), T_pjlarray(nullptr),
310311
T_jlfunc(nullptr), T_jlfuncparams(nullptr), T_sigatomic(nullptr), T_ppint8(nullptr),
@@ -315,6 +316,7 @@ struct jl_typecache_t {
315316
return;
316317
}
317318
initialized = true;
319+
T_ptr = getInt8PtrTy(context);
318320
T_ppint8 = PointerType::get(getInt8PtrTy(context), 0);
319321
T_sigatomic = Type::getIntNTy(context, sizeof(sig_atomic_t) * 8);
320322
T_size = DL.getIntPtrType(context);

src/intrinsics.cpp

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -625,10 +625,14 @@ static jl_cgval_t generic_bitcast(jl_codectx_t &ctx, ArrayRef<jl_cgval_t> argv)
625625
vx = ctx.builder.CreateZExt(vx, llvmt);
626626
} else if (vxt->isPointerTy() && !llvmt->isPointerTy()) {
627627
vx = ctx.builder.CreatePtrToInt(vx, llvmt);
628-
setName(ctx.emission_context, vx, "bitcast_coercion");
628+
if (isa<Instruction>(vx) && !vx->hasName())
629+
// CreatePtrToInt may undo an IntToPtr
630+
setName(ctx.emission_context, vx, "bitcast_coercion");
629631
} else if (!vxt->isPointerTy() && llvmt->isPointerTy()) {
630632
vx = emit_inttoptr(ctx, vx, llvmt);
631-
setName(ctx.emission_context, vx, "bitcast_coercion");
633+
if (isa<Instruction>(vx) && !vx->hasName())
634+
// emit_inttoptr may undo an PtrToInt
635+
setName(ctx.emission_context, vx, "bitcast_coercion");
632636
} else {
633637
vx = emit_bitcast(ctx, vx, llvmt);
634638
setName(ctx.emission_context, vx, "bitcast_coercion");
@@ -741,7 +745,8 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, ArrayRef<jl_cgval_t> argv)
741745

742746
if (ety == (jl_value_t*)jl_any_type) {
743747
Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ);
744-
setName(ctx.emission_context, thePtr, "unbox_any_ptr");
748+
if (isa<Instruction>(thePtr) && !thePtr->hasName())
749+
setName(ctx.emission_context, thePtr, "unbox_any_ptr");
745750
LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, thePtr, im1), Align(align_nb));
746751
setName(ctx.emission_context, load, "any_unbox");
747752
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_data);
@@ -1270,6 +1275,27 @@ static jl_cgval_t emit_intrinsic(jl_codectx_t &ctx, intrinsic f, jl_value_t **ar
12701275
++Emitted_pointerset;
12711276
assert(nargs == 4);
12721277
return emit_pointerset(ctx, argv);
1278+
1279+
case add_ptr: {
1280+
assert(nargs == 2);
1281+
if (!jl_is_cpointer_type(argv[0].typ) || argv[1].typ != (jl_value_t*)jl_ulong_type)
1282+
return emit_runtime_call(ctx, f, argv, nargs);
1283+
Value *ptr = emit_unbox(ctx, ctx.types().T_ptr, argv[0], argv[0].typ);
1284+
Value *off = emit_unbox(ctx, ctx.types().T_size, argv[1], argv[1].typ);
1285+
Value *ans = ctx.builder.CreateGEP(getInt8Ty(ctx.builder.getContext()), ptr, off);
1286+
return mark_julia_type(ctx, ans, false, argv[0].typ);
1287+
}
1288+
case sub_ptr: {
1289+
assert(nargs == 2);
1290+
if (!jl_is_cpointer_type(argv[0].typ) || argv[1].typ != (jl_value_t*)jl_ulong_type)
1291+
return emit_runtime_call(ctx, f, argv, nargs);
1292+
Value *ptr = emit_unbox(ctx, ctx.types().T_ptr, argv[0], argv[0].typ);
1293+
Value *off = emit_unbox(ctx, ctx.types().T_size, argv[1], argv[1].typ);
1294+
Value *ans = ctx.builder.CreateGEP(getInt8Ty(ctx.builder.getContext()), ptr,
1295+
ctx.builder.CreateNeg(off));
1296+
return mark_julia_type(ctx, ans, false, argv[0].typ);
1297+
}
1298+
12731299
case atomic_fence:
12741300
++Emitted_atomic_fence;
12751301
assert(nargs == 1);
@@ -1437,26 +1463,6 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, ArrayRef<Va
14371463
case srem_int: return ctx.builder.CreateSRem(x, y);
14381464
case urem_int: return ctx.builder.CreateURem(x, y);
14391465

1440-
// LLVM will not fold ptrtoint+arithmetic+inttoptr to GEP. The reason for this
1441-
// has to do with alias analysis. When adding two integers, either one of them
1442-
// could be the pointer base. With getelementptr, it is clear which of the
1443-
// operands is the pointer base. We also have this information at the julia
1444-
// level. Thus, to not lose information, we need to have a separate intrinsic
1445-
// for pointer arithmetic which lowers to getelementptr.
1446-
case add_ptr: {
1447-
return ctx.builder.CreatePtrToInt(
1448-
ctx.builder.CreateGEP(getInt8Ty(ctx.builder.getContext()),
1449-
emit_inttoptr(ctx, x, getInt8PtrTy(ctx.builder.getContext())), y), t);
1450-
1451-
}
1452-
1453-
case sub_ptr: {
1454-
return ctx.builder.CreatePtrToInt(
1455-
ctx.builder.CreateGEP(getInt8Ty(ctx.builder.getContext()),
1456-
emit_inttoptr(ctx, x, getInt8PtrTy(ctx.builder.getContext())), ctx.builder.CreateNeg(y)), t);
1457-
1458-
}
1459-
14601466
case neg_float: return math_builder(ctx)().CreateFNeg(x);
14611467
case neg_float_fast: return math_builder(ctx, true)().CreateFNeg(x);
14621468
case add_float: return math_builder(ctx)().CreateFAdd(x, y);

src/runtime_intrinsics.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,10 +1384,8 @@ JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b, jl_value_t *c)
13841384
un_iintrinsic_fast(LLVMNeg, neg, neg_int, u)
13851385
#define add(a,b) a + b
13861386
bi_iintrinsic_fast(LLVMAdd, add, add_int, u)
1387-
bi_iintrinsic_fast(LLVMAdd, add, add_ptr, u)
13881387
#define sub(a,b) a - b
13891388
bi_iintrinsic_fast(LLVMSub, sub, sub_int, u)
1390-
bi_iintrinsic_fast(LLVMSub, sub, sub_ptr, u)
13911389
#define mul(a,b) a * b
13921390
bi_iintrinsic_fast(LLVMMul, mul, mul_int, u)
13931391
#define div(a,b) a / b
@@ -1696,3 +1694,19 @@ JL_DLLEXPORT jl_value_t *jl_have_fma(jl_value_t *typ)
16961694
else
16971695
return jl_false;
16981696
}
1697+
1698+
JL_DLLEXPORT jl_value_t *jl_add_ptr(jl_value_t *ptr, jl_value_t *offset)
1699+
{
1700+
JL_TYPECHK(add_ptr, pointer, ptr);
1701+
JL_TYPECHK(add_ptr, ulong, offset);
1702+
long ptrval = jl_unbox_long(ptr) + jl_unbox_long(offset);
1703+
return jl_new_bits(jl_typeof(ptr), &ptrval);
1704+
}
1705+
1706+
JL_DLLEXPORT jl_value_t *jl_sub_ptr(jl_value_t *ptr, jl_value_t *offset)
1707+
{
1708+
JL_TYPECHK(sub_ptr, pointer, ptr);
1709+
JL_TYPECHK(sub_ptr, ulong, offset);
1710+
long ptrval = jl_unbox_long(ptr) - jl_unbox_long(offset);
1711+
return jl_new_bits(jl_typeof(ptr), &ptrval);
1712+
}

0 commit comments

Comments
 (0)