@@ -17,8 +17,7 @@ STATISTIC(EmittedRuntimeCalls, "Number of runtime intrinsic calls emitted");
1717STATISTIC (EmittedIntrinsics, " Number of intrinsic calls emitted" );
1818STATISTIC (Emitted_pointerref, " Number of pointerref calls emitted" );
1919STATISTIC (Emitted_pointerset, " Number of pointerset calls emitted" );
20- STATISTIC (Emitted_add_ptr, " Number of add_ptr calls emitted" );
21- STATISTIC (Emitted_sub_ptr, " Number of sub_ptr calls emitted" );
20+ STATISTIC (Emitted_pointerarith, " Number of pointer arithmetic calls emitted" );
2221STATISTIC (Emitted_atomic_fence, " Number of atomic_fence calls emitted" );
2322STATISTIC (Emitted_atomic_pointerref, " Number of atomic_pointerref calls emitted" );
2423STATISTIC (Emitted_atomic_pointerop, " Number of atomic_pointerop calls emitted" );
@@ -860,6 +859,34 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, ArrayRef<jl_cgval_t> argv)
860859 return e;
861860}
862861
862+ // ptr + offset
863+ // ptr - offset
864+ static jl_cgval_t emit_pointerarith (jl_codectx_t &ctx, intrinsic f,
865+ ArrayRef<jl_cgval_t > argv)
866+ {
867+ jl_value_t *ptrtyp = argv[0 ].typ ;
868+ jl_value_t *offtyp = argv[1 ].typ ;
869+ if (!jl_is_cpointer_type (ptrtyp) || offtyp != (jl_value_t *)jl_ulong_type)
870+ return emit_runtime_call (ctx, f, argv, argv.size ());
871+ assert (f == add_ptr || f == sub_ptr);
872+
873+ Value *ptr = emit_unbox (ctx, ctx.types ().T_ptr , argv[0 ], ptrtyp);
874+ Value *off = emit_unbox (ctx, ctx.types ().T_size , argv[1 ], offtyp);
875+ if (f == sub_ptr)
876+ off = ctx.builder .CreateNeg (off);
877+ Value *ans = ctx.builder .CreateGEP (getInt8Ty (ctx.builder .getContext ()), ptr, off);
878+
879+ if (jl_is_concrete_type (ptrtyp)) {
880+ return mark_julia_type (ctx, ans, false , ptrtyp);
881+ }
882+ else {
883+ Value *box = emit_allocobj (ctx, (jl_datatype_t *)ptrtyp, true );
884+ setName (ctx.emission_context , box, " ptr_box" );
885+ init_bits_value (ctx, box, ans, ctx.tbaa ().tbaa_immut );
886+ return mark_julia_type (ctx, box, true , (jl_datatype_t *)ptrtyp);
887+ }
888+ }
889+
863890static jl_cgval_t emit_atomicfence (jl_codectx_t &ctx, ArrayRef<jl_cgval_t > argv)
864891{
865892 const jl_cgval_t &ord = argv[0 ];
@@ -1278,29 +1305,11 @@ static jl_cgval_t emit_intrinsic(jl_codectx_t &ctx, intrinsic f, jl_value_t **ar
12781305 assert (nargs == 4 );
12791306 return emit_pointerset (ctx, argv);
12801307
1281- case add_ptr: {
1282- ++Emitted_add_ptr;
1308+ case add_ptr:
1309+ case sub_ptr:
1310+ ++Emitted_pointerarith;
12831311 assert (nargs == 2 );
1284- if (!jl_is_cpointer_type (argv[0 ].typ ) || jl_has_free_typevars (argv[0 ].typ ) ||
1285- argv[1 ].typ != (jl_value_t *)jl_ulong_type)
1286- return emit_runtime_call (ctx, f, argv, nargs);
1287- Value *ptr = emit_unbox (ctx, ctx.types ().T_ptr , argv[0 ], argv[0 ].typ );
1288- Value *off = emit_unbox (ctx, ctx.types ().T_size , argv[1 ], argv[1 ].typ );
1289- Value *ans = ctx.builder .CreateGEP (getInt8Ty (ctx.builder .getContext ()), ptr, off);
1290- return mark_julia_type (ctx, ans, false , argv[0 ].typ );
1291- }
1292- case sub_ptr: {
1293- ++Emitted_sub_ptr;
1294- assert (nargs == 2 );
1295- if (!jl_is_cpointer_type (argv[0 ].typ ) || jl_has_free_typevars (argv[0 ].typ ) ||
1296- argv[1 ].typ != (jl_value_t *)jl_ulong_type)
1297- return emit_runtime_call (ctx, f, argv, nargs);
1298- Value *ptr = emit_unbox (ctx, ctx.types ().T_ptr , argv[0 ], argv[0 ].typ );
1299- Value *off = emit_unbox (ctx, ctx.types ().T_size , argv[1 ], argv[1 ].typ );
1300- Value *ans = ctx.builder .CreateGEP (getInt8Ty (ctx.builder .getContext ()), ptr,
1301- ctx.builder .CreateNeg (off));
1302- return mark_julia_type (ctx, ans, false , argv[0 ].typ );
1303- }
1312+ return emit_pointerarith (ctx, f, argv);
13041313
13051314 case atomic_fence:
13061315 ++Emitted_atomic_fence;
0 commit comments