diff --git a/base/pointer.jl b/base/pointer.jl index 924a5c18ca1d3..0813d0a0c9735 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -56,8 +56,8 @@ function unsafe_convert end unsafe_convert(::Type{Ptr{UInt8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{UInt8}, (Any,), x) unsafe_convert(::Type{Ptr{Int8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{Int8}, (Any,), x) -unsafe_convert(::Type{Ptr{UInt8}}, s::String) = convert(Ptr{UInt8}, pointer_from_objref(s)+sizeof(Int)) -unsafe_convert(::Type{Ptr{Int8}}, s::String) = convert(Ptr{Int8}, pointer_from_objref(s)+sizeof(Int)) +unsafe_convert(::Type{Ptr{UInt8}}, s::String) = ccall(:jl_string_ptr, Ptr{UInt8}, (Any,), s) +unsafe_convert(::Type{Ptr{Int8}}, s::String) = ccall(:jl_string_ptr, Ptr{Int8}, (Any,), s) # convert strings to String etc. to pass as pointers cconvert(::Type{Ptr{UInt8}}, s::AbstractString) = String(s) cconvert(::Type{Ptr{Int8}}, s::AbstractString) = String(s) diff --git a/src/ccall.cpp b/src/ccall.cpp index ce5fc1fc160bc..6ce7ab59caf24 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1227,6 +1227,10 @@ std::string generate_func_sig(const char *fname) continue; attributes = attributes.addAttributes(jl_LLVMContext, i + 1, as); } + // If return value is boxed it must be non-null. + if (retboxed) + attributes = attributes.addAttribute(jl_LLVMContext, AttributeList::ReturnIndex, + Attribute::NonNull); if (rt == jl_bottom_type) { attributes = attributes.addAttribute(jl_LLVMContext, AttributeList::FunctionIndex, @@ -1692,8 +1696,25 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) else if (is_libjulia_func(jl_string_ptr)) { assert(lrt == T_size); assert(!isVa && !llvmcall && nccallargs == 1); - Value *obj = ctx.builder.CreatePtrToInt(emit_pointer_from_objref(ctx, boxed(ctx, argv[0])), T_size); - Value *strp = ctx.builder.CreateAdd(obj, ConstantInt::get(T_size, sizeof(void*))); + auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])), + T_pprjlvalue); + // The inbounds gep makes it more clear to LLVM that the resulting value is not + // a null pointer. + auto strp = ctx.builder.CreateConstInBoundsGEP1_32(T_prjlvalue, obj, 1); + strp = ctx.builder.CreatePtrToInt(strp, T_size); + JL_GC_POP(); + return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt); + } + else if (is_libjulia_func(jl_symbol_name)) { + assert(lrt == T_size); + assert(!isVa && !llvmcall && nccallargs == 1); + auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])), + T_pprjlvalue); + // The inbounds gep makes it more clear to LLVM that the resulting value is not + // a null pointer. + auto strp = ctx.builder.CreateConstInBoundsGEP1_32( + T_prjlvalue, obj, (sizeof(jl_sym_t) + sizeof(void*) - 1) / sizeof(void*)); + strp = ctx.builder.CreatePtrToInt(strp, T_size); JL_GC_POP(); return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt); } diff --git a/src/codegen.cpp b/src/codegen.cpp index 18196377995a0..f3d746e4bfae0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -361,7 +361,7 @@ static AttributeList get_attrs_sext(LLVMContext &C) { return AttributeList::get(C, AttributeSet(), - AttributeSet(), + Attributes(C, {Attribute::NonNull}), {Attributes(C, {Attribute::SExt})}); } @@ -369,7 +369,7 @@ static AttributeList get_attrs_zext(LLVMContext &C) { return AttributeList::get(C, AttributeSet(), - AttributeSet(), + Attributes(C, {Attribute::NonNull}), {Attributes(C, {Attribute::ZExt})}); } @@ -614,7 +614,7 @@ static const auto jl_newbits_func = new JuliaFunction{ {T_prjlvalue, T_pint8}, false); }, [](LLVMContext &C) { return AttributeList::get(C, AttributeSet(), - Attributes(C, {Attribute::NoAlias, Attribute::NonNull}), + Attributes(C, {Attribute::NonNull}), None); }, }; static const auto jl_typeof_func = new JuliaFunction{ @@ -769,9 +769,9 @@ BOX_FUNC(uint32, T_prjlvalue, T_int32, get_attrs_zext); BOX_FUNC(int64, T_prjlvalue, T_int64, get_attrs_sext); BOX_FUNC(uint64, T_prjlvalue, T_int64, get_attrs_zext); BOX_FUNC(char, T_prjlvalue, T_char, get_attrs_zext); -BOX_FUNC(float32, T_prjlvalue, T_float32, nullptr); -BOX_FUNC(float64, T_prjlvalue, T_float64, nullptr); -BOX_FUNC(ssavalue, T_prjlvalue, T_size, nullptr); +BOX_FUNC(float32, T_prjlvalue, T_float32, get_func_attrs); +BOX_FUNC(float64, T_prjlvalue, T_float64, get_func_attrs); +BOX_FUNC(ssavalue, T_prjlvalue, T_size, get_func_attrs); #undef BOX_FUNC @@ -805,7 +805,7 @@ static const auto pointer_from_objref_func = new JuliaFunction{ {PointerType::get(T_jlvalue, AddressSpace::Derived)}, false); }, [](LLVMContext &C) { return AttributeList::get(C, AttributeSet::get(C, makeArrayRef({Attribute::get(C, Attribute::ReadNone), Attribute::get(C, Attribute::NoUnwind)})), - AttributeSet(), + Attributes(C, {Attribute::NonNull}), None); }, }; diff --git a/src/julia.h b/src/julia.h index 6ee5c5bce69de..166c6b59f2806 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1012,6 +1012,7 @@ STATIC_INLINE jl_value_t *jl_field_type_concrete(jl_datatype_t *st JL_PROPAGATES #define jl_datatype_nfields(t) (((jl_datatype_t*)(t))->layout->nfields) #define jl_datatype_isinlinealloc(t) (((jl_datatype_t *)(t))->isinlinealloc) +JL_DLLEXPORT void *jl_symbol_name(jl_sym_t *s); // inline version with strong type check to detect typos in a `->name` chain STATIC_INLINE char *jl_symbol_name_(jl_sym_t *s) JL_NOTSAFEPOINT {