From d9040a59326f6a2b24e4582c062577840e35045d Mon Sep 17 00:00:00 2001 From: Simone Carlo Surace <51025924+simsurace@users.noreply.github.com> Date: Mon, 16 Jan 2023 11:55:48 +0100 Subject: [PATCH 01/45] Fix mistake in docstring of `keys(::RegexMatch)` (#48252) This method was added in 1.7.0 and is not available in any 1.6 release (cherry picked from commit 12c3b1cb67ee8a40c5334a8a9ef26a5eef16093f) --- base/regex.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/regex.jl b/base/regex.jl index dfd5d29b8d978..b47ddd816df63 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -197,8 +197,8 @@ That is, `idx` will be in the return value even if `m[idx] == nothing`. Unnamed capture groups will have integer keys corresponding to their index. Named capture groups will have string keys. -!!! compat "Julia 1.6" - This method was added in Julia 1.6 +!!! compat "Julia 1.7" + This method was added in Julia 1.7 # Examples ```jldoctest From 4dc9a108296184b18b2c15387a65d1c9f5a22a49 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 16 Jan 2023 13:16:48 +0100 Subject: [PATCH 02/45] Avoid dtrace regenerating the header (#48278) (cherry picked from commit a9ce60a8ceef96cc1d5ab36efbdd8954fa2c6471) --- src/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile b/src/Makefile index 2cfade630987f..a6939f629412f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -91,6 +91,7 @@ endif else DTRACE_HEADERS := endif +.SECONDARY: $(addprefix $(BUILDDIR)/,$(DTRACE_HEADERS)) # headers are used for dependency tracking, while public headers will be part of the dist UV_HEADERS := From e640e7b1367c4f389bc0d0360584b03ce826ebf1 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Mon, 16 Jan 2023 20:00:37 -0500 Subject: [PATCH 03/45] Profile: print profile peek to stderr (#48291) (cherry picked from commit 36007b7816cd9c6d955cf8b9a5c87e123b3307af) --- stdlib/Profile/src/Profile.jl | 8 ++++---- stdlib/Profile/test/runtests.jl | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index f016e19cd3e05..ba2d7390a214c 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -39,9 +39,9 @@ function profile_printing_listener() wait(PROFILE_PRINT_COND[]) peek_report[]() if get(ENV, "JULIA_PROFILE_PEEK_HEAP_SNAPSHOT", nothing) === "1" - println("Saving heap snapshot...") + println(stderr, "Saving heap snapshot...") fname = take_heap_snapshot() - println("Heap snapshot saved to `$(fname)`") + println(stderr, "Heap snapshot saved to `$(fname)`") end end catch ex @@ -54,9 +54,9 @@ end # An internal function called to show the report after an information request (SIGINFO or SIGUSR1). function _peek_report() iob = IOBuffer() - ioc = IOContext(IOContext(iob, stdout), :displaysize=>displaysize(stdout)) + ioc = IOContext(IOContext(iob, stderr), :displaysize=>displaysize(stderr)) print(ioc, groupby = [:thread, :task]) - Base.print(stdout, String(take!(iob))) + Base.print(stderr, String(take!(iob))) end # This is a ref so that it can be overridden by other profile info consumers. const peek_report = Ref{Function}(_peek_report) diff --git a/stdlib/Profile/test/runtests.jl b/stdlib/Profile/test/runtests.jl index 1246dcf25a82c..2a39640d215ed 100644 --- a/stdlib/Profile/test/runtests.jl +++ b/stdlib/Profile/test/runtests.jl @@ -199,14 +199,14 @@ if Sys.isbsd() || Sys.islinux() let cmd = Base.julia_cmd() script = """ x = rand(1000, 1000) - println("started") + println(stderr, "started") while true x * x yield() end """ iob = Base.BufferStream() - p = run(pipeline(`$cmd -e $script`, stderr = devnull, stdout = iob), wait = false) + p = run(pipeline(`$cmd -e $script`, stderr = iob, stdout = devnull), wait = false) t = Timer(120) do t # should be under 10 seconds, so give it 2 minutes then report failure println("KILLING BY PROFILE TEST WATCHDOG\n") From 5da6d97f91164f29241d2ed694e654e2f0e1afe3 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Fri, 13 Jan 2023 13:31:27 +0900 Subject: [PATCH 04/45] NFC followups for #48246 (#48264) --- base/compiler/abstractinterpretation.jl | 18 ++++++++---------- base/compiler/effects.jl | 4 ++-- base/compiler/inferencestate.jl | 2 +- base/expr.jl | 4 ++-- test/compiler/effects.jl | 1 + 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 9dcc48841c24f..ae508ab4b8bf3 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -2045,14 +2045,13 @@ function abstract_eval_value_expr(interp::AbstractInterpreter, e::Expr, vtypes:: end elseif head === :boundscheck if isa(sv, InferenceState) - flag = sv.src.ssaflags[sv.currpc] - # If there is no particular @inbounds for this function, then we only taint `noinbounds`, - # which will subsequently taint consistency if this function is called from another - # function that uses `@inbounds`. However, if this :boundscheck is itself within an + # If there is no particular `@inbounds` for this function, then we only taint `:noinbounds`, + # which will subsequently taint `:consistent`-cy if this function is called from another + # function that uses `@inbounds`. However, if this `:boundscheck` is itself within an # `@inbounds` region, its value depends on `--check-bounds`, so we need to taint - # consistency here also. + # `:consistent`-cy here also. merge_effects!(interp, sv, Effects(EFFECTS_TOTAL; noinbounds=false, - consistent = (flag & IR_FLAG_INBOUNDS) != 0 ? ALWAYS_FALSE : ALWAYS_TRUE)) + consistent = (get_curr_ssaflag(sv) & IR_FLAG_INBOUNDS) != 0 ? ALWAYS_FALSE : ALWAYS_TRUE)) end rt = Bool elseif head === :inbounds @@ -2333,8 +2332,8 @@ function abstract_eval_phi(interp::AbstractInterpreter, phi::PhiNode, vtypes::Un end function stmt_taints_inbounds_consistency(sv::InferenceState) - flag = sv.src.ssaflags[sv.currpc] - return sv.src.propagate_inbounds || (flag & IR_FLAG_INBOUNDS) != 0 + sv.src.propagate_inbounds && return true + return (get_curr_ssaflag(sv) & IR_FLAG_INBOUNDS) != 0 end function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), vtypes::VarTable, sv::InferenceState) @@ -2346,13 +2345,12 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), end (;rt, effects) = abstract_eval_statement_expr(interp, e, vtypes, sv, nothing) if !effects.noinbounds - flag = sv.src.ssaflags[sv.currpc] if !sv.src.propagate_inbounds # The callee read our inbounds flag, but unless we propagate inbounds, # we ourselves don't read our parent's inbounds. effects = Effects(effects; noinbounds=true) end - if (flag & IR_FLAG_INBOUNDS) != 0 + if (get_curr_ssaflag(sv) & IR_FLAG_INBOUNDS) != 0 effects = Effects(effects; consistent=ALWAYS_FALSE) end end diff --git a/base/compiler/effects.jl b/base/compiler/effects.jl index 48842d7f51cd8..27e41bf04865d 100644 --- a/base/compiler/effects.jl +++ b/base/compiler/effects.jl @@ -40,8 +40,8 @@ following meanings: This state corresponds to LLVM's `inaccessiblemem_or_argmemonly` function attribute. - `nonoverlayed::Bool`: indicates that any methods that may be called within this method are not defined in an [overlayed method table](@ref OverlayMethodTable). -- `noinbounds::Bool`: If set, indicates that this method does not read the parent's :inbounds - state. In particular, it does not have any reached :boundscheck exprs, not propagates inbounds +- `noinbounds::Bool`: If set, indicates that this method does not read the parent's `:inbounds` + state. In particular, it does not have any reached `:boundscheck` exprs, not propagates inbounds to any children that do. Note that the representations above are just internal implementation details and thus likely diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index cb6ebe5e76dc3..9145abd769cee 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -177,7 +177,7 @@ mutable struct InferenceState valid_worlds = WorldRange(src.min_world, src.max_world == typemax(UInt) ? get_world_counter() : src.max_world) bestguess = Bottom - ipo_effects = Effects(EFFECTS_TOTAL) + ipo_effects = EFFECTS_TOTAL params = InferenceParams(interp) restrict_abstract_call_sites = isa(linfo.def, Module) diff --git a/base/expr.jl b/base/expr.jl index 76e9c3af9a2c6..26203c210adea 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -608,8 +608,8 @@ currently equivalent to the following `setting`s: must consistently throw given the same argument values. !!! note - An explict `@inbounds` annotation inside the function will also disable - constant propagation and not be overriden by :foldable. + An explicit `@inbounds` annotation inside the function will also disable + constant folding and not be overriden by `:foldable`. --- ## `:total` diff --git a/test/compiler/effects.jl b/test/compiler/effects.jl index 5e18d5386089d..3aad5d1bdd8ab 100644 --- a/test/compiler/effects.jl +++ b/test/compiler/effects.jl @@ -682,6 +682,7 @@ let src = code_typed1(mksparamunused, (Any,)) end # Test that dead `@inbounds` does not taint consistency +# https://github.com/JuliaLang/julia/issues/48243 @test Base.infer_effects() do false && @inbounds (1,2,3)[1] return 1 From 9c99454b0bd2a4b4dc5ea3bd201e5c1f0b673b5f Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 18 Jan 2023 05:34:53 +0100 Subject: [PATCH 05/45] fix some issues discovered by JET (#48303) --- base/binaryplatforms.jl | 2 +- base/loading.jl | 28 ++++++++++++++----------- stdlib/Artifacts/src/Artifacts.jl | 2 +- stdlib/FileWatching/src/FileWatching.jl | 2 +- stdlib/LibGit2/src/LibGit2.jl | 2 +- stdlib/LibGit2/src/callbacks.jl | 21 ++++++++++--------- stdlib/LibGit2/src/gitcredential.jl | 5 +++-- stdlib/LibGit2/src/types.jl | 13 +++++++----- stdlib/LibGit2/src/utils.jl | 4 ++-- 9 files changed, 44 insertions(+), 35 deletions(-) diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index ea55e67a305f6..272c5958bdb0c 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -872,7 +872,7 @@ function detect_libstdcxx_version(max_minor_version::Int=30) end # Brute-force our way through GLIBCXX_* symbols to discover which version we're linked against - hdl = Libdl.dlopen(first(libstdcxx_paths)) + hdl = Libdl.dlopen(first(libstdcxx_paths))::Ptr{Cvoid} # Try all GLIBCXX versions down to GCC v4.8: # https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html for minor_version in max_minor_version:-1:18 diff --git a/base/loading.jl b/base/loading.jl index b1f6d608daf32..6648c87c3f454 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -865,7 +865,11 @@ function explicit_manifest_uuid_path(project_file::String, pkg::PkgId)::Union{No uuid = get(entry, "uuid", nothing)::Union{Nothing, String} extensions = get(entry, "extensions", nothing)::Union{Nothing, Dict{String, Any}} if extensions !== nothing && haskey(extensions, pkg.name) && uuid !== nothing && uuid5(UUID(uuid), pkg.name) == pkg.uuid - p = normpath(dirname(locate_package(PkgId(UUID(uuid), name))), "..") + parent_path = locate_package(PkgId(UUID(uuid), name)) + if parent_path === nothing + error("failed to find source of parent package: \"$name\"") + end + p = normpath(dirname(parent_path), "..") extfiledir = joinpath(p, "ext", pkg.name, pkg.name * ".jl") isfile(extfiledir) && return extfiledir return joinpath(p, "ext", pkg.name * ".jl") @@ -1138,10 +1142,10 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi dep_name in weakdeps || continue entries::Vector{Any} if length(entries) != 1 - error("expected a single entry for $(repr(name)) in $(repr(project_file))") + error("expected a single entry for $(repr(dep_name)) in $(repr(project_file))") end entry = first(entries)::Dict{String, Any} - uuid = get(entry, "uuid", nothing)::Union{String, Nothing} + uuid = entry["uuid"]::String d_weakdeps[dep_name] = uuid end @assert length(d_weakdeps) == length(weakdeps) @@ -1247,7 +1251,7 @@ function _tryrequire_from_serialized(modkey::PkgId, build_id::UInt128) loading = get(package_locks, modkey, false) if loading !== false # load already in progress for this module - loaded = wait(loading) + loaded = wait(loading::Threads.Condition) else package_locks[modkey] = Threads.Condition(require_lock) try @@ -1282,7 +1286,7 @@ function _tryrequire_from_serialized(modkey::PkgId, path::String, ocachepath::Un loading = get(package_locks, modkey, false) if loading !== false # load already in progress for this module - loaded = wait(loading) + loaded = wait(loading::Threads.Condition) else for i in 1:length(depmods) dep = depmods[i] @@ -1324,7 +1328,7 @@ function _tryrequire_from_serialized(pkg::PkgId, path::String, ocachepath::Union pkgimage = !isempty(clone_targets) if pkgimage ocachepath !== nothing || return ArgumentError("Expected ocachepath to be provided") - isfile(ocachepath) || return ArgumentError("Ocachepath $ocachpath is not a file.") + isfile(ocachepath) || return ArgumentError("Ocachepath $ocachepath is not a file.") ocachepath == ocachefile_from_cachefile(path) || return ArgumentError("$ocachepath is not the expected ocachefile") # TODO: Check for valid clone_targets? isvalid_pkgimage_crc(io, ocachepath) || return ArgumentError("Invalid checksum in cache file $ocachepath.") @@ -1404,13 +1408,13 @@ end staledeps = true break end - staledeps[i] = dep + (staledeps::Vector{Any})[i] = dep end if staledeps === true ocachefile = nothing continue end - restored = _include_from_serialized(pkg, path_to_try, ocachefile, staledeps) + restored = _include_from_serialized(pkg, path_to_try, ocachefile::String, staledeps::Vector{Any}) if !isa(restored, Module) @debug "Deserialization checks failed while attempting to load cache from $path_to_try" exception=restored else @@ -1667,7 +1671,7 @@ function _require(pkg::PkgId, env=nothing) loading = get(package_locks, pkg, false) if loading !== false # load already in progress for this module - return wait(loading) + return wait(loading::Threads.Condition) end package_locks[pkg] = Threads.Condition(require_lock) @@ -2160,12 +2164,12 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in rename(tmppath_so, ocachefile::String; force=true) catch e e isa IOError || rethrow() - isfile(ocachefile) || rethrow() + isfile(ocachefile::String) || rethrow() # Windows prevents renaming a file that is in use so if there is a Julia session started # with a package image loaded, we cannot rename that file. # The code belows append a `_i` to the name of the cache file where `i` is the smallest number such that # that cache file does not exist. - ocachename, ocacheext = splitext(ocachefile) + ocachename, ocacheext = splitext(ocachefile::String) old_cachefiles = Set(readdir(cachepath)) num = 1 while true @@ -2185,7 +2189,7 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in finally rm(tmppath, force=true) if cache_objects - rm(tmppath_o, force=true) + rm(tmppath_o::String, force=true) rm(tmppath_so, force=true) end end diff --git a/stdlib/Artifacts/src/Artifacts.jl b/stdlib/Artifacts/src/Artifacts.jl index 4bcf98df2a1d9..a9554c95f3151 100644 --- a/stdlib/Artifacts/src/Artifacts.jl +++ b/stdlib/Artifacts/src/Artifacts.jl @@ -52,7 +52,7 @@ function artifacts_dirs(args...) return String[abspath(depot, "artifacts", args...) for depot in Base.DEPOT_PATH] else # If we've been given an override, use _only_ that directory. - return String[abspath(ARTIFACTS_DIR_OVERRIDE[], args...)] + return String[abspath(ARTIFACTS_DIR_OVERRIDE[]::String, args...)] end end diff --git a/stdlib/FileWatching/src/FileWatching.jl b/stdlib/FileWatching/src/FileWatching.jl index 1b4886c0d8e32..17ae24460db6b 100644 --- a/stdlib/FileWatching/src/FileWatching.jl +++ b/stdlib/FileWatching/src/FileWatching.jl @@ -215,7 +215,7 @@ mutable struct _FDWatcher t.refcount = (0, 0) t.active = (false, false) @static if Sys.isunix() - if FDWatchers[t.fdnum] == t + if FDWatchers[t.fdnum] === t FDWatchers[t.fdnum] = nothing end end diff --git a/stdlib/LibGit2/src/LibGit2.jl b/stdlib/LibGit2/src/LibGit2.jl index cd7dd01615648..6a797937ccf0b 100644 --- a/stdlib/LibGit2/src/LibGit2.jl +++ b/stdlib/LibGit2/src/LibGit2.jl @@ -848,7 +848,7 @@ function rebase!(repo::GitRepo, upstream::AbstractString="", newbase::AbstractSt end finally if !isempty(newbase) - close(onto_ann) + close(onto_ann::GitAnnotated) end close(upst_ann) close(head_ann) diff --git a/stdlib/LibGit2/src/callbacks.jl b/stdlib/LibGit2/src/callbacks.jl index 83ac58010ac32..3bc6463140d5f 100644 --- a/stdlib/LibGit2/src/callbacks.jl +++ b/stdlib/LibGit2/src/callbacks.jl @@ -276,18 +276,20 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Cvoid}}, url_ptr::Cstring, # information cached inside the payload. if isempty(p.url) p.url = unsafe_string(url_ptr) - m = match(URL_REGEX, p.url) + m = match(URL_REGEX, p.url)::RegexMatch p.scheme = something(m[:scheme], SubString("")) p.username = something(m[:user], SubString("")) - p.host = m[:host] + p.host = something(m[:host]) # When an explicit credential is supplied we will make sure to use the given # credential during the first callback by modifying the allowed types. The # modification only is in effect for the first callback since `allowed_types` cannot # be mutated. - if p.explicit !== nothing - cred = p.explicit + cache = p.cache + explicit = p.explicit + if explicit !== nothing + cred = explicit # Copy explicit credentials to avoid mutating approved credentials. # invalidation fix from cred being non-inferrable @@ -300,16 +302,15 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Cvoid}}, url_ptr::Cstring, else allowed_types &= Cuint(0) # Unhandled credential type end - elseif p.cache !== nothing + elseif cache !== nothing cred_id = credential_identifier(p.scheme, p.host) # Perform a deepcopy as we do not want to mutate approved cached credentials - if haskey(p.cache, cred_id) - # invalidation fix from p.cache[cred_id] being non-inferrable - p.credential = Base.invokelatest(deepcopy, p.cache[cred_id]) + if haskey(cache, cred_id) + # invalidation fix from cache[cred_id] being non-inferrable + p.credential = Base.invokelatest(deepcopy, cache[cred_id]) end end - p.first_pass = true else p.first_pass = false @@ -447,7 +448,7 @@ function ssh_knownhost_check( ) if (m = match(r"^(.+):(\d+)$", host)) !== nothing host = m.captures[1] - port = parse(Int, m.captures[2]) + port = parse(Int, something(m.captures[2])) else port = 22 # default SSH port end diff --git a/stdlib/LibGit2/src/gitcredential.jl b/stdlib/LibGit2/src/gitcredential.jl index acfde02578523..7ff20ca1fdf2c 100644 --- a/stdlib/LibGit2/src/gitcredential.jl +++ b/stdlib/LibGit2/src/gitcredential.jl @@ -46,7 +46,8 @@ function Base.shred!(cred::GitCredential) cred.host = nothing cred.path = nothing cred.username = nothing - cred.password !== nothing && Base.shred!(cred.password) + pwd = cred.password + pwd !== nothing && Base.shred!(pwd) cred.password = nothing return cred end @@ -122,7 +123,7 @@ function Base.read!(io::IO, cred::GitCredential) if key == "url" # Any components which are missing from the URL will be set to empty # https://git-scm.com/docs/git-credential#git-credential-codeurlcode - Base.shred!(parse(GitCredential, value)) do urlcred + Base.shred!(parse(GitCredential, value::AbstractString)) do urlcred copy!(cred, urlcred) end elseif key in GIT_CRED_ATTRIBUTES diff --git a/stdlib/LibGit2/src/types.jl b/stdlib/LibGit2/src/types.jl index d5ed9014aea86..1ea6c797d1636 100644 --- a/stdlib/LibGit2/src/types.jl +++ b/stdlib/LibGit2/src/types.jl @@ -1389,7 +1389,8 @@ CredentialPayload(p::CredentialPayload) = p function Base.shred!(p::CredentialPayload) # Note: Avoid shredding the `explicit` or `cache` fields as these are just references # and it is not our responsibility to shred them. - p.credential !== nothing && Base.shred!(p.credential) + credential = p.credential + credential !== nothing && Base.shred!(credential) p.credential = nothing end @@ -1430,8 +1431,9 @@ function approve(p::CredentialPayload; shred::Bool=true) # Each `approve` call needs to avoid shredding the passed in credential as we need # the credential information intact for subsequent approve calls. - if p.cache !== nothing - approve(p.cache, cred, p.url) + cache = p.cache + if cache !== nothing + approve(cache, cred, p.url) shred = false # Avoid wiping `cred` as this would also wipe the cached copy end if p.allow_git_helpers @@ -1460,8 +1462,9 @@ function reject(p::CredentialPayload; shred::Bool=true) # Note: each `reject` call needs to avoid shredding the passed in credential as we need # the credential information intact for subsequent reject calls. - if p.cache !== nothing - reject(p.cache, cred, p.url) + cache = p.cache + if cache !== nothing + reject(cache, cred, p.url) end if p.allow_git_helpers reject(p.config, cred, p.url) diff --git a/stdlib/LibGit2/src/utils.jl b/stdlib/LibGit2/src/utils.jl index b601ea4efe601..5234e9b6fc291 100644 --- a/stdlib/LibGit2/src/utils.jl +++ b/stdlib/LibGit2/src/utils.jl @@ -171,7 +171,7 @@ end function credential_identifier(url::AbstractString) m = match(URL_REGEX, url) - scheme = something(m[:scheme], "") - host = m[:host] + scheme = something(m[:scheme], SubString("")) + host = something(m[:host]) credential_identifier(scheme, host) end From 914ec6970083a916dbf9d45952ca96e625686af6 Mon Sep 17 00:00:00 2001 From: Jeremie Knuesel Date: Thu, 19 Jan 2023 13:06:27 +0100 Subject: [PATCH 06/45] Fix Splat->splat in NEWS.md (#48350) --- NEWS.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 4c272f7fb95bb..0ad9c515fb4b4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -68,8 +68,6 @@ New library functions --------------------- * New function `Iterators.flatmap` ([#44792]). -* New helper `Splat(f)` which acts like `x -> f(x...)`, with pretty printing for - inspecting which function `f` was originally wrapped ([#42717]). * New `pkgversion(m::Module)` function to get the version of the package that loaded a given module, similar to `pkgdir(m::Module)` ([#45607]). * New function `stack(x)` which generalises `reduce(hcat, x::Vector{<:Vector})` to any dimensionality, @@ -98,6 +96,8 @@ Standard library changes * `@kwdef` is now exported and added to the public API ([#46273]). * An issue with order of operations in `fld1` is now fixed ([#28973]). * Sorting is now always stable by default, as `QuickSort` was stabilized ([#45222]). +* `Base.splat` is now exported. The return value is now a `Base.Splat` instead + of an anonymous function, which allows for pretty printing ([#42717]). #### Package Manager @@ -185,7 +185,6 @@ Standard library changes Deprecated or removed --------------------- -* Unexported `splat` is deprecated in favor of exported `Splat`, which has pretty printing of the wrapped function ([#42717]). External dependencies --------------------- From 986dc4067bfad21c216c4568f15187ea71b25939 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Sun, 22 Jan 2023 23:07:38 -0500 Subject: [PATCH 07/45] run doc/NEWS-update.jl --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 0ad9c515fb4b4..37ddf4b171776 100644 --- a/NEWS.md +++ b/NEWS.md @@ -218,6 +218,7 @@ Tooling Improvements [#44358]: https://github.com/JuliaLang/julia/issues/44358 [#44360]: https://github.com/JuliaLang/julia/issues/44360 [#44512]: https://github.com/JuliaLang/julia/issues/44512 +[#44527]: https://github.com/JuliaLang/julia/issues/44527 [#44534]: https://github.com/JuliaLang/julia/issues/44534 [#44571]: https://github.com/JuliaLang/julia/issues/44571 [#44714]: https://github.com/JuliaLang/julia/issues/44714 @@ -247,5 +248,7 @@ Tooling Improvements [#46609]: https://github.com/JuliaLang/julia/issues/46609 [#46862]: https://github.com/JuliaLang/julia/issues/46862 [#46976]: https://github.com/JuliaLang/julia/issues/46976 +[#47117]: https://github.com/JuliaLang/julia/issues/47117 +[#47184]: https://github.com/JuliaLang/julia/issues/47184 [#47367]: https://github.com/JuliaLang/julia/issues/47367 [#47392]: https://github.com/JuliaLang/julia/issues/47392 From f8b78eb17827cdf60a2c0edd57ef54b2de4d253c Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sun, 8 Jan 2023 19:48:28 +0100 Subject: [PATCH 08/45] deps: fix broken `p7zip` url (#48176) (cherry picked from commit f6b5157eb5d0c490dff7ee2d0c284a8b04cd62d9) --- deps/p7zip.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/p7zip.mk b/deps/p7zip.mk index 5fea4b63366c2..c7c2874d49a5e 100644 --- a/deps/p7zip.mk +++ b/deps/p7zip.mk @@ -4,7 +4,7 @@ include $(SRCDIR)/p7zip.version ifneq ($(USE_BINARYBUILDER_P7ZIP),1) $(SRCCACHE)/p7zip-$(P7ZIP_VER).tar.gz: | $(SRCCACHE) - $(JLDOWNLOAD) $@ https://github.com/jinfeihan57/p7zip/archive/refs/tags/v$(P7ZIP_VER).tar.gz + $(JLDOWNLOAD) $@ https://github.com/p7zip-project/p7zip/archive/refs/tags/v$(P7ZIP_VER).tar.gz $(BUILDDIR)/p7zip-$(P7ZIP_VER)/source-extracted: $(SRCCACHE)/p7zip-$(P7ZIP_VER).tar.gz $(JLCHECKSUM) $< From 957c93f3f6d3e8a5ce01d0ddda0e2e0a6e36266e Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 17 Jan 2023 17:11:53 +0100 Subject: [PATCH 09/45] improve docs for IPython mode (#48314) (cherry picked from commit a6694d4edf7c331e7c4f8e7a20421ced272e26b5) --- stdlib/REPL/docs/src/index.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index d696c069fbdb7..a23b8f224a6cb 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -629,7 +629,20 @@ atreplinit() do repl end ``` -to your `startup.jl` file. +to your `startup.jl` file. In `IPython` mode the variable `Out[n]` (where `n` is an integer) can be used to refer to earlier results: + +```julia-repl +In [1]: 5 + 3 +Out[1]: 8 + +In [2]: Out[1] + 5 +Out[2]: 13 + +In [3]: Out +Out[3]: Dict{Int64, Any} with 2 entries: + 2 => 13 + 1 => 8 +``` ## TerminalMenus From dbe520d8918540026e7c83b3d2aa4374d69ffbf0 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 18 Jan 2023 09:44:46 +0100 Subject: [PATCH 10/45] fix an erronous type assert (#48327) (cherry picked from commit c4cf1e69de6907e6e56382df02f2ce9bcf9e7c19) --- base/loading.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index 6648c87c3f454..02bbd6fcff7f8 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1414,7 +1414,7 @@ end ocachefile = nothing continue end - restored = _include_from_serialized(pkg, path_to_try, ocachefile::String, staledeps::Vector{Any}) + restored = _include_from_serialized(pkg, path_to_try, ocachefile, staledeps::Vector{Any}) if !isa(restored, Module) @debug "Deserialization checks failed while attempting to load cache from $path_to_try" exception=restored else From 7114a8e43bb6e28ead69da24a315801a321b68e7 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 19 Jan 2023 12:44:29 +0100 Subject: [PATCH 11/45] add a type assert to `read` on a `Cmd` (#48334) (cherry picked from commit 1bff32b2f8d2d3972cb992ffc79850b4eac78304) --- base/process.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/process.jl b/base/process.jl index 65d06d73dff0b..55df523c1f7d2 100644 --- a/base/process.jl +++ b/base/process.jl @@ -447,7 +447,7 @@ function read(cmd::AbstractCmd) procs = open(cmd, "r", devnull) bytes = read(procs.out) success(procs) || pipeline_error(procs) - return bytes + return bytes::Vector{UInt8} end """ From 60dfe2cbcfc088c2e7ab244ff2a931eb6b1e96fb Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 19 Jan 2023 21:38:42 +0100 Subject: [PATCH 12/45] allow extensions to be loaded from non top level env (#48352) (cherry picked from commit 4cab76ce52850f67c8f89a95a8c55c463c933ea3) --- base/loading.jl | 1 - test/loading.jl | 43 ++++++++++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 02bbd6fcff7f8..0d26912a12e7b 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1112,7 +1112,6 @@ function insert_extension_triggers(pkg::PkgId) pkg.uuid === nothing && return for env in load_path() insert_extension_triggers(env, pkg) - break # For now, only insert triggers for packages in the first load_path. end end diff --git a/test/loading.jl b/test/loading.jl index a7e48d6b02160..f98f08103c9d7 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -1000,24 +1000,37 @@ end try tmp = mktempdir() push!(empty!(DEPOT_PATH), joinpath(tmp, "depot")) - proj = joinpath(@__DIR__, "project", "Extensions", "HasDepWithExtensions.jl") - for compile in (`--compiled-modules=no`, ``, ``) # Once when requiring precomilation, once where it is already precompiled - cmd = `$(Base.julia_cmd()) $compile --project=$proj --startup-file=no -e ' - begin - using HasExtensions - # Base.get_extension(HasExtensions, :Extension) === nothing || error("unexpectedly got an extension") - HasExtensions.ext_loaded && error("ext_loaded set") - using HasDepWithExtensions - # Base.get_extension(HasExtensions, :Extension).extvar == 1 || error("extvar in Extension not set") - HasExtensions.ext_loaded || error("ext_loaded not set") - HasExtensions.ext_folder_loaded && error("ext_folder_loaded set") - HasDepWithExtensions.do_something() || error("do_something errored") - using ExtDep2 - HasExtensions.ext_folder_loaded || error("ext_folder_loaded not set") + function gen_extension_cmd(compile) + ```$(Base.julia_cmd()) $compile --startup-file=no -e ' + begin + using HasExtensions + # Base.get_extension(HasExtensions, :Extension) === nothing || error("unexpectedly got an extension") + HasExtensions.ext_loaded && error("ext_loaded set") + using HasDepWithExtensions + # Base.get_extension(HasExtensions, :Extension).extvar == 1 || error("extvar in Extension not set") + HasExtensions.ext_loaded || error("ext_loaded not set") + HasExtensions.ext_folder_loaded && error("ext_folder_loaded set") + HasDepWithExtensions.do_something() || error("do_something errored") + using ExtDep2 + HasExtensions.ext_folder_loaded || error("ext_folder_loaded not set") end - '` + ' + ``` + end + + for compile in (`--compiled-modules=no`, ``, ``) # Once when requiring precomilation, once where it is already precompiled + cmd = gen_extension_cmd(compile) + withenv("JULIA_LOAD_PATH" => proj) do + @test success(cmd) + end + end + + # 48351 + sep = Sys.iswindows() ? ';' : ':' + withenv("JULIA_LOAD_PATH" => join([mktempdir(), proj], sep)) do + cmd = gen_extension_cmd(``) @test success(cmd) end finally From d3fbdf1e05914764f48732ebf441301a2ed8a219 Mon Sep 17 00:00:00 2001 From: t-bltg Date: Sun, 22 Jan 2023 06:32:45 +0100 Subject: [PATCH 13/45] make `dlopen`ing `libssp` non fatal (#48333) (cherry picked from commit 29498798ebda5d37bc8f5300a3d0eeaa5ee0a44c) --- .../src/CompilerSupportLibraries_jll.jl | 5 +---- stdlib/CompilerSupportLibraries_jll/test/runtests.jl | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/stdlib/CompilerSupportLibraries_jll/src/CompilerSupportLibraries_jll.jl b/stdlib/CompilerSupportLibraries_jll/src/CompilerSupportLibraries_jll.jl index 0068414f942e8..097659e01b396 100644 --- a/stdlib/CompilerSupportLibraries_jll/src/CompilerSupportLibraries_jll.jl +++ b/stdlib/CompilerSupportLibraries_jll/src/CompilerSupportLibraries_jll.jl @@ -21,8 +21,6 @@ libstdcxx_handle = C_NULL libstdcxx_path = "" libgomp_handle = C_NULL libgomp_path = "" -libssp_handle = C_NULL -libssp_path = "" if Sys.iswindows() if arch(HostPlatform()) == "x86_64" @@ -64,8 +62,7 @@ function __init__() global libgomp_handle = dlopen(libgomp) global libgomp_path = dlpath(libgomp_handle) @static if libc(HostPlatform()) != "musl" - global libssp_handle = dlopen(libssp) - global libssp_path = dlpath(libssp_handle) + dlopen(libssp; throw_error = false) end global artifact_dir = dirname(Sys.BINDIR) LIBPATH[] = dirname(libgcc_s_path) diff --git a/stdlib/CompilerSupportLibraries_jll/test/runtests.jl b/stdlib/CompilerSupportLibraries_jll/test/runtests.jl index 840a36bdd8d49..85cf132c3a5bd 100644 --- a/stdlib/CompilerSupportLibraries_jll/test/runtests.jl +++ b/stdlib/CompilerSupportLibraries_jll/test/runtests.jl @@ -1,13 +1,10 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -using Test, CompilerSupportLibraries_jll, Base.BinaryPlatforms +using Test, CompilerSupportLibraries_jll @testset "CompilerSupportLibraries_jll" begin @test isfile(CompilerSupportLibraries_jll.libgcc_s_path) @test isfile(CompilerSupportLibraries_jll.libgfortran_path) @test isfile(CompilerSupportLibraries_jll.libstdcxx_path) @test isfile(CompilerSupportLibraries_jll.libgomp_path) - if libc(HostPlatform()) != "musl" - @test isfile(CompilerSupportLibraries_jll.libssp_path) - end end From 9a67956f03e38c7681e64a75d19ba388fb9321e6 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Mon, 23 Jan 2023 10:53:38 +0100 Subject: [PATCH 14/45] set max_methods = 1 for REPL methods (#48330) * set max_methods = 1 for REPL methods (cherry picked from commit f8493c718d28bdbdbc132773c6ef4b4850591add) --- stdlib/REPL/src/LineEdit.jl | 2 +- stdlib/REPL/src/REPL.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 348defe79d197..0dffcc6c1e276 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -452,7 +452,7 @@ function refresh_multi_line(termbuf::TerminalBuffer, terminal::UnixTerminal, buf # Write out the prompt string lindent = write_prompt(termbuf, prompt, hascolor(terminal))::Int # Count the '\n' at the end of the line if the terminal emulator does (specific to DOS cmd prompt) - miscountnl = @static Sys.iswindows() ? (isa(Terminals.pipe_reader(terminal), Base.TTY) && !Base.ispty(Terminals.pipe_reader(terminal))) : false + miscountnl = @static Sys.iswindows() ? (isa(Terminals.pipe_reader(terminal), Base.TTY) && !(Base.ispty(Terminals.pipe_reader(terminal)))::Bool) : false # Now go through the buffer line by line seek(buf, 0) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 9c8712e0d41fc..e3912a48df429 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -14,6 +14,7 @@ Run Evaluate Print Loop (REPL) module REPL Base.Experimental.@optlevel 1 +Base.Experimental.@max_methods 1 using Base.Meta, Sockets import InteractiveUtils From 86fc8b69aeccdbf0b0ad131c2e97832028cf0551 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 31 Jan 2023 00:29:09 +0900 Subject: [PATCH 15/45] inlining: make union splitting account for uncovered call (#48455) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JuliaLang/julia#44421 changed the union-splitting to skip generating unnecessary fallback dynamic dispatch call when there is any fully covered call. But it turned out that this is only valid when there is any fully covered call in matches for all signatures that inference split, and it is invalid if there is any union split signature against which any uncovered call is found. Consider the following example: # case 1 # def nosplit(::Any) = [...] nosplit(::Int) = [...] # call nosplit(a::Any) split1: a::Any ┬ nosplit(a::Int) └ nosplit(a::Any) # fully covers split1 # case 2 # def convert(::Type{T}, ::T) = T # call convert(::Type{Union{Bool,Tuple{Int,String}}}, a::Union{Bool,Tuple{Int,Any}}) split1: a::Bool ─ convert(::Type{Bool}, ::Bool) # fully covers split1 split2: a::Tuple{Int,Any} ─ convert(::Type{Tuple{Int,String}}, ::Tuple{Int,String}) # NOT fully covers split2 JuliaLang/julia#44421 allows us to optimize the the first case, but handles the second case wrongly. This commit fixes it up while still optimizing the first case. fix #48397. --- base/compiler/ssair/inlining.jl | 14 +++++++------- test/compiler/inline.jl | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 0c946a7348a80..c9fcb32ac58ab 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -1348,14 +1348,13 @@ function compute_inlining_cases(@nospecialize(info::CallInfo), flag::UInt8, sig: nunion === nothing && return nothing cases = InliningCase[] argtypes = sig.argtypes - local any_fully_covered = false local handled_all_cases::Bool = true local revisit_idx = nothing local only_method = nothing local meth::MethodLookupResult local all_result_count = 0 local joint_effects::Effects = EFFECTS_TOTAL - local nothrow::Bool = true + local fully_covered::Bool = true for i = 1:nunion meth = getsplit(info, i) if meth.ambig @@ -1377,12 +1376,12 @@ function compute_inlining_cases(@nospecialize(info::CallInfo), flag::UInt8, sig: only_method = false end end + local split_fully_covered::Bool = false for (j, match) in enumerate(meth) all_result_count += 1 result = getresult(info, all_result_count) joint_effects = merge_effects(joint_effects, info_effects(result, match, state)) - nothrow &= match.fully_covers - any_fully_covered |= match.fully_covers + split_fully_covered |= match.fully_covers if !validate_sparams(match.sparams) if !match.fully_covers handled_all_cases = false @@ -1399,9 +1398,10 @@ function compute_inlining_cases(@nospecialize(info::CallInfo), flag::UInt8, sig: result, match, argtypes, info, flag, state; allow_abstract=true, allow_typevars=false) end end + fully_covered &= split_fully_covered end - joint_effects = Effects(joint_effects; nothrow) + joint_effects = Effects(joint_effects; nothrow=fully_covered) if handled_all_cases && revisit_idx !== nothing # we handled everything except one match with unmatched sparams, @@ -1428,13 +1428,13 @@ function compute_inlining_cases(@nospecialize(info::CallInfo), flag::UInt8, sig: end handle_any_const_result!(cases, result, match, argtypes, info, flag, state; allow_abstract=true, allow_typevars=true) - any_fully_covered = handled_all_cases = match.fully_covers + fully_covered = handled_all_cases = match.fully_covers elseif !handled_all_cases # if we've not seen all candidates, union split is valid only for dispatch tuples filter!(case::InliningCase->isdispatchtuple(case.sig), cases) end - return cases, (handled_all_cases & any_fully_covered), joint_effects + return cases, (handled_all_cases & fully_covered), joint_effects end function handle_call!(todo::Vector{Pair{Int,Any}}, diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 2eacda4b02581..09f32c827f3f9 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -1801,3 +1801,22 @@ let src = code_typed1(make_issue47349(Val{4}()), (Any,)) make_issue47349(Val(4))((x,nothing,Int)) end |> only === Type{Int} end + +# union splitting should account for uncovered call signature +# https://github.com/JuliaLang/julia/issues/48397 +f48397(::Bool) = :ok +f48397(::Tuple{String,String}) = :ok +let src = code_typed1((Union{Bool,Tuple{String,Any}},)) do x + f48397(x) + end + @test any(iscall((src, f48397)), src.code) +end +g48397::Union{Bool,Tuple{String,Any}} = ("48397", 48397) +@test_throws MethodError let + Base.Experimental.@force_compile + f48397(g48397) +end +@test_throws MethodError let + Base.Experimental.@force_compile + convert(Union{Bool,Tuple{String,String}}, g48397) +end From 9a8599a2088c90bed9e08a2a348862ac52e69c21 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Thu, 26 Jan 2023 21:27:42 +0100 Subject: [PATCH 16/45] add docs for `getglobal` and `setglobal!` (#48409) closes #45480 Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> (cherry picked from commit 0231c224a1ff25aba975a182b465e06de10f72e5) --- base/docs/basedocs.jl | 76 +++++++++++++++++++++++++++++++++++++++++++ doc/src/base/base.md | 2 ++ 2 files changed, 78 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 36e6d5ab398a1..ec5807f791f34 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -2205,6 +2205,82 @@ instruction, otherwise it'll use a loop. """ replacefield! +""" + getglobal(module::Module, name::Symbol, [order::Symbol=:monotonic]) + +Retrieve the value of the binding `name` from the module `module`. Optionally, an +atomic ordering can be defined for the operation, otherwise it defaults to +monotonic. + +While accessing module bindings using [`getfield`](@ref) is still supported to +maintain compatibility, using `getglobal` should always be preferred since +`getglobal` allows for control over atomic ordering (`getfield` is always +monotonic) and better signifies the code's intent both to the user as well as the +compiler. + +Most users should not have to call this function directly -- The +[`getproperty`](@ref Base.getproperty) function or corresponding syntax (i.e. +`module.name`) should be preferred in all but few very specific use cases. + +!!! compat "Julia 1.9" + This function requires Julia 1.9 or later. + +See also [`getproperty`](@ref Base.getproperty) and [`setglobal!`](@ref). + +# Examples +```jldoctest +julia> a = 1 +1 + +julia> module M + a = 2 + end; + +julia> getglobal(@__MODULE__, :a) +1 + +julia> getglobal(M, :a) +2 +``` +""" +getglobal + +""" + setglobal!(module::Module, name::Symbol, x, [order::Symbol=:monotonic]) + +Set or change the value of the binding `name` in the module `module` to `x`. No +type conversion is performed, so if a type has already been declared for the +binding, `x` must be of appropriate type or an error is thrown. + +Additionally, an atomic ordering can be specified for this operation, otherwise it +defaults to monotonic. + +Users will typically access this functionality through the +[`setproperty!`](@ref Base.setproperty!) function or corresponding syntax +(i.e. `module.name = x`) instead, so this is intended only for very specific use +cases. + +!!! compat "Julia 1.9" + This function requires Julia 1.9 or later. + +See also [`setproperty!`](@ref Base.setproperty!) and [`getglobal`](@ref) + +# Examples +```jldoctest +julia> module M end; + +julia> M.a # same as `getglobal(M, :a)` +ERROR: UndefVarError: `a` not defined + +julia> setglobal!(M, :a, 1) +1 + +julia> M.a +1 +``` +""" +setglobal! + """ typeof(x) diff --git a/doc/src/base/base.md b/doc/src/base/base.md index f01dab2a5d1de..a47307da94c43 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -143,6 +143,8 @@ Base.hasproperty Core.getfield Core.setfield! Core.isdefined +Core.getglobal +Core.setglobal! Base.@isdefined Base.convert Base.promote From 0a1da6949cdefecb75b015523f4ded1db5631a9b Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Thu, 26 Jan 2023 23:50:36 +0100 Subject: [PATCH 17/45] add docs for try-catch-else (#48414) ref #46928 Co-authored-by: Ian Butterworth (cherry picked from commit d77575063d7ecb5e79ee6fc9f3b73242f8282853) --- doc/src/manual/control-flow.md | 38 +++++++++++++++++++++++++ doc/src/manual/variables-and-scoping.md | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 18a84957fe625..ba78a8c5b1670 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -827,6 +827,44 @@ no error has occurred, but the ability to unwind the stack and pass a value to a is desirable. Julia provides the [`rethrow`](@ref), [`backtrace`](@ref), [`catch_backtrace`](@ref) and [`current_exceptions`](@ref) functions for more advanced error handling. +### `else` Clauses + +!!! compat "Julia 1.8" + This functionality requires at least Julia 1.8. + +In some cases, one may not only want to appropriately handle the error case, but also want to run +some code only if the `try` block succeeds. For this, an `else` clause can be specified after the +`catch` block that is run whenever no error was thrown previously. The advantage over including +this code in the `try` block instead is that any further errors don't get silently caught by the +`catch` clause. + +```julia +local x +try + x = read("file", String) +catch + # handle read errors +else + # do something with x +end +``` + +!!! note + The `try`, `catch`, `else`, and `finally` clauses each introduce their own scope blocks, so if + a variable is only defined in the `try` block, it can not be accessed by the `else` or `finally` + clause: + ```jldoctest + julia> try + foo = 1 + catch + else + foo + end + ERROR: UndefVarError: `foo` not defined + ``` + Use the [`local` keyword](@ref local-scope) outside the `try` block to make the variable + accessible from anywhere within the outer scope. + ### `finally` Clauses In code that performs state changes or uses resources like files, there is typically clean-up diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index ebb4559b3e854..8bd62fe7ee5bf 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -111,7 +111,7 @@ x = 1 Note that the interactive prompt (aka REPL) is in the global scope of the module `Main`. -## Local Scope +## [Local Scope](@id local-scope) A new local scope is introduced by most code blocks (see above [table](@ref man-scope-table) for a complete list). If such a block is syntactically nested From 90c98397e477c43a5701d9d945a709befc891dd7 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Fri, 27 Jan 2023 14:53:04 +0100 Subject: [PATCH 18/45] Store the frontend task object in the REPL struct. (#48400) (cherry picked from commit 87f8958a218215df0aaffab59736c30eb6f51d2e) --- stdlib/REPL/src/REPL.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index e3912a48df429..b2eb8cf63c8da 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -389,6 +389,7 @@ end mutable struct BasicREPL <: AbstractREPL terminal::TextTerminal waserror::Bool + frontend_task::Task BasicREPL(t) = new(t, false) end @@ -396,6 +397,7 @@ outstream(r::BasicREPL) = r.terminal hascolor(r::BasicREPL) = hascolor(r.terminal) function run_frontend(repl::BasicREPL, backend::REPLBackendRef) + repl.frontend_task = current_task() d = REPLDisplay(repl) dopushdisplay = !in(d,Base.Multimedia.displays) dopushdisplay && pushdisplay(d) @@ -462,6 +464,7 @@ mutable struct LineEditREPL <: AbstractREPL last_shown_line_infos::Vector{Tuple{String,Int}} interface::ModalInterface backendref::REPLBackendRef + frontend_task::Task function LineEditREPL(t,hascolor,prompt_color,input_color,answer_color,shell_color,help_color,history_file,in_shell,in_help,envcolors) opts = Options() opts.hascolor = hascolor @@ -1281,6 +1284,7 @@ function setup_interface( end function run_frontend(repl::LineEditREPL, backend::REPLBackendRef) + repl.frontend_task = current_task() d = REPLDisplay(repl) dopushdisplay = repl.specialdisplay === nothing && !in(d,Base.Multimedia.displays) dopushdisplay && pushdisplay(d) @@ -1306,6 +1310,7 @@ mutable struct StreamREPL <: AbstractREPL input_color::String answer_color::String waserror::Bool + frontend_task::Task StreamREPL(stream,pc,ic,ac) = new(stream,pc,ic,ac,false) end StreamREPL(stream::IO) = StreamREPL(stream, Base.text_colors[:green], Base.input_color(), Base.answer_color()) @@ -1364,6 +1369,7 @@ ends_with_semicolon(code::Union{String,SubString{String}}) = contains(_rm_strings_and_comments(code), r";\s*$") function run_frontend(repl::StreamREPL, backend::REPLBackendRef) + repl.frontend_task = current_task() have_color = hascolor(repl) Base.banner(repl.stream) d = REPLDisplay(repl) From 186f5a590a86832c1aa6529ba1c44415f4d026e0 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 28 Jan 2023 23:06:21 -0500 Subject: [PATCH 19/45] avoid hang when only threads are starting IO (#48433) When not in threaded region, only thread 0 will manage IO events, but it may have gone to sleep if there were no IO objects active for it to watch earlier. Fix #48430 (cherry picked from commit 45b7e7ab2b6ec90dfa4b4f156c5c5d77ebe28b8b) --- src/partr.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/partr.c b/src/partr.c index f5f63f54e7d25..aceaf9dc2c5b5 100644 --- a/src/partr.c +++ b/src/partr.c @@ -229,7 +229,7 @@ JL_DLLEXPORT void jl_wakeup_thread(int16_t tid) } else { // something added to the sticky-queue: notify that thread - if (wake_thread(tid)) { + if (wake_thread(tid) && uvlock != ct) { // check if we need to notify uv_run too jl_fence(); jl_ptls_t other = jl_atomic_load_relaxed(&jl_all_tls_states)[tid]; @@ -237,7 +237,7 @@ JL_DLLEXPORT void jl_wakeup_thread(int16_t tid) // now that we have changed the thread to not-sleeping, ensure that // either it has not yet acquired the libuv lock, or that it will // observe the change of state to not_sleeping - if (uvlock != ct && jl_atomic_load_relaxed(&jl_uv_mutex.owner) == tid_task) + if (jl_atomic_load_relaxed(&jl_uv_mutex.owner) == tid_task) wake_libuv(); } } @@ -365,7 +365,16 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, } else if (ptls->tid == 0) { uvlock = 1; - JL_UV_LOCK(); // jl_mutex_lock(&jl_uv_mutex); + JL_UV_LOCK(); + } + else { + // Since we might have started some IO work, we might need + // to ensure tid = 0 will go watch that new event source. + // If trylock would have succeeded, that may have been our + // responsibility, so need to make sure thread 0 will take care + // of us. + if (jl_atomic_load_relaxed(&jl_uv_mutex.owner) == NULL) // aka trylock + jl_wakeup_thread(0); } if (uvlock) { int enter_eventloop = may_sleep(ptls); From 775c97f8d452ddce3fb3f3a86876b7f976c7ba9f Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Mon, 30 Jan 2023 09:58:44 -0600 Subject: [PATCH 20/45] Sorting documentation fixups for 1.9 (#48440) - Fix typos - Clarify that ! means mutation, not "in-place-ness". This should be backported because sort! is even less in place in 1.9 than it already was in 1.8. - Rewrite the section on default policy to reflect the new default policy - Move examples and extended description of previously default sorting algorithms out of sort.md and into their respective docstrings (still rendered in sort.md) Co-authored-by: Jeremie Knuesel (cherry picked from commit a1c4d855bc133758ef65102f32bdeff22fb6d0af) --- base/sort.jl | 26 ++++++++++++++-- doc/src/base/sort.md | 70 ++++++++++---------------------------------- 2 files changed, 39 insertions(+), 57 deletions(-) diff --git a/base/sort.jl b/base/sort.jl index c5a293a72be57..3d57c7d59ee81 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -524,7 +524,7 @@ Base.size(v::WithoutMissingVector) = size(v.data) send_to_end!(f::Function, v::AbstractVector; [lo, hi]) Send every element of `v` for which `f` returns `true` to the end of the vector and return -the index of the last element which for which `f` returns `false`. +the index of the last element for which `f` returns `false`. `send_to_end!(f, v, lo, hi)` is equivalent to `send_to_end!(f, view(v, lo:hi))+lo-1` @@ -1245,7 +1245,7 @@ Otherwise, we dispatch to [`InsertionSort`](@ref) for inputs with `length <= 40` perform a presorted check ([`CheckSorted`](@ref)). We check for short inputs before performing the presorted check to avoid the overhead of the -check for small inputs. Because the alternate dispatch is to [`InseritonSort`](@ref) which +check for small inputs. Because the alternate dispatch is to [`InsertionSort`](@ref) which has efficient `O(n)` runtime on presorted inputs, the check is not necessary for small inputs. @@ -1906,6 +1906,26 @@ Characteristics: ignores case). * *in-place* in memory. * *divide-and-conquer*: sort strategy similar to [`MergeSort`](@ref). + + Note that `PartialQuickSort(k)` does not necessarily sort the whole array. For example, + +```jldoctest +julia> x = rand(100); + +julia> k = 50:100; + +julia> s1 = sort(x; alg=QuickSort); + +julia> s2 = sort(x; alg=PartialQuickSort(k)); + +julia> map(issorted, (s1, s2)) +(true, false) + +julia> map(x->issorted(x[k]), (s1, s2)) +(true, true) + +julia> s1[k] == s2[k] +true """ struct PartialQuickSort{T <: Union{Integer,OrdinalRange}} <: Algorithm k::T @@ -1942,6 +1962,8 @@ Characteristics: case). * *not in-place* in memory. * *divide-and-conquer* sort strategy. + * *good performance* for large collections but typically not quite as + fast as [`QuickSort`](@ref). """ const MergeSort = MergeSortAlg() diff --git a/doc/src/base/sort.md b/doc/src/base/sort.md index e93d9716b1487..41b7096391a04 100644 --- a/doc/src/base/sort.md +++ b/doc/src/base/sort.md @@ -21,7 +21,8 @@ julia> sort([2,3,1], rev=true) 1 ``` -To sort an array in-place, use the "bang" version of the sort function: +`sort` constructs a sorted copy leaving its input unchanged. Use the "bang" version of +the sort function to mutate an existing array: ```jldoctest julia> a = [2,3,1]; @@ -134,65 +135,23 @@ Base.Sort.partialsortperm! ## Sorting Algorithms -There are currently four sorting algorithms available in base Julia: +There are currently four sorting algorithms publicly available in base Julia: * [`InsertionSort`](@ref) * [`QuickSort`](@ref) * [`PartialQuickSort(k)`](@ref) * [`MergeSort`](@ref) -`InsertionSort` is an O(n²) stable sorting algorithm. It is efficient for very small `n`, -and is used internally by `QuickSort`. +By default, the `sort` family of functions uses stable sorting algorithms that are fast +on most inputs. The exact algorithm choice is an implementation detail to allow for +future performance improvements. Currently, a hybrid of `RadixSort`, `ScratchQuickSort`, +`InsertionSort`, and `CountingSort` is used based on input type, size, and composition. +Implementation details are subject to change but currently available in the extended help +of `??Base.DEFAULT_STABLE` and the docstrings of internal sorting algorithms listed there. -`QuickSort` is a very fast sorting algorithm with an average-case time complexity of -O(n log n). `QuickSort` is stable, i.e., elements considered equal will remain in the same -order. Notice that O(n²) is worst-case complexity, but it gets vanishingly unlikely as the -pivot selection is randomized. - -`PartialQuickSort(k::OrdinalRange)` is similar to `QuickSort`, but the output array is only -sorted in the range of `k`. For example: - -```jldoctest -julia> x = rand(1:500, 100); - -julia> k = 50:100; - -julia> s1 = sort(x; alg=QuickSort); - -julia> s2 = sort(x; alg=PartialQuickSort(k)); - -julia> map(issorted, (s1, s2)) -(true, false) - -julia> map(x->issorted(x[k]), (s1, s2)) -(true, true) - -julia> s1[k] == s2[k] -true -``` - -!!! compat "Julia 1.9" - The `QuickSort` and `PartialQuickSort` algorithms are stable since Julia 1.9. - -`MergeSort` is an O(n log n) stable sorting algorithm but is not in-place – it requires a temporary -array of half the size of the input array – and is typically not quite as fast as `QuickSort`. -It is the default algorithm for non-numeric data. - -The default sorting algorithms are chosen on the basis that they are fast and stable. -Usually, `QuickSort` is selected, but `InsertionSort` is preferred for small data. -You can also explicitly specify your preferred algorithm, e.g. -`sort!(v, alg=PartialQuickSort(10:20))`. - -The mechanism by which Julia picks default sorting algorithms is implemented via the -`Base.Sort.defalg` function. It allows a particular algorithm to be registered as the -default in all sorting functions for specific arrays. For example, here is the default -method from [`sort.jl`](https://github.com/JuliaLang/julia/blob/master/base/sort.jl): - -```julia -defalg(v::AbstractArray) = DEFAULT_STABLE -``` - -You may change the default behavior for specific types by defining new methods for `defalg`. +You can explicitly specify your preferred algorithm with the `alg` keyword +(e.g. `sort!(v, alg=PartialQuickSort(10:20))`) or reconfigure the default sorting algorithm +for custom types by adding a specialized method to the `Base.Sort.defalg` function. For example, [InlineStrings.jl](https://github.com/JuliaStrings/InlineStrings.jl/blob/v1.3.2/src/InlineStrings.jl#L903) defines the following method: ```julia @@ -200,8 +159,9 @@ Base.Sort.defalg(::AbstractArray{<:Union{SmallInlineStrings, Missing}}) = Inline ``` !!! compat "Julia 1.9" - The default sorting algorithm (returned by `Base.Sort.defalg`) is guaranteed - to be stable since Julia 1.9. Previous versions had unstable edge cases when sorting numeric arrays. + The default sorting algorithm (returned by `Base.Sort.defalg`) is guaranteed to + be stable since Julia 1.9. Previous versions had unstable edge cases when + sorting numeric arrays. ## Alternate orderings From de89a2cb7330170a22c3dee9ed81d8e1f6d483b3 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 31 Jan 2023 05:48:12 +0100 Subject: [PATCH 21/45] prevent heap snapshot test to write to julia dir (#48458) Co-authored-by: Ian (cherry picked from commit 94c4fb5e8221a9382a461f0206354445af040598) --- stdlib/Profile/test/runtests.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stdlib/Profile/test/runtests.jl b/stdlib/Profile/test/runtests.jl index 2a39640d215ed..6ff4890004f62 100644 --- a/stdlib/Profile/test/runtests.jl +++ b/stdlib/Profile/test/runtests.jl @@ -272,7 +272,10 @@ end end @testset "HeapSnapshot" begin - fname = read(`$(Base.julia_cmd()) --startup-file=no -e "using Profile; print(Profile.take_heap_snapshot())"`, String) + tmpdir = mktempdir() + fname = cd(tmpdir) do + read(`$(Base.julia_cmd()) --startup-file=no -e "using Profile; print(Profile.take_heap_snapshot())"`, String) + end @test isfile(fname) @@ -281,6 +284,7 @@ end end rm(fname) + rm(tmpdir, force = true, recursive = true) end include("allocs.jl") From fcd3ca81a66c42cb6f26cc7fd0fcc3d129145640 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 26 Jan 2023 14:10:09 -0800 Subject: [PATCH 22/45] Merge pull request #47676 from gbaraldi/gmp-libblas-version Use versioned libblastrampoline and GMP (cherry picked from commit 335cd5ea2d00f8561daf23ca0f95da9ff4e84caf) --- base/gmp.jl | 92 ++++--- base/mpfr.jl | 245 +++++++++--------- deps/blastrampoline.version | 6 +- deps/checksums/blastrampoline | 68 ++--- deps/checksums/suitesparse | 64 ++--- stdlib/SuiteSparse_jll/Project.toml | 2 +- stdlib/libblastrampoline_jll/Project.toml | 2 +- .../src/libblastrampoline_jll.jl | 6 +- stdlib/libblastrampoline_jll/test/runtests.jl | 2 +- 9 files changed, 252 insertions(+), 235 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 0e5eb66d0d193..42979df0382c2 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -21,8 +21,16 @@ else end const CdoubleMax = Union{Float16, Float32, Float64} -version() = VersionNumber(unsafe_string(unsafe_load(cglobal((:__gmp_version, :libgmp), Ptr{Cchar})))) -bits_per_limb() = Int(unsafe_load(cglobal((:__gmp_bits_per_limb, :libgmp), Cint))) +if Sys.iswindows() + const libgmp = "libgmp-10.dll" +elseif Sys.isapple() + const libgmp = "@rpath/libgmp.10.dylib" +else + const libgmp = "libgmp.so.10" +end + +version() = VersionNumber(unsafe_string(unsafe_load(cglobal((:__gmp_version, libgmp), Ptr{Cchar})))) +bits_per_limb() = Int(unsafe_load(cglobal((:__gmp_bits_per_limb, libgmp), Cint))) const VERSION = version() const BITS_PER_LIMB = bits_per_limb() @@ -54,7 +62,7 @@ mutable struct BigInt <: Signed function BigInt(; nbits::Integer=0) b = MPZ.init2!(new(), nbits) - finalizer(cglobal((:__gmpz_clear, :libgmp)), b) + finalizer(cglobal((:__gmpz_clear, libgmp)), b) return b end end @@ -100,7 +108,7 @@ function __init__() bits_per_limb() != BITS_PER_LIMB ? @error(msg) : @warn(msg) end - ccall((:__gmp_set_memory_functions, :libgmp), Cvoid, + ccall((:__gmp_set_memory_functions, libgmp), Cvoid, (Ptr{Cvoid},Ptr{Cvoid},Ptr{Cvoid}), cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), @@ -112,7 +120,7 @@ function __init__() end # This only works with a patched version of GMP, ignore otherwise try - ccall((:__gmp_set_alloc_overflow_function, :libgmp), Cvoid, + ccall((:__gmp_set_alloc_overflow_function, libgmp), Cvoid, (Ptr{Cvoid},), cglobal(:jl_throw_out_of_memory_error)) ALLOC_OVERFLOW_FUNCTION[] = true @@ -132,20 +140,20 @@ module MPZ # - a method modifying its input has a "!" appended to its name, according to Julia's conventions # - some convenient methods are added (in addition to the pure MPZ ones), e.g. `add(a, b) = add!(BigInt(), a, b)` # and `add!(x, a) = add!(x, x, a)`. -using ..GMP: BigInt, Limb, BITS_PER_LIMB +using ..GMP: BigInt, Limb, BITS_PER_LIMB, libgmp const mpz_t = Ref{BigInt} const bitcnt_t = Culong -gmpz(op::Symbol) = (Symbol(:__gmpz_, op), :libgmp) +gmpz(op::Symbol) = (Symbol(:__gmpz_, op), libgmp) -init!(x::BigInt) = (ccall((:__gmpz_init, :libgmp), Cvoid, (mpz_t,), x); x) -init2!(x::BigInt, a) = (ccall((:__gmpz_init2, :libgmp), Cvoid, (mpz_t, bitcnt_t), x, a); x) +init!(x::BigInt) = (ccall((:__gmpz_init, libgmp), Cvoid, (mpz_t,), x); x) +init2!(x::BigInt, a) = (ccall((:__gmpz_init2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a); x) -realloc2!(x, a) = (ccall((:__gmpz_realloc2, :libgmp), Cvoid, (mpz_t, bitcnt_t), x, a); x) +realloc2!(x, a) = (ccall((:__gmpz_realloc2, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a); x) realloc2(a) = realloc2!(BigInt(), a) -sizeinbase(a::BigInt, b) = Int(ccall((:__gmpz_sizeinbase, :libgmp), Csize_t, (mpz_t, Cint), a, b)) +sizeinbase(a::BigInt, b) = Int(ccall((:__gmpz_sizeinbase, libgmp), Csize_t, (mpz_t, Cint), a, b)) for (op, nbits) in (:add => :(BITS_PER_LIMB*(1 + max(abs(a.size), abs(b.size)))), :sub => :(BITS_PER_LIMB*(1 + max(abs(a.size), abs(b.size)))), @@ -161,7 +169,7 @@ for (op, nbits) in (:add => :(BITS_PER_LIMB*(1 + max(abs(a.size), abs(b.size)))) end invert!(x::BigInt, a::BigInt, b::BigInt) = - ccall((:__gmpz_invert, :libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) + ccall((:__gmpz_invert, libgmp), Cint, (mpz_t, mpz_t, mpz_t), x, a, b) invert(a::BigInt, b::BigInt) = invert!(BigInt(), a, b) invert!(x::BigInt, b::BigInt) = invert!(x, x, b) @@ -174,7 +182,7 @@ for op in (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) end end -ui_sub!(x::BigInt, a, b::BigInt) = (ccall((:__gmpz_ui_sub, :libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b); x) +ui_sub!(x::BigInt, a, b::BigInt) = (ccall((:__gmpz_ui_sub, libgmp), Cvoid, (mpz_t, Culong, mpz_t), x, a, b); x) ui_sub(a, b::BigInt) = ui_sub!(BigInt(), a, b) for op in (:scan1, :scan0) @@ -183,7 +191,7 @@ for op in (:scan1, :scan0) @eval $op(a::BigInt, b) = Int(signed(ccall($(gmpz(op)), Culong, (mpz_t, Culong), a, b))) end -mul_si!(x::BigInt, a::BigInt, b) = (ccall((:__gmpz_mul_si, :libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b); x) +mul_si!(x::BigInt, a::BigInt, b) = (ccall((:__gmpz_mul_si, libgmp), Cvoid, (mpz_t, mpz_t, Clong), x, a, b); x) mul_si(a::BigInt, b) = mul_si!(BigInt(), a, b) mul_si!(x::BigInt, b) = mul_si!(x, x, b) @@ -205,47 +213,47 @@ for (op, T) in ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, end end -popcount(a::BigInt) = Int(signed(ccall((:__gmpz_popcount, :libgmp), Culong, (mpz_t,), a))) +popcount(a::BigInt) = Int(signed(ccall((:__gmpz_popcount, libgmp), Culong, (mpz_t,), a))) -mpn_popcount(d::Ptr{Limb}, s::Integer) = Int(ccall((:__gmpn_popcount, :libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) +mpn_popcount(d::Ptr{Limb}, s::Integer) = Int(ccall((:__gmpn_popcount, libgmp), Culong, (Ptr{Limb}, Csize_t), d, s)) mpn_popcount(a::BigInt) = mpn_popcount(a.d, abs(a.size)) function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) - ccall((:__gmpz_tdiv_qr, :libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) + ccall((:__gmpz_tdiv_qr, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, y, a, b) x, y end tdiv_qr(a::BigInt, b::BigInt) = tdiv_qr!(BigInt(), BigInt(), a, b) powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = - (ccall((:__gmpz_powm, :libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c); x) + (ccall((:__gmpz_powm, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t), x, a, b, c); x) powm(a::BigInt, b::BigInt, c::BigInt) = powm!(BigInt(), a, b, c) powm!(x::BigInt, b::BigInt, c::BigInt) = powm!(x, x, b, c) function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) - ccall((:__gmpz_gcdext, :libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) + ccall((:__gmpz_gcdext, libgmp), Cvoid, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), x, y, z, a, b) x, y, z end gcdext(a::BigInt, b::BigInt) = gcdext!(BigInt(), BigInt(), BigInt(), a, b) -cmp(a::BigInt, b::BigInt) = Int(ccall((:__gmpz_cmp, :libgmp), Cint, (mpz_t, mpz_t), a, b)) -cmp_si(a::BigInt, b) = Int(ccall((:__gmpz_cmp_si, :libgmp), Cint, (mpz_t, Clong), a, b)) -cmp_ui(a::BigInt, b) = Int(ccall((:__gmpz_cmp_ui, :libgmp), Cint, (mpz_t, Culong), a, b)) -cmp_d(a::BigInt, b) = Int(ccall((:__gmpz_cmp_d, :libgmp), Cint, (mpz_t, Cdouble), a, b)) +cmp(a::BigInt, b::BigInt) = Int(ccall((:__gmpz_cmp, libgmp), Cint, (mpz_t, mpz_t), a, b)) +cmp_si(a::BigInt, b) = Int(ccall((:__gmpz_cmp_si, libgmp), Cint, (mpz_t, Clong), a, b)) +cmp_ui(a::BigInt, b) = Int(ccall((:__gmpz_cmp_ui, libgmp), Cint, (mpz_t, Culong), a, b)) +cmp_d(a::BigInt, b) = Int(ccall((:__gmpz_cmp_d, libgmp), Cint, (mpz_t, Cdouble), a, b)) -mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = ccall((:__gmpn_cmp, :libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) +mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = ccall((:__gmpn_cmp, libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) mpn_cmp(a::BigInt, b::BigInt, c) = mpn_cmp(a.d, b.d, c) -get_str!(x, a, b::BigInt) = (ccall((:__gmpz_get_str,:libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b); x) -set_str!(x::BigInt, a, b) = Int(ccall((:__gmpz_set_str, :libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) -get_d(a::BigInt) = ccall((:__gmpz_get_d, :libgmp), Cdouble, (mpz_t,), a) +get_str!(x, a, b::BigInt) = (ccall((:__gmpz_get_str,libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, b); x) +set_str!(x::BigInt, a, b) = Int(ccall((:__gmpz_set_str, libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), x, a, b)) +get_d(a::BigInt) = ccall((:__gmpz_get_d, libgmp), Cdouble, (mpz_t,), a) -limbs_write!(x::BigInt, a) = ccall((:__gmpz_limbs_write, :libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) -limbs_finish!(x::BigInt, a) = ccall((:__gmpz_limbs_finish, :libgmp), Cvoid, (mpz_t, Clong), x, a) -import!(x::BigInt, a, b, c, d, e, f) = ccall((:__gmpz_import, :libgmp), Cvoid, +limbs_write!(x::BigInt, a) = ccall((:__gmpz_limbs_write, libgmp), Ptr{Limb}, (mpz_t, Clong), x, a) +limbs_finish!(x::BigInt, a) = ccall((:__gmpz_limbs_finish, libgmp), Cvoid, (mpz_t, Clong), x, a) +import!(x::BigInt, a, b, c, d, e, f) = ccall((:__gmpz_import, libgmp), Cvoid, (mpz_t, Csize_t, Cint, Csize_t, Cint, Csize_t, Ptr{Cvoid}), x, a, b, c, d, e, f) -setbit!(x, a) = (ccall((:__gmpz_setbit, :libgmp), Cvoid, (mpz_t, bitcnt_t), x, a); x) -tstbit(a::BigInt, b) = ccall((:__gmpz_tstbit, :libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool +setbit!(x, a) = (ccall((:__gmpz_setbit, libgmp), Cvoid, (mpz_t, bitcnt_t), x, a); x) +tstbit(a::BigInt, b) = ccall((:__gmpz_tstbit, libgmp), Cint, (mpz_t, bitcnt_t), a, b) % Bool end # module MPZ @@ -878,9 +886,9 @@ module MPQ # Rational{BigInt} import .Base: unsafe_rational, __throw_rational_argerror_zero -import ..GMP: BigInt, MPZ, Limb, isneg +import ..GMP: BigInt, MPZ, Limb, isneg, libgmp -gmpq(op::Symbol) = (Symbol(:__gmpq_, op), :libgmp) +gmpq(op::Symbol) = (Symbol(:__gmpq_, op), libgmp) mutable struct _MPQ num_alloc::Cint @@ -917,20 +925,20 @@ function Rational{BigInt}(num::BigInt, den::BigInt) return set_si(flipsign(1, num), 0) end xq = _MPQ(MPZ.set(num), MPZ.set(den)) - ccall((:__gmpq_canonicalize, :libgmp), Cvoid, (mpq_t,), xq) + ccall((:__gmpq_canonicalize, libgmp), Cvoid, (mpq_t,), xq) return sync_rational!(xq) end # define set, set_ui, set_si, set_z, and their inplace versions function set!(z::Rational{BigInt}, x::Rational{BigInt}) zq = _MPQ(z) - ccall((:__gmpq_set, :libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) + ccall((:__gmpq_set, libgmp), Cvoid, (mpq_t, mpq_t), zq, _MPQ(x)) return sync_rational!(zq) end function set_z!(z::Rational{BigInt}, x::BigInt) zq = _MPQ(z) - ccall((:__gmpq_set_z, :libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) + ccall((:__gmpq_set_z, libgmp), Cvoid, (mpq_t, MPZ.mpz_t), zq, x) return sync_rational!(zq) end @@ -962,7 +970,7 @@ function add!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) return set!(z, iszero(x.den) ? x : y) end zq = _MPQ(z) - ccall((:__gmpq_add, :libgmp), Cvoid, + ccall((:__gmpq_add, libgmp), Cvoid, (mpq_t,mpq_t,mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end @@ -976,7 +984,7 @@ function sub!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) return set_si!(z, flipsign(-1, y.num), 0) end zq = _MPQ(z) - ccall((:__gmpq_sub, :libgmp), Cvoid, + ccall((:__gmpq_sub, libgmp), Cvoid, (mpq_t,mpq_t,mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end @@ -989,7 +997,7 @@ function mul!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) return set_si!(z, ifelse(xor(isneg(x.num), isneg(y.num)), -1, 1), 0) end zq = _MPQ(z) - ccall((:__gmpq_mul, :libgmp), Cvoid, + ccall((:__gmpq_mul, libgmp), Cvoid, (mpq_t,mpq_t,mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end @@ -1010,7 +1018,7 @@ function div!(z::Rational{BigInt}, x::Rational{BigInt}, y::Rational{BigInt}) return set_si!(z, flipsign(1, x.num), 0) end zq = _MPQ(z) - ccall((:__gmpq_div, :libgmp), Cvoid, + ccall((:__gmpq_div, libgmp), Cvoid, (mpq_t,mpq_t,mpq_t), zq, _MPQ(x), _MPQ(y)) return sync_rational!(zq) end @@ -1024,7 +1032,7 @@ for (fJ, fC) in ((:+, :add), (:-, :sub), (:*, :mul), (://, :div)) end function Base.cmp(x::Rational{BigInt}, y::Rational{BigInt}) - Int(ccall((:__gmpq_cmp, :libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) + Int(ccall((:__gmpq_cmp, libgmp), Cint, (mpq_t, mpq_t), _MPQ(x), _MPQ(y))) end end # MPQ module diff --git a/base/mpfr.jl b/base/mpfr.jl index 119b0dd67b79f..a07606f2aa81e 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -20,12 +20,21 @@ import import ..Rounding: rounding_raw, setrounding_raw -import ..GMP: ClongMax, CulongMax, CdoubleMax, Limb +import ..GMP: ClongMax, CulongMax, CdoubleMax, Limb, libgmp import ..FastMath.sincos_fast -version() = VersionNumber(unsafe_string(ccall((:mpfr_get_version,:libmpfr), Ptr{Cchar}, ()))) -patches() = split(unsafe_string(ccall((:mpfr_get_patches,:libmpfr), Ptr{Cchar}, ())),' ') +if Sys.iswindows() + const libmpfr = "libmpfr-6.dll" +elseif Sys.isapple() + const libmpfr = "@rpath/libmpfr.6.dylib" +else + const libmpfr = "libmpfr.so.6" +end + + +version() = VersionNumber(unsafe_string(ccall((:mpfr_get_version,libmpfr), Ptr{Cchar}, ()))) +patches() = split(unsafe_string(ccall((:mpfr_get_patches,libmpfr), Ptr{Cchar}, ())),' ') function __init__() try @@ -100,16 +109,16 @@ mutable struct BigFloat <: AbstractFloat global function _BigFloat(prec::Clong, sign::Cint, exp::Clong, d::String) # ccall-based version, inlined below #z = new(zero(Clong), zero(Cint), zero(Clong), C_NULL, d) - #ccall((:mpfr_custom_init,:libmpfr), Cvoid, (Ptr{Limb}, Clong), d, prec) # currently seems to be a no-op in mpfr + #ccall((:mpfr_custom_init,libmpfr), Cvoid, (Ptr{Limb}, Clong), d, prec) # currently seems to be a no-op in mpfr #NAN_KIND = Cint(0) - #ccall((:mpfr_custom_init_set,:libmpfr), Cvoid, (Ref{BigFloat}, Cint, Clong, Ptr{Limb}), z, NAN_KIND, prec, d) + #ccall((:mpfr_custom_init_set,libmpfr), Cvoid, (Ref{BigFloat}, Cint, Clong, Ptr{Limb}), z, NAN_KIND, prec, d) #return z return new(prec, sign, exp, pointer(d), d) end function BigFloat(; precision::Integer=DEFAULT_PRECISION[]) precision < 1 && throw(DomainError(precision, "`precision` cannot be less than 1.")) - nb = ccall((:mpfr_custom_get_size,:libmpfr), Csize_t, (Clong,), precision) + nb = ccall((:mpfr_custom_get_size,libmpfr), Csize_t, (Clong,), precision) nb = (nb + Core.sizeof(Limb) - 1) ÷ Core.sizeof(Limb) # align to number of Limb allocations required for this #d = Vector{Limb}(undef, nb) d = _string_n(nb * Core.sizeof(Limb)) @@ -185,7 +194,7 @@ function BigFloat(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::I return x else z = BigFloat(;precision=precision) - ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), + ccall((:mpfr_set, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, r) return z end @@ -193,7 +202,7 @@ end function _duplicate(x::BigFloat) z = BigFloat(;precision=_precision(x)) - ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, 0) + ccall((:mpfr_set, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), z, x, 0) return z end @@ -202,7 +211,7 @@ for (fJ, fC) in ((:si,:Clong), (:ui,:Culong)) @eval begin function BigFloat(x::($fC), r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) z = BigFloat(;precision=precision) - ccall(($(string(:mpfr_set_,fJ)), :libmpfr), Int32, (Ref{BigFloat}, $fC, MPFRRoundingMode), z, x, r) + ccall(($(string(:mpfr_set_,fJ)), libmpfr), Int32, (Ref{BigFloat}, $fC, MPFRRoundingMode), z, x, r) return z end end @@ -210,7 +219,7 @@ end function BigFloat(x::Float64, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) z = BigFloat(;precision=precision) - ccall((:mpfr_set_d, :libmpfr), Int32, (Ref{BigFloat}, Float64, MPFRRoundingMode), z, x, r) + ccall((:mpfr_set_d, libmpfr), Int32, (Ref{BigFloat}, Float64, MPFRRoundingMode), z, x, r) if isnan(x) && signbit(x) != signbit(z) z.sign = -z.sign end @@ -219,7 +228,7 @@ end function BigFloat(x::BigInt, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) z = BigFloat(;precision=precision) - ccall((:mpfr_set_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, r) + ccall((:mpfr_set_z, libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, r) return z end @@ -247,7 +256,7 @@ end function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=DEFAULT_PRECISION[], rounding::MPFRRoundingMode=ROUNDING_MODE[]) !isempty(s) && isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base = base) z = BigFloat(precision=precision) - err = ccall((:mpfr_set_str, :libmpfr), Int32, (Ref{BigFloat}, Cstring, Int32, MPFRRoundingMode), z, s, base, rounding) + err = ccall((:mpfr_set_str, libmpfr), Int32, (Ref{BigFloat}, Cstring, Int32, MPFRRoundingMode), z, s, base, rounding) err == 0 ? z : nothing end @@ -268,16 +277,16 @@ BigFloat(x::AbstractString, r::RoundingMode; precision::Integer=DEFAULT_PRECISIO _unchecked_cast(T, x::BigFloat, r::RoundingMode) = _unchecked_cast(T, x, convert(MPFRRoundingMode, r)) function _unchecked_cast(::Type{Int64}, x::BigFloat, r::MPFRRoundingMode) - ccall((:__gmpfr_mpfr_get_sj,:libmpfr), Cintmax_t, (Ref{BigFloat}, MPFRRoundingMode), x, r) + ccall((:__gmpfr_mpfr_get_sj,libmpfr), Cintmax_t, (Ref{BigFloat}, MPFRRoundingMode), x, r) end function _unchecked_cast(::Type{UInt64}, x::BigFloat, r::MPFRRoundingMode) - ccall((:__gmpfr_mpfr_get_uj,:libmpfr), Cuintmax_t, (Ref{BigFloat}, MPFRRoundingMode), x, r) + ccall((:__gmpfr_mpfr_get_uj,libmpfr), Cuintmax_t, (Ref{BigFloat}, MPFRRoundingMode), x, r) end function _unchecked_cast(::Type{BigInt}, x::BigFloat, r::MPFRRoundingMode) z = BigInt() - ccall((:mpfr_get_z, :libmpfr), Int32, (Ref{BigInt}, Ref{BigFloat}, MPFRRoundingMode), z, x, r) + ccall((:mpfr_get_z, libmpfr), Int32, (Ref{BigInt}, Ref{BigFloat}, MPFRRoundingMode), z, x, r) return z end @@ -338,11 +347,11 @@ end _cpynansgn(x::AbstractFloat, y::BigFloat) = isnan(x) && signbit(x) != signbit(y) ? -x : x Float64(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]) = - _cpynansgn(ccall((:mpfr_get_d,:libmpfr), Float64, (Ref{BigFloat}, MPFRRoundingMode), x, r), x) + _cpynansgn(ccall((:mpfr_get_d,libmpfr), Float64, (Ref{BigFloat}, MPFRRoundingMode), x, r), x) Float64(x::BigFloat, r::RoundingMode) = Float64(x, convert(MPFRRoundingMode, r)) Float32(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]) = - _cpynansgn(ccall((:mpfr_get_flt,:libmpfr), Float32, (Ref{BigFloat}, MPFRRoundingMode), x, r), x) + _cpynansgn(ccall((:mpfr_get_flt,libmpfr), Float32, (Ref{BigFloat}, MPFRRoundingMode), x, r), x) Float32(x::BigFloat, r::RoundingMode) = Float32(x, convert(MPFRRoundingMode, r)) function Float16(x::BigFloat) :: Float16 @@ -385,14 +394,14 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # BigFloat function ($fJ)(x::BigFloat, y::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)),:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)),libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end # Unsigned Integer function ($fJ)(x::BigFloat, c::CulongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_ui)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_ui)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end ($fJ)(c::CulongMax, x::BigFloat) = ($fJ)(x,c) @@ -400,7 +409,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # Signed Integer function ($fJ)(x::BigFloat, c::ClongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_si)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_si)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end ($fJ)(c::ClongMax, x::BigFloat) = ($fJ)(x,c) @@ -408,7 +417,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # Float32/Float64 function ($fJ)(x::BigFloat, c::CdoubleMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_d)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_d)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end ($fJ)(c::CdoubleMax, x::BigFloat) = ($fJ)(x,c) @@ -416,7 +425,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # BigInt function ($fJ)(x::BigFloat, c::BigInt) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_z)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_z)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end ($fJ)(c::BigInt, x::BigFloat) = ($fJ)(x,c) @@ -428,50 +437,50 @@ for (fJ, fC) in ((:-,:sub), (:/,:div)) # BigFloat function ($fJ)(x::BigFloat, y::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)),:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)),libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end # Unsigned Int function ($fJ)(x::BigFloat, c::CulongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_ui)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_ui)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end function ($fJ)(c::CulongMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:ui_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:ui_,fC)), libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) return z end # Signed Integer function ($fJ)(x::BigFloat, c::ClongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_si)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_si)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end function ($fJ)(c::ClongMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:si_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:si_,fC)), libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) return z end # Float32/Float64 function ($fJ)(x::BigFloat, c::CdoubleMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_d)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_d)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end function ($fJ)(c::CdoubleMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:d_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:d_,fC)), libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) return z end # BigInt function ($fJ)(x::BigFloat, c::BigInt) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_z)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_z)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) return z end # no :mpfr_z_div function @@ -480,7 +489,7 @@ end function -(c::BigInt, x::BigFloat) z = BigFloat() - ccall((:mpfr_z_sub, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) + ccall((:mpfr_z_sub, libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) return z end @@ -488,7 +497,7 @@ inv(x::BigFloat) = one(Clong) / x # faster than fallback one(x)/x function fma(x::BigFloat, y::BigFloat, z::BigFloat) r = BigFloat() - ccall(("mpfr_fma",:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), r, x, y, z, ROUNDING_MODE[]) + ccall(("mpfr_fma",libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), r, x, y, z, ROUNDING_MODE[]) return r end @@ -496,58 +505,58 @@ end # BigFloat function div(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_div,:libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, RoundToZero) - ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) + ccall((:mpfr_div,libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, RoundToZero) + ccall((:mpfr_trunc, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end # Unsigned Int function div(x::BigFloat, c::CulongMax) z = BigFloat() - ccall((:mpfr_div_ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, RoundToZero) - ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) + ccall((:mpfr_div_ui, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, RoundToZero) + ccall((:mpfr_trunc, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end function div(c::CulongMax, x::BigFloat) z = BigFloat() - ccall((:mpfr_ui_div, :libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) - ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) + ccall((:mpfr_ui_div, libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) + ccall((:mpfr_trunc, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end # Signed Integer function div(x::BigFloat, c::ClongMax) z = BigFloat() - ccall((:mpfr_div_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, RoundToZero) - ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) + ccall((:mpfr_div_si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, RoundToZero) + ccall((:mpfr_trunc, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end function div(c::ClongMax, x::BigFloat) z = BigFloat() - ccall((:mpfr_si_div, :libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) - ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) + ccall((:mpfr_si_div, libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) + ccall((:mpfr_trunc, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end # Float32/Float64 function div(x::BigFloat, c::CdoubleMax) z = BigFloat() - ccall((:mpfr_div_d, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, RoundToZero) - ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) + ccall((:mpfr_div_d, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, RoundToZero) + ccall((:mpfr_trunc, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end function div(c::CdoubleMax, x::BigFloat) z = BigFloat() - ccall((:mpfr_d_div, :libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) - ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) + ccall((:mpfr_d_div, libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, MPFRRoundingMode), z, c, x, RoundToZero) + ccall((:mpfr_trunc, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end # BigInt function div(x::BigFloat, c::BigInt) z = BigFloat() - ccall((:mpfr_div_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, RoundToZero) - ccall((:mpfr_trunc, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) + ccall((:mpfr_div_z, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, RoundToZero) + ccall((:mpfr_trunc, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, z) return z end @@ -557,23 +566,23 @@ for (fJ, fC, fI) in ((:+, :add, 0), (:*, :mul, 1)) @eval begin function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) return z end function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, ROUNDING_MODE[]) return z end function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat, e::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, e, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, e, ROUNDING_MODE[]) return z end end @@ -581,14 +590,14 @@ end function -(x::BigFloat) z = BigFloat() - ccall((:mpfr_neg, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall((:mpfr_neg, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) return z end function sqrt(x::BigFloat) isnan(x) && return x z = BigFloat() - ccall((:mpfr_sqrt, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall((:mpfr_sqrt, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) isnan(z) && throw(DomainError(x, "NaN result for non-NaN input.")) return z end @@ -597,25 +606,25 @@ sqrt(x::BigInt) = sqrt(BigFloat(x)) function ^(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_pow, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end function ^(x::BigFloat, y::CulongMax) z = BigFloat() - ccall((:mpfr_pow_ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_ui, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end function ^(x::BigFloat, y::ClongMax) z = BigFloat() - ccall((:mpfr_pow_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end function ^(x::BigFloat, y::BigInt) z = BigFloat() - ccall((:mpfr_pow_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_z, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -625,7 +634,7 @@ end for f in (:exp, :exp2, :exp10, :expm1, :cosh, :sinh, :tanh, :sech, :csch, :coth, :cbrt) @eval function $f(x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) return z end end @@ -633,7 +642,7 @@ end function sincos_fast(v::BigFloat) s = BigFloat() c = BigFloat() - ccall((:mpfr_sin_cos, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), s, c, v, ROUNDING_MODE[]) + ccall((:mpfr_sin_cos, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), s, c, v, ROUNDING_MODE[]) return (s, c) end sincos(v::BigFloat) = sincos_fast(v) @@ -641,18 +650,18 @@ sincos(v::BigFloat) = sincos_fast(v) # return log(2) function big_ln2() c = BigFloat() - ccall((:mpfr_const_log2, :libmpfr), Cint, (Ref{BigFloat}, MPFRRoundingMode), c, MPFR.ROUNDING_MODE[]) + ccall((:mpfr_const_log2, libmpfr), Cint, (Ref{BigFloat}, MPFRRoundingMode), c, MPFR.ROUNDING_MODE[]) return c end function ldexp(x::BigFloat, n::Clong) z = BigFloat() - ccall((:mpfr_mul_2si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, n, ROUNDING_MODE[]) + ccall((:mpfr_mul_2si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, n, ROUNDING_MODE[]) return z end function ldexp(x::BigFloat, n::Culong) z = BigFloat() - ccall((:mpfr_mul_2ui, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, n, ROUNDING_MODE[]) + ccall((:mpfr_mul_2ui, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, n, ROUNDING_MODE[]) return z end ldexp(x::BigFloat, n::ClongMax) = ldexp(x, convert(Clong, n)) @@ -665,13 +674,13 @@ function factorial(x::BigFloat) end ui = convert(Culong, x) z = BigFloat() - ccall((:mpfr_fac_ui, :libmpfr), Int32, (Ref{BigFloat}, Culong, MPFRRoundingMode), z, ui, ROUNDING_MODE[]) + ccall((:mpfr_fac_ui, libmpfr), Int32, (Ref{BigFloat}, Culong, MPFRRoundingMode), z, ui, ROUNDING_MODE[]) return z end function hypot(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_hypot, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_hypot, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -682,7 +691,7 @@ for f in (:log, :log2, :log10) "with a complex argument. Try ", $f, "(complex(x))."))) end z = BigFloat() - ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) return z end end @@ -693,7 +702,7 @@ function log1p(x::BigFloat) "with a complex argument. Try log1p(complex(x))."))) end z = BigFloat() - ccall((:mpfr_log1p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall((:mpfr_log1p, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) return z end @@ -717,19 +726,19 @@ end function modf(x::BigFloat) zint = BigFloat() zfloat = BigFloat() - ccall((:mpfr_modf, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), zint, zfloat, x, ROUNDING_MODE[]) + ccall((:mpfr_modf, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), zint, zfloat, x, ROUNDING_MODE[]) return (zfloat, zint) end function rem(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_fmod, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_fmod, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end function rem(x::BigFloat, y::BigFloat, ::RoundingMode{:Nearest}) z = BigFloat() - ccall((:mpfr_remainder, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_remainder, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -739,7 +748,7 @@ rem2pi(x::BigFloat, r::RoundingMode) = rem(x, 2*BigFloat(pi), r) function sum(arr::AbstractArray{BigFloat}) z = BigFloat(0) for i in arr - ccall((:mpfr_add, :libmpfr), Int32, + ccall((:mpfr_add, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, i, ROUNDING_MODE[]) end return z @@ -751,7 +760,7 @@ for f in (:sin, :cos, :tan, :sec, :csc, :acos, :asin, :atan, :acosh, :asinh, :at function ($f)(x::BigFloat) isnan(x) && return x z = BigFloat() - ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) isnan(z) && throw(DomainError(x, "NaN result for non-NaN input.")) return z end @@ -760,28 +769,28 @@ end function atan(y::BigFloat, x::BigFloat) z = BigFloat() - ccall((:mpfr_atan2, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, y, x, ROUNDING_MODE[]) + ccall((:mpfr_atan2, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, y, x, ROUNDING_MODE[]) return z end # Utility functions -==(x::BigFloat, y::BigFloat) = ccall((:mpfr_equal_p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 -<=(x::BigFloat, y::BigFloat) = ccall((:mpfr_lessequal_p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 ->=(x::BigFloat, y::BigFloat) = ccall((:mpfr_greaterequal_p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 -<(x::BigFloat, y::BigFloat) = ccall((:mpfr_less_p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 ->(x::BigFloat, y::BigFloat) = ccall((:mpfr_greater_p, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 +==(x::BigFloat, y::BigFloat) = ccall((:mpfr_equal_p, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 +<=(x::BigFloat, y::BigFloat) = ccall((:mpfr_lessequal_p, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 +>=(x::BigFloat, y::BigFloat) = ccall((:mpfr_greaterequal_p, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 +<(x::BigFloat, y::BigFloat) = ccall((:mpfr_less_p, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 +>(x::BigFloat, y::BigFloat) = ccall((:mpfr_greater_p, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), x, y) != 0 function cmp(x::BigFloat, y::BigInt) isnan(x) && return 1 - ccall((:mpfr_cmp_z, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}), x, y) + ccall((:mpfr_cmp_z, libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}), x, y) end function cmp(x::BigFloat, y::ClongMax) isnan(x) && return 1 - ccall((:mpfr_cmp_si, :libmpfr), Int32, (Ref{BigFloat}, Clong), x, y) + ccall((:mpfr_cmp_si, libmpfr), Int32, (Ref{BigFloat}, Clong), x, y) end function cmp(x::BigFloat, y::CulongMax) isnan(x) && return 1 - ccall((:mpfr_cmp_ui, :libmpfr), Int32, (Ref{BigFloat}, Culong), x, y) + ccall((:mpfr_cmp_ui, libmpfr), Int32, (Ref{BigFloat}, Culong), x, y) end cmp(x::BigFloat, y::Integer) = cmp(x,big(y)) cmp(x::Integer, y::BigFloat) = -cmp(y,x) @@ -789,7 +798,7 @@ cmp(x::Integer, y::BigFloat) = -cmp(y,x) function cmp(x::BigFloat, y::CdoubleMax) isnan(x) && return isnan(y) ? 0 : 1 isnan(y) && return -1 - ccall((:mpfr_cmp_d, :libmpfr), Int32, (Ref{BigFloat}, Cdouble), x, y) + ccall((:mpfr_cmp_d, libmpfr), Int32, (Ref{BigFloat}, Cdouble), x, y) end cmp(x::CdoubleMax, y::BigFloat) = -cmp(y,x) @@ -808,7 +817,7 @@ cmp(x::CdoubleMax, y::BigFloat) = -cmp(y,x) <=(x::BigFloat, y::CdoubleMax) = !isnan(x) && !isnan(y) && cmp(x,y) <= 0 <=(x::CdoubleMax, y::BigFloat) = !isnan(x) && !isnan(y) && cmp(y,x) >= 0 -signbit(x::BigFloat) = ccall((:mpfr_signbit, :libmpfr), Int32, (Ref{BigFloat},), x) != 0 +signbit(x::BigFloat) = ccall((:mpfr_signbit, libmpfr), Int32, (Ref{BigFloat},), x) != 0 function sign(x::BigFloat) c = cmp(x, 0) (c == 0 || isnan(x)) && return x @@ -816,7 +825,7 @@ function sign(x::BigFloat) end function _precision(x::BigFloat) # precision of an object of type BigFloat - return ccall((:mpfr_get_prec, :libmpfr), Clong, (Ref{BigFloat},), x) + return ccall((:mpfr_get_prec, libmpfr), Clong, (Ref{BigFloat},), x) end precision(x::BigFloat; base::Integer=2) = _precision(x, base) @@ -852,7 +861,7 @@ maxintfloat(::Type{BigFloat}) = BigFloat(2)^precision(BigFloat) function copysign(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_copysign, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_copysign, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) return z end @@ -861,27 +870,27 @@ function exponent(x::BigFloat) throw(DomainError(x, "`x` must be non-zero and finite.")) end # The '- 1' is to make it work as Base.exponent - return ccall((:mpfr_get_exp, :libmpfr), Clong, (Ref{BigFloat},), x) - 1 + return ccall((:mpfr_get_exp, libmpfr), Clong, (Ref{BigFloat},), x) - 1 end function frexp(x::BigFloat) z = BigFloat() c = Ref{Clong}() - ccall((:mpfr_frexp, :libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, ROUNDING_MODE[]) + ccall((:mpfr_frexp, libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, ROUNDING_MODE[]) return (z, c[]) end function significand(x::BigFloat) z = BigFloat() c = Ref{Clong}() - ccall((:mpfr_frexp, :libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, ROUNDING_MODE[]) + ccall((:mpfr_frexp, libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, ROUNDING_MODE[]) # Double the significand to make it work as Base.significand - ccall((:mpfr_mul_si, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, z, 2, ROUNDING_MODE[]) + ccall((:mpfr_mul_si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, z, 2, ROUNDING_MODE[]) return z end function isinteger(x::BigFloat) - return ccall((:mpfr_integer_p, :libmpfr), Int32, (Ref{BigFloat},), x) != 0 + return ccall((:mpfr_integer_p, libmpfr), Int32, (Ref{BigFloat},), x) != 0 end for (f,R) in ((:roundeven, :Nearest), @@ -892,18 +901,18 @@ for (f,R) in ((:roundeven, :Nearest), @eval begin function round(x::BigFloat, ::RoundingMode{$(QuoteNode(R))}) z = BigFloat() - ccall(($(string(:mpfr_,f)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, x) + ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}), z, x) return z end end end function isinf(x::BigFloat) - return ccall((:mpfr_inf_p, :libmpfr), Int32, (Ref{BigFloat},), x) != 0 + return ccall((:mpfr_inf_p, libmpfr), Int32, (Ref{BigFloat},), x) != 0 end function isnan(x::BigFloat) - return ccall((:mpfr_nan_p, :libmpfr), Int32, (Ref{BigFloat},), x) != 0 + return ccall((:mpfr_nan_p, libmpfr), Int32, (Ref{BigFloat},), x) != 0 end isfinite(x::BigFloat) = !isinf(x) && !isnan(x) @@ -917,7 +926,7 @@ isone(x::BigFloat) = x == Clong(1) function nextfloat!(x::BigFloat, n::Integer=1) signbit(n) && return prevfloat!(x, abs(n)) for i = 1:n - ccall((:mpfr_nextabove, :libmpfr), Int32, (Ref{BigFloat},), x) + ccall((:mpfr_nextabove, libmpfr), Int32, (Ref{BigFloat},), x) end return x end @@ -925,7 +934,7 @@ end function prevfloat!(x::BigFloat, n::Integer=1) signbit(n) && return nextfloat!(x, abs(n)) for i = 1:n - ccall((:mpfr_nextbelow, :libmpfr), Int32, (Ref{BigFloat},), x) + ccall((:mpfr_nextbelow, libmpfr), Int32, (Ref{BigFloat},), x) end return x end @@ -971,7 +980,7 @@ setprecision(f::Function, prec::Integer; base::Integer=2) = setprecision(f, BigF function string_mpfr(x::BigFloat, fmt::String) pc = Ref{Ptr{UInt8}}() - n = ccall((:mpfr_asprintf,:libmpfr), Cint, + n = ccall((:mpfr_asprintf,libmpfr), Cint, (Ptr{Ptr{UInt8}}, Ptr{UInt8}, Ref{BigFloat}...), pc, fmt, x) p = pc[] @@ -983,7 +992,7 @@ function string_mpfr(x::BigFloat, fmt::String) end end str = unsafe_string(p) - ccall((:mpfr_free_str, :libmpfr), Cvoid, (Ptr{UInt8},), p) + ccall((:mpfr_free_str, libmpfr), Cvoid, (Ptr{UInt8},), p) return str end @@ -1034,17 +1043,17 @@ function show(io::IO, b::BigFloat) end # get/set exponent min/max -get_emax() = ccall((:mpfr_get_emax, :libmpfr), Clong, ()) -get_emax_min() = ccall((:mpfr_get_emax_min, :libmpfr), Clong, ()) -get_emax_max() = ccall((:mpfr_get_emax_max, :libmpfr), Clong, ()) +get_emax() = ccall((:mpfr_get_emax, libmpfr), Clong, ()) +get_emax_min() = ccall((:mpfr_get_emax_min, libmpfr), Clong, ()) +get_emax_max() = ccall((:mpfr_get_emax_max, libmpfr), Clong, ()) -get_emin() = ccall((:mpfr_get_emin, :libmpfr), Clong, ()) -get_emin_min() = ccall((:mpfr_get_emin_min, :libmpfr), Clong, ()) -get_emin_max() = ccall((:mpfr_get_emin_max, :libmpfr), Clong, ()) +get_emin() = ccall((:mpfr_get_emin, libmpfr), Clong, ()) +get_emin_min() = ccall((:mpfr_get_emin_min, libmpfr), Clong, ()) +get_emin_max() = ccall((:mpfr_get_emin_max, libmpfr), Clong, ()) check_exponent_err(ret) = ret == 0 || throw(ArgumentError("Invalid MPFR exponent range")) -set_emax!(x) = check_exponent_err(ccall((:mpfr_set_emax, :libmpfr), Cint, (Clong,), x)) -set_emin!(x) = check_exponent_err(ccall((:mpfr_set_emin, :libmpfr), Cint, (Clong,), x)) +set_emax!(x) = check_exponent_err(ccall((:mpfr_set_emax, libmpfr), Cint, (Clong,), x)) +set_emin!(x) = check_exponent_err(ccall((:mpfr_set_emin, libmpfr), Cint, (Clong,), x)) function Base.deepcopy_internal(x::BigFloat, stackdict::IdDict) get!(stackdict, x) do @@ -1052,7 +1061,7 @@ function Base.deepcopy_internal(x::BigFloat, stackdict::IdDict) d = x._d d′ = GC.@preserve d unsafe_string(pointer(d), sizeof(d)) # creates a definitely-new String y = _BigFloat(x.prec, x.sign, x.exp, d′) - #ccall((:mpfr_custom_move,:libmpfr), Cvoid, (Ref{BigFloat}, Ptr{Limb}), y, d) # unnecessary + #ccall((:mpfr_custom_move,libmpfr), Cvoid, (Ref{BigFloat}, Ptr{Limb}), y, d) # unnecessary return y end end @@ -1064,7 +1073,7 @@ function decompose(x::BigFloat)::Tuple{BigInt, Int, Int} s = BigInt() s.size = cld(x.prec, 8*sizeof(Limb)) # limbs b = s.size * sizeof(Limb) # bytes - ccall((:__gmpz_realloc2, :libgmp), Cvoid, (Ref{BigInt}, Culong), s, 8b) # bits + ccall((:__gmpz_realloc2, libgmp), Cvoid, (Ref{BigInt}, Culong), s, 8b) # bits ccall(:memcpy, Ptr{Cvoid}, (Ptr{Cvoid}, Ptr{Cvoid}, Csize_t), s.d, x.d, b) # bytes s, x.exp - 8b, x.sign end @@ -1075,11 +1084,11 @@ function lerpi(j::Integer, d::Integer, a::BigFloat, b::BigFloat) end # flags -clear_flags() = ccall((:mpfr_clear_flags, :libmpfr), Cvoid, ()) -had_underflow() = ccall((:mpfr_underflow_p, :libmpfr), Cint, ()) != 0 -had_overflow() = ccall((:mpfr_underflow_p, :libmpfr), Cint, ()) != 0 -had_nan() = ccall((:mpfr_nanflag_p, :libmpfr), Cint, ()) != 0 -had_inexact_exception() = ccall((:mpfr_inexflag_p, :libmpfr), Cint, ()) != 0 -had_range_exception() = ccall((:mpfr_erangeflag_p, :libmpfr), Cint, ()) != 0 +clear_flags() = ccall((:mpfr_clear_flags, libmpfr), Cvoid, ()) +had_underflow() = ccall((:mpfr_underflow_p, libmpfr), Cint, ()) != 0 +had_overflow() = ccall((:mpfr_underflow_p, libmpfr), Cint, ()) != 0 +had_nan() = ccall((:mpfr_nanflag_p, libmpfr), Cint, ()) != 0 +had_inexact_exception() = ccall((:mpfr_inexflag_p, libmpfr), Cint, ()) != 0 +had_range_exception() = ccall((:mpfr_erangeflag_p, libmpfr), Cint, ()) != 0 end #module diff --git a/deps/blastrampoline.version b/deps/blastrampoline.version index 9d124df6490b9..2ab10915a73a1 100644 --- a/deps/blastrampoline.version +++ b/deps/blastrampoline.version @@ -2,6 +2,6 @@ BLASTRAMPOLINE_JLL_NAME := libblastrampoline ## source build -BLASTRAMPOLINE_VER := 5.2.0 -BLASTRAMPOLINE_BRANCH=v5.2.0 -BLASTRAMPOLINE_SHA1=4a934fd00056c6d351e9b9a445c3b05bf8a0669d +BLASTRAMPOLINE_VER := 5.4.0 +BLASTRAMPOLINE_BRANCH=v5.4.0 +BLASTRAMPOLINE_SHA1=d00e6ca235bb747faae4c9f3a297016cae6959ed diff --git a/deps/checksums/blastrampoline b/deps/checksums/blastrampoline index ee10c4a624386..786085c82769f 100644 --- a/deps/checksums/blastrampoline +++ b/deps/checksums/blastrampoline @@ -1,34 +1,34 @@ -blastrampoline-4a934fd00056c6d351e9b9a445c3b05bf8a0669d.tar.gz/md5/2ae549854dc028744c1447c9672b565b -blastrampoline-4a934fd00056c6d351e9b9a445c3b05bf8a0669d.tar.gz/sha512/4b1ce0f3a3f7584e54b3ffd479e1eb3d3cdf6762f8221e443761b791228a08347a9397e52fa433c5d2731559ad23b415999c07f3cac879cbdb265df76ce53307 -libblastrampoline.v5.2.0+0.aarch64-apple-darwin.tar.gz/md5/05f9dd63b9c7c427d0c7c2acb808cb74 -libblastrampoline.v5.2.0+0.aarch64-apple-darwin.tar.gz/sha512/7ef2c680272281d054f0820be03be8bc2d31527a0c64c0ad781895a05b55c78b4bb37851f4fae8e323c121a5e74a5f7301b800543065d208c3ac05cf27011ace -libblastrampoline.v5.2.0+0.aarch64-linux-gnu.tar.gz/md5/bec29cbfd4dbba2830db53bdf5fe6931 -libblastrampoline.v5.2.0+0.aarch64-linux-gnu.tar.gz/sha512/ec64fe14865414ffd9a30a03c7ef2eec57700386a1d47fc4ff72395dd6f2dc2ab11784cdb630a097bc56ceb3c808b6ebed4a0b6bf65439ab61330c3c87c33cb0 -libblastrampoline.v5.2.0+0.aarch64-linux-musl.tar.gz/md5/489798e0362ee4160211f77b0b585cd1 -libblastrampoline.v5.2.0+0.aarch64-linux-musl.tar.gz/sha512/0ed2e222912843a56565c09d0e30184dd7212bb14498d4f21e79cda6c78fb04bb49d33691e0c56da94c401cc1875ac73fa6ad6505ff3f80fb6af80f1ad3bab36 -libblastrampoline.v5.2.0+0.armv6l-linux-gnueabihf.tar.gz/md5/67d14b507bdd1a2830f47bf1251812d3 -libblastrampoline.v5.2.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/e1b68eacc42a1b3bb707a0814eb1fd980d14e2eb8244543bd0bed4cbd4d8aef4a53d3e12268a1e2cf470231a27ba25696b8cf734405f6e3ffe7e40af658f68eb -libblastrampoline.v5.2.0+0.armv6l-linux-musleabihf.tar.gz/md5/fe361ef2fcbbfbfffbb07d455f2272e7 -libblastrampoline.v5.2.0+0.armv6l-linux-musleabihf.tar.gz/sha512/ff72fd1980f85a8f1884426eb26e2944f0ab1256a1cd361d0e58edcc4f215908e225ea52b6073f5d01b14168785fd567bd77e56de96a19a48632ae29af47cf97 -libblastrampoline.v5.2.0+0.armv7l-linux-gnueabihf.tar.gz/md5/6e221beca7e0a9418b290284a31e3eb7 -libblastrampoline.v5.2.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/65c5539e74e0b85cf8979af1ac5c65f3466a6425bc898fa06cad82c0b8681e99e9f95b7c8e371ea2f83182fa73044cf36fc555f83f4e38b80f2bc4d96bbcb2c1 -libblastrampoline.v5.2.0+0.armv7l-linux-musleabihf.tar.gz/md5/fd5f1ace9dd0bf4137bccb997423be21 -libblastrampoline.v5.2.0+0.armv7l-linux-musleabihf.tar.gz/sha512/250d34ffddb201dc159cf80b4ca58335078d532af46c4c75b61e0e7decb2ae9f1c2b7cf329c8441453aa986db9129071bb9fd719abfca0a8e1d4388111f3c27e -libblastrampoline.v5.2.0+0.i686-linux-gnu.tar.gz/md5/dd7652272db8fb39a7d24fc9e5b48521 -libblastrampoline.v5.2.0+0.i686-linux-gnu.tar.gz/sha512/e75eaa82ada941177508e422551fa7f3c0b48d2f0d358098e00df85be975066c94a1337e80a763080de50ca16f76a72b75bb685d8368b542c3c625fa3eb3a88b -libblastrampoline.v5.2.0+0.i686-linux-musl.tar.gz/md5/740e90a91e397bb70b452c96e2a91c3f -libblastrampoline.v5.2.0+0.i686-linux-musl.tar.gz/sha512/d05c2948e9cbe27df1bc4dfb6cf88e9d80177e13ead2a73d0298ce9e6d6257f4c97569317040649721c4530ae6cc4b751a0e9183bb440c8f0314fb35600f325d -libblastrampoline.v5.2.0+0.i686-w64-mingw32.tar.gz/md5/e8ea2b8bfa9227c78e451f4689e354d5 -libblastrampoline.v5.2.0+0.i686-w64-mingw32.tar.gz/sha512/0b211ad2244b2c131a987f2bea7257671d3a1e944d1216d7e944fd8796f561941f93702099997fd7f672d705c775e4c85504d35e7f3d573c988a72d4d55e8fd5 -libblastrampoline.v5.2.0+0.powerpc64le-linux-gnu.tar.gz/md5/a4ba5014693e066f77060abfa83ec503 -libblastrampoline.v5.2.0+0.powerpc64le-linux-gnu.tar.gz/sha512/22345530227dedc4bcecd90704fb509df1da9e858a7caf9f75c5b2758a8e46701aa11d071299ce8b0dbab5d09f285717610325bb2488eb2fd1c4ba95b3bad591 -libblastrampoline.v5.2.0+0.x86_64-apple-darwin.tar.gz/md5/1cb1674caaac3cc7b0ad37b71e7afc4b -libblastrampoline.v5.2.0+0.x86_64-apple-darwin.tar.gz/sha512/22c20a05288b535e19b3d425b632163c3f9113be0d57d9169edf4a09dec9770e236aa10b7af2cb9e2ebe4082e00810c79e1c5c42ed8776f83270e3bd0b57aa0a -libblastrampoline.v5.2.0+0.x86_64-linux-gnu.tar.gz/md5/ad8ecec78a8f6d169e45283f154c146f -libblastrampoline.v5.2.0+0.x86_64-linux-gnu.tar.gz/sha512/72533611c4d197840931284fa6398d311a72bbad05857181fa061b33d316f2b3f98dea8da3ae5582a54d35863c0c34c902e2d00703c4b2cbde239b1e636a845e -libblastrampoline.v5.2.0+0.x86_64-linux-musl.tar.gz/md5/012dbe069a7716b0caf26f1b2174adab -libblastrampoline.v5.2.0+0.x86_64-linux-musl.tar.gz/sha512/95e7ec2413fb3cf798f82200eb868693935e827ad6173121c122b9a07dc9cb88591b3aa2d079f7b92e5d1030b71f15d8162c2cea54f98317c843ae60ad6d38a7 -libblastrampoline.v5.2.0+0.x86_64-unknown-freebsd.tar.gz/md5/fb509cf6304c0b9fd2a5677ada7a2cb6 -libblastrampoline.v5.2.0+0.x86_64-unknown-freebsd.tar.gz/sha512/b4fc6ad5fda1ab8e57033f15a402ee0d4c64643273ff6da407cbf1fc08860e27973b64e0d7c71305fe01d188c67821f8aa50763e82fed0f7639f2bb8f63cdb1d -libblastrampoline.v5.2.0+0.x86_64-w64-mingw32.tar.gz/md5/5fd324d37c739bb74bfdeead423d2c17 -libblastrampoline.v5.2.0+0.x86_64-w64-mingw32.tar.gz/sha512/7cdb9dc6a9d846c2713afb938a2f4b0341b7de098970e923ed2c310a6c22b2aa403ac8d6752bf618bf3cca3b3491b7cf9c7f6047c129502ce9b09aa1699f8477 +blastrampoline-d00e6ca235bb747faae4c9f3a297016cae6959ed.tar.gz/md5/b49ebb89b7f9a1eaf85217c4a9dac744 +blastrampoline-d00e6ca235bb747faae4c9f3a297016cae6959ed.tar.gz/sha512/ac3a767fdb03cc0a9e12ae6df31229e6c5050f2b7ccaee47ef14d6bef34b37a20c2d79956b73bf74d72af1f01a3d1316931db264e1b00cb6cadd57fb842e6f2f +libblastrampoline.v5.4.0+0.aarch64-apple-darwin.tar.gz/md5/9c084085ecf2f263164ab3557db634b7 +libblastrampoline.v5.4.0+0.aarch64-apple-darwin.tar.gz/sha512/c8233325dc71582efe43a741c7e8348e853e02d77cc1296261abf12027008e1b79ec369575638c775944ae4ce9cc9d5d999e0994b2b2c7ceccd956f1c49d8f75 +libblastrampoline.v5.4.0+0.aarch64-linux-gnu.tar.gz/md5/6bdce10e27dfcd219d6bd212ade361dd +libblastrampoline.v5.4.0+0.aarch64-linux-gnu.tar.gz/sha512/003a5afbc5f92ec5da518fc33f819b6c063946f75aac347775582266138a0cbf22839e0f4f5b13909185e8a2643d51db434d0d325d2898980386d8c24acfd8e7 +libblastrampoline.v5.4.0+0.aarch64-linux-musl.tar.gz/md5/048ff56f538d56f5cc2ba72c751a1bfc +libblastrampoline.v5.4.0+0.aarch64-linux-musl.tar.gz/sha512/0fdef61ee05c77722e661c522341531eeb3882e76ae2ce1add53fea813a19b70f1cd50a75643c3324aade594dfd7f5b269f43be58e4ef3f560340f9fe95cdd11 +libblastrampoline.v5.4.0+0.armv6l-linux-gnueabihf.tar.gz/md5/332f6857be4f7840bbb03a78fe5b50d4 +libblastrampoline.v5.4.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/228a9b5fe1ef57c0ac4d3130de8bce184baac702c9df02fa4706558c23973ec8396db39d0d0125638bd330065527c6fe1c205e3a095b401c27900c21e941d1c3 +libblastrampoline.v5.4.0+0.armv6l-linux-musleabihf.tar.gz/md5/5f7008ccf0155c164bf8eec5a184be1d +libblastrampoline.v5.4.0+0.armv6l-linux-musleabihf.tar.gz/sha512/0395ea3aec6ba4f4e3ce56e152a7d3db78b937a8bee603ed84143c3f35b76453ec3650c733ffd79a3b59424f5196218b33a45939ea176e8666cf4d44593e35be +libblastrampoline.v5.4.0+0.armv7l-linux-gnueabihf.tar.gz/md5/f184171d5ce4fa9238e11478f54ad6c9 +libblastrampoline.v5.4.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/3e4406f2bb09dfa17b926a83246c45107bfd72776f3d22320985c3f2c58cdab78c674d759e74bd2725e04c7e78263acfc47879598db7181660145a88af5e11af +libblastrampoline.v5.4.0+0.armv7l-linux-musleabihf.tar.gz/md5/c6996b382b042c87f714866bb1d2ce37 +libblastrampoline.v5.4.0+0.armv7l-linux-musleabihf.tar.gz/sha512/e5c69979743f228ed61931b5e1f8130c832f925a155f04de751ae817c1865d759999bfcfd0d2646ee192de3dba0a8d25626f70be7abd83d4a07c11988c6fd57c +libblastrampoline.v5.4.0+0.i686-linux-gnu.tar.gz/md5/155937c2f2e9650654d93210e82e5b9e +libblastrampoline.v5.4.0+0.i686-linux-gnu.tar.gz/sha512/e7e33da75b5076ac7fbdf1f882cc77244b861f5265bcb4f7aec28e578ed5af00d08f40513fa17dd62d15e7e911a948047b45f32e31f062eb4ef07bee4ce02010 +libblastrampoline.v5.4.0+0.i686-linux-musl.tar.gz/md5/206d874fbc0a9590390c5476edfc877d +libblastrampoline.v5.4.0+0.i686-linux-musl.tar.gz/sha512/6f6dd3468f788d717b0ee58b189172950892a84e7379379863ea9d5b316901084fcaa325b8fe7c472d16f08552aa5ab89ccafefa30c05a362ffb44330f1ec383 +libblastrampoline.v5.4.0+0.i686-w64-mingw32.tar.gz/md5/9adc6d8cd38f9151feb13b21a28aeb7b +libblastrampoline.v5.4.0+0.i686-w64-mingw32.tar.gz/sha512/13f7a6f14b0dc7db29591d6d9bbd3e41e72b4a079105987540d3393203ed487ebce32d21569c3724df29332006fc32d915e54055f99ecc74829717ca11bcafdf +libblastrampoline.v5.4.0+0.powerpc64le-linux-gnu.tar.gz/md5/e9dfb0f5a0e564231a75b3fc8a44bc91 +libblastrampoline.v5.4.0+0.powerpc64le-linux-gnu.tar.gz/sha512/fb4c1f953728acf6db4a6a2e93bc5ed8242285cd3112ba1921432bef045b03a375813c34c0d071d19508c226669774afe640acd7d85b10de5176d864eee5f73c +libblastrampoline.v5.4.0+0.x86_64-apple-darwin.tar.gz/md5/c092da8bc56af60cbd4afe5565c471c5 +libblastrampoline.v5.4.0+0.x86_64-apple-darwin.tar.gz/sha512/3fe0aafcdc51c5f2414f889a4f0970b0e302f4d1f37b36bedd094202ae9b7ea760607ca4f80aa815ca2346f526202ef932cd7d3f43522fc4a823c3db6b41604d +libblastrampoline.v5.4.0+0.x86_64-linux-gnu.tar.gz/md5/e05d2295208649a55620681241f9a6fc +libblastrampoline.v5.4.0+0.x86_64-linux-gnu.tar.gz/sha512/2bde6e6b80eb80dd78967dcf6d946b2397b3129b7c6de6fbab2168c23293770ad3d2bbc269c403ee26ea6d752b91eee87e1c651bd7f451f62a8a2acd68196db7 +libblastrampoline.v5.4.0+0.x86_64-linux-musl.tar.gz/md5/4b374750eb2d42a55a39d28cdee70d6b +libblastrampoline.v5.4.0+0.x86_64-linux-musl.tar.gz/sha512/314d877497462d521fafc92299f1e387a03193c20050da529f3e3d02da9f55063f45883377288750d7b8cc64d8701c94db79798a7ef298a73051cd51f21104be +libblastrampoline.v5.4.0+0.x86_64-unknown-freebsd.tar.gz/md5/b5549fb2b1ed82ab95b0636a1eb7682e +libblastrampoline.v5.4.0+0.x86_64-unknown-freebsd.tar.gz/sha512/b94975cef6c1ea26e7635bc70e51a4c53ad1c4610322d0c15841ccfb7e996c8e55b5f060a5ab318d6dda4cfdb615d9c77848cb13bd71c03df8c90c6ac717ff0e +libblastrampoline.v5.4.0+0.x86_64-w64-mingw32.tar.gz/md5/00bd607714c91a2cbc5e2a2f87e6d5e1 +libblastrampoline.v5.4.0+0.x86_64-w64-mingw32.tar.gz/sha512/e75a3780f65963e6a6baf68af57d7260b57052770d6ac3608971134b449d33d02a0be6f0edd0cddae1645ccb0faf6c744ecc3ff40cf7bcfed8acbf05f756013c diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index 7d6196f40951a..65db184c5cbca 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -2,35 +2,35 @@ SuiteSparse-5.10.1.tar.gz/md5/68bb912f3cf3d2b01f30ebafef690302 SuiteSparse-5.10.1.tar.gz/sha512/8f85c6d63b76cba95707dfa732c51200df7794cb4c2599dbd92100475747b8d02b05089a47096e85c60b89bc852a8e768e0670f24902a82d29494a80ccf2bb5f SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/md5/46541001073d1c3c85e18d910f8308f3 SuiteSparse-e8285dd13a6d5b5cf52d8124793fc4d622d07554.tar.gz/sha512/f7470a447b934ca9315e216a07b97e363f11bc93186f9aa057b20b2d05092c58ae4f1b733de362de4a0730861c00be4ca5588d0b3ba65f018c1798b9122b9672 -SuiteSparse.v5.10.1+0.aarch64-apple-darwin.tar.gz/md5/b9392f8e71c0c40d37489e7b2071c5ad -SuiteSparse.v5.10.1+0.aarch64-apple-darwin.tar.gz/sha512/109d67cb009e3b2931b94d63cbdaaee29d60dc190b731ebe3737181cd48d913b8a1333043c67be8179c73e4d3ae32ed1361ab4e34312c0f42e4b29f8a7afda3e -SuiteSparse.v5.10.1+0.aarch64-linux-gnu.tar.gz/md5/1b2651ede4a74cd57f65505a65093314 -SuiteSparse.v5.10.1+0.aarch64-linux-gnu.tar.gz/sha512/753f986a749d139f9a6baedac059d8ed8efdd716ed28eacdbf00e6ebe863b4e17467f01a9693dcb39571d38b4b5c4c1375dbb790b88a7e704116e3fe83f7ff3e -SuiteSparse.v5.10.1+0.aarch64-linux-musl.tar.gz/md5/051ff9bbbc95c57d58563df8a2c8eedd -SuiteSparse.v5.10.1+0.aarch64-linux-musl.tar.gz/sha512/855979ed8d6290c529d9c9e82944fb15c88f9d9d8da7db1fa2fc34efb0ed985fc6554312882107f26956f2a18ae985918909cd834e068b874906c21a0f53b6c9 -SuiteSparse.v5.10.1+0.armv6l-linux-gnueabihf.tar.gz/md5/dbc5fb4844077084663612af26e180ce -SuiteSparse.v5.10.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/b906f7275ab58006acd52927e7e04c79eec59b5f28e9d7e5d5b8556c0eedd54cfff87e494373702c205afa2384ee6b0f2bb5e811fd440b1b50d5c9eee1b47b99 -SuiteSparse.v5.10.1+0.armv6l-linux-musleabihf.tar.gz/md5/7770d256e76d5ce1484c3781508cc3ed -SuiteSparse.v5.10.1+0.armv6l-linux-musleabihf.tar.gz/sha512/4f1d46cc8da5a7eff665b4bb96f9e21319f39231f98a6164d8c3d654d5b6f93c3e4477f55a39a80b7f8125a78d690cc5a1cc58f29143ba4c109a4182d7fa2110 -SuiteSparse.v5.10.1+0.armv7l-linux-gnueabihf.tar.gz/md5/ee1fa978bcfb264842749f915bbefd77 -SuiteSparse.v5.10.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/9592a42f6474fd89eea1144f62ecc2a23796ad251173a9c36ccbc9bc18dd88687ce49f51528974f56b5652e2ab15f0aa41634513f2cc0b3c54259de3b68350bd -SuiteSparse.v5.10.1+0.armv7l-linux-musleabihf.tar.gz/md5/30f708421b92158c7741c82576e9047b -SuiteSparse.v5.10.1+0.armv7l-linux-musleabihf.tar.gz/sha512/d8793d48757dbb62aa7a21c215b6d6e63a26ce4ba740f1f7f42a3e485ad3d9628744f021ad9cc96e29c8c88bfb2f02ea92865c26b971ca739d3c05c7f28875d9 -SuiteSparse.v5.10.1+0.i686-linux-gnu.tar.gz/md5/9018b6168b9a687bab0c9a9cbf45afba -SuiteSparse.v5.10.1+0.i686-linux-gnu.tar.gz/sha512/308a92f441af6855517c40c6871b4935251677c05cc082c21fd1249e0137b635fa524f60cad61c7524026301a6de7ffea0ad1f4b9a4d9d6e3ced3f332a6719d4 -SuiteSparse.v5.10.1+0.i686-linux-musl.tar.gz/md5/99143f8d6de4f071ffa19942252b6dec -SuiteSparse.v5.10.1+0.i686-linux-musl.tar.gz/sha512/9fb719fffea03296dfac8bc221bafc3ed8f7791749eca6c4b00265994de1be5d242e7e5184693603c745b39c4538feb11ab283204e0e33df2745f904cf0c7252 -SuiteSparse.v5.10.1+0.i686-w64-mingw32.tar.gz/md5/d049c943fbda2c8380dea33e16569275 -SuiteSparse.v5.10.1+0.i686-w64-mingw32.tar.gz/sha512/174768464432b991ecff88d5e5126caca83672fb5173115de59bc2387ef8aa75a56d3e84957fce625fabaf50ba462549f2ea828aea7258be7513835b7fea2e31 -SuiteSparse.v5.10.1+0.powerpc64le-linux-gnu.tar.gz/md5/f01f7e134f8ee77849f3a46e773c1ff2 -SuiteSparse.v5.10.1+0.powerpc64le-linux-gnu.tar.gz/sha512/dc0339f2b35f05d49fbd1dcf1822c774a07af122fabc8e00eb7435dc53fcf82b3c1ec24e2bb41b1a58d3f8ab8903830eb7ece19dc6fce3f5e73d90a3dc3c4194 -SuiteSparse.v5.10.1+0.x86_64-apple-darwin.tar.gz/md5/02975a8670660c5e79eab0a70b051a0b -SuiteSparse.v5.10.1+0.x86_64-apple-darwin.tar.gz/sha512/e55685ed7a63318c5baa326795503f13f031e0a617c045c972d5c89252ab51e7325e2b0425ca10dfbd59e79c5b4200545f5a4944fddd376e7610b6ebf74ded14 -SuiteSparse.v5.10.1+0.x86_64-linux-gnu.tar.gz/md5/6c111d315fb25c529710722bd5ae6af0 -SuiteSparse.v5.10.1+0.x86_64-linux-gnu.tar.gz/sha512/c971aed91bd695a0f7f735f58ddcb075d32b9522a8a50a30ad383ba5ce2c8e572fec97644e6cb85745206f4e5da72d7865d9a9724eb63ce3c04e90a4eedc90c9 -SuiteSparse.v5.10.1+0.x86_64-linux-musl.tar.gz/md5/7c98daf0edfad31764c3078e6351b521 -SuiteSparse.v5.10.1+0.x86_64-linux-musl.tar.gz/sha512/2c4b3cae1bd8d1ce62dae6aeca3ffbf90c26a1b01c0da4fb7761d6fe4293b8fad0b6fbfd5f930cefe6ccaef7546a482022ff2f50dc59ecf17c5c0dfc6a5961f5 -SuiteSparse.v5.10.1+0.x86_64-unknown-freebsd.tar.gz/md5/aeca88a7bc3f9d239c61084996ce9182 -SuiteSparse.v5.10.1+0.x86_64-unknown-freebsd.tar.gz/sha512/0bee1ee07c3883fe28dd322c40195be9adb757d6dab3eb1730d7b0ff65dd4517520047696ccdda4ca618e671d898cdb45b787094594e142cb4b176549a74200b -SuiteSparse.v5.10.1+0.x86_64-w64-mingw32.tar.gz/md5/63e449554eee134757e3d50ca8b5f47d -SuiteSparse.v5.10.1+0.x86_64-w64-mingw32.tar.gz/sha512/95b58df4fe7520e2b526f9e3b199253909992789cd24ecca814ddb9a0c0bb37ff93c1de40239e5295a8503613cdb2431a87f0a70a3d657d94d4661f1778797f2 +SuiteSparse.v5.10.1+6.aarch64-apple-darwin.tar.gz/md5/14cc0d3c7b5271246eb45c495c7a4e79 +SuiteSparse.v5.10.1+6.aarch64-apple-darwin.tar.gz/sha512/a56da81a5165bcdf49d1913799bffcaea84efd6f8740dd002f700eb4070313cac64be5359ba88d1f39fe976944e34ee6ed6575ceade2ae2d97b850e6a1aee0ae +SuiteSparse.v5.10.1+6.aarch64-linux-gnu.tar.gz/md5/b93b047040e2db5e0277e52b9bd3feb7 +SuiteSparse.v5.10.1+6.aarch64-linux-gnu.tar.gz/sha512/e03a9ecafce9dcc6791dd202efac2f864bdf3a0a4524567801c092304c17ab15dae949abfb1fe2bc71b367a0e398260ccfdd91dad611860090df471b44e75ee3 +SuiteSparse.v5.10.1+6.aarch64-linux-musl.tar.gz/md5/22c44d9d82608724e1aa62d126fdf030 +SuiteSparse.v5.10.1+6.aarch64-linux-musl.tar.gz/sha512/39a3c11429cd3e6afa2f615dc4b0c8d16d7b94a423d76e598b3b48db2c47fe64d644233e2a672bd6654f8bd57da91dd7a787a3e4978f0f803237ab4ec6f97905 +SuiteSparse.v5.10.1+6.armv6l-linux-gnueabihf.tar.gz/md5/505ee3c0750a720ed1e4de670f81e220 +SuiteSparse.v5.10.1+6.armv6l-linux-gnueabihf.tar.gz/sha512/20fafbdd2df96427b95b730901663c255dafc415f3a8154e3364ec46ca2b205fa45a081f92272b81d7aed22b9f8373d2d4eee70ff8ab5ed8d1d80b6a340c8aad +SuiteSparse.v5.10.1+6.armv6l-linux-musleabihf.tar.gz/md5/8e1821668cbca9c2d3c5cee5ad1746c8 +SuiteSparse.v5.10.1+6.armv6l-linux-musleabihf.tar.gz/sha512/58fb4ec10a537d101e0be8417648a4d0127444b3fe8a32498320aaaefc747f5cac3c7503b70775c1d708b077034060fe5ed8609e73bf9be22f9a8729abc4c73d +SuiteSparse.v5.10.1+6.armv7l-linux-gnueabihf.tar.gz/md5/43d133a916e548ecae50671b92f64c6f +SuiteSparse.v5.10.1+6.armv7l-linux-gnueabihf.tar.gz/sha512/f7f767c0e7eb45afe10941513695bfcc9e0628195cb9245a9c24700967f9cfa7cd0030cdcfaf47a76400d5dd3eb908c1f9ea5e44efd3054ed7bba47e664279a2 +SuiteSparse.v5.10.1+6.armv7l-linux-musleabihf.tar.gz/md5/7c3b2e19d3296002b1aa72b951421eec +SuiteSparse.v5.10.1+6.armv7l-linux-musleabihf.tar.gz/sha512/7546ce844b03d0414168ab6d0925f848b14b35ed27cb545b41f2512bad44b7da4f39004e75657c7c572557ccb015177d3e0d346e2c3182b27a6ee602876ee0df +SuiteSparse.v5.10.1+6.i686-linux-gnu.tar.gz/md5/e00a73f0fad92a266dd8d3774707f9b1 +SuiteSparse.v5.10.1+6.i686-linux-gnu.tar.gz/sha512/9cc2332a78d0490170d722d2f062d6f660fb3bd9042dd177c3683675d0f44306b93bf882cb79c0707ab79318280d08582431eb1c92334f2bb50946e942be0b16 +SuiteSparse.v5.10.1+6.i686-linux-musl.tar.gz/md5/71fb647a76ecc9e547df903535011b5b +SuiteSparse.v5.10.1+6.i686-linux-musl.tar.gz/sha512/7806cd9179e46fa61b63a3f711b37289da72a48430912e564c88e3dcb4caaad8a9bd232d6f572f8270806d286e4a4eb9edfdcda29fe8d91dadb1b03d57eda76d +SuiteSparse.v5.10.1+6.i686-w64-mingw32.tar.gz/md5/d4e6c9aba53b2107469cda6de9ca2724 +SuiteSparse.v5.10.1+6.i686-w64-mingw32.tar.gz/sha512/c0c49641c6e7f3f0333e3fa44ce62dcd4ad5942c74b2429aaeb49fd0d7b8c13c872150ae4d54cc5cfaae07a65a24a7d4ea731adc78db3d9341a54e5edb5c80f0 +SuiteSparse.v5.10.1+6.powerpc64le-linux-gnu.tar.gz/md5/5432dca00f7e0f42b7dbd16083537318 +SuiteSparse.v5.10.1+6.powerpc64le-linux-gnu.tar.gz/sha512/61946a7faa2a49613ea2c08a01f064b619c9ec134f0d9509eb42a96bebf2a63f5fb57b14702f25618def410658da8334bb6aa5200280956e573aa944476efef2 +SuiteSparse.v5.10.1+6.x86_64-apple-darwin.tar.gz/md5/ca175d433a02f91407e2921872c2b67c +SuiteSparse.v5.10.1+6.x86_64-apple-darwin.tar.gz/sha512/14d9b01e2db8c04f9a1076bcbac022c6573728f708f31344825805fed53971e922aecebeb4b2f567a6b5f44ad27c0d66e142887ff4684c8679ab65b902538abf +SuiteSparse.v5.10.1+6.x86_64-linux-gnu.tar.gz/md5/6c271ced91dbb1bf748efbaace1dac10 +SuiteSparse.v5.10.1+6.x86_64-linux-gnu.tar.gz/sha512/5984db9c101ef80d63024bc3b51821268349450deedd5aaea5fade0fc5932992379a0133c4f91711af134014835afea1bde518ae1e7efd482d556a97e54b0238 +SuiteSparse.v5.10.1+6.x86_64-linux-musl.tar.gz/md5/c7d55069969dbb98997687c847ab643d +SuiteSparse.v5.10.1+6.x86_64-linux-musl.tar.gz/sha512/b54012765f7c7329125b41c3fb678e23888a858d3fd5a139c52bd980e383a308282238020754e795de6457fb312b61c39e6ab2d665ca5af95c65f52f0c354067 +SuiteSparse.v5.10.1+6.x86_64-unknown-freebsd.tar.gz/md5/e641be38c8205e362a7299c736aedad5 +SuiteSparse.v5.10.1+6.x86_64-unknown-freebsd.tar.gz/sha512/d55e85335bccb59210014c35233ad9e42f5d086f01a43fe0ee13f21cbb8555ea05f1d91c95a6d3f883477086851e123c4b0cde7cd2dcd8e08835fe9f685d5b25 +SuiteSparse.v5.10.1+6.x86_64-w64-mingw32.tar.gz/md5/45cad947fa962e1f192cb7b52a1f7b3c +SuiteSparse.v5.10.1+6.x86_64-w64-mingw32.tar.gz/sha512/e6545c681ba7d2346baf8fafabdf25f2faf6ea54763d999b14499f30d235e90f34fd4f83430ea7f17c01adea0699dff6c4d7ae3cb938c749d6a15f8bf4f1519f diff --git a/stdlib/SuiteSparse_jll/Project.toml b/stdlib/SuiteSparse_jll/Project.toml index f36ce756c834c..d1fb2c25fa68b 100644 --- a/stdlib/SuiteSparse_jll/Project.toml +++ b/stdlib/SuiteSparse_jll/Project.toml @@ -1,6 +1,6 @@ name = "SuiteSparse_jll" uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "5.10.1+0" +version = "5.10.1+6" [deps] libblastrampoline_jll = "8e850b90-86db-534c-a0d3-1478176c7d93" diff --git a/stdlib/libblastrampoline_jll/Project.toml b/stdlib/libblastrampoline_jll/Project.toml index dc5fbe9b4712d..08ba2e266512d 100644 --- a/stdlib/libblastrampoline_jll/Project.toml +++ b/stdlib/libblastrampoline_jll/Project.toml @@ -1,6 +1,6 @@ name = "libblastrampoline_jll" uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.2.0+0" +version = "5.4.0+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl b/stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl index 77882067ed633..108b7d6558079 100644 --- a/stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl +++ b/stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl @@ -19,11 +19,11 @@ libblastrampoline_handle = C_NULL libblastrampoline_path = "" const libblastrampoline = if Sys.iswindows() - "libblastrampoline.dll" + "libblastrampoline-5.dll" elseif Sys.isapple() - "@rpath/libblastrampoline.dylib" + "@rpath/libblastrampoline.5.dylib" else - "libblastrampoline.so" + "libblastrampoline.so.5" end function __init__() diff --git a/stdlib/libblastrampoline_jll/test/runtests.jl b/stdlib/libblastrampoline_jll/test/runtests.jl index 80095e70f0c76..e64fc328771be 100644 --- a/stdlib/libblastrampoline_jll/test/runtests.jl +++ b/stdlib/libblastrampoline_jll/test/runtests.jl @@ -3,5 +3,5 @@ using Test, Libdl, libblastrampoline_jll @testset "libblastrampoline_jll" begin - @test isa(Libdl.dlsym(Libdl.dlopen(:libblastrampoline), :dgemm_64_), Ptr{Nothing}) + @test isa(Libdl.dlsym(libblastrampoline_jll.libblastrampoline_handle, :dgemm_64_), Ptr{Nothing}) end From 017365c41896c56cf8abdcb94371754817e4c927 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 23 Jan 2023 09:02:43 +0100 Subject: [PATCH 23/45] Fix `apply_type_tfunc` for `Union{T::TypeVar}` The type parameters to `Union` may be `Type`s or `TypeVar`s, but `apply_type_tfunc` failed to recognize the latter as valid in the single-argument case. (cherry picked from commit fd79b589236efab502a11c87a69b7ec13d9c73aa) --- base/compiler/tfuncs.jl | 2 +- test/compiler/inference.jl | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 22e0716290d10..ec8b76cf1a7c3 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -1541,7 +1541,7 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...) end end if largs == 1 # Union{T} --> T - u1 = typeintersect(widenconst(args[1]), Type) + u1 = typeintersect(widenconst(args[1]), Union{Type,TypeVar}) valid_as_lattice(u1) || return Bottom return u1 end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index e09fa500248d0..715ecb3173c06 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -2364,9 +2364,9 @@ end |> only === Int # Equivalence of Const(T.instance) and T for singleton types @test Const(nothing) ⊑ Nothing && Nothing ⊑ Const(nothing) -# Don't pessimize apply_type to anything worse than Type and yield Bottom for invalid Unions +# Don't pessimize apply_type to anything worse than Type (or TypeVar) and yield Bottom for invalid Unions @test only(Base.return_types(Core.apply_type, Tuple{Type{Union}})) == Type{Union{}} -@test only(Base.return_types(Core.apply_type, Tuple{Type{Union},Any})) == Type +@test only(Base.return_types(Core.apply_type, Tuple{Type{Union},Any})) == Union{Type,TypeVar} @test only(Base.return_types(Core.apply_type, Tuple{Type{Union},Any,Any})) == Type @test only(Base.return_types(Core.apply_type, Tuple{Type{Union},Int})) == Union{} @test only(Base.return_types(Core.apply_type, Tuple{Type{Union},Any,Int})) == Union{} @@ -4277,3 +4277,6 @@ end # Issue #46839: `abstract_invoke` should handle incorrect call type @test only(Base.return_types(()->invoke(BitSet, Any, x), ())) === Union{} @test only(Base.return_types(()->invoke(BitSet, Union{Tuple{Int32},Tuple{Int64}}, 1), ())) === Union{} + +# issue #48374 +@test (() -> Union{<:Nothing})() == Nothing From 085d4a48377d43c43251849af2f2ae323b714923 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 19 Jan 2023 04:25:15 +0000 Subject: [PATCH 24/45] Move `libstdc++` path into `LOADER_*_DEP_LIBS` After adding `libstdc++` probing into the Julia loader [0], we originally made the assumption that the `libstdc++` that is shipped with `julia` would always be co-located with `libjulia.so` [1]. This is not the case when building with `USE_SYSTEM_CSL=1`, however, where we sequester system libraries in `usr/lib/julia`, even at build-time. The path to `libstdc++.so` has already been getting altered when moving from build-time to install time via `stringreplace` [2], but after further thought, I decided that it would be better to just use the pre-existing `LOADER_*_DEP_LIBS` mechanism to communicate to the loader what the correct relative path to `libstdc++.so` is. This also allows the single `stringreplace` to update all of our "special" library paths. [0] https://github.com/JuliaLang/julia/pull/46976 [1] https://github.com/JuliaLang/julia/pull/46976/files#diff-8c5c98f26f3f7aac8905a1074c5bec11a57e9b9c7c556791deac5a3b27cc096fR379 [2] https://github.com/JuliaLang/julia/blob/master/Makefile#L430 (cherry picked from commit fb97c8287f0bdaef5b9345dcd4dac6e2201fd09b) --- Make.inc | 21 +++++++++++--- Makefile | 6 ---- cli/loader_lib.c | 72 +++++++++++++++++++++++++++++++----------------- 3 files changed, 64 insertions(+), 35 deletions(-) diff --git a/Make.inc b/Make.inc index 323db88ed5876..b9a73338c31de 100644 --- a/Make.inc +++ b/Make.inc @@ -1526,6 +1526,19 @@ LIBGCC_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/$(L endif LIBGCC_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBGCC_NAME)) +# We only bother to define this on Linux, as that's the only platform that does libstdc++ probing +# On all other platforms, the LIBSTDCXX_*_DEPLIB variables will be empty. +ifeq ($(OS),Linux) +LIBSTDCXX_NAME := libstdc++.so.6 +ifeq ($(USE_SYSTEM_CSL),1) +LIBSTDCXX_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_private_shlibdir)/$(LIBSTDCXX_NAME)) +else +LIBSTDCXX_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/$(LIBSTDCXX_NAME)) +endif +LIBSTDCXX_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBSTDCXX_NAME)) +endif + + # USE_SYSTEM_LIBM and USE_SYSTEM_OPENLIBM causes it to get symlinked into build_private_shlibdir ifeq ($(USE_SYSTEM_LIBM),1) LIBM_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_private_shlibdir)/$(LIBMNAME).$(SHLIB_EXT)) @@ -1548,10 +1561,10 @@ LIBM_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBMN # That second point will no longer be true for most deps once they are placed within Artifacts directories. # Note that we prefix `libjulia-codegen` and `libjulia-internal` with `@` to signify to the loader that it # should not automatically dlopen() it in its loading loop. -LOADER_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_BUILD_DEPLIB):@$(LIBJULIACODEGEN_BUILD_DEPLIB): -LOADER_DEBUG_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_BUILD_DEPLIB): -LOADER_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_INSTALL_DEPLIB): -LOADER_DEBUG_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_INSTALL_DEPLIB): +LOADER_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBSTDCXX_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_BUILD_DEPLIB):@$(LIBJULIACODEGEN_BUILD_DEPLIB): +LOADER_DEBUG_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBSTDCXX_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_BUILD_DEPLIB): +LOADER_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBSTDCXX_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_INSTALL_DEPLIB): +LOADER_DEBUG_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBSTDCXX_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_INSTALL_DEPLIB): # Colors for make ifndef VERBOSE diff --git a/Makefile b/Makefile index 9ff447e04c144..8010088bd1b17 100644 --- a/Makefile +++ b/Makefile @@ -410,12 +410,6 @@ ifeq ($(OS), Linux) -$(PATCHELF) --set-rpath '$$ORIGIN' $(DESTDIR)$(private_shlibdir)/libLLVM.$(SHLIB_EXT) endif - # Replace libstdc++ path, which is also moving from `lib` to `../lib/julia`. -ifeq ($(OS),Linux) - $(call stringreplace,$(DESTDIR)$(shlibdir)/libjulia.$(JL_MAJOR_MINOR_SHLIB_EXT),\*libstdc++\.so\.6$$,*$(call dep_lib_path,$(shlibdir),$(private_shlibdir)/libstdc++.so.6)) -endif - - ifneq ($(LOADER_BUILD_DEP_LIBS),$(LOADER_INSTALL_DEP_LIBS)) # Next, overwrite relative path to libjulia-internal in our loader if $$(LOADER_BUILD_DEP_LIBS) != $$(LOADER_INSTALL_DEP_LIBS) ifeq ($(JULIA_BUILD_MODE),release) diff --git a/cli/loader_lib.c b/cli/loader_lib.c index fc057b52508f2..db0e3e1f9dc85 100644 --- a/cli/loader_lib.c +++ b/cli/loader_lib.c @@ -350,6 +350,50 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { void *cxx_handle; + // We keep track of "special" libraries names (ones whose name is prefixed with `@`) + // which are libraries that we want to load in some special, custom way. + // The current list is: + // special_library_names = { + // libstdc++, + // libjulia-internal, + // libjulia-codegen, + // } + int special_idx = 0; + char * special_library_names[3] = {NULL}; + while (1) { + // try to find next colon character; if we can't, break out + char * colon = strchr(curr_dep, ':'); + if (colon == NULL) + break; + + // If this library name starts with `@`, don't open it here (but mark it as special) + if (curr_dep[0] == '@') { + if (special_idx > sizeof(special_library_names)/sizeof(char *)) { + jl_loader_print_stderr("ERROR: Too many special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n"); + exit(1); + } + special_library_names[special_idx] = curr_dep + 1; + special_idx += 1; + + // Chop the string at the colon so it's a valid-ending-string + *colon = '\0'; + } + + // Skip to next dep + curr_dep = colon + 1; + } + + // Assert that we have exactly the right number of special library names + if (special_idx != sizeof(special_library_names)/sizeof(char *)) { + jl_loader_print_stderr("ERROR: Too few special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n"); + exit(1); + } + + // Unpack our special library names. This is why ordering of library names matters. + char * bundled_libstdcxx_path = special_library_names[0]; + libjulia_internal = load_library(special_library_names[1], lib_dir, 1); + void *libjulia_codegen = load_library(special_library_names[2], lib_dir, 0); + #if defined(_OS_LINUX_) int do_probe = 1; int done_probe = 0; @@ -375,16 +419,10 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { } } if (!done_probe) { - const static char bundled_path[256] = "\0*libstdc++.so.6"; - load_library(&bundled_path[2], lib_dir, 1); + load_library(bundled_libstdcxx_path, lib_dir, 1); } #endif - // We keep track of "special" libraries names (ones whose name is prefixed with `@`) - // which are libraries that we want to load in some special, custom way, such as - // `libjulia-internal` or `libjulia-codegen`. - int special_idx = 0; - char * special_library_names[2] = {NULL}; while (1) { // try to find next colon character; if we can't, break out char * colon = strchr(curr_dep, ':'); @@ -394,16 +432,8 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { // Chop the string at the colon so it's a valid-ending-string *colon = '\0'; - // If this library name starts with `@`, don't open it here (but mark it as special) - if (curr_dep[0] == '@') { - if (special_idx > sizeof(special_library_names)/sizeof(char *)) { - jl_loader_print_stderr("ERROR: Too many special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n"); - exit(1); - } - special_library_names[special_idx] = curr_dep + 1; - special_idx += 1; - } - else { + // If this library name starts with `@`, don't open it here + if (curr_dep[0] != '@') { load_library(curr_dep, lib_dir, 1); } @@ -411,14 +441,6 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { curr_dep = colon + 1; } - if (special_idx != sizeof(special_library_names)/sizeof(char *)) { - jl_loader_print_stderr("ERROR: Too few special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n"); - exit(1); - } - - // Unpack our special library names. This is why ordering of library names matters. - libjulia_internal = load_library(special_library_names[0], lib_dir, 1); - void *libjulia_codegen = load_library(special_library_names[1], lib_dir, 0); const char * const * codegen_func_names; const char *codegen_liberr; if (libjulia_codegen == NULL) { From e80db09b072fb12bed16839992ebba3bfc5bb058 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 19 Jan 2023 18:10:37 +0000 Subject: [PATCH 25/45] Load special libraries in-order The `DEPS_LIBS` RPATH-substitute mechanism contains a list of paths to load, and some of these paths are "special", in that they require more involved loading than simply `load_library()`. These libraries are thereby denoted by a `@` prefixing them. Previously, we made note of these libraries, then loaded them at the end of the loading loop, but with the addition of `libstdc++` it is now important to have the order of the libraries (including special libraries) to be obeyed by the loading loop, so I have inlined special library handling into the loading loop. In the future, we may wish to denote special libraries more explicitly than simply relying on there being exactly three libraries, with the ordering being mapped to `libstdc++`, `libjulia-internal`, and `libjulia-codegen`. (cherry picked from commit 4e99860f76e48c58a259ea4da395c89d2a4182eb) --- Make.inc | 48 ++++++++++++++++--- cli/loader_lib.c | 118 ++++++++++++++++++++++++++--------------------- 2 files changed, 108 insertions(+), 58 deletions(-) diff --git a/Make.inc b/Make.inc index b9a73338c31de..9fd75d76190e9 100644 --- a/Make.inc +++ b/Make.inc @@ -1479,7 +1479,7 @@ JULIA_SYSIMG_release := $(build_private_libdir)/sys.$(SHLIB_EXT) JULIA_SYSIMG := $(JULIA_SYSIMG_$(JULIA_BUILD_MODE)) define dep_lib_path -$$($(PYTHON) $(call python_cygpath,$(JULIAHOME)/contrib/relative_path.py) $(1) $(2)) +$(shell $(PYTHON) $(call python_cygpath,$(JULIAHOME)/contrib/relative_path.py) $(1) $(2)) endef LIBJULIAINTERNAL_BUILD_DEPLIB := $(call dep_lib_path,$(build_libdir),$(build_shlibdir)/libjulia-internal.$(JL_MAJOR_SHLIB_EXT)) @@ -1552,6 +1552,8 @@ LIBM_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBMN # We list: # * libgcc_s, because FreeBSD needs to load ours, not the system one. # * libopenlibm, because Windows has an untrustworthy libm, and we want to use ours more than theirs +# * libstdc++, because while performing `libstdc++` probing we need to +# know the path to the bundled `libstdc++` library. # * libjulia-internal, which must always come second-to-last. # * libjulia-codegen, which must always come last # @@ -1560,11 +1562,45 @@ LIBM_INSTALL_DEPLIB := $(call dep_lib_path,$(libdir),$(private_shlibdir)/$(LIBMN # * install time relative paths are not equal to build time relative paths (../lib vs. ../lib/julia) # That second point will no longer be true for most deps once they are placed within Artifacts directories. # Note that we prefix `libjulia-codegen` and `libjulia-internal` with `@` to signify to the loader that it -# should not automatically dlopen() it in its loading loop. -LOADER_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBSTDCXX_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_BUILD_DEPLIB):@$(LIBJULIACODEGEN_BUILD_DEPLIB): -LOADER_DEBUG_BUILD_DEP_LIBS = $(LIBGCC_BUILD_DEPLIB):$(LIBM_BUILD_DEPLIB):@$(LIBSTDCXX_BUILD_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_BUILD_DEPLIB): -LOADER_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBSTDCXX_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_INSTALL_DEPLIB): -LOADER_DEBUG_INSTALL_DEP_LIBS = $(LIBGCC_INSTALL_DEPLIB):$(LIBM_INSTALL_DEPLIB):@$(LIBSTDCXX_INSTALL_DEPLIB):@$(LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB):@$(LIBJULIACODEGEN_DEBUG_INSTALL_DEPLIB): +# should not automatically dlopen() it in its loading loop, it is "special" and should happen later. +# We do the same for `libstdc++`, and explicitly place it _after_ `libgcc_s`, and `libm` since `libstdc++` +# may depend on those libraries (e.g. when USE_SYSTEM_LIBM=1) + +# Helper function to join a list with colons, then place an extra at the end. +define build_deplibs +$(subst $(SPACE),:,$(strip $(1))): +endef + +LOADER_BUILD_DEP_LIBS = $(call build_deplibs, \ + $(LIBGCC_BUILD_DEPLIB) \ + $(LIBM_BUILD_DEPLIB) \ + @$(LIBSTDCXX_BUILD_DEPLIB) \ + @$(LIBJULIAINTERNAL_BUILD_DEPLIB) \ + @$(LIBJULIACODEGEN_BUILD_DEPLIB) \ +) + +LOADER_DEBUG_BUILD_DEP_LIBS = $(call build_deplibs, \ + $(LIBGCC_BUILD_DEPLIB) \ + $(LIBM_BUILD_DEPLIB) \ + @$(LIBSTDCXX_BUILD_DEPLIB) \ + @$(LIBJULIAINTERNAL_DEBUG_BUILD_DEPLIB) \ + @$(LIBJULIACODEGEN_DEBUG_BUILD_DEPLIB) \ +) + +LOADER_INSTALL_DEP_LIBS = $(call build_deplibs, \ + $(LIBGCC_INSTALL_DEPLIB) \ + $(LIBM_INSTALL_DEPLIB) \ + @$(LIBSTDCXX_INSTALL_DEPLIB) \ + @$(LIBJULIAINTERNAL_INSTALL_DEPLIB) \ + @$(LIBJULIACODEGEN_INSTALL_DEPLIB) \ +) +LOADER_DEBUG_INSTALL_DEP_LIBS = $(call build_deplibs, \ + $(LIBGCC_INSTALL_DEPLIB) \ + $(LIBM_INSTALL_DEPLIB) \ + @$(LIBSTDCXX_INSTALL_DEPLIB) \ + @$(LIBJULIAINTERNAL_DEBUG_INSTALL_DEPLIB) \ + @$(LIBJULIACODEGEN_DEBUG_INSTALL_DEPLIB) \ +) # Colors for make ifndef VERBOSE diff --git a/cli/loader_lib.c b/cli/loader_lib.c index db0e3e1f9dc85..295fa94a93bbb 100644 --- a/cli/loader_lib.c +++ b/cli/loader_lib.c @@ -334,7 +334,8 @@ static char *libstdcxxprobe(void) } #endif -void * libjulia_internal = NULL; +void *libjulia_internal = NULL; +void *libjulia_codegen = NULL; __attribute__((constructor)) void jl_load_libjulia_internal(void) { // Only initialize this once if (libjulia_internal != NULL) { @@ -348,18 +349,14 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { int deps_len = strlen(&dep_libs[1]); char *curr_dep = &dep_libs[1]; - void *cxx_handle; - // We keep track of "special" libraries names (ones whose name is prefixed with `@`) // which are libraries that we want to load in some special, custom way. // The current list is: - // special_library_names = { - // libstdc++, - // libjulia-internal, - // libjulia-codegen, - // } + // libstdc++ + // libjulia-internal + // libjulia-codegen + const int NUM_SPECIAL_LIBRARIES = 3; int special_idx = 0; - char * special_library_names[3] = {NULL}; while (1) { // try to find next colon character; if we can't, break out char * colon = strchr(curr_dep, ':'); @@ -368,15 +365,11 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { // If this library name starts with `@`, don't open it here (but mark it as special) if (curr_dep[0] == '@') { - if (special_idx > sizeof(special_library_names)/sizeof(char *)) { + special_idx += 1; + if (special_idx > NUM_SPECIAL_LIBRARIES) { jl_loader_print_stderr("ERROR: Too many special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n"); exit(1); } - special_library_names[special_idx] = curr_dep + 1; - special_idx += 1; - - // Chop the string at the colon so it's a valid-ending-string - *colon = '\0'; } // Skip to next dep @@ -384,45 +377,18 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { } // Assert that we have exactly the right number of special library names - if (special_idx != sizeof(special_library_names)/sizeof(char *)) { + if (special_idx != NUM_SPECIAL_LIBRARIES) { jl_loader_print_stderr("ERROR: Too few special library names specified, check LOADER_BUILD_DEP_LIBS and friends!\n"); exit(1); } - // Unpack our special library names. This is why ordering of library names matters. - char * bundled_libstdcxx_path = special_library_names[0]; - libjulia_internal = load_library(special_library_names[1], lib_dir, 1); - void *libjulia_codegen = load_library(special_library_names[2], lib_dir, 0); - -#if defined(_OS_LINUX_) - int do_probe = 1; - int done_probe = 0; - char *probevar = getenv("JULIA_PROBE_LIBSTDCXX"); - if (probevar) { - if (strcmp(probevar, "1") == 0 || strcmp(probevar, "yes") == 0) - do_probe = 1; - else if (strcmp(probevar, "0") == 0 || strcmp(probevar, "no") == 0) - do_probe = 0; - } - if (do_probe) { - char *cxxpath = libstdcxxprobe(); - if (cxxpath) { - cxx_handle = dlopen(cxxpath, RTLD_LAZY); - char *dlr = dlerror(); - if (dlr) { - jl_loader_print_stderr("ERROR: Unable to dlopen(cxxpath) in parent!\n"); - jl_loader_print_stderr3("Message: ", dlr, "\n"); - exit(1); - } - free(cxxpath); - done_probe = 1; - } - } - if (!done_probe) { - load_library(bundled_libstdcxx_path, lib_dir, 1); - } -#endif - + // Now that we've asserted that we have the right number of special + // libraries, actually run a loop over the deps loading them in-order. + // If it's a special library, we do slightly different things, especially + // for libstdc++, where we actually probe for a system libstdc++ and + // load that if it's newer. + special_idx = 0; + curr_dep = &dep_libs[1]; while (1) { // try to find next colon character; if we can't, break out char * colon = strchr(curr_dep, ':'); @@ -432,8 +398,56 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { // Chop the string at the colon so it's a valid-ending-string *colon = '\0'; - // If this library name starts with `@`, don't open it here - if (curr_dep[0] != '@') { + // If this library name starts with `@`, it's a special library + // and requires special handling: + if (curr_dep[0] == '@') { + // Skip the `@` for future function calls. + curr_dep += 1; + + // First special library to be loaded is `libstdc++`; perform probing here. + if (special_idx == 0) { +#if defined(_OS_LINUX_) + int do_probe = 1; + int probe_successful = 0; + + // Check to see if the user has disabled libstdc++ probing + char *probevar = getenv("JULIA_PROBE_LIBSTDCXX"); + if (probevar) { + if (strcmp(probevar, "1") == 0 || strcmp(probevar, "yes") == 0) + do_probe = 1; + else if (strcmp(probevar, "0") == 0 || strcmp(probevar, "no") == 0) + do_probe = 0; + } + if (do_probe) { + char *cxxpath = libstdcxxprobe(); + if (cxxpath) { + void *cxx_handle = dlopen(cxxpath, RTLD_LAZY); + const char *dlr = dlerror(); + if (dlr) { + jl_loader_print_stderr("ERROR: Unable to dlopen(cxxpath) in parent!\n"); + jl_loader_print_stderr3("Message: ", dlr, "\n"); + exit(1); + } + free(cxxpath); + probe_successful = 1; + } + } + // If the probe rejected the system libstdc++ (or didn't find one!) + // just load our bundled libstdc++ as identified by curr_dep; + if (!probe_successful) { + load_library(curr_dep, lib_dir, 1); + } +#endif + } else if (special_idx == 1) { + // This special library is `libjulia-internal` + libjulia_internal = load_library(curr_dep, lib_dir, 1); + } else if (special_idx == 2) { + // This special library is `libjulia-codegen` + libjulia_codegen = load_library(curr_dep, lib_dir, 0); + } + special_idx++; + } else { + // Otherwise, just load it as "normal" load_library(curr_dep, lib_dir, 1); } From f5a6860559ebb09910306207cdb2f0d63fb37677 Mon Sep 17 00:00:00 2001 From: Kristoffer Date: Wed, 1 Feb 2023 11:27:12 +0100 Subject: [PATCH 26/45] bump Pkg to latest v1.9 --- .../Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/md5 | 1 - .../Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/sha512 | 1 - .../Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 | 1 + .../Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 create mode 100644 deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 diff --git a/deps/checksums/Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/md5 b/deps/checksums/Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/md5 deleted file mode 100644 index 5909850ca1339..0000000000000 --- a/deps/checksums/Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -b7984c17799c54794adccdeb6d89a022 diff --git a/deps/checksums/Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/sha512 b/deps/checksums/Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/sha512 deleted file mode 100644 index c2c3868afaae1..0000000000000 --- a/deps/checksums/Pkg-5fda6496e22534d27532bc5cf9374ec85ba6ff95.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -58db4ed65bec3768de4acc96eb224786ca61cab65e53d7db011e1d1bf081f8ab072ac5a387c41cdb3186383a955d87b8d394859f793fe6b020da5f01e4dc6249 diff --git a/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 b/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 new file mode 100644 index 0000000000000..3fe266bbf95cf --- /dev/null +++ b/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 @@ -0,0 +1 @@ +f9dd5088c318bfc489e44bd39153c08c diff --git a/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 b/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 new file mode 100644 index 0000000000000..5285f263a7032 --- /dev/null +++ b/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 @@ -0,0 +1 @@ +10fb53b40a38d685f542a8dee1802cf878e87e8b85084df09efb84994b9fbaded53814205ab34e50b01d3f2be93204db4f9e00d862223e72ff5558247d4e2622 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index d87b52628b350..3aa12eadf4758 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = release-1.9 -PKG_SHA1 = 5fda6496e22534d27532bc5cf9374ec85ba6ff95 +PKG_SHA1 = 8ab37b338bcf64dd7734ecc2adc86a3f65502224 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From 0f0d425f51ca043503e35309b2436cc86c84d6f5 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Thu, 12 Jan 2023 10:40:03 -0700 Subject: [PATCH 27/45] Add !noalias and !alias.scope metadata The main idea here is that the TBAA domain is ill-equipped for reasoning about regions (and, in particular, suffers total precision less when merging disparate types in a `memcpy`). Instead, `!noalias` should be used for region-based memory information and `!tbaa` should be used exclusively for layout. We use (5) regions corresponding to the top level of the TBAA tree: - gcframe - stack - data - constant - type_metadata For now, this leaves the TBAA hierarchy in tact and only adds additional `!noalias` metadata. `!tbaa` annotations should be the same as before. --- src/cgutils.cpp | 57 ++++++++++---- src/codegen.cpp | 198 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 238 insertions(+), 17 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index e56c570c3afae..c0e9f88bd117f 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -886,8 +886,8 @@ static Value *data_pointer(jl_codectx_t &ctx, const jl_cgval_t &x) return data; } -static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Value *src, MDNode *tbaa_src, - uint64_t sz, unsigned align, bool is_volatile) +static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, Value *src, + jl_aliasinfo_t const &src_ai, uint64_t sz, unsigned align, bool is_volatile) { if (sz == 0) return; @@ -929,44 +929,73 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Va src = emit_bitcast(ctx, src, dstty); } if (directel) { - auto val = tbaa_decorate(tbaa_src, ctx.builder.CreateAlignedLoad(directel, src, Align(align), is_volatile)); - tbaa_decorate(tbaa_dst, ctx.builder.CreateAlignedStore(val, dst, Align(align), is_volatile)); + auto val = src_ai.decorateInst(ctx.builder.CreateAlignedLoad(directel, src, Align(align), is_volatile)); + dst_ai.decorateInst(ctx.builder.CreateAlignedStore(val, dst, Align(align), is_volatile)); ++SkippedMemcpys; return; } } #endif + ++EmittedMemcpys; + // the memcpy intrinsic does not allow to specify different alias tags // for the load part (x.tbaa) and the store part (ctx.tbaa().tbaa_stack). // since the tbaa lattice has to be a tree we have unfortunately // x.tbaa ∪ ctx.tbaa().tbaa_stack = tbaa_root if x.tbaa != ctx.tbaa().tbaa_stack - ++EmittedMemcpys; - ctx.builder.CreateMemCpy(dst, MaybeAlign(align), src, MaybeAlign(0), sz, is_volatile, MDNode::getMostGenericTBAA(tbaa_dst, tbaa_src)); + + // Now that we use scoped aliases to label disparate regions of memory, the TBAA + // metadata should be revisited so that it only represents memory layouts. Once + // that's done, we can expect that in most cases tbaa(src) == tbaa(dst) and the + // above problem won't be as serious. + + auto merged_ai = dst_ai.merge(src_ai); + ctx.builder.CreateMemCpy(dst, MaybeAlign(align), src, MaybeAlign(0), sz, is_volatile, + merged_ai.tbaa, merged_ai.tbaa_struct, merged_ai.scope, merged_ai.noalias); } -static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Value *src, MDNode *tbaa_src, - Value *sz, unsigned align, bool is_volatile) +static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, Value *src, + jl_aliasinfo_t const &src_ai, Value *sz, unsigned align, bool is_volatile) { if (auto const_sz = dyn_cast(sz)) { - emit_memcpy_llvm(ctx, dst, tbaa_dst, src, tbaa_src, const_sz->getZExtValue(), align, is_volatile); + emit_memcpy_llvm(ctx, dst, dst_ai, src, src_ai, const_sz->getZExtValue(), align, is_volatile); return; } ++EmittedMemcpys; - ctx.builder.CreateMemCpy(dst, MaybeAlign(align), src, MaybeAlign(0), sz, is_volatile, MDNode::getMostGenericTBAA(tbaa_dst, tbaa_src)); + + auto merged_ai = dst_ai.merge(src_ai); + ctx.builder.CreateMemCpy(dst, MaybeAlign(align), src, MaybeAlign(0), sz, is_volatile, + merged_ai.tbaa, merged_ai.tbaa_struct, merged_ai.scope, merged_ai.noalias); } template static void emit_memcpy(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Value *src, MDNode *tbaa_src, T1 &&sz, unsigned align, bool is_volatile=false) { - emit_memcpy_llvm(ctx, dst, tbaa_dst, src, tbaa_src, sz, align, is_volatile); + emit_memcpy_llvm(ctx, dst, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), src, + jl_aliasinfo_t::fromTBAA(ctx, tbaa_src), sz, align, is_volatile); } template static void emit_memcpy(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, const jl_cgval_t &src, T1 &&sz, unsigned align, bool is_volatile=false) { - emit_memcpy_llvm(ctx, dst, tbaa_dst, data_pointer(ctx, src), src.tbaa, sz, align, is_volatile); + emit_memcpy_llvm(ctx, dst, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), data_pointer(ctx, src), + jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), sz, align, is_volatile); +} + +template +static void emit_memcpy(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, Value *src, + jl_aliasinfo_t const &src_ai, T1 &&sz, unsigned align, bool is_volatile=false) +{ + emit_memcpy_llvm(ctx, dst, dst_ai, src, src_ai, sz, align, is_volatile); +} + +template +static void emit_memcpy(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, const jl_cgval_t &src, + T1 &&sz, unsigned align, bool is_volatile=false) +{ + auto src_ai = jl_aliasinfo_t::fromTBAA(ctx, src.tbaa); + emit_memcpy_llvm(ctx, dst, dst_ai, data_pointer(ctx, src), src_ai, sz, align, is_volatile); } static LoadInst *emit_nthptr_recast(jl_codectx_t &ctx, Value *v, Value *idx, MDNode *tbaa, Type *type) @@ -2695,7 +2724,9 @@ static Value *emit_arrayptr_internal(jl_codectx_t &ctx, const jl_cgval_t &tinfo, LoadInst *LI = ctx.builder.CreateAlignedLoad(LoadT, addr, Align(sizeof(char *))); LI->setOrdering(AtomicOrdering::NotAtomic); LI->setMetadata(LLVMContext::MD_nonnull, MDNode::get(ctx.builder.getContext(), None)); - tbaa_decorate(arraytype_constshape(tinfo.typ) ? ctx.tbaa().tbaa_const : ctx.tbaa().tbaa_arrayptr, LI); + jl_aliasinfo_t aliasinfo = jl_aliasinfo_t::fromTBAA(ctx, arraytype_constshape(tinfo.typ) ? ctx.tbaa().tbaa_const : ctx.tbaa().tbaa_arrayptr); + aliasinfo.decorateInst(LI); + return LI; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 6a884c861a457..5885405179c4b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -356,6 +356,57 @@ struct jl_tbaacache_t { } }; +struct jl_noaliascache_t { + // Each domain operates completely independently. + // "No aliasing" is inferred if it is implied by any domain. + + // memory regions domain + struct jl_regions_t { + MDNode *gcframe; // GC frame + MDNode *stack; // Stack slot + MDNode *data; // Any user data that `pointerset/ref` are allowed to alias + MDNode *type_metadata; // Non-user-accessible type metadata incl. size, union selectors, etc. + MDNode *constant; // Memory that is immutable by the time LLVM can see it + + jl_regions_t(): gcframe(nullptr), stack(nullptr), data(nullptr), type_metadata(nullptr), constant(nullptr) {} + + void initialize(llvm::LLVMContext &context) { + MDBuilder mbuilder(context); + MDNode *domain = mbuilder.createAliasScopeDomain("jnoalias"); + + this->gcframe = mbuilder.createAliasScope("jnoalias_gcframe", domain); + this->stack = mbuilder.createAliasScope("jnoalias_stack", domain); + this->data = mbuilder.createAliasScope("jnoalias_data", domain); + this->type_metadata = mbuilder.createAliasScope("jnoalias_typemd", domain); + this->constant = mbuilder.createAliasScope("jnoalias_const", domain); + } + } regions; + + // `@aliasscope` domain + struct jl_aliasscope_t { + MDNode *current; + + jl_aliasscope_t(): current(nullptr) {} + + // No init required, this->current is only used to store the currently active aliasscope + void initialize(llvm::LLVMContext &context) {} + } aliasscope; + + bool initialized; + + jl_noaliascache_t(): regions(), aliasscope(), initialized(false) {} + + void initialize(llvm::LLVMContext &context) { + if (initialized) { + assert(®ions.constant->getContext() == &context); + return; + } + initialized = true; + regions.initialize(context); + aliasscope.initialize(context); + } +}; + struct jl_debugcache_t { // Basic DITypes DIDerivedType *jl_pvalue_dillvmt; @@ -1266,6 +1317,69 @@ static bool deserves_sret(jl_value_t *dt, Type *T) return (size_t)jl_datatype_size(dt) > sizeof(void*) && !T->isFloatingPointTy() && !T->isVectorTy(); } +// Alias Analysis Info (analogous to llvm::AAMDNodes) +struct jl_aliasinfo_t { + MDNode *tbaa = nullptr; // '!tbaa': Struct-path TBAA. TBAA graph forms a tree (indexed by offset). + // Two pointers do not alias if they are not transitive parents + // (effectively, subfields) of each other or equal. + MDNode *tbaa_struct = nullptr; // '!tbaa.struct': Describes memory layout of struct. + MDNode *scope = nullptr; // '!alias.scope': Generic "noalias" memory access sets. + // If alias.scope(inst_a) ⊆ noalias(inst_b) (in any "domain") + // => inst_a, inst_b do not alias. + MDNode *noalias = nullptr; // '!noalias': See '!alias.scope' above. + + enum class Region { unknown, gcframe, stack, data, constant, type_metadata }; // See jl_regions_t + + explicit jl_aliasinfo_t() = default; + explicit jl_aliasinfo_t(jl_codectx_t &ctx, Region r, MDNode *tbaa); + explicit jl_aliasinfo_t(MDNode *tbaa, MDNode *tbaa_struct, MDNode *scope, MDNode *noalias) + : tbaa(tbaa), tbaa_struct(tbaa_struct), scope(scope), noalias(noalias) {} + jl_aliasinfo_t(const jl_aliasinfo_t &) = default; + + // Add !tbaa, !tbaa.struct, !alias.scope, !noalias annotations to an instruction. + // + // Also adds `invariant.load` to load instructions in the constant !noalias scope. + Instruction *decorateInst(Instruction *inst) const { + + if (this->tbaa) + inst->setMetadata(LLVMContext::MD_tbaa, this->tbaa); + if (this->tbaa_struct) + inst->setMetadata(LLVMContext::MD_tbaa_struct, this->tbaa_struct); + if (this->scope) + inst->setMetadata(LLVMContext::MD_alias_scope, this->scope); + if (this->noalias) + inst->setMetadata(LLVMContext::MD_noalias, this->noalias); + + if (this->scope && isa(inst)) { + // If this is in the read-only region, mark the load with "!invariant.load" + if (this->scope->getNumOperands() == 1) { + MDNode *operand = cast(this->scope->getOperand(0)); + auto scope_name = cast(operand->getOperand(0))->getString(); + if (scope_name == "jnoalias_const") + inst->setMetadata(LLVMContext::MD_invariant_load, MDNode::get(inst->getContext(), None)); + } + } + + return inst; + } + + // Merge two sets of alias information. + jl_aliasinfo_t merge(const jl_aliasinfo_t &other) const { + jl_aliasinfo_t result; + result.tbaa = MDNode::getMostGenericTBAA(this->tbaa, other.tbaa); + result.tbaa_struct = nullptr; + result.scope = MDNode::getMostGenericAliasScope(this->scope, other.scope); + result.noalias = MDNode::intersect(this->noalias, other.noalias); + return result; + } + + // Create alias information based on the provided TBAA metadata. + // + // This function only exists to help transition to using !noalias to encode + // memory region non-aliasing. It should be deleted once the TBAA metadata + // is improved to encode only memory layout and *not* memory regions. + static jl_aliasinfo_t fromTBAA(jl_codectx_t &ctx, MDNode *tbaa); +}; // metadata tracking for a llvm Value* during codegen struct jl_cgval_t { @@ -1431,6 +1545,7 @@ class jl_codectx_t { jl_module_t *module = NULL; jl_typecache_t type_cache; jl_tbaacache_t tbaa_cache; + jl_noaliascache_t aliasscope_cache; jl_method_instance_t *linfo = NULL; jl_value_t *rettype = NULL; jl_code_info_t *source = NULL; @@ -1442,7 +1557,6 @@ class jl_codectx_t { Value *spvals_ptr = NULL; Value *argArray = NULL; Value *argCount = NULL; - MDNode *aliasscope = NULL; std::string funcName; int vaSlot = -1; // name of vararg argument int nReqArgs = 0; @@ -1481,6 +1595,11 @@ class jl_codectx_t { return tbaa_cache; } + jl_noaliascache_t &noalias() { + aliasscope_cache.initialize(builder.getContext()); + return aliasscope_cache; + } + ~jl_codectx_t() { // Transfer local delayed calls to the global queue for (auto call_target : call_targets) @@ -1492,6 +1611,77 @@ GlobalVariable *JuliaVariable::realize(jl_codectx_t &ctx) { return realize(jl_Module); } +jl_aliasinfo_t::jl_aliasinfo_t(jl_codectx_t &ctx, Region r, MDNode *tbaa): tbaa(tbaa), tbaa_struct(nullptr) { + MDNode *alias_scope = nullptr; + jl_noaliascache_t::jl_regions_t regions = ctx.noalias().regions; + switch (r) { + case Region::unknown: + alias_scope = nullptr; + break; + case Region::gcframe: + alias_scope = regions.gcframe; + break; + case Region::stack: + alias_scope = regions.stack; + break; + case Region::data: + alias_scope = regions.data; + break; + case Region::constant: + alias_scope = regions.constant; + break; + case Region::type_metadata: + alias_scope = regions.type_metadata; + break; + } + + MDNode *all_scopes[5] = { regions.gcframe, regions.stack, regions.data, regions.type_metadata, regions.constant }; + if (alias_scope) { + // The matching region is added to !alias.scope + // All other regions are added to !noalias + + int i = 0; + Metadata *scopes[1] = { alias_scope }; + Metadata *noaliases[4]; + for (auto const &scope: all_scopes) { + if (scope == alias_scope) continue; + noaliases[i++] = scope; + } + + this->scope = MDNode::get(ctx.builder.getContext(), ArrayRef(scopes)); + this->noalias = MDNode::get(ctx.builder.getContext(), ArrayRef(noaliases)); + } +} + +jl_aliasinfo_t jl_aliasinfo_t::fromTBAA(jl_codectx_t &ctx, MDNode *tbaa) { + auto cache = ctx.tbaa(); + + // Each top-level TBAA node has a corresponding !alias.scope scope + MDNode *tbaa_srcs[5] = { cache.tbaa_gcframe, cache.tbaa_stack, cache.tbaa_data, cache.tbaa_array, cache.tbaa_const }; + Region regions[5] = { Region::gcframe, Region::stack, Region::data, Region::type_metadata, Region::constant }; + + if (tbaa != nullptr) { + MDNode *node = cast(tbaa->getOperand(1)); + if (cast(node->getOperand(0))->getString() != "jtbaa") { + + // Climb up to node just before root + MDNode *parent_node = cast(node->getOperand(1)); + while (cast(parent_node->getOperand(0))->getString() != "jtbaa") { + node = parent_node; + parent_node = cast(node->getOperand(1)); + } + + // Find the matching node's index + for (int i = 0; i < 5; i++) { + if (cast(tbaa_srcs[i]->getOperand(1)) == node) + return jl_aliasinfo_t(ctx, regions[i], tbaa); + } + } + } + + return jl_aliasinfo_t(ctx, Region::unknown, tbaa); +} + static Type *julia_type_to_llvm(jl_codectx_t &ctx, jl_value_t *jt, bool *isboxed = NULL); static jl_returninfo_t get_specsig_function(jl_codectx_t &ctx, Module *M, StringRef name, jl_value_t *sig, jl_value_t *jlrettype, bool is_opaque_closure); static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval = -1); @@ -3238,7 +3428,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, *ret = emit_unionload(ctx, data, ptindex, ety, elsz, al, ctx.tbaa().tbaa_arraybuf, true, union_max, ctx.tbaa().tbaa_arrayselbyte); } else { - MDNode *aliasscope = (f == jl_builtin_const_arrayref) ? ctx.aliasscope : nullptr; + MDNode *aliasscope = (f == jl_builtin_const_arrayref) ? ctx.noalias().aliasscope.current : nullptr; *ret = typed_load(ctx, emit_arrayptr(ctx, ary, ary_ex), idx, ety, @@ -3353,7 +3543,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, emit_arrayptr(ctx, ary, ary_ex, isboxed), idx, val, jl_cgval_t(), ety, isboxed ? ctx.tbaa().tbaa_ptrarraybuf : ctx.tbaa().tbaa_arraybuf, - ctx.aliasscope, + ctx.noalias().aliasscope.current, data_owner, isboxed, isboxed ? AtomicOrdering::Release : AtomicOrdering::NotAtomic, // TODO: we should do this for anything with CountTrackedPointers(elty).count > 0 @@ -7651,7 +7841,7 @@ static jl_llvm_functions_t ctx.builder.SetCurrentDebugLocation(linetable.at(debuginfoloc).loc); coverageVisitStmt(debuginfoloc); } - ctx.aliasscope = aliasscopes[cursor]; + ctx.noalias().aliasscope.current = aliasscopes[cursor]; jl_value_t *stmt = jl_array_ptr_ref(stmts, cursor); jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr; if (jl_is_returnnode(stmt)) { From d04d36ffd8ad3149739139584df9cd3a35af90de Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Thu, 12 Jan 2023 11:00:20 -0700 Subject: [PATCH 28/45] Derive `!noalias` from `!tbaa` for most loads/stores This is an interim solution that derives the correct `!noalias` region from the existing TBAA information. Later we will want to: - Revise the TBAA hierarchy to remove region information - Delete `jl_aliasinfo_t::fromTBAA()` - Update `jl_cgval_t` to store a `jl_aliasinfo_t` --- src/ccall.cpp | 30 +++-- src/cgutils.cpp | 202 +++++++++++++++++---------------- src/codegen.cpp | 122 ++++++++++++-------- src/intrinsics.cpp | 35 +++--- test/llvmpasses/aliasscopes.jl | 27 +++-- 5 files changed, 234 insertions(+), 182 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 498109f069cc6..1ff2ca7828b06 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -550,10 +550,12 @@ static Value *julia_to_native( // since those are immutable. Value *slot = emit_static_alloca(ctx, to); if (!jvinfo.ispointer()) { - tbaa_decorate(jvinfo.tbaa, ctx.builder.CreateStore(emit_unbox(ctx, to, jvinfo, jlto), slot)); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, jvinfo.tbaa); + ai.decorateInst(ctx.builder.CreateStore(emit_unbox(ctx, to, jvinfo, jlto), slot)); } else { - emit_memcpy(ctx, slot, jvinfo.tbaa, jvinfo, jl_datatype_size(jlto), julia_alignment(jlto)); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, jvinfo.tbaa); + emit_memcpy(ctx, slot, ai, jvinfo, jl_datatype_size(jlto), julia_alignment(jlto)); } return slot; } @@ -1571,7 +1573,8 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) const int tid_offset = offsetof(jl_task_t, tid); Value *ptid = ctx.builder.CreateInBoundsGEP(getInt16Ty(ctx.builder.getContext()), ptask_i16, ConstantInt::get(getSizeTy(ctx.builder.getContext()), tid_offset / sizeof(int16_t))); LoadInst *tid = ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), ptid, Align(sizeof(int16_t))); - tbaa_decorate(ctx.tbaa().tbaa_gcframe, tid); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe); + ai.decorateInst(tid); return mark_or_box_ccall_result(ctx, tid, retboxed, rt, unionall, static_rt); } else if (is_libjulia_func(jl_gc_disable_finalizers_internal) @@ -1675,8 +1678,10 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) len = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ptr, Align(sizeof(size_t))); // Only mark with TBAA if we are sure about the type. // This could otherwise be in a dead branch - if (svecv.typ == (jl_value_t*)jl_simplevector_type) - tbaa_decorate(ctx.tbaa().tbaa_const, cast(len)); + if (svecv.typ == (jl_value_t*)jl_simplevector_type) { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + ai.decorateInst(cast(len)); + } MDBuilder MDB(ctx.builder.getContext()); auto rng = MDB.createRange( Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), INTPTR_MAX / sizeof(void*) - 1)); @@ -1701,8 +1706,10 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) load->setAtomic(AtomicOrdering::Unordered); // Only mark with TBAA if we are sure about the type. // This could otherwise be in a dead branch - if (svecv.typ == (jl_value_t*)jl_simplevector_type) - tbaa_decorate(ctx.tbaa().tbaa_const, load); + if (svecv.typ == (jl_value_t*)jl_simplevector_type) { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + ai.decorateInst(load); + } JL_GC_POP(); return mark_or_box_ccall_result(ctx, load, retboxed, rt, unionall, static_rt); } @@ -1736,7 +1743,8 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, arrayptr, idx); LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr, Align(sizeof(void*))); load->setAtomic(AtomicOrdering::Unordered); - tbaa_decorate(ctx.tbaa().tbaa_ptrarraybuf, load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_ptrarraybuf); + ai.decorateInst(load); Value *res = ctx.builder.CreateZExt(ctx.builder.CreateICmpNE(load, Constant::getNullValue(ctx.types().T_prjlvalue)), getInt32Ty(ctx.builder.getContext())); JL_GC_POP(); return mark_or_box_ccall_result(ctx, res, retboxed, rt, unionall, static_rt); @@ -1838,7 +1846,8 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) Value *ph1 = emit_bitcast(ctx, decay_derived(ctx, boxed(ctx, val)), getSizePtrTy(ctx.builder.getContext())); Value *ph2 = ctx.builder.CreateInBoundsGEP(getSizeTy(ctx.builder.getContext()), ph1, ConstantInt::get(getSizeTy(ctx.builder.getContext()), hash_offset / sizeof(size_t))); LoadInst *hashval = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ph2, Align(sizeof(size_t))); - tbaa_decorate(ctx.tbaa().tbaa_const, hashval); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + ai.decorateInst(hashval); return mark_or_box_ccall_result(ctx, hashval, retboxed, rt, unionall, static_rt); } else if (!val.isboxed) { @@ -2128,7 +2137,8 @@ jl_cgval_t function_sig_t::emit_a_ccall( auto slot = emit_static_alloca(ctx, resultTy); slot->setAlignment(Align(boxalign)); ctx.builder.CreateAlignedStore(result, slot, Align(boxalign)); - emit_memcpy(ctx, strct, tbaa, slot, tbaa, rtsz, boxalign); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + emit_memcpy(ctx, strct, ai, slot, ai, rtsz, boxalign); } else { init_bits_value(ctx, strct, result, tbaa, boxalign); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index c0e9f88bd117f..8188c741c1dc4 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -474,7 +474,8 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p) if (!ctx.emission_context.imaging) return literal_static_pointer_val(p, ctx.types().T_pjlvalue); Value *pgv = literal_pointer_val_slot(ctx, p); - return tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + return ai.decorateInst(maybe_mark_load_dereferenceable( ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*))), false, jl_typeof(p))); } @@ -489,7 +490,8 @@ static Value *literal_pointer_val(jl_codectx_t &ctx, jl_binding_t *p) return literal_static_pointer_val(p, ctx.types().T_pjlvalue); // bindings are prefixed with jl_bnd# Value *pgv = julia_pgv(ctx, "jl_bnd#", p->name, p->owner, p); - return tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + return ai.decorateInst(maybe_mark_load_dereferenceable( ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, pgv, Align(sizeof(void*))), false, sizeof(jl_binding_t), alignof(jl_binding_t))); } @@ -526,9 +528,11 @@ static Value *julia_binding_gv(jl_codectx_t &ctx, jl_binding_t *b) { // emit a literal_pointer_val to a jl_binding_t // binding->value are prefixed with * - if (ctx.emission_context.imaging) - return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, + if (ctx.emission_context.imaging) { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + return ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, julia_pgv(ctx, "*", b->name, b->owner, b), Align(sizeof(void*)))); + } else return literal_static_pointer_val(b, ctx.types().T_pjlvalue); } @@ -967,22 +971,6 @@ static void emit_memcpy_llvm(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const merged_ai.tbaa, merged_ai.tbaa_struct, merged_ai.scope, merged_ai.noalias); } -template -static void emit_memcpy(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, Value *src, MDNode *tbaa_src, - T1 &&sz, unsigned align, bool is_volatile=false) -{ - emit_memcpy_llvm(ctx, dst, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), src, - jl_aliasinfo_t::fromTBAA(ctx, tbaa_src), sz, align, is_volatile); -} - -template -static void emit_memcpy(jl_codectx_t &ctx, Value *dst, MDNode *tbaa_dst, const jl_cgval_t &src, - T1 &&sz, unsigned align, bool is_volatile=false) -{ - emit_memcpy_llvm(ctx, dst, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), data_pointer(ctx, src), - jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), sz, align, is_volatile); -} - template static void emit_memcpy(jl_codectx_t &ctx, Value *dst, jl_aliasinfo_t const &dst_ai, Value *src, jl_aliasinfo_t const &src_ai, T1 &&sz, unsigned align, bool is_volatile=false) @@ -1006,7 +994,8 @@ static LoadInst *emit_nthptr_recast(jl_codectx_t &ctx, Value *v, Value *idx, MDN emit_bitcast(ctx, maybe_decay_tracked(ctx, v), ctx.types().T_pprjlvalue), idx); LoadInst *load = ctx.builder.CreateLoad(type, emit_bitcast(ctx, vptr, PointerType::get(type, 0))); - tbaa_decorate(tbaa, load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.decorateInst(load); return load; } @@ -1049,9 +1038,10 @@ static jl_cgval_t emit_typeof(jl_codectx_t &ctx, const jl_cgval_t &p, bool maybe p.typ, counter); auto emit_unboxty = [&] () -> Value* { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); if (ctx.emission_context.imaging) return track_pjlvalue( - ctx, tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, datatype_or_p, Align(sizeof(void*))))); + ctx, ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, datatype_or_p, Align(sizeof(void*))))); return datatype_or_p; }; Value *res; @@ -1093,25 +1083,28 @@ static Value *emit_datatype_types(jl_codectx_t &ctx, Value *dt) { Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), ctx.types().T_ppjlvalue); Value *Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_t, types) / sizeof(void*)); - return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + return ai.decorateInst(ctx.builder.CreateAlignedLoad( ctx.types().T_pjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_pjlvalue, Ptr, Idx), Align(sizeof(void*)))); } static Value *emit_datatype_nfields(jl_codectx_t &ctx, Value *dt) { Value *type_svec = emit_bitcast(ctx, emit_datatype_types(ctx, dt), getSizePtrTy(ctx.builder.getContext())); - return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), type_svec, Align(sizeof(void*)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + return ai.decorateInst(ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), type_svec, Align(sizeof(void*)))); } static Value *emit_datatype_size(jl_codectx_t &ctx, Value *dt) { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), getInt32PtrTy(ctx.builder.getContext())->getPointerTo()); Value *Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_t, layout) / sizeof(int32_t*)); Ptr = ctx.builder.CreateInBoundsGEP(getInt32PtrTy(ctx.builder.getContext()), Ptr, Idx); - Ptr = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt32PtrTy(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t*)))); + Ptr = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt32PtrTy(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t*)))); Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_layout_t, size) / sizeof(int32_t)); Ptr = ctx.builder.CreateInBoundsGEP(getInt32Ty(ctx.builder.getContext()), Ptr, Idx); - return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t)))); + return ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t)))); } /* this is valid code, it's simply unused @@ -1165,12 +1158,13 @@ static Value *emit_sizeof(jl_codectx_t &ctx, const jl_cgval_t &p) static Value *emit_datatype_mutabl(jl_codectx_t &ctx, Value *dt) { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), ctx.types().T_ppint8); Value *Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_t, name)); - Value *Nam = tbaa_decorate(ctx.tbaa().tbaa_const, + Value *Nam = ai.decorateInst( ctx.builder.CreateAlignedLoad(getInt8PtrTy(ctx.builder.getContext()), ctx.builder.CreateInBoundsGEP(getInt8PtrTy(ctx.builder.getContext()), Ptr, Idx), Align(sizeof(int8_t*)))); Value *Idx2 = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_typename_t, n_uninitialized) + sizeof(((jl_typename_t*)nullptr)->n_uninitialized)); - Value *mutabl = tbaa_decorate(ctx.tbaa().tbaa_const, + Value *mutabl = ai.decorateInst( ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), Nam, Idx2), Align(1))); mutabl = ctx.builder.CreateLShr(mutabl, 1); return ctx.builder.CreateTrunc(mutabl, getInt1Ty(ctx.builder.getContext())); @@ -1181,7 +1175,8 @@ static Value *emit_datatype_isprimitivetype(jl_codectx_t &ctx, Value *typ) { Value *isprimitive; isprimitive = ctx.builder.CreateConstInBoundsGEP1_32(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, decay_derived(ctx, typ), getInt8PtrTy(ctx.builder.getContext())), offsetof(jl_datatype_t, hash) + sizeof(((jl_datatype_t*)nullptr)->hash)); - isprimitive = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), isprimitive, Align(1))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + isprimitive = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), isprimitive, Align(1))); isprimitive = ctx.builder.CreateLShr(isprimitive, 7); isprimitive = ctx.builder.CreateTrunc(isprimitive, getInt1Ty(ctx.builder.getContext())); return isprimitive; @@ -1194,7 +1189,8 @@ static Value *emit_datatype_name(jl_codectx_t &ctx, Value *dt) ctx.types().T_pjlvalue, emit_bitcast(ctx, maybe_decay_tracked(ctx, dt), ctx.types().T_ppjlvalue), ConstantInt::get(getSizeTy(ctx.builder.getContext()), n)); - return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, vptr, Align(sizeof(void*)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + return ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, vptr, Align(sizeof(void*)))); } // --- generating various error checks --- @@ -1596,7 +1592,8 @@ static Value *emit_isconcrete(jl_codectx_t &ctx, Value *typ) { Value *isconcrete; isconcrete = ctx.builder.CreateConstInBoundsGEP1_32(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, decay_derived(ctx, typ), getInt8PtrTy(ctx.builder.getContext())), offsetof(jl_datatype_t, hash) + sizeof(((jl_datatype_t*)nullptr)->hash)); - isconcrete = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), isconcrete, Align(1))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + isconcrete = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), isconcrete, Align(1))); isconcrete = ctx.builder.CreateLShr(isconcrete, 1); isconcrete = ctx.builder.CreateTrunc(isconcrete, getInt1Ty(ctx.builder.getContext())); return isconcrete; @@ -1774,17 +1771,16 @@ static jl_cgval_t typed_load(jl_codectx_t &ctx, Value *ptr, Value *idx_0based, j else if (!alignment) alignment = julia_alignment(jltype); if (intcast && Order == AtomicOrdering::NotAtomic) { - emit_memcpy(ctx, intcast, ctx.tbaa().tbaa_stack, data, tbaa, nb, alignment); + emit_memcpy(ctx, intcast, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), data, jl_aliasinfo_t::fromTBAA(ctx, tbaa), nb, alignment); } else { LoadInst *load = ctx.builder.CreateAlignedLoad(elty, data, Align(alignment), false); load->setOrdering(Order); - if (aliasscope) - load->setMetadata("alias.scope", aliasscope); if (isboxed) maybe_mark_load_dereferenceable(load, true, jltype); - if (tbaa) - tbaa_decorate(tbaa, load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.scope = MDNode::concatenate(aliasscope, ai.scope); + ai.decorateInst(load); instr = load; if (elty != realelty) instr = ctx.builder.CreateTrunc(instr, realelty); @@ -1908,20 +1904,18 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, auto *load = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment)); if (isboxed) load->setOrdering(AtomicOrdering::Unordered); - if (aliasscope) - load->setMetadata("noalias", aliasscope); - if (tbaa) - tbaa_decorate(tbaa, load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); + ai.decorateInst(load); assert(realelty == elty); instr = load; } if (r) { StoreInst *store = ctx.builder.CreateAlignedStore(r, ptr, Align(alignment)); store->setOrdering(Order == AtomicOrdering::NotAtomic && isboxed ? AtomicOrdering::Release : Order); - if (aliasscope) - store->setMetadata("noalias", aliasscope); - if (tbaa) - tbaa_decorate(tbaa, store); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); + ai.decorateInst(store); } else { assert(Order == AtomicOrdering::NotAtomic && !isboxed && rhs.typ == jltype); @@ -1938,10 +1932,9 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, auto *store = ctx.builder.CreateAtomicRMW(AtomicRMWInst::Xchg, ptr, r, Order); store->setAlignment(Align(alignment)); #endif - if (aliasscope) - store->setMetadata("noalias", aliasscope); - if (tbaa) - tbaa_decorate(tbaa, store); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); + ai.decorateInst(store); instr = store; } else { @@ -1964,11 +1957,9 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, ctx.builder.SetInsertPoint(SkipBB); LoadInst *load = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment)); load->setOrdering(FailOrder == AtomicOrdering::NotAtomic && isboxed ? AtomicOrdering::Monotonic : FailOrder); - if (aliasscope) - load->setMetadata("noalias", aliasscope); - if (tbaa) - tbaa_decorate(tbaa, load); - instr = load; + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); + instr = ai.decorateInst(load); ctx.builder.CreateBr(DoneBB); ctx.builder.SetInsertPoint(DoneBB); Succ = ctx.builder.CreatePHI(getInt1Ty(ctx.builder.getContext()), 2); @@ -1995,11 +1986,9 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, else { // swap or modify LoadInst *Current = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment)); Current->setOrdering(Order == AtomicOrdering::NotAtomic && !isboxed ? Order : AtomicOrdering::Monotonic); - if (aliasscope) - Current->setMetadata("noalias", aliasscope); - if (tbaa) - tbaa_decorate(tbaa, Current); - Compare = Current; + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); + Compare = ai.decorateInst(Current); needloop = !isswapfield || Order != AtomicOrdering::NotAtomic; } BasicBlock *BB = NULL; @@ -2051,12 +2040,11 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, // modifyfield or replacefield assert(elty == realelty && !intcast); auto *load = ctx.builder.CreateAlignedLoad(elty, ptr, Align(alignment)); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); + ai.decorateInst(load); if (isboxed) load->setOrdering(AtomicOrdering::Monotonic); - if (aliasscope) - load->setMetadata("noalias", aliasscope); - if (tbaa) - tbaa_decorate(tbaa, load); Value *first_ptr = nullptr; if (maybe_null_if_boxed && !ismodifyfield) first_ptr = isboxed ? load : extract_first_ptr(ctx, load); @@ -2072,10 +2060,9 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, ctx.builder.SetInsertPoint(XchgBB); if (r) { auto *store = ctx.builder.CreateAlignedStore(r, ptr, Align(alignment)); - if (aliasscope) - store->setMetadata("noalias", aliasscope); - if (tbaa) - tbaa_decorate(tbaa, store); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); + ai.decorateInst(store); } else { assert(!isboxed && rhs.typ == jltype); @@ -2100,10 +2087,9 @@ static jl_cgval_t typed_store(jl_codectx_t &ctx, auto *store = ctx.builder.CreateAtomicCmpXchg(ptr, Compare, r, Order, FailOrder); store->setAlignment(Align(alignment)); #endif - if (aliasscope) - store->setMetadata("noalias", aliasscope); - if (tbaa) - tbaa_decorate(tbaa, store); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.noalias = MDNode::concatenate(aliasscope, ai.noalias); + ai.decorateInst(store); instr = ctx.builder.Insert(ExtractValueInst::Create(store, 0)); Success = ctx.builder.Insert(ExtractValueInst::Create(store, 1)); Done = Success; @@ -2329,7 +2315,8 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx, idx0()); LoadInst *fld = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, fldptr, Align(sizeof(void*))); fld->setOrdering(AtomicOrdering::Unordered); - tbaa_decorate(strct.tbaa, fld); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, strct.tbaa); + ai.decorateInst(fld); maybe_mark_load_dereferenceable(fld, maybe_null, minimum_field_size, minimum_align); if (maybe_null) null_pointer_check(ctx, fld); @@ -2368,7 +2355,8 @@ static jl_cgval_t emit_unionload(jl_codectx_t &ctx, Value *addr, Value *ptindex, unsigned union_max, MDNode *tbaa_ptindex) { ++EmittedUnionLoads; - Instruction *tindex0 = tbaa_decorate(tbaa_ptindex, ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), ptindex, Align(1))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa_ptindex); + Instruction *tindex0 = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), ptindex, Align(1))); tindex0->setMetadata(LLVMContext::MD_range, MDNode::get(ctx.builder.getContext(), { ConstantAsMetadata::get(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0)), ConstantAsMetadata::get(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), union_max)) })); @@ -2379,7 +2367,8 @@ static jl_cgval_t emit_unionload(jl_codectx_t &ctx, Value *addr, Value *ptindex, AllocaInst *lv = emit_static_alloca(ctx, AT); if (al > 1) lv->setAlignment(Align(al)); - emit_memcpy(ctx, lv, tbaa, addr, tbaa, fsz, al); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + emit_memcpy(ctx, lv, ai, addr, ai, fsz, al); addr = lv; } return mark_julia_slot(fsz > 0 ? addr : nullptr, jfty, tindex, tbaa); @@ -2449,7 +2438,8 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st LoadInst *Load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, maybe_bitcast(ctx, addr, ctx.types().T_pprjlvalue), Align(sizeof(void*))); Load->setOrdering(order <= jl_memory_order_notatomic ? AtomicOrdering::Unordered : get_llvm_atomic_order(order)); maybe_mark_load_dereferenceable(Load, maybe_null, jl_field_type(jt, idx)); - Value *fldv = tbaa_decorate(tbaa, Load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + Value *fldv = ai.decorateInst(Load); if (maybe_null) null_pointer_check(ctx, fldv, nullcheck); return mark_julia_type(ctx, fldv, true, jfty); @@ -2691,7 +2681,8 @@ static Value *emit_arraylen_prim(jl_codectx_t &ctx, const jl_cgval_t &tinfo) MDBuilder MDB(ctx.builder.getContext()); auto rng = MDB.createRange(Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), arraytype_maxsize(tinfo.typ))); len->setMetadata(LLVMContext::MD_range, rng); - return tbaa_decorate(tbaa, len); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + return ai.decorateInst(len); } static Value *emit_arraylen(jl_codectx_t &ctx, const jl_cgval_t &tinfo) @@ -2762,7 +2753,8 @@ static Value *emit_arrayflags(jl_codectx_t &ctx, const jl_cgval_t &tinfo) ctx.types().T_jlarray, emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray), arrayflag_field); - return tbaa_decorate(ctx.tbaa().tbaa_arrayflags, ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_arrayflags); + return ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t)))); } static Value *emit_arrayndims(jl_codectx_t &ctx, const jl_cgval_t &ary) @@ -2783,7 +2775,8 @@ static Value *emit_arrayelsize(jl_codectx_t &ctx, const jl_cgval_t &tinfo) Value *addr = ctx.builder.CreateStructGEP(ctx.types().T_jlarray, emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray), elsize_field); - return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + return ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt16Ty(ctx.builder.getContext()), addr, Align(sizeof(int16_t)))); } static Value *emit_arrayoffset(jl_codectx_t &ctx, const jl_cgval_t &tinfo, int nd) @@ -2798,7 +2791,8 @@ static Value *emit_arrayoffset(jl_codectx_t &ctx, const jl_cgval_t &tinfo, int n ctx.types().T_jlarray, emit_bitcast(ctx, decay_derived(ctx, t), ctx.types().T_pjlarray), offset_field); - return tbaa_decorate(ctx.tbaa().tbaa_arrayoffset, ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), addr, Align(sizeof(int32_t)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_arrayoffset); + return ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), addr, Align(sizeof(int32_t)))); } // Returns the size of the array represented by `tinfo` for the given dimension `dim` if @@ -2911,8 +2905,9 @@ static Value *emit_allocobj(jl_codectx_t &ctx, size_t static_size, Value *jt); static void init_bits_value(jl_codectx_t &ctx, Value *newv, Value *v, MDNode *tbaa, unsigned alignment = sizeof(void*)) // min alignment in julia's gc is pointer-aligned { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); // newv should already be tagged - tbaa_decorate(tbaa, ctx.builder.CreateAlignedStore(v, emit_bitcast(ctx, newv, + ai.decorateInst(ctx.builder.CreateAlignedStore(v, emit_bitcast(ctx, newv, PointerType::get(v->getType(), 0)), Align(alignment))); } @@ -2920,7 +2915,7 @@ static void init_bits_cgval(jl_codectx_t &ctx, Value *newv, const jl_cgval_t& v, { // newv should already be tagged if (v.ispointer()) { - emit_memcpy(ctx, newv, tbaa, v, jl_datatype_size(v.typ), sizeof(void*)); + emit_memcpy(ctx, newv, jl_aliasinfo_t::fromTBAA(ctx, tbaa), v, jl_datatype_size(v.typ), sizeof(void*)); } else { init_bits_value(ctx, newv, v.V, tbaa); @@ -3028,7 +3023,8 @@ static Value *load_i8box(jl_codectx_t &ctx, Value *v, jl_datatype_t *ty) GlobalVariable *gv = prepare_global_in(jl_Module, jvar); Value *idx[] = {ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0), ctx.builder.CreateZExt(v, getInt32Ty(ctx.builder.getContext()))}; auto slot = ctx.builder.CreateInBoundsGEP(gv->getValueType(), gv, idx); - return tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + return ai.decorateInst(maybe_mark_load_dereferenceable( ctx.builder.CreateAlignedLoad(ctx.types().T_pjlvalue, slot, Align(sizeof(void*))), false, (jl_value_t*)ty)); } @@ -3383,7 +3379,8 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con // select copy dest -> dest to simulate an undef value / conditional copy // if (skip) src_ptr = ctx.builder.CreateSelect(skip, dest, src_ptr); auto f = [&] { - (void)emit_memcpy(ctx, dest, tbaa_dst, src_ptr, src.tbaa, nb, alignment, isVolatile); + (void)emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), src_ptr, + jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), nb, alignment, isVolatile); return nullptr; }; if (skip) @@ -3419,8 +3416,8 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con ctx.builder.CreateUnreachable(); return; } else { - emit_memcpy(ctx, dest, tbaa_dst, src_ptr, - src.tbaa, nb, alignment, isVolatile); + emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), src_ptr, + jl_aliasinfo_t::fromTBAA(ctx, src.tbaa), nb, alignment, isVolatile); } } ctx.builder.CreateBr(postBB); @@ -3445,7 +3442,7 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con auto f = [&] { Value *datatype = emit_typeof_boxed(ctx, src); Value *copy_bytes = emit_datatype_size(ctx, datatype); - emit_memcpy(ctx, dest, tbaa_dst, src, copy_bytes, /*TODO: min-align*/1, isVolatile); + emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dst), src, copy_bytes, /*TODO: min-align*/1, isVolatile); return nullptr; }; if (skip) @@ -3633,7 +3630,8 @@ static jl_cgval_t emit_setfield(jl_codectx_t &ctx, } Value *tindex = compute_tindex_unboxed(ctx, rhs_union, jfty); tindex = ctx.builder.CreateNUWSub(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 1)); - tbaa_decorate(ctx.tbaa().tbaa_unionselbyte, ctx.builder.CreateAlignedStore(tindex, ptindex, Align(1))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_unionselbyte); + ai.decorateInst(ctx.builder.CreateAlignedStore(tindex, ptindex, Align(1))); // copy data if (!rhs.isghost) { emit_unionmove(ctx, addr, strct.tbaa, rhs, nullptr); @@ -3707,7 +3705,7 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg else { strct = emit_static_alloca(ctx, lt); if (tracked.count) - undef_derived_strct(ctx.builder, strct, sty, ctx.tbaa().tbaa_stack); + undef_derived_strct(ctx, strct, sty, ctx.tbaa().tbaa_stack); } for (unsigned i = 0; i < na; i++) { @@ -3761,10 +3759,12 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg Value *fval = NULL; if (jl_field_isptr(sty, i)) { fval = boxed(ctx, fval_info, field_promotable); - if (!init_as_value) - cast(tbaa_decorate(ctx.tbaa().tbaa_stack, - ctx.builder.CreateAlignedStore(fval, dest, Align(jl_field_align(sty, i))))) - ->setOrdering(AtomicOrdering::Unordered); + if (!init_as_value) { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack); + StoreInst *SI = cast(ai.decorateInst( + ctx.builder.CreateAlignedStore(fval, dest, Align(jl_field_align(sty, i))))); + SI->setOrdering(AtomicOrdering::Unordered); + } } else if (jl_is_uniontype(jtype)) { // compute tindex from rhs @@ -3792,7 +3792,8 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg unsigned i = 0; for (; i < fsz / al; i++) { Value *fldp = ctx.builder.CreateConstInBoundsGEP1_32(ET, lv, i); - Value *fldv = tbaa_decorate(ctx.tbaa().tbaa_stack, ctx.builder.CreateAlignedLoad(ET, fldp, Align(al))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack); + Value *fldv = ai.decorateInst(ctx.builder.CreateAlignedLoad(ET, fldp, Align(al))); strct = ctx.builder.CreateInsertValue(strct, fldv, makeArrayRef(llvm_idx + i)); } // emit remaining bytes up to tindex @@ -3801,7 +3802,8 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg staddr = ctx.builder.CreateBitCast(staddr, getInt8PtrTy(ctx.builder.getContext())); for (; i < ptindex - llvm_idx; i++) { Value *fldp = ctx.builder.CreateConstInBoundsGEP1_32(getInt8Ty(ctx.builder.getContext()), staddr, i); - Value *fldv = tbaa_decorate(ctx.tbaa().tbaa_stack, ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), fldp, Align(1))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack); + Value *fldv = ai.decorateInst(ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), fldp, Align(1))); strct = ctx.builder.CreateInsertValue(strct, fldv, makeArrayRef(llvm_idx + i)); } } @@ -3813,7 +3815,8 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg } else { Value *ptindex = emit_struct_gep(ctx, lt, strct, offs + fsz); - tbaa_decorate(ctx.tbaa().tbaa_unionselbyte, ctx.builder.CreateAlignedStore(tindex, ptindex, Align(1))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_unionselbyte); + ai.decorateInst(ctx.builder.CreateAlignedStore(tindex, ptindex, Align(1))); if (!rhs_union.isghost) emit_unionmove(ctx, dest, ctx.tbaa().tbaa_stack, fval_info, nullptr); } @@ -3850,11 +3853,13 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg unsigned llvm_idx = convert_struct_offset(ctx, cast(lt), offs + fsz); if (init_as_value) strct = ctx.builder.CreateInsertValue(strct, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0), makeArrayRef(llvm_idx)); - else - tbaa_decorate(ctx.tbaa().tbaa_unionselbyte, ctx.builder.CreateAlignedStore( + else { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_unionselbyte); + ai.decorateInst(ctx.builder.CreateAlignedStore( ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0), ctx.builder.CreateConstInBoundsGEP2_32(lt, strct, 0, llvm_idx), Align(1))); + } } } if (type_is_ghost(lt)) @@ -3874,10 +3879,11 @@ static jl_cgval_t emit_new_struct(jl_codectx_t &ctx, jl_value_t *ty, size_t narg literal_pointer_val(ctx, (jl_value_t*)ty)); jl_cgval_t strctinfo = mark_julia_type(ctx, strct, true, ty); strct = decay_derived(ctx, strct); - undef_derived_strct(ctx.builder, strct, sty, strctinfo.tbaa); + undef_derived_strct(ctx, strct, sty, strctinfo.tbaa); for (size_t i = nargs; i < nf; i++) { if (!jl_field_isptr(sty, i) && jl_is_uniontype(jl_field_type(sty, i))) { - tbaa_decorate(ctx.tbaa().tbaa_unionselbyte, ctx.builder.CreateAlignedStore( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_unionselbyte); + ai.decorateInst(ctx.builder.CreateAlignedStore( ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0), ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, strct, getInt8PtrTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), jl_field_offset(sty, i) + jl_field_size(sty, i) - 1)), diff --git a/src/codegen.cpp b/src/codegen.cpp index 5885405179c4b..4fb5c7bc0cdee 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1705,7 +1705,6 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, const static Value *literal_pointer_val(jl_codectx_t &ctx, jl_value_t *p); static GlobalVariable *prepare_global_in(Module *M, GlobalVariable *G); -Instruction *tbaa_decorate(MDNode *md, Instruction *inst); static GlobalVariable *prepare_global_in(Module *M, JuliaVariable *G) { @@ -1774,20 +1773,21 @@ static AllocaInst *emit_static_alloca(jl_codectx_t &ctx, Type *lty) return new AllocaInst(lty, ctx.topalloca->getModule()->getDataLayout().getAllocaAddrSpace(), "", /*InsertBefore=*/ctx.topalloca); } -static void undef_derived_strct(IRBuilder<> &irbuilder, Value *ptr, jl_datatype_t *sty, MDNode *tbaa) +static void undef_derived_strct(jl_codectx_t &ctx, Value *ptr, jl_datatype_t *sty, MDNode *tbaa) { assert(ptr->getType()->getPointerAddressSpace() != AddressSpace::Tracked); size_t first_offset = sty->layout->nfields ? jl_field_offset(sty, 0) : 0; if (first_offset != 0) - irbuilder.CreateMemSet(ptr, ConstantInt::get(getInt8Ty(irbuilder.getContext()), 0), first_offset, MaybeAlign(0)); + ctx.builder.CreateMemSet(ptr, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0), first_offset, MaybeAlign(0)); size_t i, np = sty->layout->npointers; if (np == 0) return; - auto T_prjlvalue = JuliaType::get_prjlvalue_ty(irbuilder.getContext()); - ptr = irbuilder.CreateBitCast(ptr, T_prjlvalue->getPointerTo(ptr->getType()->getPointerAddressSpace())); + auto T_prjlvalue = JuliaType::get_prjlvalue_ty(ctx.builder.getContext()); + ptr = ctx.builder.CreateBitCast(ptr, T_prjlvalue->getPointerTo(ptr->getType()->getPointerAddressSpace())); for (i = 0; i < np; i++) { - Value *fld = irbuilder.CreateConstInBoundsGEP1_32(T_prjlvalue, ptr, jl_ptr_offset(sty, i)); - tbaa_decorate(tbaa, irbuilder.CreateStore(Constant::getNullValue(T_prjlvalue), fld)); + Value *fld = ctx.builder.CreateConstInBoundsGEP1_32(T_prjlvalue, ptr, jl_ptr_offset(sty, i)); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.decorateInst(ctx.builder.CreateStore(Constant::getNullValue(T_prjlvalue), fld)); } } @@ -2777,7 +2777,8 @@ static jl_cgval_t emit_globalref(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t * } LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*))); v->setOrdering(order); - tbaa_decorate(ctx.tbaa().tbaa_binding, v); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_binding); + ai.decorateInst(v); return mark_julia_type(ctx, v, true, bnd->ty); } // todo: use type info to avoid undef check @@ -2790,7 +2791,8 @@ static void emit_globalset(jl_codectx_t &ctx, jl_binding_t *bnd, Value *bp, cons if (bnd && !bnd->constp && bnd->ty && jl_subtype(rval_info.typ, bnd->ty)) { StoreInst *v = ctx.builder.CreateAlignedStore(rval, julia_binding_pvalue(ctx, bp), Align(sizeof(void*))); v->setOrdering(Order); - tbaa_decorate(ctx.tbaa().tbaa_binding, v); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_binding); + ai.decorateInst(v); emit_write_barrier_binding(ctx, bp, rval); } else { @@ -2929,18 +2931,22 @@ static Value *emit_bits_compare(jl_codectx_t &ctx, jl_cgval_t arg1, jl_cgval_t a ctx.builder.CreateBitCast(varg2, getInt8PtrTy(ctx.builder.getContext())), ConstantInt::get(getSizeTy(ctx.builder.getContext()), sz) }, ArrayRef(&OpBundle, nroots ? 1 : 0)); - MDNode *tbaa = nullptr; - if (!arg1.tbaa) { - tbaa = arg2.tbaa; - } - else if (!arg2.tbaa) { - tbaa = arg1.tbaa; - } - else { - tbaa = MDNode::getMostGenericTBAA(arg1.tbaa, arg2.tbaa); + + if (arg1.tbaa || arg2.tbaa) { + jl_aliasinfo_t ai; + if (!arg1.tbaa) { + ai = jl_aliasinfo_t::fromTBAA(ctx, arg2.tbaa); + } + else if (!arg2.tbaa) { + ai = jl_aliasinfo_t::fromTBAA(ctx, arg1.tbaa); + } + else { + jl_aliasinfo_t arg1_ai = jl_aliasinfo_t::fromTBAA(ctx, arg1.tbaa); + jl_aliasinfo_t arg2_ai = jl_aliasinfo_t::fromTBAA(ctx, arg2.tbaa); + ai = arg1_ai.merge(arg2_ai); + } + ai.decorateInst(answer); } - if (tbaa) - tbaa_decorate(tbaa, answer); return ctx.builder.CreateICmpEQ(answer, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0)); } else { @@ -3495,7 +3501,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, emit_bitcast(ctx, decay_derived(ctx, aryv), ctx.types().T_pprjlvalue), jl_array_data_owner_offset(nd) / sizeof(jl_value_t*)), Align(sizeof(void*))); - tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable(own_ptr, false, (jl_value_t*)jl_array_any_type)); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + ai.decorateInst(maybe_mark_load_dereferenceable(own_ptr, false, (jl_value_t*)jl_array_any_type)); } else { own_ptr = ctx.builder.CreateCall( @@ -3532,7 +3539,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, ptindex = emit_bitcast(ctx, ptindex, getInt8PtrTy(ctx.builder.getContext())); ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, offset); ptindex = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), ptindex, idx); - tbaa_decorate(ctx.tbaa().tbaa_arrayselbyte, ctx.builder.CreateStore(tindex, ptindex)); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_arrayselbyte); + ai.decorateInst(ctx.builder.CreateStore(tindex, ptindex)); if (elsz > 0 && (!jl_is_datatype(val.typ) || jl_datatype_size(val.typ) > 0)) { // copy data (if any) emit_unionmove(ctx, data, ctx.tbaa().tbaa_arraybuf, val, nullptr); @@ -3630,7 +3638,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), ctx.nReqArgs)); Instruction *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, ctx.argArray, idx), Align(sizeof(void*))); // if we know the result type of this load, we will mark that information here too - tbaa_decorate(ctx.tbaa().tbaa_value, maybe_mark_load_dereferenceable(v, false, rt)); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_value); + ai.decorateInst(maybe_mark_load_dereferenceable(v, false, rt)); *ret = mark_julia_type(ctx, v, /*boxed*/ true, rt); return true; } @@ -3793,7 +3802,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, emit_typecheck(ctx, argv[3], (jl_value_t*)jl_bool_type, "fieldtype"); emit_bounds_check(ctx, typ, (jl_value_t*)jl_datatype_type, idx, types_len, boundscheck); Value *fieldtyp_p = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, decay_derived(ctx, emit_bitcast(ctx, types_svec, ctx.types().T_pprjlvalue)), idx); - Value *fieldtyp = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, fieldtyp_p, Align(sizeof(void*)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + Value *fieldtyp = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, fieldtyp_p, Align(sizeof(void*)))); *ret = mark_julia_type(ctx, fieldtyp, true, (jl_value_t*)jl_type_type); return true; } @@ -3818,7 +3828,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, } // String and SimpleVector's length fields have the same layout auto ptr = emit_bitcast(ctx, boxed(ctx, obj), getSizePtrTy(ctx.builder.getContext())); - Value *len = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ptr, Align(sizeof(size_t)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + Value *len = ai.decorateInst(ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), ptr, Align(sizeof(size_t)))); MDBuilder MDB(ctx.builder.getContext()); if (sty == jl_simplevector_type) { auto rng = MDB.createRange( @@ -3949,7 +3960,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, Value *addr = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, ptr, offs); // emit this using the same type as emit_getfield_knownidx // so that LLVM may be able to load-load forward them and fold the result - fldv = tbaa_decorate(tbaa, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, addr, Align(sizeof(size_t)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + fldv = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, addr, Align(sizeof(size_t)))); cast(fldv)->setOrdering(order <= jl_memory_order_notatomic ? AtomicOrdering::Unordered : get_llvm_atomic_order(order)); } else { @@ -4439,8 +4451,10 @@ static jl_cgval_t emit_checked_var(jl_codectx_t &ctx, Value *bp, jl_sym_t *name, if (isvol) v->setVolatile(true); v->setOrdering(AtomicOrdering::Unordered); - if (tbaa) - tbaa_decorate(tbaa, v); + if (tbaa) { + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.decorateInst(v); + } undef_var_error_ifnot(ctx, ctx.builder.CreateIsNotNull(v), name); return mark_julia_type(ctx, v, true, jl_any_type); } @@ -4458,7 +4472,8 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i) ctx.types().T_prjlvalue, ctx.spvals_ptr, i + sizeof(jl_svec_t) / sizeof(jl_value_t*)); - Value *sp = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + Value *sp = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)))); Value *isnull = ctx.builder.CreateICmpNE(emit_typeof(ctx, sp, false), track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_tvar_type))); jl_unionall_t *sparam = (jl_unionall_t*)ctx.linfo->def.method->sig; @@ -4513,7 +4528,8 @@ static jl_cgval_t emit_isdefined(jl_codectx_t &ctx, jl_value_t *sym) ctx.types().T_prjlvalue, ctx.spvals_ptr, i + sizeof(jl_svec_t) / sizeof(jl_value_t*)); - Value *sp = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + Value *sp = ai.decorateInst(ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*)))); isnull = ctx.builder.CreateICmpNE(emit_typeof(ctx, sp, false), track_pjlvalue(ctx, literal_pointer_val(ctx, (jl_value_t*)jl_tvar_type))); } @@ -4536,7 +4552,8 @@ static jl_cgval_t emit_isdefined(jl_codectx_t &ctx, jl_value_t *sym) Value *bp = julia_binding_gv(ctx, bnd); bp = julia_binding_pvalue(ctx, bp); LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*))); - tbaa_decorate(ctx.tbaa().tbaa_binding, v); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_binding); + ai.decorateInst(v); v->setOrdering(AtomicOrdering::Unordered); isnull = ctx.builder.CreateICmpNE(v, Constant::getNullValue(ctx.types().T_prjlvalue)); } @@ -4577,7 +4594,7 @@ static jl_cgval_t emit_varinfo(jl_codectx_t &ctx, jl_varinfo_t &vi, jl_sym_t *va else { const DataLayout &DL = jl_Module->getDataLayout(); uint64_t sz = DL.getTypeStoreSize(T); - emit_memcpy(ctx, ssaslot, ctx.tbaa().tbaa_stack, vi.value, sz, ssaslot->getAlign().value()); + emit_memcpy(ctx, ssaslot, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), vi.value, sz, ssaslot->getAlign().value()); } Value *tindex = NULL; if (vi.pTIndex) @@ -4667,7 +4684,8 @@ static void emit_vi_assignment_unboxed(jl_codectx_t &ctx, jl_varinfo_t &vi, Valu Type *dest_ty = store_ty->getPointerTo(); if (dest_ty != dest->getType()) dest = emit_bitcast(ctx, dest, dest_ty); - tbaa_decorate(ctx.tbaa().tbaa_stack, ctx.builder.CreateStore( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack); + ai.decorateInst(ctx.builder.CreateStore( emit_unbox(ctx, store_ty, rval_info, rval_info.typ), dest, vi.isVolatile)); @@ -4683,7 +4701,7 @@ static void emit_vi_assignment_unboxed(jl_codectx_t &ctx, jl_varinfo_t &vi, Valu // This check should probably mostly catch the relevant situations. if (vi.value.V != rval_info.V) { Value *copy_bytes = ConstantInt::get(getInt32Ty(ctx.builder.getContext()), jl_datatype_size(vi.value.typ)); - emit_memcpy(ctx, vi.value.V, ctx.tbaa().tbaa_stack, rval_info, copy_bytes, + emit_memcpy(ctx, vi.value.V, jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_stack), rval_info, copy_bytes, julia_alignment(rval_info.typ), vi.isVolatile); } } @@ -5397,11 +5415,9 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_ std::tie(F, specF) = get_oc_function(ctx, (jl_method_t*)source.constant, env_t, argt_typ, ub.constant); if (F) { jl_cgval_t jlcall_ptr = mark_julia_type(ctx, F, false, jl_voidpointer_type); - jl_cgval_t world_age = mark_julia_type(ctx, - tbaa_decorate(ctx.tbaa().tbaa_gcframe, - ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), get_last_age_field(ctx), Align(sizeof(size_t)))), - false, - jl_long_type); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe); + Instruction *I = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), get_last_age_field(ctx), Align(sizeof(size_t))); + jl_cgval_t world_age = mark_julia_type(ctx, ai.decorateInst(I), false, jl_long_type); jl_cgval_t fptr; if (specF) fptr = mark_julia_type(ctx, specF, false, jl_voidpointer_type); @@ -5690,7 +5706,8 @@ static void emit_cfunc_invalidate( root1 = ctx.builder.CreateConstInBoundsGEP2_32(get_returnroots_type(ctx, return_roots), root1, 0, 0); ctx.builder.CreateStore(gf_ret, root1); } - emit_memcpy(ctx, &*gf_thunk->arg_begin(), nullptr, gf_ret, nullptr, jl_datatype_size(rettype), julia_alignment(rettype)); + emit_memcpy(ctx, &*gf_thunk->arg_begin(), jl_aliasinfo_t::fromTBAA(ctx, nullptr), gf_ret, + jl_aliasinfo_t::fromTBAA(ctx, nullptr), jl_datatype_size(rettype), julia_alignment(rettype)); ctx.builder.CreateRetVoid(); break; } @@ -5857,7 +5874,8 @@ static Function* gen_cfun_wrapper( allocate_gc_frame(ctx, b0, true); Value *world_age_field = get_last_age_field(ctx); - Value *last_age = tbaa_decorate(ctx.tbaa().tbaa_gcframe, + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe); + Value *last_age = ai.decorateInst( ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), world_age_field, Align(sizeof(size_t)))); Value *world_v = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), @@ -6413,13 +6431,14 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con literal_pointer_val(ctx, (jl_value_t*)output_type)); Value *derived_strct = emit_bitcast(ctx, decay_derived(ctx, strct), getSizePtrTy(ctx.builder.getContext())); MDNode *tbaa = best_tbaa(ctx.tbaa(), output_type); - tbaa_decorate(tbaa, ctx.builder.CreateStore(F, derived_strct)); - tbaa_decorate(tbaa, ctx.builder.CreateStore( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.decorateInst(ctx.builder.CreateStore(F, derived_strct)); + ai.decorateInst(ctx.builder.CreateStore( ctx.builder.CreatePtrToInt(literal_pointer_val(ctx, fexpr_rt.constant), getSizeTy(ctx.builder.getContext())), ctx.builder.CreateConstInBoundsGEP1_32(getSizeTy(ctx.builder.getContext()), derived_strct, 1))); - tbaa_decorate(tbaa, ctx.builder.CreateStore(Constant::getNullValue(getSizeTy(ctx.builder.getContext())), + ai.decorateInst(ctx.builder.CreateStore(Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ctx.builder.CreateConstInBoundsGEP1_32(getSizeTy(ctx.builder.getContext()), derived_strct, 2))); - tbaa_decorate(tbaa, ctx.builder.CreateStore(Constant::getNullValue(getSizeTy(ctx.builder.getContext())), + ai.decorateInst(ctx.builder.CreateStore(Constant::getNullValue(getSizeTy(ctx.builder.getContext())), ctx.builder.CreateConstInBoundsGEP1_32(getSizeTy(ctx.builder.getContext()), derived_strct, 3))); F = strct; } @@ -6553,7 +6572,8 @@ static Function *gen_invoke_wrapper(jl_method_instance_t *lam, jl_value_t *jlret } else { Value *argPtr = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, argArray, i - 1); - theArg = tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + theArg = ai.decorateInst(maybe_mark_load_dereferenceable( ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, argPtr, Align(sizeof(void*))), false, ty)); @@ -7196,7 +7216,8 @@ static jl_llvm_functions_t Value *last_age = NULL; Value *world_age_field = get_last_age_field(ctx); if (toplevel || ctx.is_opaque_closure) { - last_age = tbaa_decorate(ctx.tbaa().tbaa_gcframe, ctx.builder.CreateAlignedLoad( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe); + last_age = ai.decorateInst(ctx.builder.CreateAlignedLoad( getSizeTy(ctx.builder.getContext()), world_age_field, Align(sizeof(size_t)))); } @@ -7437,7 +7458,8 @@ static jl_llvm_functions_t } else { Value *argPtr = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, argArray, i - 1); - Value *load = tbaa_decorate(ctx.tbaa().tbaa_const, maybe_mark_load_dereferenceable( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const); + Value *load = ai.decorateInst(maybe_mark_load_dereferenceable( 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); @@ -7921,8 +7943,8 @@ static jl_llvm_functions_t } if (returninfo.cc == jl_returninfo_t::SRet) { assert(jl_is_concrete_type(jlrettype)); - emit_memcpy(ctx, sret, nullptr, retvalinfo, jl_datatype_size(jlrettype), - julia_alignment(jlrettype)); + emit_memcpy(ctx, sret, jl_aliasinfo_t::fromTBAA(ctx, nullptr), retvalinfo, + jl_datatype_size(jlrettype), julia_alignment(jlrettype)); } else { // must be jl_returninfo_t::Union emit_unionmove(ctx, sret, nullptr, retvalinfo, /*skip*/isboxed_union); diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 38d923cb5a99e..b822907e63524 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -397,7 +397,8 @@ static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_va Value *p = x.constant ? literal_pointer_val(ctx, x.constant) : x.V; if (jt == (jl_value_t*)jl_bool_type || to->isIntegerTy(1)) { - Instruction *unbox_load = tbaa_decorate(x.tbaa, ctx.builder.CreateLoad(getInt8Ty(ctx.builder.getContext()), maybe_bitcast(ctx, p, getInt8PtrTy(ctx.builder.getContext())))); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, x.tbaa); + Instruction *unbox_load = ai.decorateInst(ctx.builder.CreateLoad(getInt8Ty(ctx.builder.getContext()), maybe_bitcast(ctx, p, getInt8PtrTy(ctx.builder.getContext())))); if (jt == (jl_value_t*)jl_bool_type) unbox_load->setMetadata(LLVMContext::MD_range, MDNode::get(ctx.builder.getContext(), { ConstantAsMetadata::get(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0)), @@ -425,12 +426,14 @@ static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_va (to->isFloatingPointTy() || to->isIntegerTy() || to->isPointerTy()) && DL.getTypeSizeInBits(AllocType) == DL.getTypeSizeInBits(to)) { Instruction *load = ctx.builder.CreateAlignedLoad(AllocType, p, Align(alignment)); - return emit_unboxed_coercion(ctx, to, tbaa_decorate(x.tbaa, load)); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, x.tbaa); + return emit_unboxed_coercion(ctx, to, ai.decorateInst(load)); } } p = maybe_bitcast(ctx, p, ptype); Instruction *load = ctx.builder.CreateAlignedLoad(to, p, Align(alignment)); - return tbaa_decorate(x.tbaa, load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, x.tbaa); + return ai.decorateInst(load); } // emit code to store a raw value into a destination @@ -459,12 +462,13 @@ static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value *dest dest = emit_bitcast(ctx, dest, dest_ty); StoreInst *store = ctx.builder.CreateAlignedStore(unboxed, dest, Align(alignment)); store->setVolatile(isVolatile); - tbaa_decorate(tbaa_dest, store); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa_dest); + ai.decorateInst(store); return; } Value *src = data_pointer(ctx, x); - emit_memcpy(ctx, dest, tbaa_dest, src, x.tbaa, jl_datatype_size(x.typ), alignment, isVolatile); + emit_memcpy(ctx, dest, jl_aliasinfo_t::fromTBAA(ctx, tbaa_dest), src, jl_aliasinfo_t::fromTBAA(ctx, x.tbaa), jl_datatype_size(x.typ), alignment, isVolatile); } static jl_datatype_t *staticeval_bitstype(const jl_cgval_t &targ) @@ -546,7 +550,8 @@ static jl_cgval_t generic_bitcast(jl_codectx_t &ctx, const jl_cgval_t *argv) if (isboxed) vxt = llvmt; auto storage_type = vxt->isIntegerTy(1) ? getInt8Ty(ctx.builder.getContext()) : vxt; - vx = tbaa_decorate(v.tbaa, ctx.builder.CreateLoad( + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, v.tbaa); + vx = ai.decorateInst(ctx.builder.CreateLoad( storage_type, emit_bitcast(ctx, data_pointer(ctx, v), storage_type->getPointerTo()))); @@ -662,7 +667,8 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) if (ety == (jl_value_t*)jl_any_type) { Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ); LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, thePtr, im1), Align(align_nb)); - tbaa_decorate(ctx.tbaa().tbaa_data, load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_data); + ai.decorateInst(load); return mark_julia_type(ctx, load, true, ety); } else if (!jl_isbits(ety)) { @@ -675,7 +681,7 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) Value *thePtr = emit_unbox(ctx, getInt8PtrTy(ctx.builder.getContext()), e, e.typ); thePtr = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, thePtr, getInt8PtrTy(ctx.builder.getContext())), im1); MDNode *tbaa = best_tbaa(ctx.tbaa(), ety); - emit_memcpy(ctx, strct, tbaa, thePtr, nullptr, size, 1); + emit_memcpy(ctx, strct, jl_aliasinfo_t::fromTBAA(ctx, tbaa), thePtr, jl_aliasinfo_t::fromTBAA(ctx, nullptr), size, 1); return mark_julia_type(ctx, strct, true, ety); } else { @@ -735,14 +741,15 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, jl_cgval_t *argv) Instruction *store = ctx.builder.CreateAlignedStore( ctx.builder.CreatePtrToInt(emit_pointer_from_objref(ctx, boxed(ctx, x)), getSizeTy(ctx.builder.getContext())), ctx.builder.CreateInBoundsGEP(getSizeTy(ctx.builder.getContext()), thePtr, im1), Align(align_nb)); - tbaa_decorate(ctx.tbaa().tbaa_data, store); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_data); + ai.decorateInst(store); } else if (!jl_isbits(ety)) { thePtr = emit_unbox(ctx, getInt8PtrTy(ctx.builder.getContext()), e, e.typ); uint64_t size = jl_datatype_size(ety); im1 = ctx.builder.CreateMul(im1, ConstantInt::get(getSizeTy(ctx.builder.getContext()), LLT_ALIGN(size, jl_datatype_align(ety)))); - emit_memcpy(ctx, ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1), nullptr, x, size, align_nb); + emit_memcpy(ctx, ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1), jl_aliasinfo_t::fromTBAA(ctx, nullptr), x, size, align_nb); } else { bool isboxed; @@ -793,7 +800,8 @@ static jl_cgval_t emit_atomic_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) if (ety == (jl_value_t*)jl_any_type) { Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ); LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, thePtr, Align(sizeof(jl_value_t*))); - tbaa_decorate(ctx.tbaa().tbaa_data, load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_data); + ai.decorateInst(load); load->setOrdering(llvm_order); return mark_julia_type(ctx, load, true, ety); } @@ -819,11 +827,12 @@ static jl_cgval_t emit_atomic_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv) thePtr = emit_bitcast(ctx, thePtr, loadT->getPointerTo()); MDNode *tbaa = best_tbaa(ctx.tbaa(), ety); LoadInst *load = ctx.builder.CreateAlignedLoad(loadT, thePtr, Align(nb)); - tbaa_decorate(tbaa, load); + jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, tbaa); + ai.decorateInst(load); load->setOrdering(llvm_order); thePtr = emit_bitcast(ctx, strct, thePtr->getType()); StoreInst *store = ctx.builder.CreateAlignedStore(load, thePtr, Align(julia_alignment(ety))); - tbaa_decorate(tbaa, store); + ai.decorateInst(store); return mark_julia_type(ctx, strct, true, ety); } else { diff --git a/test/llvmpasses/aliasscopes.jl b/test/llvmpasses/aliasscopes.jl index 5c0fe48091ade..751e351dfad1e 100644 --- a/test/llvmpasses/aliasscopes.jl +++ b/test/llvmpasses/aliasscopes.jl @@ -18,8 +18,8 @@ import Base.Experimental: Const, @aliasscope function simple(A, B) @aliasscope @inbounds for I in eachindex(A, B) A[I] = Const(B)[I] -# CHECK: load double, {{.*}} !alias.scope [[SCOPE:![0-9]+]] -# CHECK: store double {{.*}} !noalias [[SCOPE]] +# CHECK: load double, {{.*}} !alias.scope [[SCOPE_LD:![0-9]+]] +# CHECK: store double {{.*}} !noalias [[SCOPE_ST:![0-9]+]] end return 0 # return nothing causes japi1 end @@ -28,8 +28,8 @@ end function constargs(A, B::Const) @aliasscope @inbounds for I in eachindex(A, B) A[I] = B[I] -# CHECK: load double, {{.*}} !alias.scope [[SCOPE2:![0-9]+]] -# CHECK: store double {{.*}} !noalias [[SCOPE2]] +# CHECK: load double, {{.*}} !alias.scope [[SCOPE2_LD:![0-9]+]] +# CHECK: store double {{.*}} !noalias [[SCOPE2_ST:![0-9]+]] end return 0 end @@ -40,10 +40,10 @@ function micro_ker!(AB, Ac, Bc, kc, offSetA, offSetB) @inbounds @aliasscope for k in 1:kc for j in 1:NR, i in 1:MR AB[i+(j-1)*MR] = muladd(Const(Ac)[offSetA+i], Const(Bc)[offSetB+j], Const(AB)[i+(j-1)*MR]) -# CHECK: load double, {{.*}} !alias.scope [[SCOPE3:![0-9]+]] -# CHECK: load double, {{.*}} !alias.scope [[SCOPE3]] -# CHECK: load double, {{.*}} !alias.scope [[SCOPE3]] -# CHECK: store double {{.*}} !noalias [[SCOPE3]] +# CHECK: load double, {{.*}} !alias.scope [[SCOPE3_LD:![0-9]+]] +# CHECK: load double, {{.*}} !alias.scope [[SCOPE3_LD]] +# CHECK: load double, {{.*}} !alias.scope [[SCOPE3_LD]] +# CHECK: store double {{.*}} !noalias [[SCOPE3_ST:![0-9]+]] end offSetA += MR offSetB += NR @@ -51,9 +51,14 @@ function micro_ker!(AB, Ac, Bc, kc, offSetA, offSetB) return end -# CHECK: [[SCOPE]] = !{[[ALIASSCOPE:![0-9]+]]} -# CHECK: [[ALIASSCOPE]] = !{!"aliasscope", [[MDNODE:![0-9]+]]} -# CHECK: [[MDNODE]] = !{!"simple"} +# CHECK-DAG: [[SCOPE_LD]] = !{[[ALIASSCOPE:![0-9]+]] +# CHECK-DAG: [[SCOPE_ST]] = !{[[ALIASSCOPE]] +# CHECK-DAG: [[SCOPE2_LD]] = !{[[ALIASSCOPE2:![0-9]+]] +# CHECK-DAG: [[SCOPE2_ST]] = !{[[ALIASSCOPE2]] +# CHECK-DAG: [[SCOPE3_LD]] = !{[[ALIASSCOPE3:![0-9]+]] +# CHECK-DAG: [[SCOPE3_ST]] = !{[[ALIASSCOPE3]] +# CHECK-DAG: [[ALIASSCOPE]] = !{!"aliasscope", [[MDNODE:![0-9]+]]} +# CHECK-DAG: [[MDNODE]] = !{!"simple"} emit(simple, Vector{Float64}, Vector{Float64}) emit(constargs, Vector{Float64}, Const{Float64, 1}) From 08aa3f00b26708f86bda134ecaa0a1b661fbc4a3 Mon Sep 17 00:00:00 2001 From: Kristoffer Date: Sun, 5 Feb 2023 11:52:14 +0100 Subject: [PATCH 29/45] bump Pkg to latest v1.9 --- .../Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/md5 | 1 + .../Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/sha512 | 1 + .../Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 | 1 - .../Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/md5 create mode 100644 deps/checksums/Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 diff --git a/deps/checksums/Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/md5 b/deps/checksums/Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/md5 new file mode 100644 index 0000000000000..a49b1c1f37011 --- /dev/null +++ b/deps/checksums/Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/md5 @@ -0,0 +1 @@ +f2a882c79d05792efa642a25444337da diff --git a/deps/checksums/Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/sha512 b/deps/checksums/Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/sha512 new file mode 100644 index 0000000000000..ed4616089416e --- /dev/null +++ b/deps/checksums/Pkg-887b06bb9b768bfca0622f112dc739d1a770932c.tar.gz/sha512 @@ -0,0 +1 @@ +7a0c9b2f5e83e85c5b174b1daf3fbe148e262d986452bf4c6f62a29f9f5bba883515c8bdd248307bdd8ff029859d26a7c93a7599cb4440e9667e3d96d6b57059 diff --git a/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 b/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 deleted file mode 100644 index 3fe266bbf95cf..0000000000000 --- a/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -f9dd5088c318bfc489e44bd39153c08c diff --git a/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 b/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 deleted file mode 100644 index 5285f263a7032..0000000000000 --- a/deps/checksums/Pkg-8ab37b338bcf64dd7734ecc2adc86a3f65502224.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -10fb53b40a38d685f542a8dee1802cf878e87e8b85084df09efb84994b9fbaded53814205ab34e50b01d3f2be93204db4f9e00d862223e72ff5558247d4e2622 diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 3aa12eadf4758..db247a2342127 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = release-1.9 -PKG_SHA1 = 8ab37b338bcf64dd7734ecc2adc86a3f65502224 +PKG_SHA1 = 887b06bb9b768bfca0622f112dc739d1a770932c PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From 68cd01c131d1e8a899734d0f1aafce503ead0fd9 Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Wed, 1 Feb 2023 14:21:49 -0500 Subject: [PATCH 30/45] Avoid unnecessary Docs.META initializations (#48469) If the target module does not have a Docs.META dict (e.g. if `--strip-metadata` is used), `Docs.meta()` has the side effect of creating a new IdDict and initializing the Docs.META field of the target module. We need to avoid eval'ing into modules after they've been closed, so for methods that do not mutate the new IdDict we should avoid the init. Resolves #48390. Co-authored-by: Steve Kelly (cherry picked from commit 798b589f09fe6da103e753bdf36c94b691c88d46) --- base/docs/Docs.jl | 7 ++++--- stdlib/REPL/src/docview.jl | 10 +++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 994d8077edc4d..6453fd274fe8a 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -73,9 +73,9 @@ const modules = Module[] const META = gensym(:meta) const METAType = IdDict{Any,Any} -function meta(m::Module) +function meta(m::Module; autoinit::Bool=true) if !isdefined(m, META) || getfield(m, META) === nothing - initmeta(m) + autoinit ? initmeta(m) : return nothing end return getfield(m, META)::METAType end @@ -161,7 +161,8 @@ end function docstr(binding::Binding, typesig = Union{}) @nospecialize typesig for m in modules - dict = meta(m) + dict = meta(m; autoinit=false) + isnothing(dict) && continue if haskey(dict, binding) docs = dict[binding].docs if haskey(docs, typesig) diff --git a/stdlib/REPL/src/docview.jl b/stdlib/REPL/src/docview.jl index 24bbfc2e6282d..ea663fa16007f 100644 --- a/stdlib/REPL/src/docview.jl +++ b/stdlib/REPL/src/docview.jl @@ -164,7 +164,8 @@ function doc(binding::Binding, sig::Type = Union{}) results, groups = DocStr[], MultiDoc[] # Lookup `binding` and `sig` for matches in all modules of the docsystem. for mod in modules - dict = meta(mod) + dict = meta(mod; autoinit=false) + isnothing(dict) && continue if haskey(dict, binding) multidoc = dict[binding] push!(groups, multidoc) @@ -565,7 +566,8 @@ Return documentation for a particular `field` of a type if it exists. """ function fielddoc(binding::Binding, field::Symbol) for mod in modules - dict = meta(mod) + dict = meta(mod; autoinit=false) + isnothing(dict) && continue if haskey(dict, binding) multidoc = dict[binding] if haskey(multidoc.docs, Union{}) @@ -834,7 +836,9 @@ function apropos(io::IO, needle::Regex) for mod in modules # Module doc might be in README.md instead of the META dict docsearch(doc(mod), needle) && println(io, mod) - for (k, v) in meta(mod) + dict = meta(mod; autoinit=false) + isnothing(dict) && continue + for (k, v) in dict docsearch(v, needle) && println(io, k) end end From 30dcbba8f0e64a3d05ebe4aedd694a04cd0da08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Fri, 27 Jan 2023 23:02:20 +0000 Subject: [PATCH 31/45] Fix `Base.libblas_name`/`Base.liblapack_name` On Windows they need to include the major soversion of libblastrampoline. (cherry picked from commit d5911c02fa6c06af01ad8916c95cd9327c9c597e) --- base/Base.jl | 7 ++++--- stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index f1d3423205312..0f4b0a3e2ae09 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -186,9 +186,10 @@ end include(strcat((length(Core.ARGS)>=2 ? Core.ARGS[2] : ""), "build_h.jl")) # include($BUILDROOT/base/build_h.jl) include(strcat((length(Core.ARGS)>=2 ? Core.ARGS[2] : ""), "version_git.jl")) # include($BUILDROOT/base/version_git.jl) -# These used to be in build_h.jl and are retained for backwards compatibility -const libblas_name = "libblastrampoline" -const liblapack_name = "libblastrampoline" +# These used to be in build_h.jl and are retained for backwards compatibility. +# NOTE: keep in sync with `libblastrampoline_jll.libblastrampoline`. +const libblas_name = "libblastrampoline" * (Sys.iswindows() ? "-5" : "") +const liblapack_name = libblas_name # numeric operations include("hashing.jl") diff --git a/stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl b/stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl index 108b7d6558079..c223b513382d7 100644 --- a/stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl +++ b/stdlib/libblastrampoline_jll/src/libblastrampoline_jll.jl @@ -18,6 +18,7 @@ artifact_dir = "" libblastrampoline_handle = C_NULL libblastrampoline_path = "" +# NOTE: keep in sync with `Base.libblas_name` and `Base.liblapack_name`. const libblastrampoline = if Sys.iswindows() "libblastrampoline-5.dll" elseif Sys.isapple() From b9c655c97e23e47c1801c3ed05802f3502276aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sat, 28 Jan 2023 00:08:18 +0000 Subject: [PATCH 32/45] Move `libblas_name`/`liblapack_name` to after `Sys` module (cherry picked from commit f2d7055fc1f796e2c7a5e10bc61925a41d8eda13) --- base/Base.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index 0f4b0a3e2ae09..d04b6ff666ada 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -186,11 +186,6 @@ end include(strcat((length(Core.ARGS)>=2 ? Core.ARGS[2] : ""), "build_h.jl")) # include($BUILDROOT/base/build_h.jl) include(strcat((length(Core.ARGS)>=2 ? Core.ARGS[2] : ""), "version_git.jl")) # include($BUILDROOT/base/version_git.jl) -# These used to be in build_h.jl and are retained for backwards compatibility. -# NOTE: keep in sync with `libblastrampoline_jll.libblastrampoline`. -const libblas_name = "libblastrampoline" * (Sys.iswindows() ? "-5" : "") -const liblapack_name = libblas_name - # numeric operations include("hashing.jl") include("rounding.jl") @@ -291,6 +286,11 @@ include("sysinfo.jl") include("libc.jl") using .Libc: getpid, gethostname, time +# These used to be in build_h.jl and are retained for backwards compatibility. +# NOTE: keep in sync with `libblastrampoline_jll.libblastrampoline`. +const libblas_name = "libblastrampoline" * (Sys.iswindows() ? "-5" : "") +const liblapack_name = libblas_name + # Logging include("logging.jl") using .CoreLogging From 8b00ed3f6aef0ec58c888ec1da69df21afd87187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sat, 28 Jan 2023 17:17:17 +0000 Subject: [PATCH 33/45] Add test for use of `Base.libblas_name` (cherry picked from commit a93ac543394a40e90fa7030e5edc6d845a718c86) --- stdlib/LinearAlgebra/test/blas.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index cbaf0e4628b9a..9139c8dcf79f1 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -4,6 +4,7 @@ module TestBLAS using Test, LinearAlgebra, Random using LinearAlgebra: BlasReal, BlasComplex +using Libdl: dlsym, dlopen fabs(x::Real) = abs(x) fabs(x::Complex) = abs(real(x)) + abs(imag(x)) @@ -713,4 +714,11 @@ end end end +# Make sure we can use `Base.libblas_name`. Avoid causing +# https://github.com/JuliaLang/julia/issues/48427 again. +@testset "libblas_name" begin + dot_sym = dlsym(dlopen(Base.libblas_name), "cblas_ddot" * (Sys.WORD_SIZE == 64 ? "64_" : "")) + @test 23.0 === @ccall $(dot_sym)(2::Cint, [2.0, 3.0]::Ref{Cdouble}, 1::Cint, [4.0, 5.0]::Ref{Cdouble}, 1::Cint)::Cdouble +end + end # module TestBLAS From a7f04b82fd34a68d18b6cb94c074a0f199b784c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Fri, 3 Feb 2023 16:38:53 +0000 Subject: [PATCH 34/45] [LinearAlgebra] Fix `libblas_name` test Use `Int` as type for integer arguments, instead of `Cint`. (cherry picked from commit cdc6eafb3681840ddef395aa7ffad45db3064e71) --- stdlib/LinearAlgebra/test/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index 9139c8dcf79f1..4252d9ee7938b 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -718,7 +718,7 @@ end # https://github.com/JuliaLang/julia/issues/48427 again. @testset "libblas_name" begin dot_sym = dlsym(dlopen(Base.libblas_name), "cblas_ddot" * (Sys.WORD_SIZE == 64 ? "64_" : "")) - @test 23.0 === @ccall $(dot_sym)(2::Cint, [2.0, 3.0]::Ref{Cdouble}, 1::Cint, [4.0, 5.0]::Ref{Cdouble}, 1::Cint)::Cdouble + @test 23.0 === @ccall $(dot_sym)(2::Int, [2.0, 3.0]::Ref{Cdouble}, 1::Int, [4.0, 5.0]::Ref{Cdouble}, 1::Int)::Cdouble end end # module TestBLAS From 26b6e81c6e1b274bac006a0d58b44c2fe755293b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 19 Jan 2023 13:52:46 -0600 Subject: [PATCH 35/45] remove precompile mutation step from staticdata (#48309) Make sure things are properly ordered here, so that when serializing, nothing is mutating the system at the same time. Fix #48047 (cherry picked from commit 87b8896fa36d37e988867f404a9b1caebdc98dda) --- src/gf.c | 18 +++++-- src/precompile_utils.c | 4 ++ src/staticdata.c | 112 ++++++++++++++++++++++------------------- src/staticdata_utils.c | 59 +++++----------------- 4 files changed, 90 insertions(+), 103 deletions(-) diff --git a/src/gf.c b/src/gf.c index 69551f9beebd7..e62eedde81572 100644 --- a/src/gf.c +++ b/src/gf.c @@ -281,11 +281,9 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t *mi, size_t world, int force) return NULL; jl_task_t *ct = jl_current_task; if (ct->reentrant_inference == (uint16_t)-1) { - // TODO: We should avoid attempting to re-inter inference here at all - // and turn on this warning, but that requires further refactoring - // of the precompile code, so for now just catch that case here. - //jl_printf(JL_STDERR, "ERROR: Attempted to enter inference while writing out image."); - return NULL; + // We must avoid attempting to re-enter inference here + assert(0 && "attempted to enter inference while writing out image"); + abort(); } if (ct->reentrant_inference > 2) return NULL; @@ -487,6 +485,7 @@ int foreach_mtable_in_module( // this is the original/primary binding for the type (name/wrapper) jl_methtable_t *mt = tn->mt; if (mt != NULL && (jl_value_t*)mt != jl_nothing && mt != jl_type_type_mt && mt != jl_nonfunction_mt) { + assert(mt->module == m); if (!visit(mt, env)) return 0; } @@ -500,6 +499,15 @@ int foreach_mtable_in_module( return 0; } } + else if (jl_is_mtable(v)) { + jl_methtable_t *mt = (jl_methtable_t*)v; + if (mt->module == m && mt->name == b->name) { + // this is probably an external method table here, so let's + // assume so as there is no way to precisely distinguish them + if (!visit(mt, env)) + return 0; + } + } } } } diff --git a/src/precompile_utils.c b/src/precompile_utils.c index f251d00f76cfd..9f52ce911a92f 100644 --- a/src/precompile_utils.c +++ b/src/precompile_utils.c @@ -132,6 +132,8 @@ static int compile_all_collect__(jl_typemap_entry_t *ml, void *env) { jl_array_t *allmeths = (jl_array_t*)env; jl_method_t *m = ml->func.method; + if (m->external_mt) + return 1; if (m->source) { // method has a non-generated definition; can be compiled generically jl_array_ptr_1d_push(allmeths, (jl_value_t*)m); @@ -204,6 +206,8 @@ static int precompile_enq_specialization_(jl_method_instance_t *mi, void *closur static int precompile_enq_all_specializations__(jl_typemap_entry_t *def, void *closure) { jl_method_t *m = def->func.method; + if (m->external_mt) + return 1; if ((m->name == jl_symbol("__init__") || m->ccallable) && jl_is_dispatch_tupletype(m->sig)) { // ensure `__init__()` and @ccallables get strongly-hinted, specialized, and compiled jl_method_instance_t *mi = jl_specializations_get_linfo(m, m->sig, jl_emptysvec); diff --git a/src/staticdata.c b/src/staticdata.c index be2dbc919d7d6..f3e24a8eb615c 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -2229,9 +2229,8 @@ JL_DLLEXPORT jl_value_t *jl_as_global_root(jl_value_t *val JL_MAYBE_UNROOTED) } static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *newly_inferred, uint64_t worklist_key, - /* outputs */ jl_array_t **extext_methods, - jl_array_t **new_specializations, jl_array_t **method_roots_list, - jl_array_t **ext_targets, jl_array_t **edges) + /* outputs */ jl_array_t **extext_methods, jl_array_t **new_specializations, + jl_array_t **method_roots_list, jl_array_t **ext_targets, jl_array_t **edges) { // extext_methods: [method1, ...], worklist-owned "extending external" methods added to functions owned by modules outside the worklist // ext_targets: [invokesig1, callee1, matches1, ...] non-worklist callees of worklist-owned methods @@ -2239,24 +2238,19 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new // `invoke` dispatch: invokesig is signature, callee is MethodInstance // abstract call: callee is signature // edges: [caller1, ext_targets_indexes1, ...] for worklist-owned methods calling external methods - assert(edges_map == NULL); - JL_GC_PUSH1(&edges_map); - // Save the inferred code from newly inferred, external methods htable_new(&external_mis, 0); // we need external_mis until after `jl_collect_edges` finishes + // Save the inferred code from newly inferred, external methods *new_specializations = queue_external_cis(newly_inferred); - // Collect the new method roots - htable_t methods_with_newspecs; - htable_new(&methods_with_newspecs, 0); - jl_collect_methods(&methods_with_newspecs, *new_specializations); - *method_roots_list = jl_alloc_vec_any(0); - jl_collect_new_roots(*method_roots_list, &methods_with_newspecs, worklist_key); - htable_free(&methods_with_newspecs); // Collect method extensions and edges data - edges_map = jl_alloc_vec_any(0); + JL_GC_PUSH1(&edges_map); + if (edges) + edges_map = jl_alloc_vec_any(0); *extext_methods = jl_alloc_vec_any(0); + jl_collect_methtable_from_mod(jl_type_type_mt, *extext_methods); + jl_collect_methtable_from_mod(jl_nonfunction_mt, *extext_methods); size_t i, len = jl_array_len(mod_array); for (i = 0; i < len; i++) { jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(mod_array, i); @@ -2264,15 +2258,23 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new if (m->parent == m) // some toplevel modules (really just Base) aren't actually jl_collect_extext_methods_from_mod(*extext_methods, m); } - jl_collect_methtable_from_mod(*extext_methods, jl_type_type_mt); - jl_collect_missing_backedges(jl_type_type_mt); - jl_collect_methtable_from_mod(*extext_methods, jl_nonfunction_mt); - jl_collect_missing_backedges(jl_nonfunction_mt); - // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges also accumulate data in callers_with_edges. - // Process this to extract `edges` and `ext_targets`. - *ext_targets = jl_alloc_vec_any(0); - *edges = jl_alloc_vec_any(0); - jl_collect_edges(*edges, *ext_targets); + + if (edges) { + jl_collect_missing_backedges(jl_type_type_mt); + jl_collect_missing_backedges(jl_nonfunction_mt); + // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges also accumulate data in callers_with_edges. + // Process this to extract `edges` and `ext_targets`. + *ext_targets = jl_alloc_vec_any(0); + *edges = jl_alloc_vec_any(0); + *method_roots_list = jl_alloc_vec_any(0); + // Collect the new method roots + htable_t methods_with_newspecs; + htable_new(&methods_with_newspecs, 0); + jl_collect_methods(&methods_with_newspecs, *new_specializations); + jl_collect_new_roots(*method_roots_list, &methods_with_newspecs, worklist_key); + htable_free(&methods_with_newspecs); + jl_collect_edges(*edges, *ext_targets); + } htable_free(&external_mis); assert(edges_map == NULL); // jl_collect_edges clears this when done @@ -2562,9 +2564,8 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_gc_enable(en); } -static void jl_write_header_for_incremental(ios_t *f, jl_array_t *worklist, jl_array_t **mod_array, jl_array_t **udeps, int64_t *srctextpos, int64_t *checksumpos) +static void jl_write_header_for_incremental(ios_t *f, jl_array_t *worklist, jl_array_t *mod_array, jl_array_t **udeps, int64_t *srctextpos, int64_t *checksumpos) { - *mod_array = jl_get_loaded_modules(); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array) assert(jl_precompile_toplevel_module == NULL); jl_precompile_toplevel_module = (jl_module_t*)jl_array_ptr_ref(worklist, jl_array_len(worklist)-1); @@ -2580,7 +2581,7 @@ static void jl_write_header_for_incremental(ios_t *f, jl_array_t *worklist, jl_a // write description of requirements for loading (modules that must be pre-loaded if initialization is to succeed) // this can return errors during deserialize, // best to keep it early (before any actual initialization) - write_mod_list(f, *mod_array); + write_mod_list(f, mod_array); } JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *worklist, bool_t emit_split, @@ -2611,49 +2612,58 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli int64_t checksumpos_ff = 0; int64_t datastartpos = 0; JL_GC_PUSH6(&mod_array, &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges); - if (worklist) { - jl_write_header_for_incremental(f, worklist, &mod_array, udeps, srctextpos, &checksumpos); - if (emit_split) { - checksumpos_ff = write_header(ff, 1); - write_uint8(ff, jl_cache_flags()); - write_mod_list(ff, mod_array); - } else { - checksumpos_ff = checksumpos; - } - { - // make sure we don't run any Julia code concurrently after this point - jl_gc_enable_finalizers(ct, 0); - assert(ct->reentrant_inference == 0); - ct->reentrant_inference = (uint16_t)-1; - } - jl_prepare_serialization_data(mod_array, newly_inferred, jl_worklist_key(worklist), &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges); + if (worklist) { + mod_array = jl_get_loaded_modules(); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array) // Generate _native_data` if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc || jl_options.outputasm) { + jl_prepare_serialization_data(mod_array, newly_inferred, jl_worklist_key(worklist), + &extext_methods, &new_specializations, NULL, NULL, NULL); jl_precompile_toplevel_module = (jl_module_t*)jl_array_ptr_ref(worklist, jl_array_len(worklist)-1); *_native_data = jl_precompile_worklist(worklist, extext_methods, new_specializations); jl_precompile_toplevel_module = NULL; + extext_methods = NULL; + new_specializations = NULL; } + jl_write_header_for_incremental(f, worklist, mod_array, udeps, srctextpos, &checksumpos); + if (emit_split) { + checksumpos_ff = write_header(ff, 1); + write_uint8(ff, jl_cache_flags()); + write_mod_list(ff, mod_array); + } + else { + checksumpos_ff = checksumpos; + } + } + else { + *_native_data = jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL); + } + // Make sure we don't run any Julia code concurrently after this point + // since it will invalidate our serialization preparations + jl_gc_enable_finalizers(ct, 0); + assert(ct->reentrant_inference == 0); + ct->reentrant_inference = (uint16_t)-1; + if (worklist) { + jl_prepare_serialization_data(mod_array, newly_inferred, jl_worklist_key(worklist), + &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges); if (!emit_split) { write_int32(f, 0); // No clone_targets write_padding(f, LLT_ALIGN(ios_pos(f), JL_CACHE_BYTE_ALIGNMENT) - ios_pos(f)); - } else { + } + else { write_padding(ff, LLT_ALIGN(ios_pos(ff), JL_CACHE_BYTE_ALIGNMENT) - ios_pos(ff)); } datastartpos = ios_pos(ff); - } else { - *_native_data = jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL); } native_functions = *_native_data; jl_save_system_image_to_stream(ff, worklist, extext_methods, new_specializations, method_roots_list, ext_targets, edges); native_functions = NULL; - if (worklist) { - // Re-enable running julia code for postoutput hooks, atexit, etc. - jl_gc_enable_finalizers(ct, 1); - ct->reentrant_inference = 0; - jl_precompile_toplevel_module = NULL; - } + // make sure we don't run any Julia code concurrently before this point + // Re-enable running julia code for postoutput hooks, atexit, etc. + jl_gc_enable_finalizers(ct, 1); + ct->reentrant_inference = 0; + jl_precompile_toplevel_module = NULL; if (worklist) { // Go back and update the checksum in the header diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index fba1af21483ad..4e3c0650bc25e 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -294,12 +294,12 @@ static void jl_collect_methods(htable_t *mset, jl_array_t *new_specializations) } } -static void jl_collect_new_roots(jl_array_t *roots, htable_t *mset, uint64_t key) +static void jl_collect_new_roots(jl_array_t *roots, const htable_t *mset, uint64_t key) { size_t i, sz = mset->size; int nwithkey; jl_method_t *m; - void **table = mset->table; + void *const *table = mset->table; jl_array_t *newroots = NULL; JL_GC_PUSH1(&newroots); for (i = 0; i < sz; i += 2) { @@ -390,6 +390,8 @@ static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) if (s && !jl_object_in_image((jl_value_t*)m->module)) { jl_array_ptr_1d_push(s, (jl_value_t*)m); } + if (edges_map == NULL) + return 1; jl_svec_t *specializations = m->specializations; size_t i, l = jl_svec_len(specializations); for (i = 0; i < l; i++) { @@ -400,9 +402,14 @@ static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) return 1; } -static void jl_collect_methtable_from_mod(jl_array_t *s, jl_methtable_t *mt) +static int jl_collect_methtable_from_mod(jl_methtable_t *mt, void *env) { - jl_typemap_visitor(mt->defs, jl_collect_methcache_from_mod, (void*)s); + if (!jl_object_in_image((jl_value_t*)mt)) + env = NULL; // do not collect any methods from here + jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), jl_collect_methcache_from_mod, env); + if (env && edges_map) + jl_collect_missing_backedges(mt); + return 1; } // Collect methods of external functions defined by modules in the worklist @@ -410,49 +417,7 @@ static void jl_collect_methtable_from_mod(jl_array_t *s, jl_methtable_t *mt) // Also collect relevant backedges static void jl_collect_extext_methods_from_mod(jl_array_t *s, jl_module_t *m) { - if (s && !jl_object_in_image((jl_value_t*)m)) - s = NULL; // do not collect any methods - size_t i; - void **table = m->bindings.table; - for (i = 1; i < m->bindings.size; i += 2) { - if (table[i] != HT_NOTFOUND) { - jl_binding_t *b = (jl_binding_t*)table[i]; - if (b->owner == m && b->value && b->constp) { - jl_value_t *bv = jl_unwrap_unionall(b->value); - if (jl_is_datatype(bv)) { - jl_typename_t *tn = ((jl_datatype_t*)bv)->name; - if (tn->module == m && tn->name == b->name && tn->wrapper == b->value) { - jl_methtable_t *mt = tn->mt; - if (mt != NULL && - (jl_value_t*)mt != jl_nothing && - (mt != jl_type_type_mt && mt != jl_nonfunction_mt)) { - assert(mt->module == tn->module); - jl_collect_methtable_from_mod(s, mt); - if (s) - jl_collect_missing_backedges(mt); - } - } - } - else if (jl_is_module(b->value)) { - jl_module_t *child = (jl_module_t*)b->value; - if (child != m && child->parent == m && child->name == b->name) { - // this is the original/primary binding for the submodule - jl_collect_extext_methods_from_mod(s, (jl_module_t*)b->value); - } - } - else if (jl_is_mtable(b->value)) { - jl_methtable_t *mt = (jl_methtable_t*)b->value; - if (mt->module == m && mt->name == b->name) { - // this is probably an external method table, so let's assume so - // as there is no way to precisely distinguish them, - // and the rest of this serializer does not bother - // to handle any method tables specially - jl_collect_methtable_from_mod(s, (jl_methtable_t*)bv); - } - } - } - } - } + foreach_mtable_in_module(m, jl_collect_methtable_from_mod, s); } static void jl_record_edges(jl_method_instance_t *caller, arraylist_t *wq, jl_array_t *edges) From 62b70e3cabfc182dcd21d13a4ffc683864deb2cd Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 28 Jan 2023 00:49:24 -0500 Subject: [PATCH 36/45] avoid generating native code if only output ji file (#48431) (cherry picked from commit 2eeefbe20830984fb111c8e41ee9d649ce5ab64e) --- src/precompile.c | 5 +++-- src/staticdata.c | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/precompile.c b/src/precompile.c index bfc123cf3fda8..603e92b6d0dbe 100644 --- a/src/precompile.c +++ b/src/precompile.c @@ -114,8 +114,9 @@ JL_DLLEXPORT void jl_write_compiler_output(void) ios_t *s = NULL; ios_t *z = NULL; int64_t srctextpos = 0 ; - jl_create_system_image(&native_code, jl_options.incremental ? worklist : NULL, emit_split, - &s, &z, &udeps, &srctextpos); + jl_create_system_image(emit_native ? &native_code : NULL, + jl_options.incremental ? worklist : NULL, + emit_split, &s, &z, &udeps, &srctextpos); if (!emit_split) z = s; diff --git a/src/staticdata.c b/src/staticdata.c index f3e24a8eb615c..4224a52374b10 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -2616,7 +2616,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli if (worklist) { mod_array = jl_get_loaded_modules(); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array) // Generate _native_data` - if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc || jl_options.outputasm) { + if (_native_data != NULL) { jl_prepare_serialization_data(mod_array, newly_inferred, jl_worklist_key(worklist), &extext_methods, &new_specializations, NULL, NULL, NULL); jl_precompile_toplevel_module = (jl_module_t*)jl_array_ptr_ref(worklist, jl_array_len(worklist)-1); @@ -2635,7 +2635,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli checksumpos_ff = checksumpos; } } - else { + else if (_native_data != NULL) { *_native_data = jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL); } @@ -2656,9 +2656,11 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli } datastartpos = ios_pos(ff); } - native_functions = *_native_data; + if (_native_data != NULL) + native_functions = *_native_data; jl_save_system_image_to_stream(ff, worklist, extext_methods, new_specializations, method_roots_list, ext_targets, edges); - native_functions = NULL; + if (_native_data != NULL) + native_functions = NULL; // make sure we don't run any Julia code concurrently before this point // Re-enable running julia code for postoutput hooks, atexit, etc. jl_gc_enable_finalizers(ct, 1); From d1b9ff9501ea403e96e460e0a229c508600114a3 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 12 Dec 2022 16:15:41 -0500 Subject: [PATCH 37/45] convert algorithms to SCC (#47866) These places in the code can either be more efficient O(1) or more correct using something more similar to the published SCC algorithm by Tarjan for strongly connected components. (cherry picked from commit b03439c8e3e14d9068f8ebc0782c8a9d2f2736f2) --- src/gf.c | 1 + src/jitlayers.cpp | 101 ++++++++++++------------ src/staticdata_utils.c | 172 ++++++++++++++--------------------------- 3 files changed, 111 insertions(+), 163 deletions(-) diff --git a/src/gf.c b/src/gf.c index e62eedde81572..024faa145c6f7 100644 --- a/src/gf.c +++ b/src/gf.c @@ -3421,6 +3421,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, } } // then we'll merge those numbers to assign each item in the group the same number + // (similar to Kosaraju's SCC algorithm?) uint32_t groupid = 0; uint32_t grouphi = 0; for (i = 0; i < len; i++) { diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index b36a12443c7e0..db99cee8b724d 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -137,7 +137,11 @@ void jl_dump_llvm_opt_impl(void *s) **jl_ExecutionEngine->get_dump_llvm_opt_stream() = (JL_STREAM*)s; } -static void jl_add_to_ee(orc::ThreadSafeModule &M, StringMap &NewExports); +static int jl_add_to_ee( + orc::ThreadSafeModule &M, + const StringMap &NewExports, + DenseMap &Queued, + std::vector &Stack); static void jl_decorate_module(Module &M); static uint64_t getAddressForFunction(StringRef fname); @@ -229,10 +233,13 @@ static jl_callptr_t _jl_compile_codeinst( } } } + DenseMap Queued; + std::vector Stack; for (auto &def : emitted) { // Add the results to the execution engine now orc::ThreadSafeModule &M = std::get<0>(def.second); - jl_add_to_ee(M, NewExports); + jl_add_to_ee(M, NewExports, Queued, Stack); + assert(Queued.empty() && Stack.empty() && !M); } ++CompiledCodeinsts; MaxWorkqueueSize.updateMax(emitted.size()); @@ -1715,76 +1722,72 @@ static void jl_decorate_module(Module &M) { #endif } +// Implements Tarjan's SCC (strongly connected components) algorithm, simplified to remove the count variable static int jl_add_to_ee( orc::ThreadSafeModule &M, - StringMap &NewExports, + const StringMap &NewExports, DenseMap &Queued, - std::vector> &ToMerge, - int depth) + std::vector &Stack) { - // DAG-sort (post-dominator) the compile to compute the minimum - // merge-module sets for linkage + // First check if the TSM is empty (already compiled) if (!M) return 0; - // First check and record if it's on the stack somewhere + // Next check and record if it is on the stack somewhere { - auto &Cycle = Queued[&M]; - if (Cycle) - return Cycle; - ToMerge.push_back({}); - Cycle = depth; + auto &Id = Queued[&M]; + if (Id) + return Id; + Stack.push_back(&M); + Id = Stack.size(); } + // Finally work out the SCC + int depth = Stack.size(); int MergeUp = depth; - // Compute the cycle-id + std::vector Children; M.withModuleDo([&](Module &m) { for (auto &F : m.global_objects()) { if (F.isDeclaration() && F.getLinkage() == GlobalValue::ExternalLinkage) { auto Callee = NewExports.find(F.getName()); if (Callee != NewExports.end()) { - auto &CM = Callee->second; - int Down = jl_add_to_ee(*CM, NewExports, Queued, ToMerge, depth + 1); - assert(Down <= depth); - if (Down && Down < MergeUp) - MergeUp = Down; + auto *CM = Callee->second; + if (*CM && CM != &M) { + auto Down = Queued.find(CM); + if (Down != Queued.end()) + MergeUp = std::min(MergeUp, Down->second); + else + Children.push_back(CM); + } } } } }); - if (MergeUp == depth) { - // Not in a cycle (or at the top of it) - Queued.erase(&M); - for (auto &CM : ToMerge.at(depth - 1)) { - assert(Queued.find(CM)->second == depth); - Queued.erase(CM); - jl_merge_module(M, std::move(*CM)); - } - jl_ExecutionEngine->addModule(std::move(M)); - MergeUp = 0; + assert(MergeUp > 0); + for (auto *CM : Children) { + int Down = jl_add_to_ee(*CM, NewExports, Queued, Stack); + assert(Down <= (int)Stack.size()); + if (Down) + MergeUp = std::min(MergeUp, Down); } - else { - // Add our frame(s) to the top of the cycle - Queued[&M] = MergeUp; - auto &Top = ToMerge.at(MergeUp - 1); - Top.push_back(&M); - for (auto &CM : ToMerge.at(depth - 1)) { - assert(Queued.find(CM)->second == depth); - Queued[CM] = MergeUp; - Top.push_back(CM); + if (MergeUp < depth) + return MergeUp; + while (1) { + // Not in a cycle (or at the top of it) + // remove SCC state and merge every CM from the cycle into M + orc::ThreadSafeModule *CM = Stack.back(); + auto it = Queued.find(CM); + assert(it->second == (int)Stack.size()); + Queued.erase(it); + Stack.pop_back(); + if ((int)Stack.size() < depth) { + assert(&M == CM); + break; } + jl_merge_module(M, std::move(*CM)); } - ToMerge.pop_back(); - return MergeUp; -} - -static void jl_add_to_ee(orc::ThreadSafeModule &M, StringMap &NewExports) -{ - DenseMap Queued; - std::vector> ToMerge; - jl_add_to_ee(M, NewExports, Queued, ToMerge, 1); - assert(!M); + jl_ExecutionEngine->addModule(std::move(M)); + return 0; } - static uint64_t getAddressForFunction(StringRef fname) { auto addr = jl_ExecutionEngine->getFunctionAddress(fname); diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index 4e3c0650bc25e..c6b553ede8849 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -158,31 +158,10 @@ static int type_in_worklist(jl_value_t *v) JL_NOTSAFEPOINT return 0; } -static void mark_backedges_in_worklist(jl_method_instance_t *mi, htable_t *visited, int found) -{ - int oldfound = (char*)ptrhash_get(visited, mi) - (char*)HT_NOTFOUND; - if (oldfound < 3) - return; // not in-progress - ptrhash_put(visited, mi, (void*)((char*)HT_NOTFOUND + 1 + found)); -#ifndef NDEBUG - jl_module_t *mod = mi->def.module; - if (jl_is_method(mod)) - mod = ((jl_method_t*)mod)->module; - assert(jl_is_module(mod)); - assert(!mi->precompiled && jl_object_in_image((jl_value_t*)mod)); - assert(mi->backedges); -#endif - size_t i = 0, n = jl_array_len(mi->backedges); - while (i < n) { - jl_method_instance_t *be; - i = get_next_edge(mi->backedges, i, NULL, &be); - mark_backedges_in_worklist(be, visited, found); - } -} - // When we infer external method instances, ensure they link back to the -// package. Otherwise they might be, e.g., for external macros -static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, int depth) +// package. Otherwise they might be, e.g., for external macros. +// Implements Tarjan's SCC (strongly connected components) algorithm, simplified to remove the count variable +static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, arraylist_t *stack) { jl_module_t *mod = mi->def.module; if (jl_is_method(mod)) @@ -202,14 +181,17 @@ static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, int found = (char*)*bp - (char*)HT_NOTFOUND; if (found) return found - 1; + arraylist_push(stack, (void*)mi); + int depth = stack->len; *bp = (void*)((char*)HT_NOTFOUND + 3 + depth); // preliminarily mark as in-progress size_t i = 0, n = jl_array_len(mi->backedges); int cycle = 0; while (i < n) { jl_method_instance_t *be; i = get_next_edge(mi->backedges, i, NULL, &be); - int child_found = has_backedge_to_worklist(be, visited, depth + 1); + int child_found = has_backedge_to_worklist(be, visited, stack); if (child_found == 1) { + // found what we were looking for, so terminate early found = 1; break; } @@ -221,22 +203,15 @@ static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, } if (!found && cycle && cycle != depth) return cycle + 2; - bp = ptrhash_bp(visited, mi); // re-acquire since rehashing might change the location - *bp = (void*)((char*)HT_NOTFOUND + 1 + found); - if (cycle) { - // If we are the top of the current cycle, now mark all other parts of - // our cycle by re-walking the backedges graph and marking all WIP - // items as found. - // Be careful to only re-walk as far as we had originally scanned above. - // Or if we found a backedge, also mark all of the other parts of the - // cycle as also having an backedge. - n = i; - i = 0; - while (i < n) { - jl_method_instance_t *be; - i = get_next_edge(mi->backedges, i, NULL, &be); - mark_backedges_in_worklist(be, visited, found); - } + // If we are the top of the current cycle, now mark all other parts of + // our cycle with what we found. + // Or if we found a backedge, also mark all of the other parts of the + // cycle as also having an backedge. + while (stack->len >= depth) { + void *mi = arraylist_pop(stack); + bp = ptrhash_bp(visited, mi); + assert((char*)*bp - (char*)HT_NOTFOUND == 4 + stack->len); + *bp = (void*)((char*)HT_NOTFOUND + 1 + found); } return found; } @@ -251,9 +226,11 @@ static jl_array_t *queue_external_cis(jl_array_t *list) return NULL; size_t i; htable_t visited; + arraylist_t stack; assert(jl_is_array(list)); size_t n0 = jl_array_len(list); htable_new(&visited, n0); + arraylist_new(&stack, 0); jl_array_t *new_specializations = jl_alloc_vec_any(0); JL_GC_PUSH1(&new_specializations); for (i = 0; i < n0; i++) { @@ -264,8 +241,9 @@ static jl_array_t *queue_external_cis(jl_array_t *list) if (jl_is_method(m)) { if (jl_object_in_image((jl_value_t*)m->module)) { if (ptrhash_get(&external_mis, mi) == HT_NOTFOUND) { - int found = has_backedge_to_worklist(mi, &visited, 1); + int found = has_backedge_to_worklist(mi, &visited, &stack); assert(found == 0 || found == 1); + assert(stack.len == 0); if (found == 1) { ptrhash_put(&external_mis, mi, mi); jl_array_ptr_1d_push(new_specializations, (jl_value_t*)ci); @@ -275,6 +253,7 @@ static jl_array_t *queue_external_cis(jl_array_t *list) } } htable_free(&visited); + arraylist_free(&stack); JL_GC_POP(); return new_specializations; } @@ -977,56 +956,23 @@ static void jl_verify_methods(jl_array_t *edges, jl_array_t *valids, htable_t *v } -// Propagate the result of cycle-resolution to all edges (recursively) -static int mark_edges_in_worklist(jl_array_t *edges, int idx, jl_method_instance_t *cycle, htable_t *visited, int found) -{ - jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(edges, idx * 2); - int oldfound = (char*)ptrhash_get(visited, caller) - (char*)HT_NOTFOUND; - if (oldfound < 3) - return 0; // not in-progress - if (!found) { - ptrhash_remove(visited, (void*)caller); - } - else { - ptrhash_put(visited, (void*)caller, (void*)((char*)HT_NOTFOUND + 1 + found)); - } - jl_array_t *callee_ids = (jl_array_t*)jl_array_ptr_ref(edges, idx * 2 + 1); - assert(jl_typeis((jl_value_t*)callee_ids, jl_array_int32_type)); - int32_t *idxs = (int32_t*)jl_array_data(callee_ids); - size_t i, badidx = 0, n = jl_array_len(callee_ids); - for (i = idxs[0] + 1; i < n; i++) { - if (mark_edges_in_worklist(edges, idxs[i], cycle, visited, found) && badidx == 0) - badidx = i - idxs[0]; - } - if (_jl_debug_method_invalidation) { - jl_value_t *loctag = NULL; - JL_GC_PUSH1(&loctag); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)caller); - loctag = jl_cstr_to_string("verify_methods"); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); - jl_method_instance_t *callee = cycle; - if (badidx--) - callee = (jl_method_instance_t*)jl_array_ptr_ref(edges, 2 * badidx); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)callee); - JL_GC_POP(); - } - return 1; -} - - // Visit the entire call graph, starting from edges[idx] to determine if that method is valid -static int jl_verify_graph_edge(jl_array_t *edges, int idx, htable_t *visited, int depth) +// Implements Tarjan's SCC (strongly connected components) algorithm, simplified to remove the count variable +static int jl_verify_graph_edge(jl_array_t *edges, int idx, htable_t *visited, arraylist_t *stack) { jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(edges, idx * 2); assert(jl_is_method_instance(caller) && jl_is_method(caller->def.method)); int found = (char*)ptrhash_get(visited, (void*)caller) - (char*)HT_NOTFOUND; if (found == 0) - return 1; // valid + return 1; // NOTFOUND == valid if (found == 1) return 0; // invalid if (found != 2) return found - 1; // depth found = 0; + jl_value_t *cause = NULL; + arraylist_push(stack, (void*)caller); + int depth = stack->len; ptrhash_put(visited, (void*)caller, (void*)((char*)HT_NOTFOUND + 3 + depth)); // change 2 to in-progress at depth jl_array_t *callee_ids = (jl_array_t*)jl_array_ptr_ref(edges, idx * 2 + 1); assert(jl_typeis((jl_value_t*)callee_ids, jl_array_int32_type)); @@ -1035,18 +981,11 @@ static int jl_verify_graph_edge(jl_array_t *edges, int idx, htable_t *visited, i size_t i, n = jl_array_len(callee_ids); for (i = idxs[0] + 1; i < n; i++) { int32_t idx = idxs[i]; - int child_found = jl_verify_graph_edge(edges, idx, visited, depth + 1); + int child_found = jl_verify_graph_edge(edges, idx, visited, stack); if (child_found == 0) { + // found what we were looking for, so terminate early found = 1; - if (_jl_debug_method_invalidation) { - jl_value_t *loctag = NULL; - JL_GC_PUSH1(&loctag); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)caller); - loctag = jl_cstr_to_string("verify_methods"); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, jl_array_ptr_ref(edges, idx * 2)); - JL_GC_POP(); - } + cause = jl_array_ptr_ref(edges, idx * 2); break; } else if (child_found >= 2 && child_found - 2 < cycle) { @@ -1055,24 +994,27 @@ static int jl_verify_graph_edge(jl_array_t *edges, int idx, htable_t *visited, i assert(cycle); } } - if (!found) { - if (cycle && cycle != depth) - return cycle + 2; - ptrhash_remove(visited, (void*)caller); - } - else { // found invalid - ptrhash_put(visited, (void*)caller, (void*)((char*)HT_NOTFOUND + 1 + found)); - } - if (cycle) { - // If we are the top of the current cycle, now mark all other parts of - // our cycle by re-walking the backedges graph and marking all WIP - // items as found. - // Be careful to only re-walk as far as we had originally scanned above. - // Or if we found a backedge, also mark all of the other parts of the - // cycle as also having an backedge. - n = i; - for (i = idxs[0] + 1; i < n; i++) { - mark_edges_in_worklist(edges, idxs[i], caller, visited, found); + if (!found && cycle && cycle != depth) + return cycle + 2; + // If we are the top of the current cycle, now mark all other parts of + // our cycle with what we found. + // Or if we found a backedge, also mark all of the other parts of the + // cycle as also having an backedge. + while (stack->len >= depth) { + void *mi = arraylist_pop(stack); + assert((char*)ptrhash_get(visited, mi) - (char*)HT_NOTFOUND == 4 + stack->len); + if (found) + ptrhash_put(visited, mi, (void*)((char*)HT_NOTFOUND + 1 + found)); + else + ptrhash_remove(visited, mi); // assign as NOTFOUND in table + if (_jl_debug_method_invalidation && found) { + jl_value_t *loctag = NULL; + JL_GC_PUSH1(&loctag); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi); + loctag = jl_cstr_to_string("verify_methods"); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)cause); + JL_GC_POP(); } } return found ? 0 : 1; @@ -1081,13 +1023,15 @@ static int jl_verify_graph_edge(jl_array_t *edges, int idx, htable_t *visited, i // Visit all entries in edges, verify if they are valid static jl_array_t *jl_verify_graph(jl_array_t *edges, htable_t *visited) { + arraylist_t stack; + arraylist_new(&stack, 0); size_t i, n = jl_array_len(edges) / 2; jl_array_t *valids = jl_alloc_array_1d(jl_array_uint8_type, n); JL_GC_PUSH1(&valids); int8_t *valids_data = (int8_t*)jl_array_data(valids); - for (i = 0; i < n; i++) { - valids_data[i] = jl_verify_graph_edge(edges, i, visited, 1); - } + for (i = 0; i < n; i++) + valids_data[i] = jl_verify_graph_edge(edges, i, visited, &stack); + arraylist_free(&stack); JL_GC_POP(); return valids; } @@ -1103,8 +1047,8 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets, jl_a JL_GC_PUSH1(&valids); htable_t visited; htable_new(&visited, 0); - jl_verify_methods(edges, valids, &visited); - valids = jl_verify_graph(edges, &visited); + jl_verify_methods(edges, valids, &visited); // consumes valids, creates visited + valids = jl_verify_graph(edges, &visited); // consumes visited, creates valids size_t i, l = jl_array_len(edges) / 2; // next build a map from external MethodInstances to their CodeInstance for insertion From a83399cfd72220558c2f844df9f25a1444d0c20e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 4 Feb 2023 03:52:20 -0500 Subject: [PATCH 38/45] precompile: do not reanimate zombie external methods (#48475) Backedges are only applicable to cache objects with max_world==Inf Fix #48391 (cherry picked from commit b9398a3a187914c79e9a627370a0a85d720fe7fb) --- src/staticdata.c | 12 ++---- src/staticdata_utils.c | 84 ++++++++++++++++++++---------------------- test/precompile.jl | 79 +++++++++++++++++++++------------------ 3 files changed, 87 insertions(+), 88 deletions(-) diff --git a/src/staticdata.c b/src/staticdata.c index 4224a52374b10..07e971a10d33b 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -2240,7 +2240,6 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new // edges: [caller1, ext_targets_indexes1, ...] for worklist-owned methods calling external methods assert(edges_map == NULL); - htable_new(&external_mis, 0); // we need external_mis until after `jl_collect_edges` finishes // Save the inferred code from newly inferred, external methods *new_specializations = queue_external_cis(newly_inferred); @@ -2268,14 +2267,9 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new *edges = jl_alloc_vec_any(0); *method_roots_list = jl_alloc_vec_any(0); // Collect the new method roots - htable_t methods_with_newspecs; - htable_new(&methods_with_newspecs, 0); - jl_collect_methods(&methods_with_newspecs, *new_specializations); - jl_collect_new_roots(*method_roots_list, &methods_with_newspecs, worklist_key); - htable_free(&methods_with_newspecs); - jl_collect_edges(*edges, *ext_targets); - } - htable_free(&external_mis); + jl_collect_new_roots(*method_roots_list, *new_specializations, worklist_key); + jl_collect_edges(*edges, *ext_targets, *new_specializations); + } assert(edges_map == NULL); // jl_collect_edges clears this when done JL_GC_POP(); diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index c6b553ede8849..f636485541aed 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -1,5 +1,5 @@ static htable_t new_code_instance_validate; -static htable_t external_mis; + // inverse of backedges graph (caller=>callees hash) jl_array_t *edges_map JL_GLOBALLY_ROOTED = NULL; // rooted for the duration of our uses of this @@ -108,11 +108,6 @@ JL_DLLEXPORT void jl_push_newly_inferred(jl_value_t* ci) } -static int method_instance_in_queue(jl_method_instance_t *mi) -{ - return ptrhash_get(&external_mis, mi) != HT_NOTFOUND; -} - // compute whether a type references something internal to worklist // and thus could not have existed before deserialize // and thus does not need delayed unique-ing @@ -216,10 +211,10 @@ static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, return found; } -// given the list of CodeInstances that were inferred during the -// build, select those that are (1) external, and (2) are inferred to be called -// from the worklist or explicitly added by a `precompile` statement. -// Also prepares for method_instance_in_queue queries. +// Given the list of CodeInstances that were inferred during the build, select +// those that are (1) external, (2) still valid, and (3) are inferred to be +// called from the worklist or explicitly added by a `precompile` statement. +// These will be preserved in the image. static jl_array_t *queue_external_cis(jl_array_t *list) { if (list == NULL) @@ -238,17 +233,12 @@ static jl_array_t *queue_external_cis(jl_array_t *list) assert(jl_is_code_instance(ci)); jl_method_instance_t *mi = ci->def; jl_method_t *m = mi->def.method; - if (jl_is_method(m)) { - if (jl_object_in_image((jl_value_t*)m->module)) { - if (ptrhash_get(&external_mis, mi) == HT_NOTFOUND) { - int found = has_backedge_to_worklist(mi, &visited, &stack); - assert(found == 0 || found == 1); - assert(stack.len == 0); - if (found == 1) { - ptrhash_put(&external_mis, mi, mi); - jl_array_ptr_1d_push(new_specializations, (jl_value_t*)ci); - } - } + if (jl_is_method(m) && jl_object_in_image((jl_value_t*)m->module)) { + int found = has_backedge_to_worklist(mi, &visited, &stack); + assert(found == 0 || found == 1); + assert(stack.len == 0); + if (found == 1 && ci->max_world == ~(size_t)0) { + jl_array_ptr_1d_push(new_specializations, (jl_value_t*)ci); } } } @@ -259,31 +249,25 @@ static jl_array_t *queue_external_cis(jl_array_t *list) } // New roots for external methods -static void jl_collect_methods(htable_t *mset, jl_array_t *new_specializations) +static void jl_collect_new_roots(jl_array_t *roots, jl_array_t *new_specializations, uint64_t key) { - size_t i, l = new_specializations ? jl_array_len(new_specializations) : 0; - jl_value_t *v; - jl_method_t *m; - for (i = 0; i < l; i++) { - v = jl_array_ptr_ref(new_specializations, i); - assert(jl_is_code_instance(v)); - m = ((jl_code_instance_t*)v)->def->def.method; + htable_t mset; + htable_new(&mset, 0); + size_t l = new_specializations ? jl_array_len(new_specializations) : 0; + for (size_t i = 0; i < l; i++) { + jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(new_specializations, i); + assert(jl_is_code_instance(ci)); + jl_method_t *m = ci->def->def.method; assert(jl_is_method(m)); - ptrhash_put(mset, (void*)m, (void*)m); + ptrhash_put(&mset, (void*)m, (void*)m); } -} - -static void jl_collect_new_roots(jl_array_t *roots, const htable_t *mset, uint64_t key) -{ - size_t i, sz = mset->size; int nwithkey; - jl_method_t *m; - void *const *table = mset->table; + void *const *table = mset.table; jl_array_t *newroots = NULL; JL_GC_PUSH1(&newroots); - for (i = 0; i < sz; i += 2) { + for (size_t i = 0; i < mset.size; i += 2) { if (table[i+1] != HT_NOTFOUND) { - m = (jl_method_t*)table[i]; + jl_method_t *m = (jl_method_t*)table[i]; assert(jl_is_method(m)); nwithkey = nroots_with_key(m, key); if (nwithkey) { @@ -305,6 +289,7 @@ static void jl_collect_new_roots(jl_array_t *roots, const htable_t *mset, uint64 } } JL_GC_POP(); + htable_free(&mset); } // Create the forward-edge map (caller => callees) @@ -422,9 +407,18 @@ static void jl_record_edges(jl_method_instance_t *caller, arraylist_t *wq, jl_ar // Extract `edges` and `ext_targets` from `edges_map` // `edges` = [caller1, targets_indexes1, ...], the list of methods and their edges // `ext_targets` is [invokesig1, callee1, matches1, ...], the edges for each target -static void jl_collect_edges(jl_array_t *edges, jl_array_t *ext_targets) +static void jl_collect_edges(jl_array_t *edges, jl_array_t *ext_targets, jl_array_t *external_cis) { size_t world = jl_atomic_load_acquire(&jl_world_counter); + htable_t external_mis; + htable_new(&external_mis, 0); + if (external_cis) { + for (size_t i = 0; i < jl_array_len(external_cis); i++) { + jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(external_cis, i); + jl_method_instance_t *mi = ci->def; + ptrhash_put(&external_mis, (void*)mi, (void*)mi); + } + } arraylist_t wq; arraylist_new(&wq, 0); void **table = (void**)jl_array_data(edges_map); // edges_map is caller => callees @@ -438,10 +432,11 @@ static void jl_collect_edges(jl_array_t *edges, jl_array_t *ext_targets) continue; assert(jl_is_method_instance(caller) && jl_is_method(caller->def.method)); if (!jl_object_in_image((jl_value_t*)caller->def.method->module) || - method_instance_in_queue(caller)) { + ptrhash_get(&external_mis, caller) != HT_NOTFOUND) { jl_record_edges(caller, &wq, edges); } } + htable_free(&external_mis); while (wq.len) { jl_method_instance_t *caller = (jl_method_instance_t*)arraylist_pop(&wq); jl_record_edges(caller, &wq, edges); @@ -1060,6 +1055,7 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets, jl_a htable_reset(&visited, l); for (i = 0; i < l; i++) { jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(ci_list, i); + assert(ci->max_world == 1 || ci->max_world == ~(size_t)0); assert(ptrhash_get(&visited, (void*)ci->def) == HT_NOTFOUND); // check that we don't have multiple cis for same mi ptrhash_put(&visited, (void*)ci->def, (void*)ci); } @@ -1120,7 +1116,7 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets, jl_a assert(jl_is_code_instance(ci)); jl_code_instance_t *codeinst = (jl_code_instance_t*)ci; remove_code_instance_from_validation(codeinst); // mark it as handled - assert(codeinst->min_world >= world && codeinst->inferred); + assert(codeinst->min_world == world && codeinst->inferred); codeinst->max_world = ~(size_t)0; if (jl_rettype_inferred(caller, world, ~(size_t)0) == jl_nothing) { jl_mi_cache_insert(caller, codeinst); @@ -1160,8 +1156,8 @@ static void validate_new_code_instances(void) //assert(0 && "unexpected unprocessed CodeInstance found"); jl_code_instance_t *ci = (jl_code_instance_t*)new_code_instance_validate.table[i]; JL_GC_PROMISE_ROOTED(ci); // TODO: this needs a root (or restructuring to avoid it) - assert(ci->min_world >= world && ci->inferred); - ci->max_world = ~(size_t)0; + assert(ci->min_world == world && ci->inferred); + assert(ci->max_world == ~(size_t)0); jl_method_instance_t *caller = ci->def; if (jl_rettype_inferred(caller, world, ~(size_t)0) == jl_nothing) { jl_mi_cache_insert(caller, ci); diff --git a/test/precompile.jl b/test/precompile.jl index 6c4c00dc14652..da44f4740d185 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -1658,64 +1658,73 @@ end precompile_test_harness("DynamicExpressions") do load_path # https://github.com/JuliaLang/julia/pull/47184#issuecomment-1364716312 write(joinpath(load_path, "Float16MWE.jl"), - """ - module Float16MWE - struct Node{T} - val::T - end - doconvert(::Type{<:Node}, val) = convert(Float16, val) - precompile(Tuple{typeof(doconvert), Type{Node{Float16}}, Float64}) - end # module Float16MWE - """) + """ + module Float16MWE + struct Node{T} + val::T + end + doconvert(::Type{<:Node}, val) = convert(Float16, val) + precompile(Tuple{typeof(doconvert), Type{Node{Float16}}, Float64}) + end # module Float16MWE + """) Base.compilecache(Base.PkgId("Float16MWE")) - (@eval (using Float16MWE)) - Base.invokelatest() do - @test Float16MWE.doconvert(Float16MWE.Node{Float16}, -1.2) === Float16(-1.2) - end + @eval using Float16MWE + @test @invokelatest(Float16MWE.doconvert(Float16MWE.Node{Float16}, -1.2)) === Float16(-1.2) end precompile_test_harness("BadInvalidations") do load_path write(joinpath(load_path, "BadInvalidations.jl"), - """ - module BadInvalidations + """ + module BadInvalidations Base.Experimental.@compiler_options compile=min optimize=1 getval() = Base.a_method_to_overwrite_in_test() getval() - end # module BadInvalidations - """) + end # module BadInvalidations + """) Base.compilecache(Base.PkgId("BadInvalidations")) - (@eval Base a_method_to_overwrite_in_test() = inferencebarrier(2)) - (@eval (using BadInvalidations)) - Base.invokelatest() do - @test BadInvalidations.getval() === 2 - end + @eval Base a_method_to_overwrite_in_test() = inferencebarrier(2) + @eval using BadInvalidations + @test Base.invokelatest(BadInvalidations.getval) === 2 end # https://github.com/JuliaLang/julia/issues/48074 precompile_test_harness("WindowsCacheOverwrite") do load_path # https://github.com/JuliaLang/julia/pull/47184#issuecomment-1364716312 write(joinpath(load_path, "WindowsCacheOverwrite.jl"), - """ - module WindowsCacheOverwrite - - end # module - """) + """ + module WindowsCacheOverwrite + end # module + """) ji, ofile = Base.compilecache(Base.PkgId("WindowsCacheOverwrite")) - (@eval (using WindowsCacheOverwrite)) + @eval using WindowsCacheOverwrite write(joinpath(load_path, "WindowsCacheOverwrite.jl"), - """ - module WindowsCacheOverwrite - - f() = "something new" - - end # module - """) + """ + module WindowsCacheOverwrite + f() = "something new" + end # module + """) ji_2, ofile_2 = Base.compilecache(Base.PkgId("WindowsCacheOverwrite")) @test ofile_2 == Base.ocachefile_from_cachefile(ji_2) end +precompile_test_harness("Issue #48391") do load_path + write(joinpath(load_path, "I48391.jl"), + """ + module I48391 + struct SurrealFinite <: Real end + precompile(Tuple{typeof(Base.isless), SurrealFinite, SurrealFinite}) + Base.:(<)(x::SurrealFinite, y::SurrealFinite) = "good" + end + """) + ji, ofile = Base.compilecache(Base.PkgId("I48391")) + @eval using I48391 + x = Base.invokelatest(I48391.SurrealFinite) + @test Base.invokelatest(isless, x, x) === "good" + @test_throws ErrorException isless(x, x) +end + empty!(Base.DEPOT_PATH) append!(Base.DEPOT_PATH, original_depot_path) empty!(Base.LOAD_PATH) From d4e0f366651e67d0fca4c77b10457b22fbe7e3c8 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 7 Feb 2023 08:59:12 +0100 Subject: [PATCH 39/45] Merge pull request #48513 from JuliaLang/jn/extend-once ensure extension triggers are only run by the package that satified them --- base/loading.jl | 149 ++++++++++++++++++++++++++++++------------------ 1 file changed, 94 insertions(+), 55 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 0d26912a12e7b..a9b1c54f56e50 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1076,9 +1076,9 @@ function register_restored_modules(sv::SimpleVector, pkg::PkgId, path::String) end function run_package_callbacks(modkey::PkgId) + run_extension_callbacks(modkey) assert_havelock(require_lock) unlock(require_lock) - run_extension_callbacks() try for callback in package_callbacks invokelatest(callback, modkey) @@ -1099,23 +1099,23 @@ end ############## mutable struct ExtensionId - const id::PkgId # Could be symbol? - const parentid::PkgId - const triggers::Vector{PkgId} # What packages have to be loaded for the extension to get loaded - triggered::Bool - succeeded::Bool + const id::PkgId + const parentid::PkgId # just need the name, for printing + ntriggers::Int # how many more packages must be defined until this is loaded end -const EXT_DORMITORY = ExtensionId[] +const EXT_DORMITORY = Dict{PkgId,Vector{ExtensionId}}() +const EXT_DORMITORY_FAILED = ExtensionId[] function insert_extension_triggers(pkg::PkgId) pkg.uuid === nothing && return + extensions_added = Set{PkgId}() for env in load_path() - insert_extension_triggers(env, pkg) + insert_extension_triggers!(extensions_added, env, pkg) end end -function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missing} +function insert_extension_triggers!(extensions_added::Set{PkgId}, env::String, pkg::PkgId)::Union{Nothing,Missing} project_file = env_project_file(env) if project_file isa String manifest_file = project_file_manifest_path(project_file) @@ -1133,7 +1133,7 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi extensions === nothing && return weakdeps === nothing && return if weakdeps isa Dict{String, Any} - return _insert_extension_triggers(pkg, extensions, weakdeps) + return _insert_extension_triggers!(extensions_added, pkg, extensions, weakdeps) end d_weakdeps = Dict{String, String}() @@ -1148,7 +1148,7 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi d_weakdeps[dep_name] = uuid end @assert length(d_weakdeps) == length(weakdeps) - return _insert_extension_triggers(pkg, extensions, d_weakdeps) + return _insert_extension_triggers!(extensions_added, pkg, extensions, d_weakdeps) end end end @@ -1156,62 +1156,89 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi return nothing end -function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, <:Any}, weakdeps::Dict{String, <:Any}) +function _insert_extension_triggers!(extensions_added::Set{PkgId}, parent::PkgId, extensions::Dict{String, <:Any}, weakdeps::Dict{String, <:Any}) for (ext::String, triggers::Union{String, Vector{String}}) in extensions triggers isa String && (triggers = [triggers]) - triggers_id = PkgId[] id = PkgId(uuid5(parent.uuid, ext), ext) + # Only add triggers for an extension from one env. + id in extensions_added && continue + push!(extensions_added, id) + gid = ExtensionId(id, parent, 1 + length(triggers)) + trigger1 = get!(Vector{ExtensionId}, EXT_DORMITORY, parent) + push!(trigger1, gid) for trigger in triggers # TODO: Better error message if this lookup fails? uuid_trigger = UUID(weakdeps[trigger]::String) - push!(triggers_id, PkgId(uuid_trigger, trigger)) + trigger_id = PkgId(uuid_trigger, trigger) + if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id) + trigger1 = get!(Vector{ExtensionId}, EXT_DORMITORY, trigger_id) + push!(trigger1, gid) + else + gid.ntriggers -= 1 + end end - gid = ExtensionId(id, parent, triggers_id, false, false) - push!(EXT_DORMITORY, gid) end end -function run_extension_callbacks(; force::Bool=false) - try - # TODO, if `EXT_DORMITORY` becomes very long, do something smarter - for extid in EXT_DORMITORY - extid.succeeded && continue - !force && extid.triggered && continue - if all(x -> haskey(Base.loaded_modules, x) && !haskey(package_locks, x), extid.triggers) - ext_not_allowed_load = nothing - extid.triggered = true - # It is possible that some of the triggers were loaded in an environment - # below the one of the parent. This will cause a load failure when the - # pkg ext tries to load the triggers. Therefore, check this first - # before loading the pkg ext. - for trigger in extid.triggers - pkgenv = Base.identify_package_env(extid.id, trigger.name) - if pkgenv === nothing - ext_not_allowed_load = trigger - break - else - pkg, env = pkgenv - path = Base.locate_package(pkg, env) - if path === nothing - ext_not_allowed_load = trigger - break - end - end - end - if ext_not_allowed_load !== nothing - @debug "Extension $(extid.id.name) of $(extid.parentid.name) not loaded due to \ - $(ext_not_allowed_load.name) loaded in environment lower in load path" - else - require(extid.id) - @debug "Extension $(extid.id.name) of $(extid.parentid.name) loaded" +function run_extension_callbacks(extid::ExtensionId) + assert_havelock(require_lock) + succeeded = try + _require_prelocked(extid.id) + @debug "Extension $(extid.id.name) of $(extid.parentid.name) loaded" + true + catch + # Try to continue loading if loading an extension errors + @error "Error during loading of extension $(extid.id.name) of $(extid.parentid.name)" + false + end + return succeeded +end + +function run_extension_callbacks(pkgid::PkgId) + assert_havelock(require_lock) + # take ownership of extids that depend on this pkgid + extids = pop!(EXT_DORMITORY, pkgid, nothing) + extids === nothing && return + for extid in extids + if extid.ntriggers > 0 + # It is possible that pkgid was loaded in an environment + # below the one of the parent. This will cause a load failure when the + # pkg ext tries to load the triggers. Therefore, check this first + # before loading the pkg ext. + pkgenv = Base.identify_package_env(extid.id, pkgid.name) + ext_not_allowed_load = false + if pkgenv === nothing + ext_not_allowed_load = true + else + pkg, env = pkgenv + path = Base.locate_package(pkg, env) + if path === nothing + ext_not_allowed_load = true end - extid.succeeded = true + end + if ext_not_allowed_load + @debug "Extension $(extid.id.name) of $(extid.parentid.name) will not be loaded \ + since $(pkgid.name) loaded in environment lower in load path" + # indicate extid is expected to fail + extid.ntriggers *= -1 + else + # indicate pkgid is loaded + extid.ntriggers -= 1 end end - catch - # Try to continue loading if loading an extension errors - errs = current_exceptions() - @error "Error during loading of extension" exception=errs + if extid.ntriggers < 0 + # indicate pkgid is loaded + extid.ntriggers += 1 + succeeded = false + else + succeeded = true + end + if extid.ntriggers == 0 + # actually load extid, now that all dependencies are met, + # and record the result + succeeded = succeeded && run_extension_callbacks(extid) + succeeded || push!(EXT_DORMITORY_FAILED, extid) + end end nothing end @@ -1224,7 +1251,19 @@ This is used in cases where the automatic loading of an extension failed due to some problem with the extension. Instead of restarting the Julia session, the extension can be fixed, and this function run. """ -retry_load_extensions() = run_extension_callbacks(; force=true) +function retry_load_extensions() + @lock require_lock begin + # this copy is desired since run_extension_callbacks will release this lock + # so this can still mutate the list to drop successful ones + failed = copy(EXT_DORMITORY_FAILED) + empty!(EXT_DORMITORY_FAILED) + filter!(failed) do extid + return !run_extension_callbacks(extid) + end + prepend!(EXT_DORMITORY_FAILED, failed) + end + nothing +end """ get_extension(parent::Module, extension::Symbol) From 27c6d97665448ecf77006271190b4f57939263ae Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 6 Feb 2023 12:25:44 -0600 Subject: [PATCH 40/45] Protect `cmd_gen` against invalidation (#48557) This gets used by `Base.require`, arguably the most painful of all invalidations. CSV is one package that invalidates it. (cherry picked from commit 5721ae700cd10c284ceb32e603792e5c487d6167) --- base/cmd.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/cmd.jl b/base/cmd.jl index ecabb5c32b1d0..4d3e514af6776 100644 --- a/base/cmd.jl +++ b/base/cmd.jl @@ -462,7 +462,7 @@ function cmd_gen(parsed) (ignorestatus, flags, env, dir) = (cmd.ignorestatus, cmd.flags, cmd.env, cmd.dir) append!(args, cmd.exec) for arg in tail(parsed) - append!(args, arg_gen(arg...)::Vector{String}) + append!(args, Base.invokelatest(arg_gen, arg...)::Vector{String}) end return Cmd(Cmd(args), ignorestatus, flags, env, dir) else From 1ef6c96c9f3adb54bc60ac515ab8861c696c44fb Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Mon, 6 Feb 2023 23:43:38 -0300 Subject: [PATCH 41/45] Change uses of int to size_t in MurmurHash (#48562) * Change uses of int to size_t in MurmurHash (cherry picked from commit 3fe69f4f4327dd4f9d39a8d8b5ff2d959113d680) --- src/support/MurmurHash3.c | 18 +++++++++--------- src/support/MurmurHash3.h | 8 ++++---- test/hashing.jl | 8 ++++++++ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/support/MurmurHash3.c b/src/support/MurmurHash3.c index fce7351f90ffe..43bd015ddd69f 100644 --- a/src/support/MurmurHash3.c +++ b/src/support/MurmurHash3.c @@ -58,11 +58,11 @@ FORCE_INLINE uint64_t fmix64 ( uint64_t k ) //----------------------------------------------------------------------------- -void MurmurHash3_x86_32 ( const void * key, int len, +void MurmurHash3_x86_32 ( const void * key, size_t len, uint32_t seed, void * out ) { const uint8_t * data = (const uint8_t*)key; - const int nblocks = len / 4; + const size_t nblocks = len / 4; uint32_t h1 = seed; @@ -74,7 +74,7 @@ void MurmurHash3_x86_32 ( const void * key, int len, const uint8_t * tail = data + nblocks*4; - for(int i = -nblocks; i; i++) + for(size_t i = -nblocks; i; i++) { uint32_t k1 = jl_load_unaligned_i32(tail + sizeof(uint32_t)*i); @@ -112,11 +112,11 @@ void MurmurHash3_x86_32 ( const void * key, int len, //----------------------------------------------------------------------------- -void MurmurHash3_x86_128 ( const void * key, const int len, +void MurmurHash3_x86_128 ( const void * key, const size_t len, uint32_t seed, void * out ) { const uint8_t * data = (const uint8_t*)key; - const int nblocks = len / 16; + const size_t nblocks = len / 16; uint32_t h1 = seed; uint32_t h2 = seed; @@ -133,7 +133,7 @@ void MurmurHash3_x86_128 ( const void * key, const int len, const uint8_t *tail = data + nblocks*16; - for(int i = -nblocks; i; i++) + for(size_t i = -nblocks; i; i++) { uint32_t k1 = jl_load_unaligned_i32(tail + sizeof(uint32_t)*(i*4 + 0)); uint32_t k2 = jl_load_unaligned_i32(tail + sizeof(uint32_t)*(i*4 + 1)); @@ -218,11 +218,11 @@ void MurmurHash3_x86_128 ( const void * key, const int len, //----------------------------------------------------------------------------- -void MurmurHash3_x64_128 ( const void * key, const int len, +void MurmurHash3_x64_128 ( const void * key, const size_t len, const uint32_t seed, void * out ) { const uint8_t * data = (const uint8_t*)key; - const int nblocks = len / 16; + const size_t nblocks = len / 16; uint64_t h1 = seed; uint64_t h2 = seed; @@ -233,7 +233,7 @@ void MurmurHash3_x64_128 ( const void * key, const int len, //---------- // body - for(int i = 0; i < nblocks; i++) + for(size_t i = 0; i < nblocks; i++) { uint64_t k1 = jl_load_unaligned_i64(data + sizeof(uint64_t)*(i*2 + 0)); uint64_t k2 = jl_load_unaligned_i64(data + sizeof(uint64_t)*(i*2 + 1)); diff --git a/src/support/MurmurHash3.h b/src/support/MurmurHash3.h index e3e7da9df62fa..6137098d6828c 100644 --- a/src/support/MurmurHash3.h +++ b/src/support/MurmurHash3.h @@ -8,14 +8,14 @@ //----------------------------------------------------------------------------- // Platform-specific functions and macros #include - +#include //----------------------------------------------------------------------------- -void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out ); +void MurmurHash3_x86_32 ( const void * key, size_t len, uint32_t seed, void * out ); -void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out ); +void MurmurHash3_x86_128 ( const void * key, size_t len, uint32_t seed, void * out ); -void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out ); +void MurmurHash3_x64_128 ( const void * key, size_t len, uint32_t seed, void * out ); //----------------------------------------------------------------------------- diff --git a/test/hashing.jl b/test/hashing.jl index 9bd076554962f..9f40e7a4a73ac 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -284,3 +284,11 @@ end end end end + +if Sys.WORD_SIZE >= 64 + @testset "very large string" begin + N = 2^31+1 + s = String('\0'^N); + objectid(s) + end +end From 997ba79d322e1d2285bf0fe9cc3b32f90d1c23d6 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Mon, 6 Feb 2023 23:15:09 -0500 Subject: [PATCH 42/45] [compiler] Fix effects of supertype abstract interpretation (#48566) This `abstract_call_known` recursion inserted `EFFECTS_TOTAL` which is incorrect because `<:` and `>:` can throw if the arguments are not types. (cherry picked from commit 0ab6e2f51ce3ddabda44eb17f358d039a3eb1f6b) --- base/compiler/abstractinterpretation.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index ae508ab4b8bf3..554ba191d4449 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1890,7 +1890,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), fargs = nothing end argtypes = Any[typeof(<:), argtypes[3], argtypes[2]] - return CallMeta(abstract_call_known(interp, <:, ArgInfo(fargs, argtypes), si, sv, max_methods).rt, EFFECTS_TOTAL, NoCallInfo()) + return abstract_call_known(interp, <:, ArgInfo(fargs, argtypes), si, sv, max_methods) elseif la == 2 && (a2 = argtypes[2]; isa(a2, Const)) && (svecval = a2.val; isa(svecval, SimpleVector)) && istopfunction(f, :length) From a3b4c3b57dc0e6ca8522055948fd2bbf1bd478ed Mon Sep 17 00:00:00 2001 From: robsmith11 Date: Mon, 6 Feb 2023 02:24:28 +0700 Subject: [PATCH 43/45] add CTRL_R to repl precompile (#48539) Co-authored-by: robsmith11 (cherry picked from commit 7827b0886f1eb4660309d9697a95e67aa4ad342a) --- contrib/generate_precompile.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/generate_precompile.jl b/contrib/generate_precompile.jl index 53ca9403463b3..45226c58d3371 100644 --- a/contrib/generate_precompile.jl +++ b/contrib/generate_precompile.jl @@ -16,6 +16,7 @@ import .FakePTYs: open_fake_pty using Base.Meta CTRL_C = '\x03' +CTRL_R = '\x12' UP_ARROW = "\e[A" DOWN_ARROW = "\e[B" @@ -58,6 +59,7 @@ display([1 2; 3 4]) @time 1+1 ; pwd $CTRL_C +$CTRL_R$CTRL_C ? reinterpret using Ra\t$CTRL_C \\alpha\t$CTRL_C From c15f52078255eecb269ef018b10d0421e2f833da Mon Sep 17 00:00:00 2001 From: Philip Bittihn Date: Sun, 5 Feb 2023 01:43:23 +0100 Subject: [PATCH 44/45] Add path tracking options from #44359 to docs (#48527) (cherry picked from commit 4d9eb896db40684cbdf9c991a51642c3e6f99276) --- doc/src/manual/command-line-interface.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/src/manual/command-line-interface.md b/doc/src/manual/command-line-interface.md index e35cbf5e313e7..54c56a354c7a3 100644 --- a/doc/src/manual/command-line-interface.md +++ b/doc/src/manual/command-line-interface.md @@ -125,8 +125,10 @@ The following is a complete list of command-line switches available when launchi |`--check-bounds={yes\|no\|auto*}` |Emit bounds checks always, never, or respect `@inbounds` declarations ($)| |`--math-mode={ieee,fast}` |Disallow or enable unsafe floating point optimizations (overrides `@fastmath` declaration)| |`--code-coverage[={none*\|user\|all}]` |Count executions of source lines (omitting setting is equivalent to `user`)| +|`--code-coverage=@` |Count executions but only in files that fall under the given file path/directory. The `@` prefix is required to select this option. A `@` with no path will track the current directory.| |`--code-coverage=tracefile.info` |Append coverage information to the LCOV tracefile (filename supports format tokens).| |`--track-allocation[={none*\|user\|all}]` |Count bytes allocated by each source line (omitting setting is equivalent to "user")| +|`--track-allocation=@` |Count bytes but only in files that fall under the given file path/directory. The `@` prefix is required to select this option. A `@` with no path will track the current directory.| |`--bug-report=KIND` |Launch a bug report session. It can be used to start a REPL, run a script, or evaluate expressions. It first tries to use BugReporting.jl installed in current environment and falls back to the latest compatible BugReporting.jl if not. For more information, see `--bug-report=help`.| |`--compile={yes*\|no\|all\|min}` |Enable or disable JIT compiler, or request exhaustive or minimal compilation| |`--output-o ` |Generate an object file (including system image data)| From d4a4629225001c406517e91b22da7bb7727f0601 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 7 Feb 2023 13:26:57 +0100 Subject: [PATCH 45/45] give a hint towards `Base.retry_load_extensions` when an extension fails to load (#48571) (cherry picked from commit e32e20c7ca3b63dafa85a3a0eca9515d055e9657) --- base/loading.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index a9b1c54f56e50..7ab232338a456 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1188,7 +1188,8 @@ function run_extension_callbacks(extid::ExtensionId) true catch # Try to continue loading if loading an extension errors - @error "Error during loading of extension $(extid.id.name) of $(extid.parentid.name)" + @error "Error during loading of extension $(extid.id.name) of $(extid.parentid.name), \ + use `Base.retry_load_extensions()` to retry." false end return succeeded