diff --git a/Makefile b/Makefile index 89fe35b470094..5ce3003dba231 100644 --- a/Makefile +++ b/Makefile @@ -289,6 +289,7 @@ else ifeq ($(JULIA_BUILD_MODE),debug) -$(INSTALL_M) $(build_libdir)/libjulia-internal-debug.dll.a $(DESTDIR)$(libdir)/ endif -$(INSTALL_M) $(wildcard $(build_private_libdir)/*.a) $(DESTDIR)$(private_libdir)/ + -rm -f $(DESTDIR)$(private_libdir)/sys-o.a # We have a single exception; we want 7z.dll to live in private_libexecdir, # not bindir, so that 7z.exe can find it. diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 1615781727669..6de08e64c14e7 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -115,15 +115,11 @@ function src_inlining_policy(interp::AbstractInterpreter, return src_inlineable elseif isa(src, IRCode) return true - elseif isa(src, SemiConcreteResult) - return true end @assert !isa(src, CodeInstance) # handled by caller return false end -function inlining_policy end # deprecated legacy name used by Cthulhu - struct InliningState{Interp<:AbstractInterpreter} edges::Vector{Any} world::UInt diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 5af074498ca7e..b659fc2a88e6c 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -873,7 +873,8 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize exc_bestguess = refine_exception_type(frame.exc_bestguess, effects) # propagate newly inferred source to the inliner, allowing efficient inlining w/o deserialization: # note that this result is cached globally exclusively, we can use this local result destructively - volatile_inf_result = isinferred && (force_inline || src_inlining_policy(interp, result.src, NoCallInfo(), IR_FLAG_NULL) !== nothing) ? + volatile_inf_result = (isinferred && (force_inline || + src_inlining_policy(interp, result.src, NoCallInfo(), IR_FLAG_NULL))) ? VolatileInferenceResult(result) : nothing return EdgeCallResult(frame.bestguess, exc_bestguess, edge, effects, volatile_inf_result) elseif frame === true diff --git a/base/pointer.jl b/base/pointer.jl index 86513c076ade6..2f67c8a6757cb 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -64,6 +64,7 @@ unsafe_convert(::Type{Ptr{Int8}}, s::String) = ccall(:jl_string_ptr, Ptr{Int8}, cconvert(::Type{<:Ptr}, a::Array) = getfield(a, :ref) unsafe_convert(::Type{Ptr{S}}, a::AbstractArray{T}) where {S,T} = convert(Ptr{S}, unsafe_convert(Ptr{T}, a)) +unsafe_convert(::Type{Ptr{T}}, a::Array{T}) where {T} = unsafe_convert(Ptr{T}, a.ref) unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("conversion to pointer not defined for $(typeof(a))") # TODO: add this deprecation to give a better error: # cconvert(::Type{<:Ptr}, a::AbstractArray) = error("conversion to pointer not defined for $(typeof(a))") diff --git a/base/precompilation.jl b/base/precompilation.jl index 4f553ac7c7efc..d50a48a141140 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -439,7 +439,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; internal_call::Bool=false # TODO: actually handle packages from other envs in the stack return else - error("No direct dependencies outside of the sysimage found matching $(repr([p.name for p in pkgs]))") + error("No direct dependencies outside of the sysimage found matching $(pkgs)") end end diff --git a/base/version.jl b/base/version.jl index 90c34b78c868f..9fa4edb32e4dd 100644 --- a/base/version.jl +++ b/base/version.jl @@ -9,12 +9,12 @@ const VInt = UInt32 VersionNumber Version number type which follows the specifications of -[semantic versioning (semver)](https://semver.org/), composed of major, minor +[semantic versioning (semver)](https://semver.org/spec/v2.0.0-rc.2.html), composed of major, minor and patch numeric values, followed by pre-release and build alphanumeric annotations. `VersionNumber` objects can be compared with all of the standard comparison -operators (`==`, `<`, `<=`, etc.), with the result following semver rules. +operators (`==`, `<`, `<=`, etc.), with the result following semver v2.0.0-rc.2 rules. `VersionNumber` has the following public fields: - `v.major::Integer` diff --git a/deps/checksums/Pkg-48eea8dbd7b651cdc932b909c1b718bb9c3f94f4.tar.gz/md5 b/deps/checksums/Pkg-48eea8dbd7b651cdc932b909c1b718bb9c3f94f4.tar.gz/md5 deleted file mode 100644 index 341ea80c32a7e..0000000000000 --- a/deps/checksums/Pkg-48eea8dbd7b651cdc932b909c1b718bb9c3f94f4.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -fea1786e8202d07744c17457a114e911 diff --git a/deps/checksums/Pkg-48eea8dbd7b651cdc932b909c1b718bb9c3f94f4.tar.gz/sha512 b/deps/checksums/Pkg-48eea8dbd7b651cdc932b909c1b718bb9c3f94f4.tar.gz/sha512 deleted file mode 100644 index 8f6d09bbb6001..0000000000000 --- a/deps/checksums/Pkg-48eea8dbd7b651cdc932b909c1b718bb9c3f94f4.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -e79913b68643ec4c448a861f446d0358484b01d16794c9dfe700b1f539d4c01ea259014d37df263b4d7dd3f3c2e1df3966c584b428041dbdf03d4e4794b52a64 diff --git a/deps/checksums/Pkg-e7d740ac82fa4c289bb58f9acb6e60eebb6d8a8e.tar.gz/md5 b/deps/checksums/Pkg-e7d740ac82fa4c289bb58f9acb6e60eebb6d8a8e.tar.gz/md5 new file mode 100644 index 0000000000000..96ceb05a2c8d4 --- /dev/null +++ b/deps/checksums/Pkg-e7d740ac82fa4c289bb58f9acb6e60eebb6d8a8e.tar.gz/md5 @@ -0,0 +1 @@ +0d226d1a3cf5c4cf207788fc3c5ba50c diff --git a/deps/checksums/Pkg-e7d740ac82fa4c289bb58f9acb6e60eebb6d8a8e.tar.gz/sha512 b/deps/checksums/Pkg-e7d740ac82fa4c289bb58f9acb6e60eebb6d8a8e.tar.gz/sha512 new file mode 100644 index 0000000000000..304829ca32df0 --- /dev/null +++ b/deps/checksums/Pkg-e7d740ac82fa4c289bb58f9acb6e60eebb6d8a8e.tar.gz/sha512 @@ -0,0 +1 @@ +e9516466573c24d2bd90645edbdc9c2dbe3f4f4e1704d665525429ff6a463208ff849ebb7c4f9d2d2627d69d1b2cc56a9b305a89e30a0e16b666cbd91f34ced3 diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index f4acffb2ae91b..1087c7f8b5ff1 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -1142,7 +1142,7 @@ some confusion regarding the matter. Version numbers can easily be expressed with non-standard string literals of the form [`v"..."`](@ref @v_str). Version number literals create [`VersionNumber`](@ref) objects which follow the -specifications of [semantic versioning](https://semver.org/), +specifications of [semantic versioning 2.0.0-rc2](https://semver.org/spec/v2.0.0-rc.2.html), and therefore are composed of major, minor and patch numeric values, followed by pre-release and build alphanumeric annotations. For example, `v"0.2.1-rc1+win64"` is broken into major version `0`, minor version `2`, patch version `1`, pre-release `rc1` and build `win64`. When entering diff --git a/doc/src/tutorials/creating-packages.md b/doc/src/tutorials/creating-packages.md index 52288e5a8924f..c5cd1f4f92f48 100644 --- a/doc/src/tutorials/creating-packages.md +++ b/doc/src/tutorials/creating-packages.md @@ -563,10 +563,10 @@ duplicated into `[extras]`. This is an unfortunate duplication, but without doing this the project verifier under older Julia versions will throw an error if it finds packages under `[compat]` that is not listed in `[extras]`. -## Package naming guidelines +## Package naming rules Package names should be sensible to most Julia users, *even to those who are not domain experts*. -The following guidelines apply to the `General` registry but may be useful for other package +The following rules apply to the `General` registry but may be useful for other package registries as well. Since the `General` registry belongs to the entire community, people may have opinions about diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 7bbf7a84a0385..b17b174dd8a8d 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -2644,6 +2644,104 @@ static jl_cgval_t emit_unionload(jl_codectx_t &ctx, Value *addr, Value *ptindex, return mark_julia_slot(fsz > 0 ? addr : nullptr, jfty, tindex, tbaa); } +static bool isTBAA(MDNode *TBAA, std::initializer_list const strset) +{ + if (!TBAA) + return false; + while (TBAA->getNumOperands() > 1) { + TBAA = cast(TBAA->getOperand(1).get()); + auto str = cast(TBAA->getOperand(0))->getString(); + for (auto str2 : strset) { + if (str == str2) { + return true; + } + } + } + return false; +} + +// Check if this is a load from an immutable value. The easiest +// way to do so is to look at the tbaa and see if it derives from +// jtbaa_immut. +static bool isLoadFromImmut(LoadInst *LI) +{ + if (LI->getMetadata(LLVMContext::MD_invariant_load)) + return true; + MDNode *TBAA = LI->getMetadata(LLVMContext::MD_tbaa); + if (isTBAA(TBAA, {"jtbaa_immut", "jtbaa_const", "jtbaa_datatype", "jtbaa_memoryptr", "jtbaa_memorylen", "jtbaa_memoryown"})) + return true; + return false; +} + +static bool isConstGV(GlobalVariable *gv) +{ + return gv->isConstant() || gv->getMetadata("julia.constgv"); +} + +// Check if this is can be traced through constant loads to an constant global +// or otherwise globally rooted value. +// Almost all `tbaa_const` loads satisfies this with the exception of +// task local constants which are constant as far as the code is concerned but aren't +// global constants. For task local constant `task_local` will be true when this function +// returns. +// Unlike this function in llvm-late-gc-lowering, we do not examine PhiNode, as those are not emitted yet +static bool isLoadFromConstGV(LoadInst *LI); +static bool isLoadFromConstGV(Value *v) +{ + v = v->stripInBoundsOffsets(); + if (auto LI = dyn_cast(v)) + return isLoadFromConstGV(LI); + if (auto gv = dyn_cast(v)) + return isConstGV(gv); + // null pointer + if (isa(v)) + return true; + // literal pointers + if (auto CE = dyn_cast(v)) + return (CE->getOpcode() == Instruction::IntToPtr && + isa(CE->getOperand(0))); + if (auto SL = dyn_cast(v)) + return (isLoadFromConstGV(SL->getTrueValue()) && + isLoadFromConstGV(SL->getFalseValue())); + if (auto call = dyn_cast(v)) { + auto callee = call->getCalledFunction(); + if (callee && callee->getName() == "julia.typeof") { + return true; + } + if (callee && callee->getName() == "julia.get_pgcstack") { + return true; + } + if (callee && callee->getName() == "julia.gc_loaded") { + return isLoadFromConstGV(call->getArgOperand(0)) && + isLoadFromConstGV(call->getArgOperand(1)); + } + } + if (isa(v)) { + return true; + } + return false; +} + +// The white list implemented here and above in `isLoadFromConstGV(Value*)` should +// cover all the cases we and LLVM generates. +static bool isLoadFromConstGV(LoadInst *LI) +{ + // We only emit single slot GV in codegen + // but LLVM global merging can change the pointer operands to GEPs/bitcasts + auto load_base = LI->getPointerOperand()->stripInBoundsOffsets(); + assert(load_base); // Static analyzer + auto gv = dyn_cast(load_base); + if (isLoadFromImmut(LI)) { + if (gv) + return true; + return isLoadFromConstGV(load_base); + } + if (gv) + return isConstGV(gv); + return false; +} + + static MDNode *best_field_tbaa(jl_codectx_t &ctx, const jl_cgval_t &strct, jl_datatype_t *jt, unsigned idx, size_t byte_offset) { auto tbaa = strct.tbaa; @@ -2664,6 +2762,8 @@ static MDNode *best_field_tbaa(jl_codectx_t &ctx, const jl_cgval_t &strct, jl_da return ctx.tbaa().tbaa_arraysize; } } + if (strct.V && jl_field_isconst(jt, idx) && isLoadFromConstGV(strct.V)) + return ctx.tbaa().tbaa_const; return tbaa; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 59c7763350fff..faa9de2762471 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8267,7 +8267,7 @@ static jl_llvm_functions_t // step 7. allocate local variables slots // must be in the first basic block for the llvm mem2reg pass to work - auto allocate_local = [&](jl_varinfo_t &varinfo, jl_sym_t *s) { + auto allocate_local = [&ctx, &dbuilder, &debuginfo, topdebugloc, va, debug_enabled, M](jl_varinfo_t &varinfo, jl_sym_t *s, int i) { jl_value_t *jt = varinfo.value.typ; assert(!varinfo.boxroot); // variables shouldn't have memory locs already if (varinfo.value.constant) { @@ -8275,10 +8275,10 @@ static jl_llvm_functions_t alloc_def_flag(ctx, varinfo); return; } - else if (varinfo.isArgument && !(specsig && i == (size_t)ctx.vaSlot)) { - // if we can unbox it, just use the input pointer - if (i != (size_t)ctx.vaSlot && jl_is_concrete_immutable(jt)) - return; + else if (varinfo.isArgument && (!va || ctx.vaSlot == -1 || i != ctx.vaSlot)) { + // just use the input pointer, if we have it + // (we will need to attach debuginfo later to it) + return; } else if (jl_is_uniontype(jt)) { bool allunbox; @@ -8289,6 +8289,7 @@ static jl_llvm_functions_t varinfo.value = mark_julia_slot(lv, jt, NULL, ctx.tbaa().tbaa_stack); varinfo.pTIndex = emit_static_alloca(ctx, getInt8Ty(ctx.builder.getContext())); setName(ctx.emission_context, varinfo.pTIndex, "tindex"); + // TODO: attach debug metadata to this variable } else if (allunbox) { // all ghost values just need a selector allocated @@ -8297,6 +8298,7 @@ static jl_llvm_functions_t varinfo.pTIndex = lv; varinfo.value.tbaa = NULL; varinfo.value.isboxed = false; + // TODO: attach debug metadata to this variable } if (lv || allunbox) alloc_def_flag(ctx, varinfo); @@ -8323,29 +8325,21 @@ static jl_llvm_functions_t } return; } - if (!varinfo.isArgument || // always need a slot if the variable is assigned - specsig || // for arguments, give them stack slots if they aren't in `argArray` (otherwise, will use that pointer) - (va && (int)i == ctx.vaSlot) || // or it's the va arg tuple - i == 0) { // or it is the first argument (which isn't in `argArray`) - AllocaInst *av = new AllocaInst(ctx.types().T_prjlvalue, M->getDataLayout().getAllocaAddrSpace(), - nullptr, Align(sizeof(jl_value_t*)), jl_symbol_name(s), /*InsertBefore*/ctx.topalloca); - StoreInst *SI = new StoreInst(Constant::getNullValue(ctx.types().T_prjlvalue), av, false, Align(sizeof(void*))); - SI->insertAfter(ctx.topalloca); - varinfo.boxroot = av; - if (debug_enabled && varinfo.dinfo) { - DIExpression *expr; - if ((Metadata*)varinfo.dinfo->getType() == debuginfo.jl_pvalue_dillvmt) { - expr = dbuilder.createExpression(); - } - else { - SmallVector addr; - addr.push_back(llvm::dwarf::DW_OP_deref); - expr = dbuilder.createExpression(addr); - } - dbuilder.insertDeclare(av, varinfo.dinfo, expr, - topdebugloc, - ctx.builder.GetInsertBlock()); - } + // otherwise give it a boxroot in this function + AllocaInst *av = new AllocaInst(ctx.types().T_prjlvalue, M->getDataLayout().getAllocaAddrSpace(), + nullptr, Align(sizeof(jl_value_t*)), jl_symbol_name(s), /*InsertBefore*/ctx.topalloca); + StoreInst *SI = new StoreInst(Constant::getNullValue(ctx.types().T_prjlvalue), av, false, Align(sizeof(void*))); + SI->insertAfter(ctx.topalloca); + varinfo.boxroot = av; + if (debug_enabled && varinfo.dinfo) { + SmallVector addr; + DIExpression *expr; + if ((Metadata*)varinfo.dinfo->getType() != debuginfo.jl_pvalue_dillvmt) + addr.push_back(llvm::dwarf::DW_OP_deref); + expr = dbuilder.createExpression(addr); + dbuilder.insertDeclare(av, varinfo.dinfo, expr, + topdebugloc, + ctx.builder.GetInsertBlock()); } }; @@ -8359,7 +8353,7 @@ static jl_llvm_functions_t varinfo.usedUndef = false; continue; } - allocate_local(varinfo, s); + allocate_local(varinfo, s, (int)i); } std::map upsilon_to_phic; @@ -8402,7 +8396,7 @@ static jl_llvm_functions_t vi.used = true; vi.isVolatile = true; vi.value = mark_julia_type(ctx, (Value*)NULL, false, typ); - allocate_local(vi, jl_symbol("phic")); + allocate_local(vi, jl_symbol("phic"), -1); } } } @@ -8542,7 +8536,7 @@ static jl_llvm_functions_t ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, argPtr, Align(sizeof(void*))), false, vi.value.typ)); theArg = mark_julia_type(ctx, load, true, vi.value.typ); - if (debug_enabled && vi.dinfo && !vi.boxroot && !vi.value.V) { + if (debug_enabled && vi.dinfo && !vi.boxroot) { SmallVector addr; addr.push_back(llvm::dwarf::DW_OP_deref); addr.push_back(llvm::dwarf::DW_OP_plus_uconst); @@ -8561,21 +8555,15 @@ static jl_llvm_functions_t assert(vi.value.V == NULL && "unexpected variable slot created for argument"); // keep track of original (possibly boxed) value to avoid re-boxing or moving vi.value = theArg; - if (specsig && theArg.V && debug_enabled && vi.dinfo) { - SmallVector addr; - Value *parg; + if (debug_enabled && vi.dinfo && theArg.V) { if (theArg.ispointer()) { - parg = theArg.V; - if ((Metadata*)vi.dinfo->getType() != debuginfo.jl_pvalue_dillvmt) - addr.push_back(llvm::dwarf::DW_OP_deref); + dbuilder.insertDeclare(theArg.V, vi.dinfo, dbuilder.createExpression(), + topdebugloc, ctx.builder.GetInsertBlock()); } else { - parg = ctx.builder.CreateAlloca(theArg.V->getType(), NULL, jl_symbol_name(s)); - ctx.builder.CreateStore(theArg.V, parg); + dbuilder.insertDbgValueIntrinsic(theArg.V, vi.dinfo, dbuilder.createExpression(), + topdebugloc, ctx.builder.GetInsertBlock()); } - dbuilder.insertDeclare(parg, vi.dinfo, dbuilder.createExpression(addr), - topdebugloc, - ctx.builder.GetInsertBlock()); } } else { diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index ca45bee7ee736..9ca239a2c6b5a 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = 48eea8dbd7b651cdc932b909c1b718bb9c3f94f4 +PKG_SHA1 = e7d740ac82fa4c289bb58f9acb6e60eebb6d8a8e PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 diff --git a/test/core.jl b/test/core.jl index aa16380c8a866..0eca2251cd146 100644 --- a/test/core.jl +++ b/test/core.jl @@ -8127,3 +8127,5 @@ let M = @__MODULE__ @test Core.set_binding_type!(M, :a_typed_global) === nothing @test Core.get_binding_type(M, :a_typed_global) === Tuple{Union{Integer,Nothing}} end + +@test Base.unsafe_convert(Ptr{Int}, [1]) !== C_NULL