diff --git a/.github/workflows/statuses.yml b/.github/workflows/statuses.yml index 36a694a7c6d20..7116a766ad8df 100644 --- a/.github/workflows/statuses.yml +++ b/.github/workflows/statuses.yml @@ -48,8 +48,6 @@ jobs: - run: | declare -a CONTEXT_LIST=( "buildbot/tester_freebsd64" - "buildbot/tester_win32" - "buildbot/tester_win64" ) for CONTEXT in "${CONTEXT_LIST[@]}" do diff --git a/Make.inc b/Make.inc index 4ef326b04ffbb..8b7f9c1c4ac32 100644 --- a/Make.inc +++ b/Make.inc @@ -66,6 +66,7 @@ USE_SYSTEM_PATCHELF:=0 USE_SYSTEM_LIBWHICH:=0 USE_SYSTEM_ZLIB:=0 USE_SYSTEM_P7ZIP:=0 +USE_SYSTEM_LLD:=0 # Link to the LLVM shared library USE_LLVM_SHLIB := 1 @@ -347,6 +348,7 @@ BUILD_LLVM_CLANG := 0 # see http://lldb.llvm.org/build.html for dependencies BUILD_LLDB := 0 BUILD_LIBCXX := 0 +BUILD_LLD := 1 # Options to enable Polly and its code-generation options USE_POLLY := 0 @@ -705,7 +707,7 @@ JLDFLAGS += $(SANITIZE_LDFLAGS) endif # SANITIZE TAR := $(shell which gtar 2>/dev/null || which tar 2>/dev/null) -TAR_TEST := $(shell $(TAR) --help 2>&1 | egrep 'bsdtar|strip-components') +TAR_TEST := $(shell $(TAR) --help 2>&1 | grep -E 'bsdtar|strip-components') ifeq (,$(findstring components,$(TAR_TEST))) ifneq (bsdtar,$(findstring bsdtar,$(TAR_TEST))) $(error "please install either GNU tar or bsdtar") @@ -772,6 +774,8 @@ else ifeq (cygwin, $(shell $(CC) -dumpmachine | cut -d\- -f3)) $(error "cannot build julia with cygwin-target compilers. set XC_HOST to i686-w64-mingw32 or x86_64-w64-mingw32 for mingw cross-compile") else ifeq (msys, $(shell $(CC) -dumpmachine | cut -d\- -f3)) $(error "cannot build julia with msys-target compilers. please see the README.windows document for instructions on setting up mingw-w64 compilers") +else ifneq (,$(findstring MSYS,$(shell uname))) +$(error "cannot build julia from a msys shell. please launch a mingw shell instead by setting MSYSTEM=MINGW64") endif ifeq ($(BUILD_OS),Darwin) @@ -1149,7 +1153,7 @@ LIBGFORTRAN_VERSION := $(subst libgfortran,,$(filter libgfortran%,$(subst -,$(SP # Note: we explicitly _do not_ define `CSL` here, since it requires some more # advanced techniques to decide whether it should be installed from a BB source # or not. See `deps/csl.mk` for more detail. -BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP +BB_PROJECTS := BLASTRAMPOLINE OPENBLAS LLVM LIBSUITESPARSE OPENLIBM GMP MBEDTLS LIBSSH2 NGHTTP2 MPFR CURL LIBGIT2 PCRE LIBUV LIBUNWIND DSFMT OBJCONV ZLIB P7ZIP LLD define SET_BB_DEFAULT # First, check to see if BB is disabled on a global setting ifeq ($$(USE_BINARYBUILDER),0) @@ -1371,7 +1375,6 @@ CLANGSA_FLAGS := CLANGSA_CXXFLAGS := ifeq ($(OS), Darwin) # on new XCode, the files are hidden CLANGSA_FLAGS += -isysroot $(shell xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -CLANGSA_CXXFLAGS += -isystem $(shell xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1 endif ifeq ($(USEGCC),1) # try to help clang find the c++ files for CC by guessing the value for --prefix @@ -1397,13 +1400,13 @@ define symlink_target # (from, to-dir, to-name) CLEAN_TARGETS += clean-$$(abspath $(2)/$(3)) clean-$$(abspath $(2)/$(3)): ifeq ($(BUILD_OS), WINNT) - -cmd //C rmdir $$(call mingw_to_dos,$(2)/$(3),cd $(2) &&) + -cmd //C rmdir $$(call cygpath_w,$(2)/$(3)) else rm -rf $$(abspath $(2)/$(3)) endif $$(abspath $(2)/$(3)): | $$(abspath $(2)) ifeq ($$(BUILD_OS), WINNT) - @cmd //C mklink //J $$(call mingw_to_dos,$(2)/$(3),cd $(2) &&) $$(call mingw_to_dos,$(1),) + @cmd //C mklink //J $$(call cygpath_w,$(2)/$(3)) $$(call cygpath_w,$(1)) else ifneq (,$$(findstring CYGWIN,$$(BUILD_OS))) @cmd /C mklink /J $$(call cygpath_w,$(2)/$(3)) $$(call cygpath_w,$(1)) else ifdef JULIA_VAGRANT_BUILD @@ -1421,7 +1424,7 @@ WINE ?= wine # many of the following targets must be = not := because the expansion of the makefile functions (and $1) shouldn't happen until later ifeq ($(BUILD_OS), WINNT) # MSYS spawn = $(1) -cygpath_w = $(1) +cygpath_w = `cygpath -w $(1)` else ifneq (,$(findstring CYGWIN,$(BUILD_OS))) # Cygwin spawn = $(1) cygpath_w = `cygpath -w $(1)` diff --git a/Makefile b/Makefile index 54fa48d748c58..e9941bcb33dc2 100644 --- a/Makefile +++ b/Makefile @@ -229,8 +229,10 @@ endif endif endif +# Note that we disable MSYS2's path munging here, as otherwise +# it replaces our `:`-separated list as a `;`-separated one. define stringreplace - $(build_depsbindir)/stringreplace $$(strings -t x - $1 | grep $2 | awk '{print $$1;}') $3 255 "$(call cygpath_w,$1)" + MSYS2_ARG_CONV_EXCL='*' $(build_depsbindir)/stringreplace $$(strings -t x - $1 | grep $2 | awk '{print $$1;}') $3 255 "$(call cygpath_w,$1)" endef @@ -304,6 +306,9 @@ endif # Install `7z` into libexec/ $(INSTALL_M) $(build_bindir)/7z$(EXE) $(DESTDIR)$(libexecdir)/ + # Install `lld` into libexec/ + $(INSTALL_M) $(build_depsbindir)/lld$(EXE) $(DESTDIR)$(libexecdir)/ + # Copy public headers cp -R -L $(build_includedir)/julia/* $(DESTDIR)$(includedir)/julia # Copy system image @@ -428,6 +433,12 @@ ifneq ($(OPENBLAS_DYNAMIC_ARCH),1) endif endif endif + +ifeq ($(USE_BINARYBUILDER_OPENBLAS),0) + # https://github.com/JuliaLang/julia/issues/46579 + USE_BINARYBUILDER_OBJCONV=0 +endif + ifneq ($(prefix),$(abspath julia-$(JULIA_COMMIT))) $(error prefix must not be set for make binary-dist) endif @@ -451,8 +462,9 @@ endif exe: - # run Inno Setup to compile installer - $(call spawn,$(JULIAHOME)/dist-extras/inno/iscc.exe /DAppVersion=$(JULIA_VERSION) /DSourceDir="$(call cygpath_w,$(BUILDROOT)/julia-$(JULIA_COMMIT))" /DRepoDir="$(call cygpath_w,$(JULIAHOME))" /F"$(JULIA_BINARYDIST_FILENAME)" /O"$(call cygpath_w,$(BUILDROOT))" $(INNO_ARGS) $(call cygpath_w,$(JULIAHOME)/contrib/windows/build-installer.iss)) + # run Inno Setup to compile installer. + # Note that we disable MSYS2 path munging, as it interferes with the `/` options: + MSYS2_ARG_CONV_EXCL='*' $(call spawn,$(JULIAHOME)/dist-extras/inno/iscc.exe /DAppVersion=$(JULIA_VERSION) /DSourceDir="$(call cygpath_w,$(BUILDROOT)/julia-$(JULIA_COMMIT))" /DRepoDir="$(call cygpath_w,$(JULIAHOME))" /F"$(JULIA_BINARYDIST_FILENAME)" /O"$(call cygpath_w,$(BUILDROOT))" $(INNO_ARGS) $(call cygpath_w,$(JULIAHOME)/contrib/windows/build-installer.iss)) chmod a+x "$(BUILDROOT)/$(JULIA_BINARYDIST_FILENAME).exe" app: @@ -577,7 +589,7 @@ win-extras: cd $(JULIAHOME)/dist-extras && \ $(JLDOWNLOAD) https://www.jrsoftware.org/download.php/is.exe && \ chmod a+x is.exe && \ - $(call spawn, $(JULIAHOME)/dist-extras/is.exe /DIR="$(call cygpath_w,$(JULIAHOME)/dist-extras/inno)" /PORTABLE=1 /CURRENTUSER /VERYSILENT) + MSYS2_ARG_CONV_EXCL='*' $(call spawn, $(JULIAHOME)/dist-extras/is.exe /DIR="$(call cygpath_w,$(JULIAHOME)/dist-extras/inno)" /PORTABLE=1 /CURRENTUSER /VERYSILENT) # various statistics about the build that may interest the user ifeq ($(USE_SYSTEM_LLVM), 1) diff --git a/NEWS.md b/NEWS.md index 7944878fb6b96..92790c54e5b35 100644 --- a/NEWS.md +++ b/NEWS.md @@ -89,6 +89,7 @@ Library changes * `eachslice` now works over multiple dimensions; `eachslice`, `eachrow` and `eachcol` return a `Slices` object, which allows dispatching to provide more efficient methods ([#32310]). * `@kwdef` is now exported and added to the public API ([#46273]) +* An issue with order of operations in `fld1` is now fixed ([#28973]). Standard library changes ------------------------ @@ -129,6 +130,9 @@ Standard library changes via the `REPL.activate(::Module)` function or via typing the module in the REPL and pressing the keybinding Alt-m ([#33872]). +* An "IPython mode" which mimics the behaviour of the prompts and storing the evaluated result in `Out` can be + activated with `REPL.ipython_mode!()`. See the manual for how to enable this at startup. + #### SparseArrays #### Test diff --git a/base/Base.jl b/base/Base.jl index 5c84cd8b063a7..63728fdba3e4e 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -87,7 +87,7 @@ if false end """ - time_ns() + time_ns() -> UInt64 Get the time in nanoseconds. The time corresponding to 0 is undefined, and wraps every 5.8 years. """ @@ -107,9 +107,6 @@ include("options.jl") include("promotion.jl") include("tuple.jl") include("expr.jl") -Pair{A, B}(@nospecialize(a), @nospecialize(b)) where {A, B} = (@inline; Pair{A, B}(convert(A, a)::A, convert(B, b)::B)) -#Pair{Any, B}(@nospecialize(a::Any), b) where {B} = (@inline; Pair{Any, B}(a, Base.convert(B, b)::B)) -#Pair{A, Any}(a, @nospecialize(b::Any)) where {A} = (@inline; Pair{A, Any}(Base.convert(A, a)::A, b)) include("pair.jl") include("traits.jl") include("range.jl") @@ -125,6 +122,13 @@ include("pointer.jl") include("refvalue.jl") include("refpointer.jl") +# now replace the Pair constructor (relevant for NamedTuples) with one that calls our Base.convert +delete_method(which(Pair{Any,Any}, (Any, Any))) +@eval function (P::Type{Pair{A, B}})(@nospecialize(a), @nospecialize(b)) where {A, B} + @inline + return $(Expr(:new, :P, :(convert(A, a)), :(convert(B, b)))) +end + # The REPL stdlib hooks into Base using this Ref const REPL_MODULE_REF = Ref{Module}() @@ -429,6 +433,7 @@ end for m in methods(include) delete_method(m) end + # These functions are duplicated in client.jl/include(::String) for # nicer stacktraces. Modifications here have to be backported there include(mod::Module, _path::AbstractString) = _include(identity, mod, _path) diff --git a/base/Enums.jl b/base/Enums.jl index 413c880fcd3f2..aea3aeeee188e 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -17,7 +17,7 @@ abstract type Enum{T<:Integer} end basetype(::Type{<:Enum{T}}) where {T<:Integer} = T (::Type{T})(x::Enum{T2}) where {T<:Integer,T2<:Integer} = T(bitcast(T2, x))::T -Base.cconvert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer} = T(x) +Base.cconvert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer} = T(x)::T Base.write(io::IO, x::Enum{T}) where {T<:Integer} = write(io, T(x)) Base.read(io::IO, ::Type{T}) where {T<:Enum} = T(read(io, basetype(T))) diff --git a/base/Makefile b/base/Makefile index 1cc050f57fb4c..0d3e89b58de29 100644 --- a/base/Makefile +++ b/base/Makefile @@ -195,6 +195,18 @@ $(build_bindir)/7z$(EXE): rm -f "$@" && \ ln -svf "$(7Z_PATH)" "$@" +symlink_lld: $(build_bindir)/lld$(EXE) + +ifneq ($(USE_SYSTEM_LLD),0) +SYMLINK_SYSTEM_LIBRARIES += symlink_lld +LLD_PATH := $(shell which lld$(EXE)) +endif + +$(build_bindir)/lld$(EXE): + [ -e "$(LLD_PATH)" ] && \ + rm -f "$@" && \ + ln -svf "$(LLD_PATH)" "$@" + # the following excludes: libuv.a, libutf8proc.a ifneq ($(USE_SYSTEM_LIBM),0) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 78c074a331cfe..28e6ca8f0cdbd 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -14,8 +14,8 @@ See also: [`AbstractVector`](@ref), [`AbstractMatrix`](@ref), [`eltype`](@ref), AbstractArray convert(::Type{T}, a::T) where {T<:AbstractArray} = a -convert(::Type{AbstractArray{T}}, a::AbstractArray) where {T} = AbstractArray{T}(a) -convert(::Type{AbstractArray{T,N}}, a::AbstractArray{<:Any,N}) where {T,N} = AbstractArray{T,N}(a) +convert(::Type{AbstractArray{T}}, a::AbstractArray) where {T} = AbstractArray{T}(a)::AbstractArray{T} +convert(::Type{AbstractArray{T,N}}, a::AbstractArray{<:Any,N}) where {T,N} = AbstractArray{T,N}(a)::AbstractArray{T,N} """ size(A::AbstractArray, [dim]) @@ -1282,7 +1282,7 @@ function unsafe_getindex(A::AbstractArray, I...) r end -struct CanonicalIndexError +struct CanonicalIndexError <: Exception func::String type::Any CanonicalIndexError(func::String, @nospecialize(type)) = new(func, type) @@ -2244,7 +2244,8 @@ _typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = _typed_hvncat_0d_only_one( _typed_hvncat_0d_only_one() = throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) -_typed_hvncat(T::Type, dim::Int, ::Bool, xs...) = _typed_hvncat(T, Val(dim), xs...) # catches from _hvncat type promoters +# `@constprop :aggressive` here to form constant `Val(dim)` type to get type stability +@constprop :aggressive _typed_hvncat(T::Type, dim::Int, ::Bool, xs...) = _typed_hvncat(T, Val(dim), xs...) # catches from _hvncat type promoters function _typed_hvncat(::Type{T}, ::Val{N}) where {T, N} N < 0 && @@ -3473,8 +3474,9 @@ function circshift!(a::AbstractVector, shift::Integer) n == 0 && return shift = mod(shift, n) shift == 0 && return - reverse!(a, 1, shift) - reverse!(a, shift+1, length(a)) + l = lastindex(a) + reverse!(a, firstindex(a), l-shift) + reverse!(a, l-shift+1, lastindex(a)) reverse!(a) return a end diff --git a/base/abstractdict.jl b/base/abstractdict.jl index 7f1d8b4a1c504..39de4c441a966 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -565,7 +565,7 @@ push!(t::AbstractDict, p::Pair, q::Pair, r::Pair...) = push!(push!(push!(t, p), convert(::Type{T}, x::T) where {T<:AbstractDict} = x function convert(::Type{T}, x::AbstractDict) where T<:AbstractDict - h = T(x) + h = T(x)::T if length(h) != length(x) error("key collision during dictionary conversion") end diff --git a/base/abstractset.jl b/base/abstractset.jl index 85d81480ab990..62784af2bd67b 100644 --- a/base/abstractset.jl +++ b/base/abstractset.jl @@ -248,7 +248,6 @@ end Construct the symmetric difference of elements in the passed in sets. When `s` is not an `AbstractSet`, the order is maintained. -Note that in this case the multiplicity of elements matters. See also [`symdiff!`](@ref), [`setdiff`](@ref), [`union`](@ref) and [`intersect`](@ref). @@ -261,11 +260,6 @@ julia> symdiff([1,2,3], [3,4,5], [4,5,6]) 6 julia> symdiff([1,2,1], [2, 1, 2]) -2-element Vector{Int64}: - 1 - 2 - -julia> symdiff(unique([1,2,1]), unique([2, 1, 2])) Int64[] ``` """ @@ -286,7 +280,9 @@ function symdiff!(s::AbstractSet, itrs...) return s end -function symdiff!(s::AbstractSet, itr) +symdiff!(s::AbstractSet, itr) = symdiff!(s::AbstractSet, Set(itr)) + +function symdiff!(s::AbstractSet, itr::AbstractSet) for x in itr x in s ? delete!(s, x) : push!(s, x) end diff --git a/base/accumulate.jl b/base/accumulate.jl index 663bd850695a8..eeb9759e125c7 100644 --- a/base/accumulate.jl +++ b/base/accumulate.jl @@ -280,7 +280,7 @@ function accumulate(op, A; dims::Union{Nothing,Integer}=nothing, kw...) elseif keys(nt) === (:init,) out = similar(A, promote_op(op, typeof(nt.init), eltype(A))) else - throw(ArgumentError("acccumulate does not support the keyword arguments $(setdiff(keys(nt), (:init,)))")) + throw(ArgumentError("accumulate does not support the keyword arguments $(setdiff(keys(nt), (:init,)))")) end accumulate!(op, out, A; dims=dims, kw...) end @@ -341,7 +341,7 @@ function accumulate!(op, B, A; dims::Union{Integer, Nothing} = nothing, kw...) elseif keys(kw) === (:init,) _accumulate!(op, B, A, dims, Some(nt.init)) else - throw(ArgumentError("acccumulate! does not support the keyword arguments $(setdiff(keys(nt), (:init,)))")) + throw(ArgumentError("accumulate! does not support the keyword arguments $(setdiff(keys(nt), (:init,)))")) end end diff --git a/base/array.jl b/base/array.jl index 85296b4d94f21..c27b2f6c7d524 100644 --- a/base/array.jl +++ b/base/array.jl @@ -610,7 +610,7 @@ oneunit(x::AbstractMatrix{T}) where {T} = _one(oneunit(T), x) ## Conversions ## -convert(::Type{T}, a::AbstractArray) where {T<:Array} = a isa T ? a : T(a) +convert(::Type{T}, a::AbstractArray) where {T<:Array} = a isa T ? a : T(a)::T promote_rule(a::Type{Array{T,n}}, b::Type{Array{S,n}}) where {T,n,S} = el_same(promote_type(T,S), a, b) @@ -2325,7 +2325,7 @@ findall(testf::Function, A) = collect(first(p) for p in pairs(A) if testf(last(p # Broadcasting is much faster for small testf, and computing # integer indices from logical index using findall has a negligible cost -findall(testf::Function, A::AbstractArray) = findall(testf.(A)) +findall(testf::F, A::AbstractArray) where {F<:Function} = findall(testf.(A)) """ findall(A) @@ -2633,6 +2633,33 @@ function filter!(f, a::AbstractVector) return a end +""" + filter(f) + +Create a function that filters its arguments with function `f` using [`filter`](@ref), i.e. +a function equivalent to `x -> filter(f, x)`. + +The returned function is of type `Base.Fix1{typeof(filter)}`, which can be +used to implement specialized methods. + +# Examples +```jldoctest +julia> (1, 2, Inf, 4, NaN, 6) |> filter(isfinite) +(1, 2, 4, 6) + +julia> map(filter(iseven), [1:3, 2:4, 3:5]) +3-element Vector{Vector{Int64}}: + [2] + [2, 4] + [4] +``` +!!! compat "Julia 1.8" + This method requires at least Julia 1.8. +""" +function filter(f) + Fix1(filter, f) +end + """ keepat!(a::Vector, inds) keepat!(a::BitVector, inds) diff --git a/base/arrayshow.jl b/base/arrayshow.jl index 0d480b64bb32d..e3028cd65dfe0 100644 --- a/base/arrayshow.jl +++ b/base/arrayshow.jl @@ -278,7 +278,7 @@ show_nd(io::IO, a::AbstractArray, print_matrix::Function, show_full::Bool) = _show_nd(io, inferencebarrier(a), print_matrix, show_full, map(unitrange, axes(a))) function _show_nd(io::IO, @nospecialize(a::AbstractArray), print_matrix::Function, show_full::Bool, axs::Tuple{Vararg{AbstractUnitRange}}) - limit::Bool = get(io, :limit, false) + limit = get(io, :limit, false)::Bool if isempty(a) return end @@ -361,7 +361,7 @@ print_array(io::IO, X::AbstractArray) = show_nd(io, X, print_matrix, true) # typeinfo aware # implements: show(io::IO, ::MIME"text/plain", X::AbstractArray) function show(io::IO, ::MIME"text/plain", X::AbstractArray) - if isempty(X) && (get(io, :compact, false) || X isa Vector) + if isempty(X) && (get(io, :compact, false)::Bool || X isa Vector) return show(io, X) end # 0) show summary before setting :compact @@ -374,12 +374,12 @@ function show(io::IO, ::MIME"text/plain", X::AbstractArray) if !haskey(io, :compact) && length(axes(X, 2)) > 1 io = IOContext(io, :compact => true) end - if get(io, :limit, false) && eltype(X) === Method + if get(io, :limit, false)::Bool && eltype(X) === Method # override usual show method for Vector{Method}: don't abbreviate long lists io = IOContext(io, :limit => false) end - if get(io, :limit, false) && displaysize(io)[1]-4 <= 0 + if get(io, :limit, false)::Bool && displaysize(io)[1]-4 <= 0 return print(io, " …") else println(io) @@ -516,7 +516,7 @@ function show_vector(io::IO, v, opn='[', cls=']') if !implicit io = IOContext(io, :typeinfo => eltype(v)) end - limited = get(io, :limit, false) + limited = get(io, :limit, false)::Bool if limited && length(v) > 20 axs1 = axes1(v) @@ -568,11 +568,11 @@ function typeinfo_prefix(io::IO, X) if X isa AbstractDict if eltype_X == eltype_ctx - sprint(show_type_name, typeof(X).name), false + sprint(show_type_name, typeof(X).name; context=io), false elseif !isempty(X) && typeinfo_implicit(keytype(X)) && typeinfo_implicit(valtype(X)) - sprint(show_type_name, typeof(X).name), true + sprint(show_type_name, typeof(X).name; context=io), true else - string(typeof(X)), false + sprint(print, typeof(X); context=io), false end else # Types hard-coded here are those which are created by default for a given syntax @@ -581,9 +581,9 @@ function typeinfo_prefix(io::IO, X) elseif !isempty(X) && typeinfo_implicit(eltype_X) "", true elseif print_without_params(eltype_X) - sprint(show_type_name, unwrap_unionall(eltype_X).name), false # Print "Array" rather than "Array{T,N}" + sprint(show_type_name, unwrap_unionall(eltype_X).name; context=io), false # Print "Array" rather than "Array{T,N}" else - string(eltype_X), false + sprint(print, eltype_X; context=io), false end end end diff --git a/base/baseext.jl b/base/baseext.jl index 8ebd599312453..625a82ff29234 100644 --- a/base/baseext.jl +++ b/base/baseext.jl @@ -16,7 +16,7 @@ VecElement # hook up VecElement constructor to Base.convert VecElement{T}(arg) where {T} = VecElement{T}(convert(T, arg)) convert(::Type{T}, arg::T) where {T<:VecElement} = arg -convert(::Type{T}, arg) where {T<:VecElement} = T(arg) +convert(::Type{T}, arg) where {T<:VecElement} = T(arg)::T # ## dims-type-converting Array constructors for convenience # type and dimensionality specified, accepting dims as series of Integers diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index f323ad4f2800e..cf08a961772da 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -259,14 +259,14 @@ end function set_compare_strategy!(p::Platform, key::String, f::Function) if !haskey(p.tags, key) - throw(ArgumentError("Cannot set comparison strategy for nonexistant tag $(key)!")) + throw(ArgumentError("Cannot set comparison strategy for nonexistent tag $(key)!")) end p.compare_strategies[key] = f end function get_compare_strategy(p::Platform, key::String, default = compare_default) if !haskey(p.tags, key) - throw(ArgumentError("Cannot get comparison strategy for nonexistant tag $(key)!")) + throw(ArgumentError("Cannot get comparison strategy for nonexistent tag $(key)!")) end return get(p.compare_strategies, key, default) end diff --git a/base/bitarray.jl b/base/bitarray.jl index 095acf6a519e3..841509a90ba44 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -577,7 +577,7 @@ julia> BitArray(x+y == 3 for x = 1:2 for y = 1:3) BitArray(itr) = gen_bitarray(IteratorSize(itr), itr) BitArray{N}(itr) where N = gen_bitarrayN(BitArray{N}, IteratorSize(itr), itr) -convert(T::Type{<:BitArray}, a::AbstractArray) = a isa T ? a : T(a) +convert(::Type{T}, a::AbstractArray) where {T<:BitArray} = a isa T ? a : T(a)::T # generic constructor from an iterable without compile-time info # (we pass start(itr) explicitly to avoid a type-instability with filters) diff --git a/base/bitset.jl b/base/bitset.jl index 22ff177695349..8727b857bd36b 100644 --- a/base/bitset.jl +++ b/base/bitset.jl @@ -316,6 +316,13 @@ function symdiff!(s::BitSet, ns) return s end +function symdiff!(s::BitSet, ns::AbstractSet) + for x in ns + int_symdiff!(s, x) + end + return s +end + function int_symdiff!(s::BitSet, n::Integer) n0 = _check_bitset_bounds(n) val = !(n0 in s) diff --git a/base/boot.jl b/base/boot.jl index f0045e5b72c91..5f3b99df1c716 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -412,7 +412,7 @@ eval(Core, quote end LineInfoNode(mod::Module, @nospecialize(method), file::Symbol, line::Int32, inlined_at::Int32) = $(Expr(:new, :LineInfoNode, :mod, :method, :file, :line, :inlined_at)) - GlobalRef(m::Module, s::Symbol) = $(Expr(:new, :GlobalRef, :m, :s)) + GlobalRef(m::Module, s::Symbol, binding::Ptr{Nothing}) = $(Expr(:new, :GlobalRef, :m, :s, :binding)) SlotNumber(n::Int) = $(Expr(:new, :SlotNumber, :n)) TypedSlot(n::Int, @nospecialize(t)) = $(Expr(:new, :TypedSlot, :n, :t)) PhiNode(edges::Array{Int32, 1}, values::Array{Any, 1}) = $(Expr(:new, :PhiNode, :edges, :values)) @@ -812,6 +812,8 @@ Unsigned(x::Union{Float16, Float32, Float64, Bool}) = UInt(x) Integer(x::Integer) = x Integer(x::Union{Float16, Float32, Float64}) = Int(x) +GlobalRef(m::Module, s::Symbol) = GlobalRef(m, s, bitcast(Ptr{Nothing}, 0)) + # Binding for the julia parser, called as # # Core._parse(text, filename, lineno, offset, options) @@ -838,8 +840,10 @@ struct Pair{A, B} # but also mark the whole function with `@inline` to ensure we will inline it whenever possible # (even if `convert(::Type{A}, a::A)` for some reason was expensive) Pair(a, b) = new{typeof(a), typeof(b)}(a, b) - Pair{A, B}(a::A, b::B) where {A, B} = new(a, b) - Pair{Any, Any}(@nospecialize(a::Any), @nospecialize(b::Any)) = new(a, b) + function Pair{A, B}(@nospecialize(a), @nospecialize(b)) where {A, B} + @inline + return new(a::A, b::B) + end end ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Core, true) diff --git a/base/broadcast.jl b/base/broadcast.jl index a54016ad00917..1eb4194d27447 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -195,7 +195,7 @@ function broadcasted(::OrOr, a, bc::Broadcasted) end Base.convert(::Type{Broadcasted{NewStyle}}, bc::Broadcasted{Style,Axes,F,Args}) where {NewStyle,Style,Axes,F,Args} = - Broadcasted{NewStyle,Axes,F,Args}(bc.f, bc.args, bc.axes) + Broadcasted{NewStyle,Axes,F,Args}(bc.f, bc.args, bc.axes)::Broadcasted{NewStyle,Axes,F,Args} function Base.show(io::IO, bc::Broadcasted{Style}) where {Style} print(io, Broadcasted) diff --git a/base/c.jl b/base/c.jl index 7d168f2293c9c..cfff070973f25 100644 --- a/base/c.jl +++ b/base/c.jl @@ -129,7 +129,7 @@ A C-style string composed of the native wide character type [`Cwchar_t`](@ref)s. `Cwstring`s are NUL-terminated. For C-style strings composed of the native character type, see [`Cstring`](@ref). For more information -about string interopability with C, see the +about string interoperability with C, see the [manual](@ref man-bits-types). """ @@ -142,7 +142,7 @@ A C-style string composed of the native character type [`Cchar`](@ref)s. `Cstring`s are NUL-terminated. For C-style strings composed of the native wide character type, see [`Cwstring`](@ref). For more information -about string interopability with C, see the +about string interoperability with C, see the [manual](@ref man-bits-types). """ Cstring diff --git a/base/channels.jl b/base/channels.jl index 46a2b4b208026..aa4d913dcdadd 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -380,7 +380,7 @@ end """ fetch(c::Channel) -Waits for and returns (with removing) the first available item from the `Channel`. +Waits for and returns (without removing) the first available item from the `Channel`. Note: `fetch` is unsupported on an unbuffered (0-size) `Channel`. # Examples diff --git a/base/char.jl b/base/char.jl index c8b1c28166bbf..08d661c41de56 100644 --- a/base/char.jl +++ b/base/char.jl @@ -181,9 +181,9 @@ end end convert(::Type{AbstractChar}, x::Number) = Char(x) # default to Char -convert(::Type{T}, x::Number) where {T<:AbstractChar} = T(x) -convert(::Type{T}, x::AbstractChar) where {T<:Number} = T(x) -convert(::Type{T}, c::AbstractChar) where {T<:AbstractChar} = T(c) +convert(::Type{T}, x::Number) where {T<:AbstractChar} = T(x)::T +convert(::Type{T}, x::AbstractChar) where {T<:Number} = T(x)::T +convert(::Type{T}, c::AbstractChar) where {T<:AbstractChar} = T(c)::T convert(::Type{T}, c::T) where {T<:AbstractChar} = c rem(x::AbstractChar, ::Type{T}) where {T<:Number} = rem(codepoint(x), T) @@ -318,7 +318,7 @@ end function show(io::IO, ::MIME"text/plain", c::T) where {T<:AbstractChar} show(io, c) - get(io, :compact, false) && return + get(io, :compact, false)::Bool && return if !ismalformed(c) print(io, ": ") if isoverlong(c) diff --git a/base/checked.jl b/base/checked.jl index c3c8a888dcd1c..d5b4112397e84 100644 --- a/base/checked.jl +++ b/base/checked.jl @@ -42,12 +42,12 @@ const UnsignedInt = Union{UInt8,UInt16,UInt32,UInt64,UInt128} # LLVM has several code generation bugs for checked integer arithmetic (see e.g. # #4905). We thus distinguish between operations that can be implemented via -# intrinsics, and operations for which we have to provide work-arounds. +# intrinsics, and operations for which we have to provide workarounds. # Note: As far as this code has been tested, most checked_* functions are # working fine in LLVM. (Note that division is still handled via `base/int.jl`, # which always checks for overflow, and which provides its own sets of -# work-arounds for LLVM codegen bugs.) However, the comments in `base/int.jl` +# workarounds for LLVM codegen bugs.) However, the comments in `base/int.jl` # and in issue #4905 are more pessimistic. For the time being, we thus retain # the ability to handle codegen bugs in LLVM, until the code here has been # tested on more systems and architectures. It also seems that things depend on diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 5b3bbdd433760..c5be04ad69f42 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -13,8 +13,9 @@ const _REF_NAME = Ref.body.name # See if the inference result of the current statement's result value might affect # the final answer for the method (aside from optimization potential and exceptions). # To do that, we need to check both for slot assignment and SSA usage. -call_result_unused(frame::InferenceState) = - isexpr(frame.src.code[frame.currpc], :call) && isempty(frame.ssavalue_uses[frame.currpc]) +call_result_unused(frame::InferenceState, currpc::Int) = + isexpr(frame.src.code[currpc], :call) && isempty(frame.ssavalue_uses[currpc]) +call_result_unused(si::StmtInfo) = !si.used function get_max_methods(mod::Module, interp::AbstractInterpreter) max_methods = ccall(:jl_get_module_max_methods, Cint, (Any,), mod) % Int @@ -50,7 +51,7 @@ function should_infer_for_effects(sv::InferenceState) end function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), - arginfo::ArgInfo, @nospecialize(atype), + arginfo::ArgInfo, si::StmtInfo, @nospecialize(atype), sv::InferenceState, max_methods::Int) ⊑ᵢ = ⊑(typeinf_lattice(interp)) if !should_infer_this_call(sv) @@ -103,7 +104,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end # try pure-evaluation - val = pure_eval_call(interp, f, applicable, arginfo, sv) + val = pure_eval_call(interp, f, applicable, arginfo) val !== nothing && return CallMeta(val, all_effects, MethodResultPure(info)) # TODO: add some sort of edge(s) for i in 1:napplicable @@ -124,23 +125,23 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), if splitunions splitsigs = switchtupleunion(sig) for sig_n in splitsigs - result = abstract_call_method(interp, method, sig_n, svec(), multiple_matches, sv) + result = abstract_call_method(interp, method, sig_n, svec(), multiple_matches, si, sv) (; rt, edge, effects) = result - edge === nothing || push!(edges, edge) this_argtypes = isa(matches, MethodMatches) ? argtypes : matches.applicable_argtypes[i] this_arginfo = ArgInfo(fargs, this_argtypes) const_call_result = abstract_call_method_with_const_args(interp, result, - f, this_arginfo, match, sv) + f, this_arginfo, si, match, sv) const_result = nothing if const_call_result !== nothing if const_call_result.rt ⊑ᵢ rt rt = const_call_result.rt - (; effects, const_result) = const_call_result + (; effects, const_result, edge) = const_call_result end end all_effects = merge_effects(all_effects, effects) push!(const_results, const_result) any_const_result |= const_result !== nothing + edge === nothing || push!(edges, edge) this_rt = tmerge(this_rt, rt) if bail_out_call(interp, this_rt, sv) break @@ -149,17 +150,16 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), this_conditional = ignorelimited(this_rt) this_rt = widenwrappedconditional(this_rt) else - result = abstract_call_method(interp, method, sig, match.sparams, multiple_matches, sv) + result = abstract_call_method(interp, method, sig, match.sparams, multiple_matches, si, sv) (; rt, edge, effects) = result this_conditional = ignorelimited(rt) this_rt = widenwrappedconditional(rt) - edge === nothing || push!(edges, edge) # try constant propagation with argtypes for this match # this is in preparation for inlining, or improving the return result this_argtypes = isa(matches, MethodMatches) ? argtypes : matches.applicable_argtypes[i] this_arginfo = ArgInfo(fargs, this_argtypes) const_call_result = abstract_call_method_with_const_args(interp, result, - f, this_arginfo, match, sv) + f, this_arginfo, si, match, sv) const_result = nothing if const_call_result !== nothing this_const_conditional = ignorelimited(const_call_result.rt) @@ -169,12 +169,13 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), if this_const_rt ⊑ᵢ this_rt this_conditional = this_const_conditional this_rt = this_const_rt - (; effects, const_result) = const_call_result + (; effects, const_result, edge) = const_call_result end end all_effects = merge_effects(all_effects, effects) push!(const_results, const_result) any_const_result |= const_result !== nothing + edge === nothing || push!(edges, edge) end @assert !(this_conditional isa Conditional) "invalid lattice element returned from inter-procedural context" seen += 1 @@ -222,17 +223,12 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), if mi !== nothing && !const_prop_methodinstance_heuristic(interp, match, mi::MethodInstance, arginfo, sv) csig = get_compileable_sig(method, sig, match.sparams) if csig !== nothing && csig !== sig - # The result of this inference is not directly used, so temporarily empty - # the use set for the current SSA value. - saved_uses = sv.ssavalue_uses[sv.currpc] - sv.ssavalue_uses[sv.currpc] = empty_bitset - abstract_call_method(interp, method, csig, match.sparams, multiple_matches, sv) - sv.ssavalue_uses[sv.currpc] = saved_uses + abstract_call_method(interp, method, csig, match.sparams, multiple_matches, StmtInfo(false), sv) end end end - if call_result_unused(sv) && !(rettype === Bottom) + if call_result_unused(si) && !(rettype === Bottom) add_remark!(interp, sv, "Call result type was widened because the return value is unused") # We're mainly only here because the optimizer might want this code, # but we ourselves locally don't typically care about it locally @@ -393,11 +389,6 @@ function collect_limitations!(@nospecialize(typ), sv::InferenceState) return typ end -function collect_limitations!(@nospecialize(typ), ::IRCode) - @assert !isa(typ, LimitedAccuracy) "semi-concrete eval on recursive call graph" - return typ -end - function from_interconditional(ipo_lattice::AbstractLattice, @nospecialize(typ), sv::InferenceState, (; fargs, argtypes)::ArgInfo, @nospecialize(maybecondinfo)) lattice = widenlattice(ipo_lattice) @@ -488,15 +479,15 @@ function add_call_backedges!(interp::AbstractInterpreter, end end for edge in edges - add_backedge!(edge, sv) + add_backedge!(sv, edge) end # also need an edge to the method table in case something gets # added that did not intersect with any existing method if isa(matches, MethodMatches) - matches.fullmatch || add_mt_backedge!(matches.mt, atype, sv) + matches.fullmatch || add_mt_backedge!(sv, matches.mt, atype) else for (thisfullmatch, mt) in zip(matches.fullmatches, matches.mts) - thisfullmatch || add_mt_backedge!(mt, atype, sv) + thisfullmatch || add_mt_backedge!(sv, mt, atype) end end end @@ -504,7 +495,7 @@ end const RECURSION_UNUSED_MSG = "Bounded recursion detected with unused result. Annotated return type may be wider than true result." const RECURSION_MSG = "Bounded recursion detected. Call was widened to force convergence." -function abstract_call_method(interp::AbstractInterpreter, method::Method, @nospecialize(sig), sparams::SimpleVector, hardlimit::Bool, sv::InferenceState) +function abstract_call_method(interp::AbstractInterpreter, method::Method, @nospecialize(sig), sparams::SimpleVector, hardlimit::Bool, si::StmtInfo, sv::InferenceState) if method.name === :depwarn && isdefined(Main, :Base) && method.module === Main.Base add_remark!(interp, sv, "Refusing to infer into `depwarn`") return MethodCallResult(Any, false, false, nothing, Effects()) @@ -522,7 +513,7 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp if infstate.linfo.specTypes::Type == sig::Type # avoid widening when detecting self-recursion # TODO: merge call cycle and return right away - if call_result_unused(sv) + if call_result_unused(si) add_remark!(interp, sv, RECURSION_UNUSED_MSG) # since we don't use the result (typically), # we have a self-cycle in the call-graph, but not in the inference graph (typically): @@ -559,7 +550,7 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp end if isdefined(method, :recursion_relation) - # We don't recquire the recursion_relation to be transitive, so + # We don't require the recursion_relation to be transitive, so # apply a hard limit hardlimit = true end @@ -570,7 +561,7 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp if newsig !== sig # continue inference, but note that we've limited parameter complexity # on this call (to ensure convergence), so that we don't cache this result - if call_result_unused(sv) + if call_result_unused(si) add_remark!(interp, sv, RECURSION_UNUSED_MSG) # if we don't (typically) actually care about this result, # don't bother trying to examine some complex abstract signature @@ -750,12 +741,12 @@ struct MethodCallResult end function pure_eval_eligible(interp::AbstractInterpreter, - @nospecialize(f), applicable::Vector{Any}, arginfo::ArgInfo, sv::InferenceState) + @nospecialize(f), applicable::Vector{Any}, arginfo::ArgInfo) # XXX we need to check that this pure function doesn't call any overlayed method return f !== nothing && length(applicable) == 1 && is_method_pure(applicable[1]::MethodMatch) && - is_all_const_arg(arginfo) + is_all_const_arg(arginfo, #=start=#2) end function is_method_pure(method::Method, @nospecialize(sig), sparams::SimpleVector) @@ -772,12 +763,12 @@ end is_method_pure(match::MethodMatch) = is_method_pure(match.method, match.spec_types, match.sparams) function pure_eval_call(interp::AbstractInterpreter, - @nospecialize(f), applicable::Vector{Any}, arginfo::ArgInfo, sv::InferenceState) - pure_eval_eligible(interp, f, applicable, arginfo, sv) || return nothing + @nospecialize(f), applicable::Vector{Any}, arginfo::ArgInfo) + pure_eval_eligible(interp, f, applicable, arginfo) || return nothing return _pure_eval_call(f, arginfo) end function _pure_eval_call(@nospecialize(f), arginfo::ArgInfo) - args = collect_const_args(arginfo) + args = collect_const_args(arginfo, #=start=#2) value = try Core._apply_pure(f, args) catch @@ -790,79 +781,71 @@ end # - false: eligible for semi-concrete evaluation # - nothing: not eligible for either of it function concrete_eval_eligible(interp::AbstractInterpreter, - @nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState) + @nospecialize(f), result::MethodCallResult, arginfo::ArgInfo) # disable all concrete-evaluation if this function call is tainted by some overlayed # method since currently there is no direct way to execute overlayed methods isoverlayed(method_table(interp)) && !is_nonoverlayed(result.effects) && return nothing if f !== nothing && result.edge !== nothing && is_foldable(result.effects) - if is_all_const_arg(arginfo) + if is_all_const_arg(arginfo, #=start=#2) return true else - # TODO: is_nothrow is not an actual requirement here, this is just a hack - # to avoid entering semi concrete eval while it doesn't properly propagate no_throw + # TODO: `is_nothrow` is not an actual requirement here, this is just a hack + # to avoid entering semi concrete eval while it doesn't properly override effects return is_nothrow(result.effects) ? false : nothing end - else - return nothing end - # if f !== nothing && result.edge !== nothing && is_foldable(result.effects) - # return is_all_const_arg(arginfo) - # else - # return nothing - # end + return nothing end -is_all_const_arg((; argtypes)::ArgInfo) = is_all_const_arg(argtypes) -function is_all_const_arg(argtypes::Vector{Any}) - for i = 2:length(argtypes) +is_all_const_arg(arginfo::ArgInfo, start::Int) = is_all_const_arg(arginfo.argtypes, start::Int) +function is_all_const_arg(argtypes::Vector{Any}, start::Int) + for i = start:length(argtypes) a = widenconditional(argtypes[i]) isa(a, Const) || isconstType(a) || issingletontype(a) || return false end return true end -collect_const_args(arginfo::ArgInfo, start::Int=2) = collect_const_args(arginfo.argtypes, start) -function collect_const_args(argtypes::Vector{Any}, start::Int=2) +collect_const_args(arginfo::ArgInfo, start::Int) = collect_const_args(arginfo.argtypes, start) +function collect_const_args(argtypes::Vector{Any}, start::Int) return Any[ let a = widenconditional(argtypes[i]) isa(a, Const) ? a.val : isconstType(a) ? (a::DataType).parameters[1] : (a::DataType).instance - end for i = 2:length(argtypes) ] -end - -function collect_semi_const_args(argtypes::Vector{Any}, start::Int=2) - return Any[ let a = widenconditional(argtypes[i]) - isa(a, Const) ? a.val : - isconstType(a) ? (a::DataType).parameters[1] : - isdefined(a, :instance) ? (a::DataType).instance : - nothing - end for i in start:length(argtypes) ] + end for i = start:length(argtypes) ] end - -function invoke_signature(invokesig::Vector{Any}) - ft, argtyps = widenconst(invokesig[2]), instanceof_tfunc(widenconst(invokesig[3]))[1] - return rewrap_unionall(Tuple{ft, unwrap_unionall(argtyps).parameters...}, argtyps) +struct InvokeCall + types # ::Type + lookupsig # ::Type + InvokeCall(@nospecialize(types), @nospecialize(lookupsig)) = new(types, lookupsig) end function concrete_eval_call(interp::AbstractInterpreter, - @nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState) - eligible = concrete_eval_eligible(interp, f, result, arginfo, sv) + @nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, si::StmtInfo, + sv::InferenceState, invokecall::Union{Nothing,InvokeCall}=nothing) + eligible = concrete_eval_eligible(interp, f, result, arginfo) eligible === nothing && return false if eligible - args = collect_const_args(arginfo) + args = collect_const_args(arginfo, #=start=#2) + if invokecall !== nothing + # this call should be `invoke`d, rewrite `args` back now + pushfirst!(args, f, invokecall.types) + f = invoke + end world = get_world_counter(interp) + edge = result.edge::MethodInstance value = try Core._call_in_world_total(world, f, args...) catch - # The evaulation threw. By :consistent-cy, we're guaranteed this would have happened at runtime - return ConstCallResults(Union{}, ConcreteResult(result.edge::MethodInstance, result.effects), result.effects) + # The evaluation threw. By :consistent-cy, we're guaranteed this would have happened at runtime + return ConstCallResults(Union{}, ConcreteResult(edge, result.effects), result.effects, edge) end - if is_inlineable_constant(value) || call_result_unused(sv) + if is_inlineable_constant(value) || call_result_unused(si) # If the constant is not inlineable, still do the const-prop, since the # code that led to the creation of the Const may be inlineable in the same # circumstance and may be optimizable. - return ConstCallResults(Const(value), ConcreteResult(result.edge::MethodInstance, EFFECTS_TOTAL, value), EFFECTS_TOTAL) + return ConstCallResults(Const(value), ConcreteResult(edge, EFFECTS_TOTAL, value), EFFECTS_TOTAL, edge) end return false else # eligible for semi-concrete evaluation @@ -889,24 +872,23 @@ struct ConstCallResults rt::Any const_result::ConstResult effects::Effects + edge::MethodInstance ConstCallResults(@nospecialize(rt), const_result::ConstResult, - effects::Effects) = - new(rt, const_result, effects) + effects::Effects, + edge::MethodInstance) = + new(rt, const_result, effects, edge) end -function abstract_call_method_with_const_args(interp::AbstractInterpreter, result::MethodCallResult, - @nospecialize(f), arginfo::ArgInfo, match::MethodMatch, - sv::InferenceState) +function abstract_call_method_with_const_args(interp::AbstractInterpreter, + result::MethodCallResult, @nospecialize(f), arginfo::ArgInfo, si::StmtInfo, match::MethodMatch, + sv::InferenceState, invokecall::Union{Nothing,InvokeCall}=nothing) if !const_prop_enabled(interp, sv, match) return nothing end - res = concrete_eval_call(interp, f, result, arginfo, sv) - if isa(res, ConstCallResults) - add_backedge!(res.const_result.mi, sv) - return res - end - mi = maybe_get_const_prop_profitable(interp, result, f, arginfo, match, sv) + res = concrete_eval_call(interp, f, result, arginfo, si, sv, invokecall) + isa(res, ConstCallResults) && return res + mi = maybe_get_const_prop_profitable(interp, result, f, arginfo, si, match, sv) mi === nothing && return nothing # try semi-concrete evaluation if res::Bool && !has_conditional(arginfo) @@ -915,9 +897,10 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, resul if code !== nothing ir = codeinst_to_ir(interp, code) if isa(ir, IRCode) - T = ir_abstract_constant_propagation(interp, mi_cache, sv, mi, ir, arginfo.argtypes) - if !isa(T, Type) || typeintersect(T, Bool) === Union{} - return ConstCallResults(T, SemiConcreteResult(mi, ir, result.effects), result.effects) + irsv = IRInterpretationState(interp, ir, mi, sv.world, arginfo.argtypes) + rt = ir_abstract_constant_propagation(interp, irsv) + if !isa(rt, Type) || typeintersect(rt, Bool) === Union{} + return ConstCallResults(rt, SemiConcreteResult(mi, ir, result.effects), result.effects, mi) end end end @@ -950,18 +933,17 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter, resul result = inf_result.result # if constant inference hits a cycle, just bail out isa(result, InferenceState) && return nothing - add_backedge!(mi, sv) - return ConstCallResults(result, ConstPropResult(inf_result), inf_result.ipo_effects) + return ConstCallResults(result, ConstPropResult(inf_result), inf_result.ipo_effects, mi) end # if there's a possibility we could get a better result with these constant arguments # (hopefully without doing too much work), returns `MethodInstance`, or nothing otherwise function maybe_get_const_prop_profitable(interp::AbstractInterpreter, result::MethodCallResult, - @nospecialize(f), arginfo::ArgInfo, match::MethodMatch, + @nospecialize(f), arginfo::ArgInfo, si::StmtInfo, match::MethodMatch, sv::InferenceState) method = match.method force = force_const_prop(interp, f, method) - force || const_prop_entry_heuristic(interp, result, sv) || return nothing + force || const_prop_entry_heuristic(interp, result, si, sv) || return nothing nargs::Int = method.nargs method.isva && (nargs -= 1) length(arginfo.argtypes) < nargs && return nothing @@ -989,8 +971,8 @@ function maybe_get_const_prop_profitable(interp::AbstractInterpreter, result::Me return mi end -function const_prop_entry_heuristic(interp::AbstractInterpreter, result::MethodCallResult, sv::InferenceState) - if call_result_unused(sv) && result.edgecycle +function const_prop_entry_heuristic(interp::AbstractInterpreter, result::MethodCallResult, si::StmtInfo, sv::InferenceState) + if call_result_unused(si) && result.edgecycle add_remark!(interp, sv, "[constprop] Disabled by entry heuristic (edgecycle with unused result)") return false end @@ -1319,7 +1301,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n return Any[Vararg{Any}], nothing end @assert !isvarargtype(itertype) - call = abstract_call_known(interp, iteratef, ArgInfo(nothing, Any[itft, itertype]), sv) + call = abstract_call_known(interp, iteratef, ArgInfo(nothing, Any[itft, itertype]), StmtInfo(true), sv) stateordonet = call.rt info = call.info # Return Bottom if this is not an iterator. @@ -1353,7 +1335,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n valtype = getfield_tfunc(stateordonet, Const(1)) push!(ret, valtype) statetype = nstatetype - call = abstract_call_known(interp, iteratef, ArgInfo(nothing, Any[Const(iteratef), itertype, statetype]), sv) + call = abstract_call_known(interp, iteratef, ArgInfo(nothing, Any[Const(iteratef), itertype, statetype]), StmtInfo(true), sv) stateordonet = call.rt stateordonet_widened = widenconst(stateordonet) push!(calls, call) @@ -1388,7 +1370,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n end valtype = tmerge(valtype, nounion.parameters[1]) statetype = tmerge(statetype, nounion.parameters[2]) - stateordonet = abstract_call_known(interp, iteratef, ArgInfo(nothing, Any[Const(iteratef), itertype, statetype]), sv).rt + stateordonet = abstract_call_known(interp, iteratef, ArgInfo(nothing, Any[Const(iteratef), itertype, statetype]), StmtInfo(true), sv).rt stateordonet_widened = widenconst(stateordonet) end if valtype !== Union{} @@ -1398,7 +1380,8 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n end # do apply(af, fargs...), where af is a function value -function abstract_apply(interp::AbstractInterpreter, argtypes::Vector{Any}, sv::Union{InferenceState, IRCode}, +function abstract_apply(interp::AbstractInterpreter, argtypes::Vector{Any}, si::StmtInfo, + sv::Union{InferenceState, IRCode}, max_methods::Int = get_max_methods(sv.mod, interp)) itft = argtype_by_index(argtypes, 2) aft = argtype_by_index(argtypes, 3) @@ -1449,7 +1432,7 @@ function abstract_apply(interp::AbstractInterpreter, argtypes::Vector{Any}, sv:: for j = 1:length(ctypes) ct = ctypes[j]::Vector{Any} if isvarargtype(ct[end]) - # This is vararg, we're not gonna be able to do any inling, + # This is vararg, we're not gonna be able to do any inlining, # drop the info info = nothing tail = tuple_tail_elem(unwrapva(ct[end]), cti) @@ -1478,7 +1461,7 @@ function abstract_apply(interp::AbstractInterpreter, argtypes::Vector{Any}, sv:: break end end - call = abstract_call(interp, ArgInfo(nothing, ct), sv, max_methods) + call = abstract_call(interp, ArgInfo(nothing, ct), si, sv, max_methods) push!(retinfos, ApplyCallInfo(call.info, arginfo)) res = tmerge(res, call.rt) effects = merge_effects(effects, call.effects) @@ -1559,6 +1542,10 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs tty_lb = tty_ub # TODO: this would be wrong if !isexact_tty, but instanceof_tfunc doesn't preserve this info if !has_free_typevars(tty_lb) && !has_free_typevars(tty_ub) ifty = typeintersect(aty, tty_ub) + if iskindtype(tty_ub) && ifty !== Bottom + # `typeintersect` may be unable narrow down `Type`-type + ifty = tty_ub + end valid_as_lattice(ifty) || (ifty = Union{}) elty = typesubtract(aty, tty_lb, InferenceParams(interp).MAX_UNION_SPLITTING) return Conditional(a, ifty, elty) @@ -1678,7 +1665,7 @@ function abstract_call_unionall(argtypes::Vector{Any}) return Any end -function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgInfo, sv::InferenceState) +function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgInfo, si::StmtInfo, sv::InferenceState) ft′ = argtype_by_index(argtypes, 2) ft = widenconst(ft′) ft === Bottom && return CallMeta(Bottom, EFFECTS_THROWS, false) @@ -1691,18 +1678,17 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn nargtype isa DataType || return CallMeta(Any, Effects(), false) # other cases are not implemented below isdispatchelem(ft) || return CallMeta(Any, Effects(), false) # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below ft = ft::DataType - types = rewrap_unionall(Tuple{ft, unwrap_unionall(types).parameters...}, types)::Type + lookupsig = rewrap_unionall(Tuple{ft, unwrap_unionall(types).parameters...}, types)::Type nargtype = Tuple{ft, nargtype.parameters...} argtype = Tuple{ft, argtype.parameters...} - match, valid_worlds, overlayed = findsup(types, method_table(interp)) + match, valid_worlds, overlayed = findsup(lookupsig, method_table(interp)) match === nothing && return CallMeta(Any, Effects(), false) update_valid_age!(sv, valid_worlds) method = match.method tienv = ccall(:jl_type_intersection_with_env, Any, (Any, Any), nargtype, method.sig)::SimpleVector ti = tienv[1]; env = tienv[2]::SimpleVector - result = abstract_call_method(interp, method, ti, env, false, sv) + result = abstract_call_method(interp, method, ti, env, false, si, sv) (; rt, edge, effects) = result - edge !== nothing && add_backedge!(edge::MethodInstance, sv, types) match = MethodMatch(ti, env, method, argtype <: method.sig) res = nothing sig = match.spec_types @@ -1714,15 +1700,18 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn # t, a = ti.parameters[i], argtypes′[i] # argtypes′[i] = t ⊑ a ? t : a # end - const_call_result = abstract_call_method_with_const_args(interp, result, - overlayed ? nothing : singleton_type(ft′), arginfo, match, sv) + f = overlayed ? nothing : singleton_type(ft′) + invokecall = InvokeCall(types, lookupsig) + const_call_result = abstract_call_method_with_const_args(interp, + result, f, arginfo, si, match, sv, invokecall) const_result = nothing if const_call_result !== nothing if ⊑(typeinf_lattice(interp), const_call_result.rt, rt) - (; rt, effects, const_result) = const_call_result + (; rt, effects, const_result, edge) = const_call_result end end effects = Effects(effects; nonoverlayed=!overlayed) + edge !== nothing && add_invoke_backedge!(sv, lookupsig, edge) return CallMeta(from_interprocedural!(ipo_lattice(interp), rt, sv, arginfo, sig), effects, InvokeCallInfo(match, const_result)) end @@ -1736,7 +1725,7 @@ end function abstract_finalizer(interp::AbstractInterpreter, argtypes::Vector{Any}, sv::InferenceState) if length(argtypes) == 3 finalizer_argvec = Any[argtypes[2], argtypes[3]] - call = abstract_call(interp, ArgInfo(nothing, finalizer_argvec), sv, 1) + call = abstract_call(interp, ArgInfo(nothing, finalizer_argvec), StmtInfo(false), sv, 1) return CallMeta(Nothing, Effects(), FinalizerInfo(call.info, call.effects)) end return CallMeta(Nothing, Effects(), false) @@ -1744,23 +1733,23 @@ end # call where the function is known exactly function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), - arginfo::ArgInfo, sv::Union{InferenceState, IRCode}, + arginfo::ArgInfo, si::StmtInfo, sv::Union{InferenceState, IRCode}, max_methods::Int = isa(sv, InferenceState) ? get_max_methods(f, sv.mod, interp) : 0) (; fargs, argtypes) = arginfo la = length(argtypes) if isa(f, Builtin) if f === _apply_iterate - return abstract_apply(interp, argtypes, sv, max_methods) + return abstract_apply(interp, argtypes, si, sv, max_methods) elseif f === invoke - return abstract_invoke(interp, arginfo, sv) + return abstract_invoke(interp, arginfo, si, sv) elseif f === modifyfield! - return abstract_modifyfield!(interp, argtypes, sv) + return abstract_modifyfield!(interp, argtypes, si, sv) elseif f === Core.finalizer return abstract_finalizer(interp, argtypes, sv) end rt = abstract_call_builtin(interp, f, arginfo, sv, max_methods) - effects = builtin_effects(f, argtypes[2:end], rt) + effects = builtin_effects(typeinf_lattice(interp), f, argtypes[2:end], rt) return CallMeta(rt, effects, false) elseif isa(f, Core.OpaqueClosure) # calling an OpaqueClosure about which we have no information returns no information @@ -1799,17 +1788,17 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), return CallMeta(Tuple, EFFECTS_UNKNOWN, false) end elseif is_return_type(f) - return return_type_tfunc(interp, argtypes, sv) + return return_type_tfunc(interp, argtypes, si, sv) elseif la == 2 && istopfunction(f, :!) # handle Conditional propagation through !Bool aty = argtypes[2] if isa(aty, Conditional) - call = abstract_call_gf_by_type(interp, f, ArgInfo(fargs, Any[Const(f), Bool]), Tuple{typeof(f), Bool}, sv, max_methods) # make sure we've inferred `!(::Bool)` + call = abstract_call_gf_by_type(interp, f, ArgInfo(fargs, Any[Const(f), Bool]), si, Tuple{typeof(f), Bool}, sv, max_methods) # make sure we've inferred `!(::Bool)` return CallMeta(Conditional(aty.slot, aty.elsetype, aty.thentype), call.effects, call.info) end elseif la == 3 && istopfunction(f, :!==) # mark !== as exactly a negated call to === - rty = abstract_call_known(interp, (===), arginfo, sv, max_methods).rt + rty = abstract_call_known(interp, (===), arginfo, si, sv, max_methods).rt if isa(rty, Conditional) return CallMeta(Conditional(rty.slot, rty.elsetype, rty.thentype), EFFECTS_TOTAL, false) # swap if-else elseif isa(rty, Const) @@ -1825,7 +1814,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), sv, max_methods).rt, EFFECTS_TOTAL, false) + return CallMeta(abstract_call_known(interp, <:, ArgInfo(fargs, argtypes), si, sv, max_methods).rt, EFFECTS_TOTAL, false) elseif la == 2 && (a2 = argtypes[2]; isa(a2, Const)) && (svecval = a2.val; isa(svecval, SimpleVector)) && istopfunction(f, :length) @@ -1842,31 +1831,30 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f), elseif la == 2 && istopfunction(f, :typename) return CallMeta(typename_static(argtypes[2]), EFFECTS_TOTAL, MethodResultPure()) elseif la == 3 && istopfunction(f, :typejoin) - if is_all_const_arg(arginfo) + if is_all_const_arg(arginfo, #=start=#2) val = _pure_eval_call(f, arginfo) return CallMeta(val === nothing ? Type : val, EFFECTS_TOTAL, MethodResultPure()) end end atype = argtypes_to_type(argtypes) - return abstract_call_gf_by_type(interp, f, arginfo, atype, sv, max_methods) + return abstract_call_gf_by_type(interp, f, arginfo, si, atype, sv, max_methods) end function abstract_call_opaque_closure(interp::AbstractInterpreter, - closure::PartialOpaque, arginfo::ArgInfo, sv::InferenceState, check::Bool=true) + closure::PartialOpaque, arginfo::ArgInfo, si::StmtInfo, sv::InferenceState, check::Bool=true) sig = argtypes_to_type(arginfo.argtypes) - result = abstract_call_method(interp, closure.source, sig, Core.svec(), false, sv) + result = abstract_call_method(interp, closure.source, sig, Core.svec(), false, si, sv) (; rt, edge, effects) = result - edge !== nothing && add_backedge!(edge, sv) tt = closure.typ sigT = (unwrap_unionall(tt)::DataType).parameters[1] match = MethodMatch(sig, Core.svec(), closure.source, sig <: rewrap_unionall(sigT, tt)) const_result = nothing if !result.edgecycle const_call_result = abstract_call_method_with_const_args(interp, result, - nothing, arginfo, match, sv) + nothing, arginfo, si, match, sv) if const_call_result !== nothing if const_call_result.rt ⊑ rt - (; rt, effects, const_result) = const_call_result + (; rt, effects, const_result, edge) = const_call_result end end end @@ -1882,6 +1870,7 @@ function abstract_call_opaque_closure(interp::AbstractInterpreter, end end rt = from_interprocedural!(ipo, rt, sv, arginfo, match.spec_types) + edge !== nothing && add_backedge!(sv, edge) return CallMeta(rt, effects, info) end @@ -1896,7 +1885,7 @@ function most_general_argtypes(closure::PartialOpaque) end # call where the function is any lattice element -function abstract_call(interp::AbstractInterpreter, arginfo::ArgInfo, +function abstract_call(interp::AbstractInterpreter, arginfo::ArgInfo, si::StmtInfo, sv::Union{InferenceState, IRCode}, max_methods::Union{Int, Nothing} = isa(sv, IRCode) ? 0 : nothing) argtypes = arginfo.argtypes ft = argtypes[1] @@ -1905,7 +1894,7 @@ function abstract_call(interp::AbstractInterpreter, arginfo::ArgInfo, newargtypes = copy(argtypes) newargtypes[1] = ft.env return abstract_call_opaque_closure(interp, - ft, ArgInfo(arginfo.fargs, newargtypes), sv, #=check=#true) + ft, ArgInfo(arginfo.fargs, newargtypes), si, sv, #=check=#true) elseif (uft = unwrap_unionall(widenconst(ft)); isa(uft, DataType) && uft.name === typename(Core.OpaqueClosure)) return CallMeta(rewrap_unionall((uft::DataType).parameters[2], widenconst(ft)), Effects(), false) elseif f === nothing @@ -1916,10 +1905,10 @@ function abstract_call(interp::AbstractInterpreter, arginfo::ArgInfo, return CallMeta(Any, Effects(), false) end max_methods = max_methods === nothing ? get_max_methods(sv.mod, interp) : max_methods - return abstract_call_gf_by_type(interp, nothing, arginfo, argtypes_to_type(argtypes), sv, max_methods) + return abstract_call_gf_by_type(interp, nothing, arginfo, si, argtypes_to_type(argtypes), sv, max_methods) end max_methods = max_methods === nothing ? get_max_methods(f, sv.mod, interp) : max_methods - return abstract_call_known(interp, f, arginfo, sv, max_methods) + return abstract_call_known(interp, f, arginfo, si, sv, max_methods) end function sp_type_rewrap(@nospecialize(T), linfo::MethodInstance, isreturn::Bool) @@ -1966,7 +1955,7 @@ function abstract_eval_cfunction(interp::AbstractInterpreter, e::Expr, vtypes::V # this may be the wrong world for the call, # but some of the result is likely to be valid anyways # and that may help generate better codegen - abstract_call(interp, ArgInfo(nothing, at), sv) + abstract_call(interp, ArgInfo(nothing, at), StmtInfo(false), sv) nothing end @@ -2003,7 +1992,7 @@ function abstract_eval_special_value(interp::AbstractInterpreter, @nospecialize( return sv.argtypes[e.n] end elseif isa(e, GlobalRef) - return abstract_eval_global(interp, e.mod, e.name, sv) + return abstract_eval_globalref(interp, e, sv) end return Const(e) @@ -2049,7 +2038,9 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp rt = Bottom effects = Effects() else - (; rt, effects, info) = abstract_call(interp, ArgInfo(ea, argtypes), sv) + arginfo = ArgInfo(ea, argtypes) + si = StmtInfo(isa(sv, IRCode) ? true : !call_result_unused(sv, sv.currpc)) + (; rt, effects, info) = abstract_call(interp, arginfo, si, sv) merge_effects!(interp, sv, effects) if isa(sv, InferenceState) sv.stmt_info[sv.currpc] = info @@ -2147,13 +2138,13 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp mi′ = isa(sv, InferenceState) ? sv.linfo : mi t = _opaque_closure_tfunc(argtypes[1], argtypes[2], argtypes[3], argtypes[4], argtypes[5:end], mi′) - if isa(t, PartialOpaque) && isa(sv, InferenceState) + if isa(t, PartialOpaque) && isa(sv, InferenceState) && !call_result_unused(sv, sv.currpc) # Infer this now so that the specialization is available to # optimization. argtypes = most_general_argtypes(t) pushfirst!(argtypes, t.env) callinfo = abstract_call_opaque_closure(interp, t, - ArgInfo(nothing, argtypes), sv, #=check=#false) + ArgInfo(nothing, argtypes), StmtInfo(true), sv, #=check=#false) sv.stmt_info[sv.currpc] = OpaqueClosureCreateInfo(callinfo) end end @@ -2249,7 +2240,9 @@ end function abstract_eval_phi(interp::AbstractInterpreter, phi::PhiNode, vtypes::Union{VarTable, Nothing}, sv::Union{InferenceState, IRCode}) rt = Union{} - for val in phi.values + for i in 1:length(phi.values) + isassigned(phi.values, i) || continue + val = phi.values[i] rt = tmerge(typeinf_lattice(interp), rt, abstract_eval_special_value(interp, val, vtypes, sv)) end return rt @@ -2277,17 +2270,24 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), return rt end -function abstract_eval_global(M::Module, s::Symbol) - if isdefined(M, s) && isconst(M, s) - return Const(getglobal(M, s)) +function isdefined_globalref(g::GlobalRef) + g.binding != C_NULL && return ccall(:jl_binding_boundp, Cint, (Ptr{Cvoid},), g.binding) != 0 + return isdefined(g.mod, g.name) +end + +function abstract_eval_globalref(g::GlobalRef) + if isdefined_globalref(g) && isconst(g) + g.binding != C_NULL && return Const(ccall(:jl_binding_value, Any, (Ptr{Cvoid},), g.binding)) + return Const(getglobal(g.mod, g.name)) end - ty = ccall(:jl_binding_type, Any, (Any, Any), M, s) + ty = ccall(:jl_binding_type, Any, (Any, Any), g.mod, g.name) ty === nothing && return Any return ty end +abstract_eval_global(M::Module, s::Symbol) = abstract_eval_globalref(GlobalRef(M, s)) -function abstract_eval_global(interp::AbstractInterpreter, M::Module, s::Symbol, frame::Union{InferenceState, IRCode}) - rt = abstract_eval_global(M, s) +function abstract_eval_globalref(interp::AbstractInterpreter, g::GlobalRef, frame::Union{InferenceState, IRCode}) + rt = abstract_eval_globalref(g) consistent = inaccessiblememonly = ALWAYS_FALSE nothrow = false if isa(rt, Const) @@ -2298,7 +2298,7 @@ function abstract_eval_global(interp::AbstractInterpreter, M::Module, s::Symbol, else nothrow = true end - elseif isdefined(M,s) + elseif isdefined_globalref(g) nothrow = true end merge_effects!(interp, frame, Effects(EFFECTS_TOTAL; consistent, nothrow, inaccessiblememonly)) @@ -2699,14 +2699,22 @@ end function conditional_change(state::VarTable, @nospecialize(typ), slot::Int) vtype = state[slot] oldtyp = vtype.typ - # approximate test for `typ ∩ oldtyp` being better than `oldtyp` - # since we probably formed these types with `typesubstract`, the comparison is likely simple - if ignorelimited(typ) ⊑ ignorelimited(oldtyp) - # typ is better unlimited, but we may still need to compute the tmeet with the limit "causes" since we ignored those in the comparison - oldtyp isa LimitedAccuracy && (typ = tmerge(typ, LimitedAccuracy(Bottom, oldtyp.causes))) - return StateUpdate(SlotNumber(slot), VarState(typ, vtype.undef), state, true) + if iskindtype(typ) + # this code path corresponds to the special handling for `isa(x, iskindtype)` check + # implemented within `abstract_call_builtin` + elseif ignorelimited(typ) ⊑ ignorelimited(oldtyp) + # approximate test for `typ ∩ oldtyp` being better than `oldtyp` + # since we probably formed these types with `typesubstract`, + # the comparison is likely simple + else + return nothing end - return nothing + if oldtyp isa LimitedAccuracy + # typ is better unlimited, but we may still need to compute the tmeet with the limit + # "causes" since we ignored those in the comparison + typ = tmerge(typ, LimitedAccuracy(Bottom, oldtyp.causes)) + end + return StateUpdate(SlotNumber(slot), VarState(typ, vtype.undef), state, true) end function bool_rt_to_conditional(@nospecialize(rt), slottypes::Vector{Any}, state::VarTable, slot_id::Int) diff --git a/base/compiler/abstractlattice.jl b/base/compiler/abstractlattice.jl index 80b16615e87b0..83e64cd4a042f 100644 --- a/base/compiler/abstractlattice.jl +++ b/base/compiler/abstractlattice.jl @@ -60,7 +60,7 @@ const IPOResultLattice = typeof(InterConditionalsLattice(PartialsLattice(ConstsL """ struct InferenceLattice{L} -The full lattice used for abstract interpration during inference. Takes +The full lattice used for abstract interpretation during inference. Takes a base lattice and adjoins `LimitedAccuracy`. """ struct InferenceLattice{L} <: AbstractLattice @@ -85,7 +85,7 @@ is_valid_lattice(lattice::OptimizerLattice, @nospecialize(elem)) = tmeet(lattice, a, b::Type) Compute the lattice meet of lattice elements `a` and `b` over the lattice -`lattice`. If `lattice` is `JLTypeLattice`, this is equiavalent to type +`lattice`. If `lattice` is `JLTypeLattice`, this is equivalent to type intersection. Note that currently `b` is restricted to being a type (interpreted as a lattice element in the JLTypeLattice sub-lattice of `lattice`). """ @@ -113,7 +113,7 @@ function tmerge end Compute the lattice ordering (i.e. less-than-or-equal) relationship between lattice elements `a` and `b` over the lattice `lattice`. If `lattice` is -`JLTypeLattice`, this is equiavalent to subtyping. +`JLTypeLattice`, this is equivalent to subtyping. """ function ⊑ end diff --git a/base/compiler/bootstrap.jl b/base/compiler/bootstrap.jl index f335cf31a8467..4b79cd57f9d11 100644 --- a/base/compiler/bootstrap.jl +++ b/base/compiler/bootstrap.jl @@ -7,9 +7,7 @@ time() = ccall(:jl_clock_now, Float64, ()) -let - world = get_world_counter() - interp = NativeInterpreter(world) +let interp = NativeInterpreter() analyze_escapes_tt = Tuple{typeof(analyze_escapes), IRCode, Int, Bool, typeof(null_escape_cache)} fs = Any[ diff --git a/base/compiler/compiler.jl b/base/compiler/compiler.jl index 5fcede1458440..3c41c353e86ad 100644 --- a/base/compiler/compiler.jl +++ b/base/compiler/compiler.jl @@ -166,21 +166,6 @@ include("compiler/abstractinterpretation.jl") include("compiler/typeinfer.jl") include("compiler/optimize.jl") -# required for bootstrap because sort.jl uses extrema -# to decide whether to dispatch to counting sort. -# -# TODO: remove it. -function extrema(x::Array) - isempty(x) && throw(ArgumentError("collection must be non-empty")) - vmin = vmax = x[1] - for i in 2:length(x) - xi = x[i] - vmax = max(vmax, xi) - vmin = min(vmin, xi) - end - return vmin, vmax -end - include("compiler/bootstrap.jl") ccall(:jl_set_typeinf_func, Cvoid, (Any,), typeinf_ext_toplevel) diff --git a/base/compiler/effects.jl b/base/compiler/effects.jl index 25de6a7d12f02..b935f2ab81385 100644 --- a/base/compiler/effects.jl +++ b/base/compiler/effects.jl @@ -166,6 +166,10 @@ is_removable_if_unused(effects::Effects) = is_terminates(effects) && is_nothrow(effects) +is_finalizer_inlineable(effects::Effects) = + is_nothrow(effects) && + is_notaskstate(effects) + is_consistent_if_notreturned(effects::Effects) = !iszero(effects.consistent & CONSISTENT_IF_NOTRETURNED) is_consistent_if_inaccessiblememonly(effects::Effects) = !iszero(effects.consistent & CONSISTENT_IF_INACCESSIBLEMEMONLY) diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 81a29dbce0100..e1d20f01042c4 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -478,38 +478,49 @@ function record_ssa_assign!(ssa_id::Int, @nospecialize(new), frame::InferenceSta return nothing end -function add_cycle_backedge!(frame::InferenceState, caller::InferenceState, currpc::Int) +function add_cycle_backedge!(caller::InferenceState, frame::InferenceState, currpc::Int) update_valid_age!(frame, caller) backedge = (caller, currpc) contains_is(frame.cycle_backedges, backedge) || push!(frame.cycle_backedges, backedge) - add_backedge!(frame.linfo, caller) + add_backedge!(caller, frame.linfo) return frame end # temporarily accumulate our edges to later add as backedges in the callee -function add_backedge!(li::MethodInstance, caller::InferenceState, invokesig::Union{Nothing,Type}=nothing) - isa(caller.linfo.def, Method) || return # don't add backedges to toplevel exprs - edges = caller.stmt_edges[caller.currpc] - if edges === nothing - edges = caller.stmt_edges[caller.currpc] = [] +function add_backedge!(caller::InferenceState, li::MethodInstance) + edges = get_stmt_edges!(caller) + if edges !== nothing + push!(edges, li) end - if invokesig !== nothing - push!(edges, invokesig) + return nothing +end + +function add_invoke_backedge!(caller::InferenceState, @nospecialize(invokesig::Type), li::MethodInstance) + edges = get_stmt_edges!(caller) + if edges !== nothing + push!(edges, invokesig, li) end - push!(edges, li) return nothing end # used to temporarily accumulate our no method errors to later add as backedges in the callee method table -function add_mt_backedge!(mt::Core.MethodTable, @nospecialize(typ), caller::InferenceState) - isa(caller.linfo.def, Method) || return # don't add backedges to toplevel exprs +function add_mt_backedge!(caller::InferenceState, mt::Core.MethodTable, @nospecialize(typ)) + edges = get_stmt_edges!(caller) + if edges !== nothing + push!(edges, mt, typ) + end + return nothing +end + +function get_stmt_edges!(caller::InferenceState) + if !isa(caller.linfo.def, Method) + return nothing # don't add backedges to toplevel exprs + end edges = caller.stmt_edges[caller.currpc] if edges === nothing edges = caller.stmt_edges[caller.currpc] = [] end - push!(edges, mt) - push!(edges, typ) - return nothing + return edges end function empty_backedges!(frame::InferenceState, currpc::Int = frame.currpc) diff --git a/base/compiler/methodtable.jl b/base/compiler/methodtable.jl index f613243b4df63..93ea00da4986e 100644 --- a/base/compiler/methodtable.jl +++ b/base/compiler/methodtable.jl @@ -44,6 +44,12 @@ struct OverlayMethodTable <: MethodTableView mt::Core.MethodTable end +struct MethodMatchKey + sig # ::Type + limit::Int + MethodMatchKey(@nospecialize(sig), limit::Int) = new(sig, limit) +end + """ struct CachedMethodTable <: MethodTableView @@ -51,27 +57,28 @@ Overlays another method table view with an additional local fast path cache that can respond to repeated, identical queries faster than the original method table. """ struct CachedMethodTable{T} <: MethodTableView - cache::IdDict{Any, Union{Missing, MethodMatchResult}} + cache::IdDict{MethodMatchKey, Union{Missing,MethodMatchResult}} table::T end -CachedMethodTable(table::T) where T = CachedMethodTable{T}(IdDict{Any, Union{Missing, MethodMatchResult}}(), table) +CachedMethodTable(table::T) where T = CachedMethodTable{T}(IdDict{MethodMatchKey, Union{Missing,MethodMatchResult}}(), table) """ - findall(sig::Type, view::MethodTableView; limit::Int=typemax(Int)) -> + findall(sig::Type, view::MethodTableView; limit::Int=-1) -> MethodMatchResult(matches::MethodLookupResult, overlayed::Bool) or missing Find all methods in the given method table `view` that are applicable to the given signature `sig`. If no applicable methods are found, an empty result is returned. -If the number of applicable methods exceeded the specified limit, `missing` is returned. +If the number of applicable methods exceeded the specified `limit`, `missing` is returned. +Note that the default setting `limit=-1` does not limit the number of applicable methods. `overlayed` indicates if any of the matching methods comes from an overlayed method table. """ -function findall(@nospecialize(sig::Type), table::InternalMethodTable; limit::Int=Int(typemax(Int32))) +function findall(@nospecialize(sig::Type), table::InternalMethodTable; limit::Int=-1) result = _findall(sig, nothing, table.world, limit) result === missing && return missing return MethodMatchResult(result, false) end -function findall(@nospecialize(sig::Type), table::OverlayMethodTable; limit::Int=Int(typemax(Int32))) +function findall(@nospecialize(sig::Type), table::OverlayMethodTable; limit::Int=-1) result = _findall(sig, table.mt, table.world, limit) result === missing && return missing nr = length(result) @@ -104,14 +111,16 @@ function _findall(@nospecialize(sig::Type), mt::Union{Nothing,Core.MethodTable}, return MethodLookupResult(ms::Vector{Any}, WorldRange(_min_val[], _max_val[]), _ambig[] != 0) end -function findall(@nospecialize(sig::Type), table::CachedMethodTable; limit::Int=Int(typemax(Int32))) +function findall(@nospecialize(sig::Type), table::CachedMethodTable; limit::Int=-1) if isconcretetype(sig) # as for concrete types, we cache result at on the next level return findall(sig, table.table; limit) end - box = Core.Box(sig) - return get!(table.cache, sig) do - findall(box.contents, table.table; limit) + key = MethodMatchKey(sig, limit) + if haskey(table.cache, key) + return table.cache[key] + else + return table.cache[key] = findall(sig, table.table; limit) end end diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 9dd6efb704b59..2f45893d6e5e2 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -24,11 +24,14 @@ const IR_FLAG_INLINE = 0x01 << 1 # This statement is marked as @noinline by user const IR_FLAG_NOINLINE = 0x01 << 2 const IR_FLAG_THROW_BLOCK = 0x01 << 3 -# This statement may be removed if its result is unused. In particular it must -# thus be both pure and effect free. +# This statement may be removed if its result is unused. In particular, +# it must be both :effect_free and :nothrow. +# TODO: Separate these out. const IR_FLAG_EFFECT_FREE = 0x01 << 4 # This statement was proven not to throw const IR_FLAG_NOTHROW = 0x01 << 5 +# This is :consistent +const IR_FLAG_CONSISTENT = 0x01 << 6 const TOP_TUPLE = GlobalRef(Core, :tuple) @@ -61,14 +64,13 @@ EdgeTracker() = EdgeTracker(Any[], 0:typemax(UInt)) intersect!(et::EdgeTracker, range::WorldRange) = et.valid_worlds[] = intersect(et.valid_worlds[], range) -push!(et::EdgeTracker, mi::MethodInstance) = push!(et.edges, mi) -function add_edge!(et::EdgeTracker, @nospecialize(invokesig), mi::MethodInstance) - invokesig === nothing && return push!(et.edges, mi) - push!(et.edges, invokesig, mi) +function add_backedge!(et::EdgeTracker, mi::MethodInstance) + push!(et.edges, mi) + return nothing end -function push!(et::EdgeTracker, ci::CodeInstance) - intersect!(et, WorldRange(min_world(li), max_world(li))) - push!(et, ci.def) +function add_invoke_backedge!(et::EdgeTracker, @nospecialize(invokesig), mi::MethodInstance) + push!(et.edges, invokesig, mi) + return nothing end struct InliningState{S <: Union{EdgeTracker, Nothing}, MICache, I<:AbstractInterpreter} @@ -152,7 +154,7 @@ mutable struct OptimizationState # This method is mostly used for unit testing the optimizer inlining = InliningState(params, nothing, - WorldView(code_cache(interp), get_world_counter()), + WorldView(code_cache(interp), get_world_counter(interp)), interp) return new(linfo, src, nothing, stmt_info, mod, sptypes, slottypes, inlining, nothing) @@ -205,21 +207,23 @@ function stmt_affects_purity(@nospecialize(stmt), ir) end """ - stmt_effect_flags(stmt, rt, src::Union{IRCode,IncrementalCompact}) + stmt_effect_flags(stmt, rt, src::Union{IRCode,IncrementalCompact}) -> + (consistent::Bool, effect_free_and_nothrow::Bool, nothrow::Bool) -Returns a tuple of (effect_free_and_nothrow, nothrow) for a given statement. +Returns a tuple of `(:consistent, :effect_free_and_nothrow, :nothrow)` flags for a given statement. """ -function stmt_effect_flags(@nospecialize(stmt), @nospecialize(rt), src::Union{IRCode,IncrementalCompact}) +function stmt_effect_flags(lattice::AbstractLattice, @nospecialize(stmt), @nospecialize(rt), src::Union{IRCode,IncrementalCompact}) # TODO: We're duplicating analysis from inference here. - isa(stmt, PiNode) && return (true, true) - isa(stmt, PhiNode) && return (true, true) - isa(stmt, ReturnNode) && return (false, true) - isa(stmt, GotoNode) && return (false, true) - isa(stmt, GotoIfNot) && return (false, argextype(stmt.cond, src) ⊑ₒ Bool) - isa(stmt, Slot) && return (false, false) # Slots shouldn't occur in the IR at this point, but let's be defensive here + isa(stmt, PiNode) && return (true, true, true) + isa(stmt, PhiNode) && return (true, true, true) + isa(stmt, ReturnNode) && return (true, false, true) + isa(stmt, GotoNode) && return (true, false, true) + isa(stmt, GotoIfNot) && return (true, false, argextype(stmt.cond, src) ⊑ₒ Bool) + isa(stmt, Slot) && return (true, false, false) # Slots shouldn't occur in the IR at this point, but let's be defensive here if isa(stmt, GlobalRef) nothrow = isdefined(stmt.mod, stmt.name) - return (nothrow, nothrow) + consistent = nothrow && isconst(stmt.mod, stmt.name) + return (consistent, nothrow, nothrow) end if isa(stmt, Expr) (; head, args) = stmt @@ -227,72 +231,85 @@ function stmt_effect_flags(@nospecialize(stmt), @nospecialize(rt), src::Union{IR etyp = (isa(src, IRCode) ? src.sptypes : src.ir.sptypes)[args[1]::Int] # if we aren't certain enough about the type, it might be an UndefVarError at runtime nothrow = isa(etyp, Const) - return (nothrow, nothrow) + return (true, nothrow, nothrow) end if head === :call f = argextype(args[1], src) f = singleton_type(f) - f === nothing && return (false, false) - if isa(f, IntrinsicFunction) - nothrow = intrinsic_nothrow(f, - Any[argextype(args[i], src) for i = 2:length(args)]) - nothrow || return (false, false) - return (intrinsic_effect_free_if_nothrow(f), nothrow) + f === nothing && return (false, false, false) + if f === UnionAll + # TODO: This is a weird special case - should be determined in inference + argtypes = Any[argextype(args[arg], src) for arg in 2:length(args)] + nothrow = _builtin_nothrow(lattice, f, argtypes, rt) + return (true, nothrow, nothrow) end - contains_is(_PURE_BUILTINS, f) && return (true, true) - # `get_binding_type` sets the type to Any if the binding doesn't exist yet - if f === Core.get_binding_type - length(args) == 3 || return false - M, s = argextype(args[2], src), argextype(args[3], src) - total = get_binding_type_effect_free(M, s) - return (total, total) - end - rt === Bottom && return (false, false) - nothrow = _builtin_nothrow(f, Any[argextype(args[i], src) for i = 2:length(args)], rt, OptimizerLattice()) - nothrow || return (false, false) - return (contains_is(_EFFECT_FREE_BUILTINS, f), nothrow) + isa(f, Builtin) || return (false, false, false) + # Needs to be handled in inlining to look at the callee effects + f === Core._apply_iterate && return (false, false, false) + argtypes = Any[argextype(args[arg], src) for arg in 2:length(args)] + effects = builtin_effects(lattice, f, argtypes, rt) + consistent = is_consistent(effects) + effect_free = is_effect_free(effects) + nothrow = is_nothrow(effects) + return (consistent, effect_free & nothrow, nothrow) elseif head === :new - typ = argextype(args[1], src) + atyp = argextype(args[1], src) # `Expr(:new)` of unknown type could raise arbitrary TypeError. - typ, isexact = instanceof_tfunc(typ) - isexact || return (false, false) - isconcretedispatch(typ) || return (false, false) + typ, isexact = instanceof_tfunc(atyp) + if !isexact + atyp = unwrap_unionall(widenconst(atyp)) + if isType(atyp) && isTypeDataType(atyp.parameters[1]) + typ = atyp.parameters[1] + else + return (false, false, false) + end + isabstracttype(typ) && return (false, false, false) + else + isconcretedispatch(typ) || return (false, false, false) + end typ = typ::DataType - fieldcount(typ) >= length(args) - 1 || return (false, false) + fieldcount(typ) >= length(args) - 1 || return (false, false, false) for fld_idx in 1:(length(args) - 1) eT = argextype(args[fld_idx + 1], src) fT = fieldtype(typ, fld_idx) - eT ⊑ₒ fT || return (false, false) + # Currently, we cannot represent any type equality constraints + # in the lattice, so if we see any type of type parameter, + # there is very little we can say about it + if !isexact && has_free_typevars(fT) + return (false, false, false) + end + eT ⊑ₒ fT || return (false, false, false) end - return (true, true) + return (false, true, true) elseif head === :foreigncall effects = foreigncall_effects(stmt) do @nospecialize x argextype(x, src) end + consistent = is_consistent(effects) effect_free = is_effect_free(effects) nothrow = is_nothrow(effects) - return (effect_free & nothrow, nothrow) + return (consistent, effect_free & nothrow, nothrow) elseif head === :new_opaque_closure - length(args) < 4 && return (false, false) + length(args) < 4 && return (false, false, false) typ = argextype(args[1], src) typ, isexact = instanceof_tfunc(typ) - isexact || return (false, false) - typ ⊑ₒ Tuple || return (false, false) + isexact || return (false, false, false) + typ ⊑ₒ Tuple || return (false, false, false) rt_lb = argextype(args[2], src) rt_ub = argextype(args[3], src) source = argextype(args[4], src) if !(rt_lb ⊑ₒ Type && rt_ub ⊑ₒ Type && source ⊑ₒ Method) - return (false, false) + return (false, false, false) end - return (true, true) + return (false, true, true) elseif head === :isdefined || head === :the_exception || head === :copyast || head === :inbounds || head === :boundscheck - return (true, true) + return (true, true, true) else # e.g. :loopinfo - return (false, false) + return (false, false, false) end end - return (true, true) + return (true, true, true) end """ @@ -333,7 +350,7 @@ function argextype( elseif isa(x, QuoteNode) return Const(x.value) elseif isa(x, GlobalRef) - return abstract_eval_global(x.mod, x.name) + return abstract_eval_globalref(x) elseif isa(x, PhiNode) return Any elseif isa(x, PiNode) @@ -383,7 +400,7 @@ function finish(interp::AbstractInterpreter, opt::OptimizationState, for i in 1:length(ir.stmts) node = ir.stmts[i] stmt = node[:inst] - if stmt_affects_purity(stmt, ir) && !stmt_effect_flags(stmt, node[:type], ir)[1] + if stmt_affects_purity(stmt, ir) && !stmt_effect_flags(optimizer_lattice(interp), stmt, node[:type], ir)[2] proven_pure = false break end @@ -529,7 +546,7 @@ function run_passes( @pass "slot2reg" ir = slot2reg(ir, ci, sv) # TODO: Domsorting can produce an updated domtree - no need to recompute here @pass "compact 1" ir = compact!(ir) - @pass "Inlining" ir = ssa_inlining_pass!(ir, ir.linetable, sv.inlining, ci.propagate_inbounds) + @pass "Inlining" ir = ssa_inlining_pass!(ir, sv.inlining, ci.propagate_inbounds) # @timeit "verify 2" verify_ir(ir) @pass "compact 2" ir = compact!(ir) @pass "SROA" ir = sroa_pass!(ir, sv.inlining) diff --git a/base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl b/base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl index 7785e61f31e09..a60cfde597f4c 100644 --- a/base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl +++ b/base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl @@ -27,12 +27,11 @@ import ._TOP_MOD: # Base definitions pop!, push!, pushfirst!, empty!, delete!, max, min, enumerate, unwrap_unionall, ismutabletype import Core.Compiler: # Core.Compiler specific definitions - Bottom, InferenceResult, IRCode, IR_FLAG_EFFECT_FREE, + Bottom, InferenceResult, IRCode, IR_FLAG_NOTHROW, isbitstype, isexpr, is_meta_expr_head, println, widenconst, argextype, singleton_type, fieldcount_noerror, try_compute_field, try_compute_fieldidx, hasintersect, ⊑, intrinsic_nothrow, array_builtin_common_typecheck, arrayset_typecheck, - setfield!_nothrow, alloc_array_ndims, stmt_effect_free, check_effect_free!, - SemiConcreteResult + setfield!_nothrow, alloc_array_ndims, stmt_effect_free, check_effect_free! include(x) = _TOP_MOD.include(@__MODULE__, x) if _TOP_MOD === Core.Compiler @@ -773,7 +772,7 @@ A preparatory linear scan before the escape analysis on `ir` to find: This array dimension analysis to compute `arrayinfo` is very local and doesn't account for flow-sensitivity nor complex aliasing. Ideally this dimension analysis should be done as a part of type inference that - propagates array dimenstions in a flow sensitive way. + propagates array dimensions in a flow sensitive way. """ function compute_frameinfo(ir::IRCode, call_resolved::Bool) nstmts, nnewnodes = length(ir.stmts), length(ir.new_nodes.stmts) @@ -1079,7 +1078,7 @@ end error("unexpected assignment found: inspect `Main.pc` and `Main.pc`") end -is_effect_free(ir::IRCode, pc::Int) = getinst(ir, pc)[:flag] & IR_FLAG_EFFECT_FREE ≠ 0 +is_nothrow(ir::IRCode, pc::Int) = getinst(ir, pc)[:flag] & IR_FLAG_NOTHROW ≠ 0 # NOTE if we don't maintain the alias set that is separated from the lattice state, we can do # something like below: it essentially incorporates forward escape propagation in our default @@ -1260,7 +1259,7 @@ function escape_foreigncall!(astate::AnalysisState, pc::Int, args::Vector{Any}) # end end # NOTE array allocations might have been proven as nothrow (https://github.com/JuliaLang/julia/pull/43565) - nothrow = is_effect_free(astate.ir, pc) + nothrow = is_nothrow(astate.ir, pc) name_info = nothrow ? ⊥ : ThrownEscape(pc) add_escape_change!(astate, name, name_info) add_liveness_change!(astate, name, pc) @@ -1336,7 +1335,7 @@ function escape_call!(astate::AnalysisState, pc::Int, args::Vector{Any}) # we escape statements with the `ThrownEscape` property using the effect-freeness # computed by `stmt_effect_flags` invoked within inlining # TODO throwness ≠ "effect-free-ness" - if is_effect_free(astate.ir, pc) + if is_nothrow(astate.ir, pc) add_liveness_changes!(astate, pc, args, 2) else add_fallback_changes!(astate, pc, args, 2) @@ -1442,7 +1441,7 @@ function escape_new!(astate::AnalysisState, pc::Int, args::Vector{Any}) add_liveness_change!(astate, arg, pc) end end - if !is_effect_free(astate.ir, pc) + if !is_nothrow(astate.ir, pc) add_thrown_escapes!(astate, pc, args) end end @@ -1504,6 +1503,8 @@ function escape_builtin!(::typeof(getfield), astate::AnalysisState, pc::Int, arg if isa(obj, SSAValue) || isa(obj, Argument) objinfo = estate[obj] else + # unanalyzable object, so the return value is also unanalyzable + add_escape_change!(astate, SSAValue(pc), ⊤) return false end AliasInfo = objinfo.AliasInfo @@ -1623,6 +1624,8 @@ function escape_builtin!(::typeof(arrayref), astate::AnalysisState, pc::Int, arg if isa(ary, SSAValue) || isa(ary, Argument) aryinfo = estate[ary] else + # unanalyzable object, so the return value is also unanalyzable + add_escape_change!(astate, SSAValue(pc), ⊤) return true end AliasInfo = aryinfo.AliasInfo @@ -1876,13 +1879,13 @@ end # # COMBAK do we want to enable this (and also backport this to Base for array allocations?) # import Core.Compiler: Cint, svec # function validate_foreigncall_args(args::Vector{Any}, -# name::Symbol, @nospecialize(rt), argtypes::SimpleVector, nreq::Int, convension::Symbol) +# name::Symbol, @nospecialize(rt), argtypes::SimpleVector, nreq::Int, convention::Symbol) # length(args) ≥ 5 || return false # normalize(args[1]) === name || return false # args[2] === rt || return false # args[3] === argtypes || return false # args[4] === vararg || return false -# normalize(args[5]) === convension || return false +# normalize(args[5]) === convention || return false # return true # end diff --git a/base/compiler/ssair/EscapeAnalysis/interprocedural.jl b/base/compiler/ssair/EscapeAnalysis/interprocedural.jl index 5b5110fdaec08..dcbc37df84635 100644 --- a/base/compiler/ssair/EscapeAnalysis/interprocedural.jl +++ b/base/compiler/ssair/EscapeAnalysis/interprocedural.jl @@ -1,12 +1,12 @@ # TODO this file contains many duplications with the inlining analysis code, factor them out import Core.Compiler: - MethodInstance, InferenceResult, Signature, ConstPropResult, ConcreteResult, + MethodInstance, InferenceResult, Signature, ConstPropResult, ConcreteResult, SemiConcreteResult, MethodResultPure, MethodMatchInfo, UnionSplitInfo, ConstCallInfo, InvokeCallInfo, call_sig, argtypes_to_type, is_builtin, is_return_type, istopfunction, validate_sparams, specialize_method, invoke_rewrite -const Linfo = Union{MethodInstance,InferenceResult,SemiConcreteResult} +const Linfo = Union{MethodInstance,InferenceResult} struct CallInfo linfos::Vector{Linfo} nothrow::Bool @@ -64,6 +64,10 @@ function analyze_invoke_call(sig::Signature, info::InvokeCallInfo) result = info.result if isa(result, ConstPropResult) return CallInfo(Linfo[result.result], true) + elseif isa(result, ConcreteResult) + return CallInfo(Linfo[result.mi], true) + elseif isa(result, SemiConcreteResult) + return CallInfo(Linfo[result.mi], true) else argtypes = invoke_rewrite(sig.argtypes) mi = analyze_match(match, length(argtypes)) @@ -98,6 +102,8 @@ function analyze_const_call(sig::Signature, cinfo::ConstCallInfo) elseif isa(result, ConcreteResult) # TODO we may want to feedback information that this call always throws if !isdefined(result, :result) push!(linfos, result.mi) + elseif isa(result, SemiConcreteResult) + push!(linfos, result.mi) elseif isa(result, ConstPropResult) push!(linfos, result.result) end diff --git a/base/compiler/ssair/domtree.jl b/base/compiler/ssair/domtree.jl index 984de95a4b58d..eaa21b52aa811 100644 --- a/base/compiler/ssair/domtree.jl +++ b/base/compiler/ssair/domtree.jl @@ -109,10 +109,16 @@ end length(D::DFSTree) = length(D.from_pre) -function DFS!(D::DFSTree, blocks::Vector{BasicBlock}) +function DFS!(D::DFSTree, blocks::Vector{BasicBlock}, is_post_dominator::Bool) copy!(D, DFSTree(length(blocks))) - to_visit = Tuple{BBNumber, PreNumber, Bool}[(1, 0, false)] - pre_num = 1 + if is_post_dominator + # TODO: We're using -1 as the virtual exit node here. Would it make + # sense to actually have a real BB for the exit always? + to_visit = Tuple{BBNumber, PreNumber, Bool}[(-1, 0, false)] + else + to_visit = Tuple{BBNumber, PreNumber, Bool}[(1, 0, false)] + end + pre_num = is_post_dominator ? 0 : 1 post_num = 1 while !isempty(to_visit) # Because we want the postorder number as well as the preorder number, @@ -123,12 +129,14 @@ function DFS!(D::DFSTree, blocks::Vector{BasicBlock}) if pushed_children # Going up the DFS tree, so all we need to do is record the # postorder number, then move on - D.to_post[current_node_bb] = post_num - D.from_post[post_num] = current_node_bb + if current_node_bb != -1 + D.to_post[current_node_bb] = post_num + D.from_post[post_num] = current_node_bb + end post_num += 1 pop!(to_visit) - elseif D.to_pre[current_node_bb] != 0 + elseif current_node_bb != -1 && D.to_pre[current_node_bb] != 0 # Node has already been visited, move on pop!(to_visit) continue @@ -136,15 +144,24 @@ function DFS!(D::DFSTree, blocks::Vector{BasicBlock}) # Going down the DFS tree # Record preorder number - D.to_pre[current_node_bb] = pre_num - D.from_pre[pre_num] = current_node_bb - D.to_parent_pre[pre_num] = parent_pre + if current_node_bb != -1 + D.to_pre[current_node_bb] = pre_num + D.from_pre[pre_num] = current_node_bb + D.to_parent_pre[pre_num] = parent_pre + end # Record that children (will) have been pushed to_visit[end] = (current_node_bb, parent_pre, true) + if is_post_dominator && current_node_bb == -1 + edges = Int[bb for bb in 1:length(blocks) if isempty(blocks[bb].succs)] + else + edges = is_post_dominator ? blocks[current_node_bb].preds : + blocks[current_node_bb].succs + end + # Push children to the stack - for succ_bb in blocks[current_node_bb].succs + for succ_bb in edges push!(to_visit, (succ_bb, pre_num, false)) end @@ -161,7 +178,7 @@ function DFS!(D::DFSTree, blocks::Vector{BasicBlock}) return D end -DFS(blocks::Vector{BasicBlock}) = DFS!(DFSTree(0), blocks) +DFS(blocks::Vector{BasicBlock}, is_post_dominator::Bool=false) = DFS!(DFSTree(0), blocks, is_post_dominator) """ Keeps the per-BB state of the Semi NCA algorithm. In the original formulation, @@ -184,7 +201,7 @@ end DomTreeNode() = DomTreeNode(1, Vector{BBNumber}()) "Data structure that encodes which basic block dominates which." -struct DomTree +struct GenericDomTree{IsPostDom} # These can be reused when updating domtree dynamically dfs_tree::DFSTree snca_state::Vector{SNCAData} @@ -195,19 +212,25 @@ struct DomTree # The nodes in the tree (ordered by BB indices) nodes::Vector{DomTreeNode} end +const DomTree = GenericDomTree{false} +const PostDomTree = GenericDomTree{true} -function DomTree() - return DomTree(DFSTree(0), SNCAData[], BBNumber[], DomTreeNode[]) +function (T::Type{<:GenericDomTree})() + return T(DFSTree(0), SNCAData[], BBNumber[], DomTreeNode[]) end function construct_domtree(blocks::Vector{BasicBlock}) return update_domtree!(blocks, DomTree(), true, 0) end -function update_domtree!(blocks::Vector{BasicBlock}, domtree::DomTree, - recompute_dfs::Bool, max_pre::PreNumber) +function construct_postdomtree(blocks::Vector{BasicBlock}) + return update_domtree!(blocks, PostDomTree(), true, 0) +end + +function update_domtree!(blocks::Vector{BasicBlock}, domtree::GenericDomTree{IsPostDom}, + recompute_dfs::Bool, max_pre::PreNumber) where {IsPostDom} if recompute_dfs - DFS!(domtree.dfs_tree, blocks) + DFS!(domtree.dfs_tree, blocks, IsPostDom) end if max_pre == 0 @@ -219,17 +242,24 @@ function update_domtree!(blocks::Vector{BasicBlock}, domtree::DomTree, return domtree end -function compute_domtree_nodes!(domtree::DomTree) +function compute_domtree_nodes!(domtree::GenericDomTree{IsPostDom}) where {IsPostDom} # Compute children copy!(domtree.nodes, DomTreeNode[DomTreeNode() for _ in 1:length(domtree.idoms_bb)]) for (idx, idom) in Iterators.enumerate(domtree.idoms_bb) - (idx == 1 || idom == 0) && continue + ((!IsPostDom && idx == 1) || idom == 0) && continue push!(domtree.nodes[idom].children, idx) end # n.b. now issorted(domtree.nodes[*].children) since idx is sorted above # Recursively set level - update_level!(domtree.nodes, 1, 1) + if IsPostDom + for (node, idom) in enumerate(domtree.idoms_bb) + idom == 0 || continue + update_level!(domtree.nodes, node, 1) + end + else + update_level!(domtree.nodes, 1, 1) + end return domtree.nodes end @@ -244,13 +274,18 @@ function update_level!(nodes::Vector{DomTreeNode}, node::BBNumber, level::Int) end end +dom_edges(domtree::DomTree, blocks::Vector{BasicBlock}, idx::BBNumber) = + blocks[idx].preds +dom_edges(domtree::PostDomTree, blocks::Vector{BasicBlock}, idx::BBNumber) = + blocks[idx].succs + """ The main Semi-NCA algorithm. Matches Figure 2.8 in [LG05]. Note that the pseudocode in [LG05] is not entirely accurate. The best way to understand what's happening is to read [LT79], then the description of SLT in [LG05] (warning: inconsistent notation), then the description of Semi-NCA. """ -function SNCA!(domtree::DomTree, blocks::Vector{BasicBlock}, max_pre::PreNumber) +function SNCA!(domtree::GenericDomTree{IsPostDom}, blocks::Vector{BasicBlock}, max_pre::PreNumber) where {IsPostDom} D = domtree.dfs_tree state = domtree.snca_state # There may be more blocks than are reachable in the DFS / dominator tree @@ -289,13 +324,14 @@ function SNCA!(domtree::DomTree, blocks::Vector{BasicBlock}, max_pre::PreNumber) # Calculate semidominators, but only for blocks with preorder number up to # max_pre ancestors = copy(D.to_parent_pre) - for w::PreNumber in reverse(2:max_pre) + relevant_blocks = IsPostDom ? (1:max_pre) : (2:max_pre) + for w::PreNumber in reverse(relevant_blocks) # LLVM initializes this to the parent, the paper initializes this to # `w`, but it doesn't really matter (the parent is a predecessor, so at # worst we'll discover it below). Save a memory reference here. semi_w = typemax(PreNumber) last_linked = PreNumber(w + 1) - for v ∈ blocks[D.from_pre[w]].preds + for v ∈ dom_edges(domtree, blocks, D.from_pre[w]) # For the purpose of the domtree, ignore virtual predecessors into # catch blocks. v == 0 && continue @@ -331,7 +367,7 @@ function SNCA!(domtree::DomTree, blocks::Vector{BasicBlock}, max_pre::PreNumber) # ancestor in the (immediate) dominator tree between its semidominator and # its parent (see Lemma 2.6 in [LG05]). idoms_pre = copy(D.to_parent_pre) - for v in 2:n_nodes + for v in (IsPostDom ? (1:n_nodes) : (2:n_nodes)) idom = idoms_pre[v] vsemi = state[v].semi while idom > vsemi @@ -343,10 +379,11 @@ function SNCA!(domtree::DomTree, blocks::Vector{BasicBlock}, max_pre::PreNumber) # Express idoms in BB indexing resize!(domtree.idoms_bb, n_blocks) for i::BBNumber in 1:n_blocks - if i == 1 || D.to_pre[i] == 0 + if (!IsPostDom && i == 1) || D.to_pre[i] == 0 domtree.idoms_bb[i] = 0 else - domtree.idoms_bb[i] = D.from_pre[idoms_pre[D.to_pre[i]]] + ip = idoms_pre[D.to_pre[i]] + domtree.idoms_bb[i] = ip == 0 ? 0 : D.from_pre[ip] end end end @@ -542,12 +579,28 @@ function rename_nodes!(D::DFSTree, rename_bb::Vector{BBNumber}) end """ -Checks if bb1 dominates bb2. -bb1 and bb2 are indexes into the CFG blocks. -bb1 dominates bb2 if the only way to enter bb2 is via bb1. -(Other blocks may be in between, e.g bb1->bbX->bb2). + dominates(domtree::DomTree, bb1::Int, bb2::Int) -> Bool + +Checks if `bb1` dominates `bb2`. +`bb1` and `bb2` are indexes into the `CFG` blocks. +`bb1` dominates `bb2` if the only way to enter `bb2` is via `bb1`. +(Other blocks may be in between, e.g `bb1->bbx->bb2`). +""" +dominates(domtree::DomTree, bb1::BBNumber, bb2::BBNumber) = + _dominates(domtree, bb1, bb2) + +""" + postdominates(domtree::DomTree, bb1::Int, bb2::Int) -> Bool + +Checks if `bb1` post-dominates `bb2`. +`bb1` and `bb2` are indexes into the `CFG` blocks. +`bb1` post-dominates `bb2` if every pass from `bb2` to the exit is via `bb1`. +(Other blocks may be in between, e.g `bb2->bbx->bb1->exit`). """ -function dominates(domtree::DomTree, bb1::BBNumber, bb2::BBNumber) +postdominates(domtree::PostDomTree, bb1::BBNumber, bb2::BBNumber) = + _dominates(domtree, bb1, bb2) + +function _dominates(domtree::GenericDomTree, bb1::BBNumber, bb2::BBNumber) bb1 == bb2 && return true target_level = domtree.nodes[bb1].level source_level = domtree.nodes[bb2].level @@ -582,19 +635,48 @@ function iterate(doms::DominatedBlocks, state::Nothing=nothing) return (bb, nothing) end -function naive_idoms(blocks::Vector{BasicBlock}) +""" + nearest_common_dominator(domtree::GenericDomTree, a::BBNumber, b::BBNumber) + +Compute the nearest common (post-)dominator of `a` and `b`. +""" +function nearest_common_dominator(domtree::GenericDomTree, a::BBNumber, b::BBNumber) + alevel = domtree.nodes[a].level + blevel = domtree.nodes[b].level + # W.l.g. assume blevel <= alevel + if alevel < blevel + a, b = b, a + alevel, blevel = blevel, alevel + end + while alevel > blevel + a = domtree.idoms_bb[a] + alevel -= 1 + end + while a != b && a != 0 + a = domtree.idoms_bb[a] + b = domtree.idoms_bb[b] + end + @assert a == b + return a +end + +function naive_idoms(blocks::Vector{BasicBlock}, is_post_dominator::Bool=false) nblocks = length(blocks) # The extra +1 helps us detect unreachable blocks below dom_all = BitSet(1:nblocks+1) - dominators = BitSet[n == 1 ? BitSet(1) : copy(dom_all) for n = 1:nblocks] + dominators = is_post_dominator ? + BitSet[isempty(blocks[n].succs) ? BitSet(n) : copy(dom_all) for n = 1:nblocks] : + BitSet[n == 1 ? BitSet(1) : copy(dom_all) for n = 1:nblocks] changed = true + relevant_blocks = (is_post_dominator ? (1:nblocks) : (2:nblocks)) while changed changed = false - for n = 2:nblocks - if isempty(blocks[n].preds) + for n in relevant_blocks + edges = is_post_dominator ? blocks[n].succs : blocks[n].preds + if isempty(edges) continue end - firstp, rest = Iterators.peel(Iterators.filter(p->p != 0, blocks[n].preds))::NTuple{2,Any} + firstp, rest = Iterators.peel(Iterators.filter(p->p != 0, edges))::NTuple{2,Any} new_doms = copy(dominators[firstp]) for p in rest intersect!(new_doms, dominators[p]) @@ -606,7 +688,7 @@ function naive_idoms(blocks::Vector{BasicBlock}) end # Compute idoms idoms = fill(0, nblocks) - for i = 2:nblocks + for i in relevant_blocks if dominators[i] == dom_all idoms[i] = 0 continue diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 94a008b3830e3..246dc861c6b02 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -10,7 +10,7 @@ struct Signature end struct ResolvedInliningSpec - # The LineTable and IR of the inlinee + # The IR of the inlinee ir::IRCode # If the function being inlined is a single basic block we can use a # simpler inlining algorithm. This flag determines whether that's allowed @@ -62,7 +62,7 @@ end struct InliningCase sig # Type - item # Union{InliningTodo, MethodInstance, ConstantCase} + item # Union{InliningTodo, InvokeCase, ConstantCase} function InliningCase(@nospecialize(sig), @nospecialize(item)) @assert isa(item, Union{InliningTodo, InvokeCase, ConstantCase}) "invalid inlining item" return new(sig, item) @@ -78,15 +78,32 @@ struct UnionSplit new(fully_covered, atype, cases, Int[]) end +struct InliningEdgeTracker + et::Union{Nothing,EdgeTracker} + invokesig # ::Union{Nothing,Type} + InliningEdgeTracker(et::Union{Nothing,EdgeTracker}, @nospecialize(invokesig=nothing)) = new(et, invokesig) +end + @specialize -function ssa_inlining_pass!(ir::IRCode, linetable::Vector{LineInfoNode}, state::InliningState, propagate_inbounds::Bool) - # Go through the function, performing simple ininlingin (e.g. replacing call by constants +function add_inlining_backedge!((; et, invokesig)::InliningEdgeTracker, mi::MethodInstance) + if et !== nothing + if invokesig === nothing + add_backedge!(et, mi) + else + add_invoke_backedge!(et, invokesig, mi) + end + end + return nothing +end + +function ssa_inlining_pass!(ir::IRCode, state::InliningState, propagate_inbounds::Bool) + # Go through the function, performing simple inlining (e.g. replacing call by constants # and analyzing legality of inlining). @timeit "analysis" todo = assemble_inline_todo!(ir, state) isempty(todo) && return ir # Do the actual inlining for every call we identified - @timeit "execution" ir = batch_inline!(todo, ir, linetable, propagate_inbounds, state.params) + @timeit "execution" ir = batch_inline!(todo, ir, propagate_inbounds, state.params) return ir end @@ -347,52 +364,52 @@ function ir_inline_linetable!(linetable::Vector{LineInfoNode}, inlinee_ir::IRCod return linetable_offset, extra_coverage_line end -function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector{Any}, - linetable::Vector{LineInfoNode}, item::InliningTodo, - boundscheck::Symbol, todo_bbs::Vector{Tuple{Int, Int}}) - # Ok, do the inlining here - spec = item.spec::ResolvedInliningSpec - sparam_vals = item.mi.sparam_vals - def = item.mi.def::Method - inlined_at = compact.result[idx][:line] - linetable_offset::Int32 = length(linetable) - topline::Int32 = linetable_offset + Int32(1) - linetable_offset, extra_coverage_line = ir_inline_linetable!(linetable, item.spec.ir, def, inlined_at) +function ir_prepare_inlining!(insert_node!::Inserter, inline_target::Union{IRCode, IncrementalCompact}, + linetable::Vector{LineInfoNode}, ir′::IRCode, sparam_vals::SimpleVector, + def::Method, inlined_at::Int32, argexprs::Vector{Any}) + topline::Int32 = length(linetable) + Int32(1) + linetable_offset, extra_coverage_line = ir_inline_linetable!(linetable, ir′, def, inlined_at) if extra_coverage_line != 0 - insert_node_here!(compact, NewInstruction(Expr(:code_coverage_effect), Nothing, extra_coverage_line)) + insert_node!(NewInstruction(Expr(:code_coverage_effect), Nothing, extra_coverage_line)) + end + sp_ssa = nothing + if !validate_sparams(sparam_vals) + # N.B. This works on the caller-side argexprs, (i.e. before the va fixup below) + sp_ssa = insert_node!( + effect_free(NewInstruction(Expr(:call, Core._compute_sparams, def, argexprs...), SimpleVector, topline))) end if def.isva nargs_def = Int(def.nargs::Int32) if nargs_def > 0 - argexprs = fix_va_argexprs!(compact, argexprs, nargs_def, topline) + argexprs = fix_va_argexprs!(insert_node!, inline_target, argexprs, nargs_def, topline) end end if def.is_for_opaque_closure # Replace the first argument by a load of the capture environment - argexprs[1] = insert_node_here!(compact, + argexprs[1] = insert_node!( NewInstruction(Expr(:call, GlobalRef(Core, :getfield), argexprs[1], QuoteNode(:captures)), - spec.ir.argtypes[1], topline)) + ir′.argtypes[1], topline)) end + return (Pair{Union{Nothing, SSAValue}, Vector{Any}}(sp_ssa, argexprs), linetable_offset) +end + +function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector{Any}, + linetable::Vector{LineInfoNode}, item::InliningTodo, + boundscheck::Symbol, todo_bbs::Vector{Tuple{Int, Int}}) + # Ok, do the inlining here + spec = item.spec::ResolvedInliningSpec + sparam_vals = item.mi.sparam_vals + def = item.mi.def::Method + inlined_at = compact.result[idx][:line] + + ((sp_ssa, argexprs), linetable_offset) = ir_prepare_inlining!(InsertHere(compact), compact, linetable, + item.spec.ir, sparam_vals, def, inlined_at, argexprs) + if boundscheck === :default || boundscheck === :propagate if (compact.result[idx][:flag] & IR_FLAG_INBOUNDS) != 0 boundscheck = :off end end - if !validate_sparams(sparam_vals) - if def.isva - nonva_args = argexprs[1:end-1] - va_arg = argexprs[end] - tuple_call = Expr(:call, TOP_TUPLE, def, nonva_args...) - tuple_type = tuple_tfunc(OptimizerLattice(), Any[argextype(arg, compact) for arg in nonva_args]) - tupl = insert_node_here!(compact, NewInstruction(tuple_call, tuple_type, topline)) - apply_iter_expr = Expr(:call, Core._apply_iterate, iterate, Core._compute_sparams, tupl, va_arg) - sparam_vals = insert_node_here!(compact, - effect_free(NewInstruction(apply_iter_expr, SimpleVector, topline))) - else - sparam_vals = insert_node_here!(compact, - effect_free(NewInstruction(Expr(:call, Core._compute_sparams, def, argexprs...), SimpleVector, topline))) - end - end # If the iterator already moved on to the next basic block, # temporarily re-open in again. local return_value @@ -408,7 +425,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector # face of rename_arguments! mutating in place - should figure out # something better eventually. inline_compact[idx′] = nothing - stmt′ = ssa_substitute!(idx′, stmt′, argexprs, sig, sparam_vals, linetable_offset, boundscheck, inline_compact) + stmt′ = ssa_substitute!(InsertBefore(inline_compact, SSAValue(idx′)), inline_compact[SSAValue(idx′)], stmt′, argexprs, sig, sparam_vals, sp_ssa, linetable_offset, boundscheck) if isa(stmt′, ReturnNode) val = stmt′.val return_value = SSAValue(idx′) @@ -435,7 +452,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector inline_compact = IncrementalCompact(compact, spec.ir, compact.result_idx) for ((_, idx′), stmt′) in inline_compact inline_compact[idx′] = nothing - stmt′ = ssa_substitute!(idx′, stmt′, argexprs, sig, sparam_vals, linetable_offset, boundscheck, inline_compact) + stmt′ = ssa_substitute!(InsertBefore(inline_compact, SSAValue(idx′)), inline_compact[SSAValue(idx′)], stmt′, argexprs, sig, sparam_vals, sp_ssa, linetable_offset, boundscheck) if isa(stmt′, ReturnNode) if isdefined(stmt′, :val) val = stmt′.val @@ -468,7 +485,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector return_value end -function fix_va_argexprs!(compact::IncrementalCompact, +function fix_va_argexprs!(insert_node!::Inserter, inline_target::Union{IRCode, IncrementalCompact}, argexprs::Vector{Any}, nargs_def::Int, line_idx::Int32) newargexprs = argexprs[1:(nargs_def-1)] tuple_call = Expr(:call, TOP_TUPLE) @@ -476,11 +493,11 @@ function fix_va_argexprs!(compact::IncrementalCompact, for i in nargs_def:length(argexprs) arg = argexprs[i] push!(tuple_call.args, arg) - push!(tuple_typs, argextype(arg, compact)) + push!(tuple_typs, argextype(arg, inline_target)) end tuple_typ = tuple_tfunc(OptimizerLattice(), tuple_typs) tuple_inst = NewInstruction(tuple_call, tuple_typ, line_idx) - push!(newargexprs, insert_node_here!(compact, tuple_inst)) + push!(newargexprs, insert_node!(tuple_inst)) return newargexprs end @@ -600,10 +617,9 @@ function ir_inline_unionsplit!(compact::IncrementalCompact, idx::Int, if isa(case, InliningTodo) val = ir_inline_item!(compact, idx, argexprs′, linetable, case, boundscheck, todo_bbs) elseif isa(case, InvokeCase) - effect_free = is_removable_if_unused(case.effects) - val = insert_node_here!(compact, - NewInstruction(Expr(:invoke, case.invoke, argexprs′...), typ, nothing, - line, effect_free ? IR_FLAG_EFFECT_FREE : IR_FLAG_NULL, effect_free)) + inst = Expr(:invoke, case.invoke, argexprs′...) + flag = flags_for_effects(case.effects) + val = insert_node_here!(compact, NewInstruction(inst, typ, nothing, line, flag, true)) else case = case::ConstantCase val = case.val @@ -640,7 +656,7 @@ function ir_inline_unionsplit!(compact::IncrementalCompact, idx::Int, return insert_node_here!(compact, NewInstruction(pn, typ, line)) end -function batch_inline!(todo::Vector{Pair{Int, Any}}, ir::IRCode, linetable::Vector{LineInfoNode}, propagate_inbounds::Bool, params::OptimizationParams) +function batch_inline!(todo::Vector{Pair{Int, Any}}, ir::IRCode, propagate_inbounds::Bool, params::OptimizationParams) # Compute the new CFG first (modulo statement ranges, which will be computed below) state = CFGInliningState(ir) for (idx, item) in todo @@ -677,7 +693,12 @@ function batch_inline!(todo::Vector{Pair{Int, Any}}, ir::IRCode, linetable::Vect for ((old_idx, idx), stmt) in compact if old_idx == inline_idx stmt = stmt::Expr - argexprs = copy(stmt.args) + if stmt.head === :invoke + argexprs = stmt.args[2:end] + else + @assert stmt.head === :call + argexprs = copy(stmt.args) + end refinish = false if compact.result_idx == first(compact.result_bbs[compact.active_result_bb].stmts) compact.active_result_bb -= 1 @@ -696,9 +717,9 @@ function batch_inline!(todo::Vector{Pair{Int, Any}}, ir::IRCode, linetable::Vect end end if isa(item, InliningTodo) - compact.ssa_rename[old_idx] = ir_inline_item!(compact, idx, argexprs, linetable, item, boundscheck, state.todo_bbs) + compact.ssa_rename[old_idx] = ir_inline_item!(compact, idx, argexprs, ir.linetable, item, boundscheck, state.todo_bbs) elseif isa(item, UnionSplit) - compact.ssa_rename[old_idx] = ir_inline_unionsplit!(compact, idx, argexprs, linetable, item, boundscheck, state.todo_bbs, params) + compact.ssa_rename[old_idx] = ir_inline_unionsplit!(compact, idx, argexprs, ir.linetable, item, boundscheck, state.todo_bbs, params) end compact[idx] = nothing refinish && finish_current_bb!(compact, 0) @@ -812,72 +833,106 @@ function rewrite_apply_exprargs!( return new_argtypes end -function compileable_specialization(et::Union{EdgeTracker, Nothing}, - match::MethodMatch, effects::Effects; compilesig_invokes = true) +function compileable_specialization(match::MethodMatch, effects::Effects, + et::InliningEdgeTracker; compilesig_invokes::Bool=true) mi = specialize_method(match; compilesig=compilesig_invokes) mi === nothing && return nothing - et !== nothing && push!(et, mi) + add_inlining_backedge!(et, mi) return InvokeCase(mi, effects) end -function compileable_specialization(et::Union{EdgeTracker, Nothing}, - linfo::MethodInstance, effects::Effects; compilesig_invokes = true) +function compileable_specialization(linfo::MethodInstance, effects::Effects, + et::InliningEdgeTracker; compilesig_invokes::Bool=true) mi = specialize_method(linfo.def::Method, linfo.specTypes, linfo.sparam_vals; compilesig=compilesig_invokes) mi === nothing && return nothing - et !== nothing && push!(et, mi) + add_inlining_backedge!(et, mi) return InvokeCase(mi, effects) end -function compileable_specialization(et::Union{EdgeTracker, Nothing}, result::InferenceResult, effects::Effects; kwargs...) - return compileable_specialization(et, result.linfo, effects; kwargs...) +compileable_specialization(result::InferenceResult, args...; kwargs...) = (@nospecialize; + compileable_specialization(result.linfo, args...; kwargs...)) + +struct CachedResult + src::Any + effects::Effects + CachedResult(@nospecialize(src), effects::Effects) = new(src, effects) +end +@inline function get_cached_result(state::InliningState, mi::MethodInstance) + code = get(state.mi_cache, mi, nothing) + if code isa CodeInstance + if use_const_api(code) + # in this case function can be inlined to a constant + return ConstantCase(quoted(code.rettype_const)) + else + src = @atomic :monotonic code.inferred + end + effects = decode_effects(code.ipo_purity_bits) + return CachedResult(src, effects) + else # fallback pass for external AbstractInterpreter cache + return CachedResult(code, Effects()) + end end function resolve_todo(todo::InliningTodo, state::InliningState, flag::UInt8) mi = todo.mi (; match, argtypes, invokesig) = todo.spec::DelayedInliningSpec - et = state.et + et = InliningEdgeTracker(state.et, invokesig) #XXX: update_valid_age!(min_valid[1], max_valid[1], sv) if isa(match, InferenceResult) inferred_src = match.src if isa(inferred_src, ConstAPI) # use constant calling convention - et !== nothing && add_edge!(et, invokesig, mi) + add_inlining_backedge!(et, mi) return ConstantCase(quoted(inferred_src.val)) else src = inferred_src # ::Union{Nothing,CodeInfo} for NativeInterpreter end effects = match.ipo_effects else - code = get(state.mi_cache, mi, nothing) - if code isa CodeInstance - if use_const_api(code) - # in this case function can be inlined to a constant - et !== nothing && add_edge!(et, invokesig, mi) - return ConstantCase(quoted(code.rettype_const)) - else - src = @atomic :monotonic code.inferred - end - effects = decode_effects(code.ipo_purity_bits) - else # fallback pass for external AbstractInterpreter cache - effects = Effects() - src = code + cached_result = get_cached_result(state, mi) + if cached_result isa ConstantCase + add_inlining_backedge!(et, mi) + return cached_result end + (; src, effects) = cached_result end # the duplicated check might have been done already within `analyze_method!`, but still # we need it here too since we may come here directly using a constant-prop' result if !state.params.inlining || is_stmt_noinline(flag) - return compileable_specialization(et, match, effects; + return compileable_specialization(match, effects, et; compilesig_invokes=state.params.compilesig_invokes) end src = inlining_policy(state.interp, src, flag, mi, argtypes) - src === nothing && return compileable_specialization(et, match, effects; + src === nothing && return compileable_specialization(match, effects, et; compilesig_invokes=state.params.compilesig_invokes) - et !== nothing && add_edge!(et, invokesig, mi) + add_inlining_backedge!(et, mi) + return InliningTodo(mi, retrieve_ir_for_inlining(mi, src), effects) +end + +function resolve_todo(mi::MethodInstance, argtypes::Vector{Any}, state::InliningState, flag::UInt8) + if !state.params.inlining || is_stmt_noinline(flag) + return nothing + end + + et = InliningEdgeTracker(state.et, nothing) + + cached_result = get_cached_result(state, mi) + if cached_result isa ConstantCase + add_inlining_backedge!(et, mi) + return cached_result + end + (; src, effects) = cached_result + + src = inlining_policy(state.interp, src, flag, mi, argtypes) + + src === nothing && return nothing + + add_inlining_backedge!(et, mi) return InliningTodo(mi, retrieve_ir_for_inlining(mi, src), effects) end @@ -911,13 +966,13 @@ function may_have_fcalls(m::Method) return may_have_fcall end -function can_inline_typevars(m::MethodMatch, argtypes::Vector{Any}) - may_have_fcalls(m.method) && return false - any(@nospecialize(x) -> x isa UnionAll, argtypes[2:end]) && return false +function can_inline_typevars(method::Method, argtypes::Vector{Any}) + may_have_fcalls(method) && return false return true end +can_inline_typevars(m::MethodMatch, argtypes::Vector{Any}) = can_inline_typevars(m.method, argtypes) -function analyze_method!(match::MethodMatch, argtypes::Vector{Any}, invokesig, +function analyze_method!(match::MethodMatch, argtypes::Vector{Any}, @nospecialize(invokesig), flag::UInt8, state::InliningState, allow_typevars::Bool = false) method = match.method spec_types = match.spec_types @@ -944,12 +999,13 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any}, invokesig, (allow_typevars && can_inline_typevars(match, argtypes)) || return nothing end - et = state.et - # See if there exists a specialization for this method signature mi = specialize_method(match; preexisting=true) # Union{Nothing, MethodInstance} - isa(mi, MethodInstance) || return compileable_specialization(et, - match, Effects(); compilesig_invokes=state.params.compilesig_invokes) + if mi === nothing + et = InliningEdgeTracker(state.et, invokesig) + return compileable_specialization(match, Effects(), et; + compilesig_invokes=state.params.compilesig_invokes) + end todo = InliningTodo(mi, match, argtypes, invokesig) # If we don't have caches here, delay resolving this MethodInstance @@ -969,6 +1025,19 @@ end retrieve_ir_for_inlining(mi::MethodInstance, src::CodeInfo) = inflate_ir(src, mi) retrieve_ir_for_inlining(mi::MethodInstance, ir::IRCode) = copy(ir) +function flags_for_effects(effects::Effects) + flags::UInt8 = 0 + if is_consistent(effects) + flags |= IR_FLAG_CONSISTENT + end + if is_removable_if_unused(effects) + flags |= IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW + elseif is_nothrow(effects) + flags |= IR_FLAG_NOTHROW + end + return flags +end + function handle_single_case!( ir::IRCode, idx::Int, stmt::Expr, @nospecialize(case), todo::Vector{Pair{Int, Any}}, params::OptimizationParams, isinvoke::Bool = false) @@ -979,18 +1048,14 @@ function handle_single_case!( isinvoke && rewrite_invoke_exprargs!(stmt) stmt.head = :invoke pushfirst!(stmt.args, case.invoke) - if is_removable_if_unused(case.effects) - ir[SSAValue(idx)][:flag] |= IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW - elseif is_nothrow(case.effects) - ir[SSAValue(idx)][:flag] |= IR_FLAG_NOTHROW - end + ir[SSAValue(idx)][:flag] |= flags_for_effects(case.effects) elseif case === nothing # Do, well, nothing else isinvoke && rewrite_invoke_exprargs!(stmt) push!(todo, idx=>(case::InliningTodo)) end - nothing + return nothing end rewrite_invoke_exprargs!(expr::Expr) = (expr.args = invoke_rewrite(expr.args); expr) @@ -1043,14 +1108,21 @@ end function call_sig(ir::IRCode, stmt::Expr) isempty(stmt.args) && return nothing - ft = argextype(stmt.args[1], ir) + if stmt.head === :call + offset = 1 + elseif stmt.head === :invoke + offset = 2 + else + return nothing + end + ft = argextype(stmt.args[offset], ir) has_free_typevars(ft) && return nothing f = singleton_type(ft) f === Core.Intrinsics.llvmcall && return nothing f === Core.Intrinsics.cglobal && return nothing argtypes = Vector{Any}(undef, length(stmt.args)) argtypes[1] = ft - for i = 2:length(stmt.args) + for i = (offset+1):length(stmt.args) a = argextype(stmt.args[i], ir) (a === Bottom || isvarargtype(a)) && return nothing argtypes[i] = a @@ -1143,10 +1215,10 @@ function inline_invoke!( return nothing end result = info.result + invokesig = invoke_signature(sig.argtypes) if isa(result, ConcreteResult) - item = concrete_result_item(result, state) + item = concrete_result_item(result, state, invokesig) else - invokesig = invoke_signature(sig.argtypes) argtypes = invoke_rewrite(sig.argtypes) if isa(result, ConstPropResult) (; mi) = item = InliningTodo(result.result, argtypes, invokesig) @@ -1163,6 +1235,11 @@ function inline_invoke!( return nothing end +function invoke_signature(argtypes::Vector{Any}) + ft, argtyps = widenconst(argtypes[2]), instanceof_tfunc(widenconst(argtypes[3]))[1] + return rewrap_unionall(Tuple{ft, unwrap_unionall(argtyps).parameters...}, argtyps) +end + function narrow_opaque_closure!(ir::IRCode, stmt::Expr, @nospecialize(info), state::InliningState) if isa(info, OpaqueClosureCreateInfo) lbt = argextype(stmt.args[2], ir) @@ -1174,7 +1251,7 @@ function narrow_opaque_closure!(ir::IRCode, stmt::Expr, @nospecialize(info), sta # Narrow opaque closure type newT = widenconst(tmeet(OptimizerLattice(), tmerge(OptimizerLattice(), lb, info.unspec.rt), ub)) if newT != ub - # N.B.: Narrowing the ub requires a backdge on the mi whose type + # N.B.: Narrowing the ub requires a backedge on the mi whose type # information we're using, since a change in that function may # invalidate ub result. stmt.args[3] = newT @@ -1186,13 +1263,16 @@ end # For primitives, we do that right here. For proper calls, we will # discover this when we consult the caches. function check_effect_free!(ir::IRCode, idx::Int, @nospecialize(stmt), @nospecialize(rt)) - (total, nothrow) = stmt_effect_flags(stmt, rt, ir) - if total + (consistent, effect_free_and_nothrow, nothrow) = stmt_effect_flags(OptimizerLattice(), stmt, rt, ir) + if consistent + ir.stmts[idx][:flag] |= IR_FLAG_CONSISTENT + end + if effect_free_and_nothrow ir.stmts[idx][:flag] |= IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW elseif nothrow ir.stmts[idx][:flag] |= IR_FLAG_NOTHROW end - return total + return effect_free_and_nothrow end # Handles all analysis and inlining of intrinsics and builtins. In particular, @@ -1211,6 +1291,10 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto inline_splatnew!(ir, idx, stmt, rt) elseif head === :new_opaque_closure narrow_opaque_closure!(ir, stmt, ir.stmts[idx][:info], state) + elseif head === :invoke + sig = call_sig(ir, stmt) + sig === nothing && return nothing + return stmt, sig end check_effect_free!(ir, idx, stmt, rt) return nothing @@ -1229,23 +1313,6 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto ir.stmts[idx][:inst] = earlyres.val return nothing end - if (sig.f === modifyfield! || sig.ft ⊑ₒ typeof(modifyfield!)) && 5 <= length(stmt.args) <= 6 - let info = ir.stmts[idx][:info] - info isa MethodResultPure && (info = info.info) - info isa ConstCallInfo && (info = info.call) - info isa MethodMatchInfo || return nothing - length(info.results) == 1 || return nothing - match = info.results[1]::MethodMatch - match.fully_covers || return nothing - case = compileable_specialization(state.et, match, Effects(); - compilesig_invokes=state.params.compilesig_invokes) - case === nothing && return nothing - stmt.head = :invoke_modify - pushfirst!(stmt.args, case.invoke) - ir.stmts[idx][:inst] = stmt - end - return nothing - end if check_effect_free!(ir, idx, stmt, rt) if sig.f === typeassert || sig.ft ⊑ₒ typeof(typeassert) @@ -1255,8 +1322,8 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto end end - if sig.f !== Core.invoke && sig.f !== Core.finalizer && is_builtin(sig) - # No inlining for builtins (other invoke/apply/typeassert) + if (sig.f !== Core.invoke && sig.f !== Core.finalizer && sig.f !== modifyfield!) && is_builtin(sig) + # No inlining for builtins (other invoke/apply/typeassert/finalizer) return nothing end @@ -1271,16 +1338,59 @@ function process_simple!(ir::IRCode, idx::Int, state::InliningState, todo::Vecto return stmt, sig end -# TODO inline non-`isdispatchtuple`, union-split callsites? -function compute_inlining_cases(infos::Vector{MethodMatchInfo}, +function handle_any_const_result!(cases::Vector{InliningCase}, @nospecialize(result), match::MethodMatch, argtypes::Vector{Any}, flag::UInt8, state::InliningState, allow_typevars::Bool=false) + if isa(result, ConcreteResult) + case = concrete_result_item(result, state) + push!(cases, InliningCase(result.mi.specTypes, case)) + return true + elseif isa(result, ConstPropResult) + return handle_const_prop_result!(result, argtypes, flag, state, cases, #=allow_abstract=#true, allow_typevars) + elseif isa(result, SemiConcreteResult) + return handle_semi_concrete_result!(result, cases, #=allow_abstract=#true) + else + @assert result === nothing + return handle_match!(match, argtypes, flag, state, cases, #=allow_abstract=#true, allow_typevars) + end +end + +function info_effects(@nospecialize(result), match::MethodMatch, state::InliningState) + if isa(result, ConcreteResult) + return result.effects + elseif isa(result, SemiConcreteResult) + return result.effects + elseif isa(result, ConstPropResult) + return result.result.ipo_effects + else + mi = specialize_method(match; preexisting=true) + if isa(mi, MethodInstance) + code = get(state.mi_cache, mi, nothing) + if code isa CodeInstance + return decode_effects(code.ipo_purity_bits) + end + end + return Effects() + end +end + +function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInfo}}, flag::UInt8, sig::Signature, state::InliningState) argtypes = sig.argtypes + if isa(info, ConstCallInfo) + (; call, results) = info + infos = isa(call, MethodMatchInfo) ? MethodMatchInfo[call] : call.matches + else + results = nothing + infos = info + end cases = InliningCase[] + local any_fully_covered = false + local handled_all_cases::Bool = true + local revisit_idx = nothing local only_method = nothing local meth::MethodLookupResult - local revisit_idx = nothing - local any_fully_covered = false - local handled_all_cases = true + local all_result_count = 0 + local joint_effects::Effects = EFFECTS_TOTAL + local nothrow::Bool = true for i in 1:length(infos) meth = infos[i].results if meth.ambig @@ -1303,6 +1413,10 @@ function compute_inlining_cases(infos::Vector{MethodMatchInfo}, end end for (j, match) in enumerate(meth) + all_result_count += 1 + result = results === nothing ? nothing : results[all_result_count] + joint_effects = merge_effects(joint_effects, info_effects(result, match, state)) + nothrow &= match.fully_covers any_fully_covered |= match.fully_covers if !validate_sparams(match.sparams) if !match.fully_covers @@ -1310,90 +1424,49 @@ function compute_inlining_cases(infos::Vector{MethodMatchInfo}, continue end if revisit_idx === nothing - revisit_idx = (i, j) + revisit_idx = (i, j, all_result_count) else handled_all_cases = false revisit_idx = nothing end else - handled_all_cases &= handle_match!(match, argtypes, flag, state, cases, #=allow_abstract=#true, #=allow_typevars=#false) + handled_all_cases &= handle_any_const_result!(cases, result, match, argtypes, flag, state, false) end end end + joint_effects = Effects(joint_effects; nothrow) + if handled_all_cases && revisit_idx !== nothing # we handled everything except one match with unmatched sparams, # so try to handle it by bypassing validate_sparams - (i, j) = revisit_idx + (i, j, k) = revisit_idx match = infos[i].results[j] - handled_all_cases &= handle_match!(match, argtypes, flag, state, cases, #=allow_abstract=#true, #=allow_typevars=#true) + result = results === nothing ? nothing : results[k] + handled_all_cases &= handle_any_const_result!(cases, result, match, argtypes, flag, state, true) elseif length(cases) == 0 && only_method isa Method # if the signature is fully covered and there is only one applicable method, - # we can try to inline it even in the prescence of unmatched sparams + # we can try to inline it even in the presence of unmatched sparams # -- But don't try it if we already tried to handle the match in the revisit_idx # case, because that'll (necessarily) be the same method. if length(infos) > 1 atype = argtypes_to_type(argtypes) (metharg, methsp) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), atype, only_method.sig)::SimpleVector match = MethodMatch(metharg, methsp::SimpleVector, only_method, true) + result = nothing else @assert length(meth) == 1 match = meth[1] + result = results === nothing ? nothing : results[1] end - handle_match!(match, argtypes, flag, state, cases, #=allow_abstract=#true, #=allow_typevars=#true) || return nothing + handle_any_const_result!(cases, result, match, argtypes, flag, state, true) any_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 -end - -function compute_inlining_cases(info::ConstCallInfo, - flag::UInt8, sig::Signature, state::InliningState) - argtypes = sig.argtypes - (; call, results) = info - infos = isa(call, MethodMatchInfo) ? MethodMatchInfo[call] : call.matches - cases = InliningCase[] - local any_fully_covered = false - local handled_all_cases = true - local j = 0 - for i in 1:length(infos) - meth = infos[i].results - if meth.ambig - # Too many applicable methods - # Or there is a (partial?) ambiguity - return nothing - elseif length(meth) == 0 - # No applicable methods; try next union split - handled_all_cases = false - continue - end - for match in meth - j += 1 - result = results[j] - any_fully_covered |= match.fully_covers - if isa(result, ConcreteResult) - case = concrete_result_item(result, state) - push!(cases, InliningCase(result.mi.specTypes, case)) - elseif isa(result, ConstPropResult) - handled_all_cases &= handle_const_prop_result!(result, argtypes, flag, state, cases, #=allow_abstract=#true) - elseif isa(result, SemiConcreteResult) - handled_all_cases &= handle_semi_concrete_result!(result, cases, #=allow_abstract=#true) - else - @assert result === nothing - handled_all_cases &= handle_match!(match, argtypes, flag, state, cases, #=allow_abstract=#true, #=allow_typevars=#false) - end - end - end - - if !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 + return cases, (handled_all_cases & any_fully_covered), joint_effects end function handle_call!( @@ -1401,9 +1474,9 @@ function handle_call!( sig::Signature, state::InliningState, todo::Vector{Pair{Int, Any}}) cases = compute_inlining_cases(infos, flag, sig, state) cases === nothing && return nothing - cases, all_covered = cases + cases, all_covered, joint_effects = cases handle_cases!(ir, idx, stmt, argtypes_to_type(sig.argtypes), cases, - all_covered, todo, state.params) + all_covered, todo, state.params, joint_effects) end function handle_const_call!( @@ -1411,9 +1484,9 @@ function handle_const_call!( sig::Signature, state::InliningState, todo::Vector{Pair{Int, Any}}) cases = compute_inlining_cases(info, flag, sig, state) cases === nothing && return nothing - cases, all_covered = cases + cases, all_covered, joint_effects = cases handle_cases!(ir, idx, stmt, argtypes_to_type(sig.argtypes), cases, - all_covered, todo, state.params) + all_covered, todo, state.params, joint_effects) end function handle_match!( @@ -1433,11 +1506,13 @@ end function handle_const_prop_result!( result::ConstPropResult, argtypes::Vector{Any}, flag::UInt8, state::InliningState, - cases::Vector{InliningCase}, allow_abstract::Bool) + cases::Vector{InliningCase}, allow_abstract::Bool, allow_typevars::Bool = false) (; mi) = item = InliningTodo(result.result, argtypes) spec_types = mi.specTypes allow_abstract || isdispatchtuple(spec_types) || return false - validate_sparams(mi.sparam_vals) || return false + if !validate_sparams(mi.sparam_vals) + (allow_typevars && can_inline_typevars(mi.def, argtypes)) || return false + end state.mi_cache !== nothing && (item = resolve_todo(item, state, flag)) item === nothing && return false push!(cases, InliningCase(spec_types, item)) @@ -1453,10 +1528,11 @@ function handle_semi_concrete_result!(result::SemiConcreteResult, cases::Vector{ return true end -function concrete_result_item(result::ConcreteResult, state::InliningState) +function concrete_result_item(result::ConcreteResult, state::InliningState, @nospecialize(invokesig=nothing)) if !isdefined(result, :result) || !is_inlineable_constant(result.result) - case = compileable_specialization(state.et, result.mi, result.effects; - compilesig_invokes = state.params.compilesig_invokes) + et = InliningEdgeTracker(state.et, invokesig) + case = compileable_specialization(result.mi, result.effects, et; + compilesig_invokes=state.params.compilesig_invokes) @assert case !== nothing "concrete evaluation should never happen for uncompileable callsite" return case end @@ -1466,7 +1542,7 @@ end function handle_cases!(ir::IRCode, idx::Int, stmt::Expr, @nospecialize(atype), cases::Vector{InliningCase}, fully_covered::Bool, todo::Vector{Pair{Int, Any}}, - params::OptimizationParams) + params::OptimizationParams, joint_effects::Effects) # If we only have one case and that case is fully covered, we may either # be able to do the inlining now (for constant cases), or push it directly # onto the todo list @@ -1478,6 +1554,8 @@ function handle_cases!(ir::IRCode, idx::Int, stmt::Expr, @nospecialize(atype), isa(case.sig, DataType) || return nothing end push!(todo, idx=>UnionSplit(fully_covered, atype, cases)) + else + ir[SSAValue(idx)][:flag] |= flags_for_effects(joint_effects) end return nothing end @@ -1492,21 +1570,47 @@ function handle_const_opaque_closure_call!( return nothing end +function handle_modifyfield!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyFieldInfo, state::InliningState) + info = info.info + info isa MethodResultPure && (info = info.info) + info isa ConstCallInfo && (info = info.call) + info isa MethodMatchInfo || return nothing + length(info.results) == 1 || return nothing + match = info.results[1]::MethodMatch + match.fully_covers || return nothing + case = compileable_specialization(match, Effects(), InliningEdgeTracker(state.et); + compilesig_invokes=state.params.compilesig_invokes) + case === nothing && return nothing + stmt.head = :invoke_modify + pushfirst!(stmt.args, case.invoke) + ir.stmts[idx][:inst] = stmt + return nothing +end + function handle_finalizer_call!( - ir::IRCode, stmt::Expr, info::FinalizerInfo, state::InliningState) + ir::IRCode, idx::Int, stmt::Expr, info::FinalizerInfo, state::InliningState) + + # Finalizers don't return values, so if their execution is not observable, + # we can just not register them + if is_removable_if_unused(info.effects) + ir[SSAValue(idx)] = nothing + return nothing + end + # Only inline finalizers that are known nothrow and notls. # This avoids having to set up state for finalizer isolation - (is_nothrow(info.effects) && is_notaskstate(info.effects)) || return nothing + is_finalizer_inlineable(info.effects) || return nothing info = info.info + if isa(info, ConstCallInfo) + # NOTE currently mutable objects are not represented as `Const` + # but `finalizer` function can be + info = info.call + end if isa(info, MethodMatchInfo) infos = MethodMatchInfo[info] elseif isa(info, UnionSplitInfo) infos = info.matches - # elseif isa(info, ConstCallInfo) - # # NOTE currently this code path isn't active as constant propagation won't happen - # # for `Core.finalizer` call because inference currently isn't able to fold a mutable - # # object as a constant else return nothing end @@ -1521,7 +1625,7 @@ function handle_finalizer_call!( cases = compute_inlining_cases(infos, #=flag=#UInt8(0), sig, state) cases === nothing && return nothing - cases, all_covered = cases + cases, all_covered, _ = cases if all_covered && length(cases) == 1 # NOTE we don't append `item1` to `stmt` here so that we don't serialize # `Core.Compiler` data structure into the global cache @@ -1540,6 +1644,16 @@ function handle_finalizer_call!( return nothing end +function handle_invoke!(todo::Vector{Pair{Int,Any}}, + idx::Int, stmt::Expr, flag::UInt8, sig::Signature, state::InliningState) + mi = stmt.args[1]::MethodInstance + case = resolve_todo(mi, sig.argtypes, state, flag) + if case !== nothing + push!(todo, idx=>(case::InliningTodo)) + end + return nothing +end + function inline_const_if_inlineable!(inst::Instruction) rt = inst[:type] if rt isa Const && is_inlineable_constant(rt.val) @@ -1558,6 +1672,15 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState) simpleres === nothing && continue stmt, sig = simpleres + flag = ir.stmts[idx][:flag] + + # `NativeInterpreter` won't need this, but provide a support for `:invoke` exprs here + # for external `AbstractInterpreter`s that may run the inlining pass multiple times + if isexpr(stmt, :invoke) + handle_invoke!(todo, idx, stmt, flag, sig, state) + continue + end + info = ir.stmts[idx][:info] # Check whether this call was @pure and evaluates to a constant @@ -1570,8 +1693,6 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState) continue end - flag = ir.stmts[idx][:flag] - if isa(info, OpaqueClosureCallInfo) result = info.result if isa(result, ConstPropResult) @@ -1589,16 +1710,15 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState) continue end - # Handle invoke - if isa(info, InvokeCallInfo) - inline_invoke!(ir, idx, stmt, info, flag, sig, state, todo) + # handle special cased builtins + if isa(info, ModifyFieldInfo) + handle_modifyfield!_call!(ir, idx, stmt, info, state) continue - end - - # Handle finalizer - if isa(info, FinalizerInfo) - handle_finalizer_call!(ir, stmt, info, state) + elseif isa(info, InvokeCallInfo) + inline_invoke!(ir, idx, stmt, info, flag, sig, state, todo) continue + elseif isa(info, FinalizerInfo) + handle_finalizer_call!(ir, idx, stmt, info, state) end # if inference arrived here with constant-prop'ed result(s), @@ -1657,7 +1777,7 @@ function early_inline_special_case( elseif ispuretopfunction(f) || contains_is(_PURE_BUILTINS, f) return SomeCase(quoted(val)) elseif contains_is(_EFFECT_FREE_BUILTINS, f) - if _builtin_nothrow(f, argtypes[2:end], type, OptimizerLattice()) + if _builtin_nothrow(OptimizerLattice(), f, argtypes[2:end], type) return SomeCase(quoted(val)) end elseif f === Core.get_binding_type @@ -1676,7 +1796,7 @@ function early_inline_special_case( setting = setting.val isa(setting, Symbol) || return nothing setting === :const || setting === :conditional || setting === :type || return nothing - # barrierred successfully already, eliminate it + # barriered successfully already, eliminate it return SomeCase(stmt.args[3]) end return nothing @@ -1703,7 +1823,7 @@ function late_inline_special_case!( elseif length(argtypes) == 3 && istopfunction(f, :(>:)) # special-case inliner for issupertype # that works, even though inference generally avoids inferring the `>:` Method - if isa(type, Const) && _builtin_nothrow(<:, Any[argtypes[3], argtypes[2]], type, OptimizerLattice()) + if isa(type, Const) && _builtin_nothrow(OptimizerLattice(), <:, Any[argtypes[3], argtypes[2]], type) return SomeCase(quoted(type.val)) end subtype_call = Expr(:call, GlobalRef(Core, :(<:)), stmt.args[3], stmt.args[2]) @@ -1727,17 +1847,35 @@ function late_inline_special_case!( return nothing end -function ssa_substitute!(idx::Int, @nospecialize(val), arg_replacements::Vector{Any}, - @nospecialize(spsig), spvals::Union{SimpleVector, SSAValue}, - linetable_offset::Int32, boundscheck::Symbol, compact::IncrementalCompact) - compact.result[idx][:flag] &= ~IR_FLAG_INBOUNDS - compact.result[idx][:line] += linetable_offset - return ssa_substitute_op!(val, arg_replacements, spsig, spvals, boundscheck, compact, idx) +function ssa_substitute!(insert_node!::Inserter, + subst_inst::Instruction, @nospecialize(val), arg_replacements::Vector{Any}, + @nospecialize(spsig), spvals::SimpleVector, + spvals_ssa::Union{Nothing, SSAValue}, + linetable_offset::Int32, boundscheck::Symbol) + subst_inst[:flag] &= ~IR_FLAG_INBOUNDS + subst_inst[:line] += linetable_offset + return ssa_substitute_op!(insert_node!, subst_inst, + val, arg_replacements, spsig, spvals, spvals_ssa, boundscheck) +end + +function insert_spval!(insert_node!::Inserter, spvals_ssa::SSAValue, spidx::Int, do_isdefined::Bool) + ret = insert_node!( + effect_free(NewInstruction(Expr(:call, Core._svec_ref, false, spvals_ssa, spidx), Any))) + tcheck_not = nothing + if do_isdefined + tcheck = insert_node!( + effect_free(NewInstruction(Expr(:call, Core.isa, ret, Core.TypeVar), Bool))) + tcheck_not = insert_node!( + effect_free(NewInstruction(Expr(:call, not_int, tcheck), Bool))) + end + return (ret, tcheck_not) end -function ssa_substitute_op!(@nospecialize(val), arg_replacements::Vector{Any}, - @nospecialize(spsig), spvals::Union{SimpleVector, SSAValue}, - boundscheck::Symbol, compact::IncrementalCompact, idx::Int) +function ssa_substitute_op!(insert_node!::Inserter, subst_inst::Instruction, + @nospecialize(val), arg_replacements::Vector{Any}, + @nospecialize(spsig), spvals::SimpleVector, + spvals_ssa::Union{Nothing, SSAValue}, + boundscheck::Symbol) if isa(val, Argument) return arg_replacements[val.n] end @@ -1745,20 +1883,36 @@ function ssa_substitute_op!(@nospecialize(val), arg_replacements::Vector{Any}, e = val::Expr head = e.head if head === :static_parameter - if isa(spvals, SimpleVector) - return quoted(spvals[e.args[1]::Int]) + spidx = e.args[1]::Int + val = spvals[spidx] + if !isa(val, TypeVar) && val !== Vararg + return quoted(val) else - ret = insert_node!(compact, SSAValue(idx), - effect_free(NewInstruction(Expr(:call, Core._svec_ref, false, spvals, e.args[1]), Any))) + flag = subst_inst[:flag] + maybe_undef = (flag & IR_FLAG_NOTHROW) == 0 && isa(val, TypeVar) + (ret, tcheck_not) = insert_spval!(insert_node!, spvals_ssa, spidx, maybe_undef) + if maybe_undef + insert_node!( + non_effect_free(NewInstruction(Expr(:throw_undef_if_not, val.name, tcheck_not), Nothing))) + end return ret end - elseif head === :cfunction && isa(spvals, SimpleVector) + elseif head === :isdefined && isa(e.args[1], Expr) && e.args[1].head === :static_parameter + spidx = (e.args[1]::Expr).args[1]::Int + val = spvals[spidx] + if !isa(val, TypeVar) + return true + else + (_, tcheck_not) = insert_spval!(insert_node!, spvals_ssa, spidx, true) + return tcheck_not + end + elseif head === :cfunction && spvals_ssa === nothing @assert !isa(spsig, UnionAll) || !isempty(spvals) e.args[3] = ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), e.args[3], spsig, spvals) e.args[4] = svec(Any[ ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), argt, spsig, spvals) for argt in e.args[4]::SimpleVector ]...) - elseif head === :foreigncall && isa(spvals, SimpleVector) + elseif head === :foreigncall && spvals_ssa === nothing @assert !isa(spsig, UnionAll) || !isempty(spvals) for i = 1:length(e.args) if i == 2 @@ -1782,7 +1936,7 @@ function ssa_substitute_op!(@nospecialize(val), arg_replacements::Vector{Any}, isa(val, Union{SSAValue, NewSSAValue}) && return val # avoid infinite loop urs = userefs(val) for op in urs - op[] = ssa_substitute_op!(op[], arg_replacements, spsig, spvals, boundscheck, compact, idx) + op[] = ssa_substitute_op!(insert_node!, subst_inst, op[], arg_replacements, spsig, spvals, spvals_ssa, boundscheck) end return urs[] end diff --git a/base/compiler/ssair/ir.jl b/base/compiler/ssair/ir.jl index d422aca269ae2..aad00edebaaca 100644 --- a/base/compiler/ssair/ir.jl +++ b/base/compiler/ssair/ir.jl @@ -28,12 +28,18 @@ function cfg_delete_edge!(cfg::CFG, from::Int, to::Int) nothing end +function bb_ordering() + lt=(<=) + by=x->first(x.stmts) + ord(lt, by, nothing, Forward) +end + function block_for_inst(index::Vector{Int}, inst::Int) return searchsortedfirst(index, inst, lt=(<=)) end function block_for_inst(index::Vector{BasicBlock}, inst::Int) - return searchsortedfirst(index, BasicBlock(StmtRange(inst, inst)), by=x->first(x.stmts), lt=(<=))-1 + return searchsortedfirst(index, BasicBlock(StmtRange(inst, inst)), bb_ordering())-1 end block_for_inst(cfg::CFG, inst::Int) = block_for_inst(cfg.index, inst) @@ -307,6 +313,9 @@ effect_free(inst::NewInstruction) = NewInstruction(inst.stmt, inst.type, inst.info, inst.line, inst.flag | IR_FLAG_EFFECT_FREE, true) non_effect_free(inst::NewInstruction) = NewInstruction(inst.stmt, inst.type, inst.info, inst.line, inst.flag & ~IR_FLAG_EFFECT_FREE, true) +with_flags(inst::NewInstruction, flags::UInt8) = + NewInstruction(inst.stmt, inst.type, inst.info, inst.line, inst.flag | flags, true) + struct IRCode stmts::InstructionStream @@ -394,7 +403,7 @@ struct UndefToken end; const UNDEF_TOKEN = UndefToken() isdefined(stmt, :val) || return OOB_TOKEN op == 1 || return OOB_TOKEN return stmt.val - elseif isa(stmt, Union{SSAValue, NewSSAValue}) + elseif isa(stmt, Union{SSAValue, NewSSAValue, GlobalRef}) op == 1 || return OOB_TOKEN return stmt elseif isa(stmt, UpsilonNode) @@ -446,7 +455,7 @@ end elseif isa(stmt, ReturnNode) op == 1 || throw(BoundsError()) stmt = typeof(stmt)(v) - elseif isa(stmt, Union{SSAValue, NewSSAValue}) + elseif isa(stmt, Union{SSAValue, NewSSAValue, GlobalRef}) op == 1 || throw(BoundsError()) stmt = v elseif isa(stmt, UpsilonNode) @@ -504,12 +513,15 @@ scan_ssa_use!(@specialize(push!), used, @nospecialize(stmt)) = foreachssa(ssa::S # Manually specialized copy of the above with push! === Compiler.push! scan_ssa_use!(used::IdSet, @nospecialize(stmt)) = foreachssa(ssa::SSAValue -> push!(used, ssa.id), stmt) -function insert_node!(ir::IRCode, pos::Int, inst::NewInstruction, attach_after::Bool=false) - node = add!(ir.new_nodes, pos, attach_after) - node[:line] = something(inst.line, ir.stmts[pos][:line]) +function insert_node!(ir::IRCode, pos::SSAValue, inst::NewInstruction, attach_after::Bool=false) + node = add!(ir.new_nodes, pos.id, attach_after) + node[:line] = something(inst.line, ir[pos][:line]) flag = inst.flag if !inst.effect_free_computed - (effect_free_and_nothrow, nothrow) = stmt_effect_flags(inst.stmt, inst.type, ir) + (consistent, effect_free_and_nothrow, nothrow) = stmt_effect_flags(fallback_lattice, inst.stmt, inst.type, ir) + if consistent + flag |= IR_FLAG_CONSISTENT + end if effect_free_and_nothrow flag |= IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW elseif nothrow @@ -519,6 +531,8 @@ function insert_node!(ir::IRCode, pos::Int, inst::NewInstruction, attach_after:: node[:inst], node[:type], node[:flag] = inst.stmt, inst.type, flag return SSAValue(length(ir.stmts) + node.idx) end +insert_node!(ir::IRCode, pos::Int, inst::NewInstruction, attach_after::Bool=false) = + insert_node!(ir, SSAValue(pos), inst, attach_after) # For bootstrapping function my_sortperm(v) @@ -666,7 +680,8 @@ end function block_for_inst(compact::IncrementalCompact, idx::SSAValue) id = idx.id if id < compact.result_idx # if ssa within result - return block_for_inst(compact.result_bbs, id) + return searchsortedfirst(compact.result_bbs, BasicBlock(StmtRange(id, id)), + 1, compact.active_result_bb, bb_ordering())-1 else return block_for_inst(compact.ir.cfg, id) end @@ -675,7 +690,8 @@ end function block_for_inst(compact::IncrementalCompact, idx::OldSSAValue) id = idx.id if id < compact.idx # if ssa within result - return block_for_inst(compact.result_bbs, compact.ssa_rename[id]) + id = compact.ssa_rename[id] + return block_for_inst(compact, SSAValue(id)) else return block_for_inst(compact.ir.cfg, id) end @@ -831,7 +847,10 @@ function insert_node_here!(compact::IncrementalCompact, inst::NewInstruction, re end flag = inst.flag if !inst.effect_free_computed - (effect_free_and_nothrow, nothrow) = stmt_effect_flags(inst.stmt, inst.type, compact) + (consistent, effect_free_and_nothrow, nothrow) = stmt_effect_flags(fallback_lattice, inst.stmt, inst.type, compact) + if consistent + flag |= IR_FLAG_CONSISTENT + end if effect_free_and_nothrow flag |= IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW elseif nothrow @@ -1133,12 +1152,21 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr elseif isa(stmt, OldSSAValue) ssa_rename[idx] = ssa_rename[stmt.id] elseif isa(stmt, GotoNode) && cfg_transforms_enabled - result[result_idx][:inst] = GotoNode(compact.bb_rename_succ[stmt.label]) + label = compact.bb_rename_succ[stmt.label] + @assert label > 0 + result[result_idx][:inst] = GotoNode(label) result_idx += 1 elseif isa(stmt, GlobalRef) - result[result_idx][:inst] = stmt - result[result_idx][:type] = argextype(stmt, compact) - result_idx += 1 + total_flags = IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE + flag = result[result_idx][:flag] + if (flag & total_flags) == total_flags + ssa_rename[idx] = stmt + else + result[result_idx][:inst] = stmt + result[result_idx][:type] = argextype(stmt, compact) + result[result_idx][:flag] = flag + result_idx += 1 + end elseif isa(stmt, GotoNode) result[result_idx][:inst] = stmt result_idx += 1 @@ -1158,19 +1186,25 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr kill_edge!(compact, active_bb, active_bb, stmt.dest) # Don't increment result_idx => Drop this statement else - result[result_idx][:inst] = GotoNode(compact.bb_rename_succ[stmt.dest]) + label = compact.bb_rename_succ[stmt.dest] + @assert label > 0 + result[result_idx][:inst] = GotoNode(label) kill_edge!(compact, active_bb, active_bb, active_bb+1) result_idx += 1 end else @label bail - result[result_idx][:inst] = GotoIfNot(cond, compact.bb_rename_succ[stmt.dest]) + label = compact.bb_rename_succ[stmt.dest] + @assert label > 0 + result[result_idx][:inst] = GotoIfNot(cond, label) result_idx += 1 end elseif isa(stmt, Expr) stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, new_new_used_ssas, late_fixup, result_idx, do_rename_ssa)::Expr if cfg_transforms_enabled && isexpr(stmt, :enter) - stmt.args[1] = compact.bb_rename_succ[stmt.args[1]::Int] + label = compact.bb_rename_succ[stmt.args[1]::Int] + @assert label > 0 + stmt.args[1] = label end result[result_idx][:inst] = stmt result_idx += 1 @@ -1343,10 +1377,7 @@ function process_newnode!(compact::IncrementalCompact, new_idx::Int, new_node_en active_bb += 1 finish_current_bb!(compact, active_bb, old_result_idx) end - (old_result_idx == result_idx) && return iterate(compact, (idx, active_bb)) - return Pair{Pair{Int, Int}, Any}( - Pair{Int,Int}(new_idx,old_result_idx), - compact.result[old_result_idx][:inst]), (idx, active_bb) + return (new_idx, old_result_idx, result_idx, idx, active_bb) end struct CompactPeekIterator @@ -1389,7 +1420,15 @@ function iterate(it::CompactPeekIterator, (idx, aidx, bidx)::NTuple{3, Int}=(it. return (compact.ir.stmts[idx][:inst], (idx + 1, aidx, bidx)) end -function iterate(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}=(compact.idx, 1)) +# This Union{Nothing, Pair{Pair{Int,Int},Any}} cannot be stack allocated, so we inline it +@inline function iterate(compact::IncrementalCompact, st::Tuple{Int, Int}=(compact.idx, 1)) + st = iterate_compact(compact, st) + st === nothing && return nothing + old_result_idx = st[1][2] + return Pair{Pair{Int,Int},Any}(st[1], compact.result[old_result_idx][:inst]), st[2] +end + +function iterate_compact(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}) # Create label to dodge recursion so that we don't stack overflow @label restart @@ -1422,9 +1461,9 @@ function iterate(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}= # Move to next block compact.idx += 1 if finish_current_bb!(compact, active_bb, old_result_idx, true) - return iterate(compact, (compact.idx, active_bb + 1)) + return iterate_compact(compact, (compact.idx, active_bb + 1)) else - return Pair{Pair{Int, Int}, Any}(Pair{Int,Int}(compact.idx-1, old_result_idx), compact.result[old_result_idx][:inst]), (compact.idx, active_bb + 1) + return Pair{Int,Int}(compact.idx-1, old_result_idx), (compact.idx, active_bb + 1) end end if compact.new_nodes_idx <= length(compact.perm) && @@ -1435,7 +1474,10 @@ function iterate(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}= new_node_entry = compact.ir.new_nodes.stmts[new_idx] new_node_info = compact.ir.new_nodes.info[new_idx] new_idx += length(compact.ir.stmts) - return process_newnode!(compact, new_idx, new_node_entry, new_node_info, idx, active_bb, true) + (new_idx, old_result_idx, result_idx, idx, active_bb) = + process_newnode!(compact, new_idx, new_node_entry, new_node_info, idx, active_bb, true) + old_result_idx == result_idx && @goto restart + return Pair{Int,Int}(new_idx, old_result_idx), (idx, active_bb) elseif !isempty(compact.pending_perm) && (info = compact.pending_nodes.info[compact.pending_perm[1]]; info.attach_after ? info.pos == idx - 1 : info.pos == idx) @@ -1443,7 +1485,10 @@ function iterate(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}= new_node_entry = compact.pending_nodes.stmts[new_idx] new_node_info = compact.pending_nodes.info[new_idx] new_idx += length(compact.ir.stmts) + length(compact.ir.new_nodes) - return process_newnode!(compact, new_idx, new_node_entry, new_node_info, idx, active_bb, false) + (new_idx, old_result_idx, result_idx, idx, active_bb) = + process_newnode!(compact, new_idx, new_node_entry, new_node_info, idx, active_bb, false) + old_result_idx == result_idx && @goto restart + return Pair{Int,Int}(new_idx, old_result_idx), (idx, active_bb) end # This will get overwritten in future iterations if # result_idx is not, incremented, but that's ok and expected @@ -1460,8 +1505,7 @@ function iterate(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}= @goto restart end @assert isassigned(compact.result.inst, old_result_idx) - return Pair{Pair{Int,Int}, Any}(Pair{Int,Int}(compact.idx-1, old_result_idx), - compact.result[old_result_idx][:inst]), (compact.idx, active_bb) + return Pair{Int,Int}(compact.idx-1, old_result_idx), (compact.idx, active_bb) end function maybe_erase_unused!( @@ -1619,6 +1663,19 @@ function complete(compact::IncrementalCompact) if __check_ssa_counts__[] oracle_check(compact) end + + # trim trailing undefined statements due to copy propagation + nundef = 0 + for i in length(compact.result):-1:1 + if isassigned(compact.result.inst, i) + break + end + nundef += 1 + end + if nundef > 0 + resize!(compact.result, length(compact.result) - nundef) + end + return IRCode(compact.ir, compact.result, cfg, compact.new_new_nodes) end @@ -1644,3 +1701,18 @@ function iterate(x::BBIdxIter, (idx, bb)::Tuple{Int, Int}=(1, 1)) end return (bb, idx), (idx + 1, next_bb) end + +# Inserters + +abstract type Inserter; end + +struct InsertHere <: Inserter + compact::IncrementalCompact +end +(i::InsertHere)(new_inst::NewInstruction) = insert_node_here!(i.compact, new_inst) + +struct InsertBefore{T<:Union{IRCode, IncrementalCompact}} <: Inserter + src::T + pos::SSAValue +end +(i::InsertBefore)(new_inst::NewInstruction) = insert_node!(i.src, i.pos, new_inst) diff --git a/base/compiler/ssair/irinterp.jl b/base/compiler/ssair/irinterp.jl index 2e7376a4bbc79..bef82684f735a 100644 --- a/base/compiler/ssair/irinterp.jl +++ b/base/compiler/ssair/irinterp.jl @@ -1,23 +1,3 @@ - -function codeinst_to_ir(interp::AbstractInterpreter, code::CodeInstance) - src = code.inferred - mi = code.def - - if isa(src, Vector{UInt8}) - src = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), mi.def, C_NULL, src)::CodeInfo - end - - isa(src, CodeInfo) || return src - - return inflate_ir(src, mi) -end - -function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), - arginfo::ArgInfo, @nospecialize(atype), - sv::IRCode, max_methods::Int) - return CallMeta(Any, Effects(), false) -end - mutable struct TwoPhaseVectorView <: AbstractVector{Int} const data::Vector{Int} count::Int @@ -104,14 +84,58 @@ function getindex(tpdum::TwoPhaseDefUseMap, idx::Int) return TwoPhaseVectorView(tpdum.data, nelems, range) end -function concrete_eval_invoke(interp::AbstractInterpreter, ir::IRCode, mi_cache, - inst::Expr, mi::MethodInstance) +struct IRInterpretationState + ir::IRCode + mi::MethodInstance + world::UInt + argtypes_refined::Vector{Bool} + tpdum::TwoPhaseDefUseMap + ssa_refined::BitSet + lazydomtree::LazyDomtree + function IRInterpretationState(interp::AbstractInterpreter, + ir::IRCode, mi::MethodInstance, world::UInt, argtypes::Vector{Any}) + argtypes = va_process_argtypes(argtypes, mi) + argtypes_refined = Bool[!⊑(typeinf_lattice(interp), ir.argtypes[i], argtypes[i]) for i = 1:length(argtypes)] + empty!(ir.argtypes) + append!(ir.argtypes, argtypes) + tpdum = TwoPhaseDefUseMap(length(ir.stmts)) + ssa_refined = BitSet() + lazydomtree = LazyDomtree(ir) + return new(ir, mi, world, argtypes_refined, tpdum, ssa_refined, lazydomtree) + end +end + +function codeinst_to_ir(interp::AbstractInterpreter, code::CodeInstance) + src = code.inferred + mi = code.def + if isa(src, Vector{UInt8}) + src = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), mi.def, C_NULL, src)::CodeInfo + else + isa(src, CodeInfo) || return src + end + return inflate_ir(src, mi) +end + +function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), + arginfo::ArgInfo, si::StmtInfo, @nospecialize(atype), + sv::IRCode, max_methods::Int) + return CallMeta(Any, Effects(), false) +end + +function collect_limitations!(@nospecialize(typ), ::IRCode) + @assert !isa(typ, LimitedAccuracy) "semi-concrete eval on recursive call graph" + return typ +end + +function concrete_eval_invoke(interp::AbstractInterpreter, + inst::Expr, mi::MethodInstance, irsv::IRInterpretationState) + mi_cache = WorldView(code_cache(interp), irsv.world) code = get(mi_cache, mi, nothing) code === nothing && return nothing - argtypes = collect_argtypes(interp, inst.args[2:end], nothing, ir) + argtypes = collect_argtypes(interp, inst.args[2:end], nothing, irsv.ir) effects = decode_effects(code.ipo_purity_bits) - if is_foldable(effects) && is_all_const_arg(argtypes) - args = collect_semi_const_args(argtypes, 1) + if is_foldable(effects) && is_all_const_arg(argtypes, #=start=#1) + args = collect_const_args(argtypes, #=start=#1) world = get_world_counter(interp) value = try Core._call_in_world_total(world, args...) @@ -124,41 +148,44 @@ function concrete_eval_invoke(interp::AbstractInterpreter, ir::IRCode, mi_cache, else ir′ = codeinst_to_ir(interp, code) if ir′ !== nothing - return _ir_abstract_constant_propagation(interp, mi_cache, mi, ir′, argtypes) + irsv′ = IRInterpretationState(interp, ir′, mi, irsv.world, argtypes) + return _ir_abstract_constant_propagation(interp, irsv′) end end return nothing end -function reprocess_instruction!(interp::AbstractInterpreter, ir::IRCode, mi::MethodInstance, - mi_cache, - tpdum::TwoPhaseDefUseMap, idx::Int, bb::Union{Int, Nothing}, - @nospecialize(inst), @nospecialize(typ), - phi_revisit::BitSet) - function update_phi!(from::Int, to::Int) - if length(ir.cfg.blocks[to].preds) == 0 - return - end - for idx in ir.cfg.blocks[to].stmts - stmt = ir.stmts[idx][:inst] - isa(stmt, Nothing) && continue - isa(stmt, PhiNode) || break - for (i, edge) in enumerate(stmt.edges) - if edge == from - deleteat!(stmt.edges, i) - deleteat!(stmt.values, i) - push!(phi_revisit, idx) - break - end - end - end - end +function abstract_eval_phi_stmt(interp::AbstractInterpreter, phi::PhiNode, ::Int, irsv::IRInterpretationState) + return abstract_eval_phi(interp, phi, nothing, irsv.ir) +end +function reprocess_instruction!(interp::AbstractInterpreter, + idx::Int, bb::Union{Int, Nothing}, @nospecialize(inst), @nospecialize(typ), + irsv::IRInterpretationState) + ir = irsv.ir if isa(inst, GotoIfNot) cond = argextype(inst.cond, ir) if isa(cond, Const) + function update_phi!(from::Int, to::Int) + if length(ir.cfg.blocks[to].preds) == 0 + return + end + for idx in ir.cfg.blocks[to].stmts + stmt = ir.stmts[idx][:inst] + isa(stmt, Nothing) && continue + isa(stmt, PhiNode) || break + for (i, edge) in enumerate(stmt.edges) + if edge == from + deleteat!(stmt.edges, i) + deleteat!(stmt.values, i) + push!(irsv.ssa_refined, idx) + break + end + end + end + end if isa(inst.cond, SSAValue) - kill_def_use!(tpdum, inst.cond, idx) + kill_def_use!(irsv.tpdum, inst.cond::SSAValue, idx) end if bb === nothing bb = block_for_inst(ir, idx) @@ -173,69 +200,56 @@ function reprocess_instruction!(interp::AbstractInterpreter, ir::IRCode, mi::Met return true end return false - else - if isa(inst, Expr) || isa(inst, PhiNode) - if isa(inst, PhiNode) || inst.head === :call || inst.head === :foreigncall || inst.head === :new - if isa(inst, PhiNode) - rt = abstract_eval_phi(interp, inst, nothing, ir) + end + + rt = nothing + if isa(inst, Expr) + if inst.head === :call || inst.head === :foreigncall || inst.head === :new + (; rt, effects) = abstract_eval_statement_expr(interp, inst, nothing, ir, irsv.mi) + # All other effects already guaranteed effect free by construction + if is_nothrow(effects) + if isa(rt, Const) && is_inlineable_constant(rt.val) + ir.stmts[idx][:inst] = quoted(rt.val) else - (;rt, effects) = abstract_eval_statement_expr(interp, inst, nothing, ir, mi) - # All other effects already guaranteed effect free by construction - if is_nothrow(effects) - ir.stmts[idx][:flag] |= IR_FLAG_EFFECT_FREE - end - end - if !⊑(typeinf_lattice(interp), typ, rt) - ir.stmts[idx][:type] = rt - return true + ir.stmts[idx][:flag] |= IR_FLAG_EFFECT_FREE end - elseif inst.head === :invoke - mi′ = inst.args[1]::MethodInstance - if mi′ !== mi # prevent infinite loop - rr = concrete_eval_invoke(interp, ir, mi_cache, inst, mi′) - if rr !== nothing - if !⊑(typeinf_lattice(interp), typ, rr) - ir.stmts[idx][:type] = rr - return true - end - end - end - else - ccall(:jl_, Cvoid, (Any,), inst) - error() end - elseif isa(inst, ReturnNode) - # Handled at the very end - return false - elseif isa(inst, PiNode) - rr = tmeet(argextype(inst.val, ir), inst.typ) - if !⊑(typeinf_lattice(interp), typ, rr) - ir.stmts[idx][:type] = rr - return true + elseif inst.head === :invoke + mi′ = inst.args[1]::MethodInstance + if mi′ !== irsv.mi # prevent infinite loop + rt = concrete_eval_invoke(interp, inst, mi′, irsv) end else ccall(:jl_, Cvoid, (Any,), inst) error() end + elseif isa(inst, PhiNode) + rt = abstract_eval_phi_stmt(interp, inst, idx, irsv) + elseif isa(inst, ReturnNode) + # Handled at the very end + return false + elseif isa(inst, PiNode) + rt = tmeet(argextype(inst.val, ir), inst.typ) + else + ccall(:jl_, Cvoid, (Any,), inst) + error() + end + if rt !== nothing && !⊑(typeinf_lattice(interp), typ, rt) + ir.stmts[idx][:type] = rt + return true end return false end -function _ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache, - mi::MethodInstance, ir::IRCode, argtypes::Vector{Any}; extra_reprocess = nothing) - argtypes = va_process_argtypes(argtypes, mi) - argtypes_refined = Bool[!⊑(typeinf_lattice(interp), ir.argtypes[i], argtypes[i]) for i = 1:length(argtypes)] - empty!(ir.argtypes) - append!(ir.argtypes, argtypes) - ssa_refined = BitSet() +function _ir_abstract_constant_propagation(interp::AbstractInterpreter, irsv::IRInterpretationState; + extra_reprocess::Union{Nothing,BitSet} = nothing) + (; ir, tpdum, ssa_refined) = irsv bbs = ir.cfg.blocks ip = BitSetBoundedMinPrioritySet(length(bbs)) push!(ip, 1) all_rets = Int[] - tpdum = TwoPhaseDefUseMap(length(ir.stmts)) - """ process_terminator! @@ -284,7 +298,7 @@ function _ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache for ur in userefs(inst) val = ur[] if isa(val, Argument) - any_refined |= argtypes_refined[val.n] + any_refined |= irsv.argtypes_refined[val.n] elseif isa(val, SSAValue) any_refined |= val.id in ssa_refined count!(tpdum, val) @@ -294,8 +308,8 @@ function _ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache any_refined = true delete!(ssa_refined, idx) end - if any_refined && reprocess_instruction!(interp, ir, mi, mi_cache, - tpdum, idx, bb, inst, typ, ssa_refined) + if any_refined && reprocess_instruction!(interp, + idx, bb, inst, typ, irsv) push!(ssa_refined, idx) end if idx == lstmt && process_terminator!(ip, bb, idx) @@ -308,92 +322,94 @@ function _ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache end @goto compute_rt -@label residual_scan - stmt_ip = BitSetBoundedMinPrioritySet(length(ir.stmts)) - # Slow Path Phase 1.A: Complete use scanning - while !isempty(ip) - bb = popfirst!(ip) - stmts = bbs[bb].stmts - lstmt = last(stmts) - for idx = stmts - inst = ir.stmts[idx][:inst] - for ur in userefs(inst) - val = ur[] - if isa(val, Argument) - if argtypes_refined[val.n] - push!(stmt_ip, idx) + # Slow path + begin @label residual_scan + stmt_ip = BitSetBoundedMinPrioritySet(length(ir.stmts)) + + # Slow Path Phase 1.A: Complete use scanning + while !isempty(ip) + bb = popfirst!(ip) + stmts = bbs[bb].stmts + lstmt = last(stmts) + for idx = stmts + inst = ir.stmts[idx][:inst] + for ur in userefs(inst) + val = ur[] + if isa(val, Argument) + if irsv.argtypes_refined[val.n] + push!(stmt_ip, idx) + end + elseif isa(val, SSAValue) + count!(tpdum, val) end - elseif isa(val, SSAValue) - count!(tpdum, val) end + idx == lstmt && process_terminator!(ip, bb, idx) end - idx == lstmt && process_terminator!(ip, bb, idx) end - end - # Slow Path Phase 1.B: Assemble def-use map - complete!(tpdum) - push!(ip, 1) - while !isempty(ip) - bb = popfirst!(ip) - stmts = bbs[bb].stmts - lstmt = last(stmts) - for idx = stmts - inst = ir.stmts[idx][:inst] - for ur in userefs(inst) - val = ur[] - if isa(val, SSAValue) - push!(tpdum[val.id], idx) + # Slow Path Phase 1.B: Assemble def-use map + complete!(tpdum) + push!(ip, 1) + while !isempty(ip) + bb = popfirst!(ip) + stmts = bbs[bb].stmts + lstmt = last(stmts) + for idx = stmts + inst = ir.stmts[idx][:inst] + for ur in userefs(inst) + val = ur[] + if isa(val, SSAValue) + push!(tpdum[val.id], idx) + end end + idx == lstmt && process_terminator!(ip, bb, idx) end - idx == lstmt && process_terminator!(ip, bb, idx) end - end - - # Slow Path Phase 2: Use def-use map to converge cycles. - # TODO: It would be possible to return to the fast path after converging - # each cycle, but that's somewhat complicated. - for val in ssa_refined - append!(stmt_ip, tpdum[val]) - end - while !isempty(stmt_ip) - idx = popfirst!(stmt_ip) - inst = ir.stmts[idx][:inst] - typ = ir.stmts[idx][:type] - if reprocess_instruction!(interp, ir, mi, mi_cache, - tpdum, idx, nothing, inst, typ, ssa_refined) - append!(stmt_ip, tpdum[idx]) + # Slow Path Phase 2: Use def-use map to converge cycles. + # TODO: It would be possible to return to the fast path after converging + # each cycle, but that's somewhat complicated. + for val in ssa_refined + append!(stmt_ip, tpdum[val]) + end + while !isempty(stmt_ip) + idx = popfirst!(stmt_ip) + inst = ir.stmts[idx][:inst] + typ = ir.stmts[idx][:type] + if reprocess_instruction!(interp, + idx, nothing, inst, typ, irsv) + append!(stmt_ip, tpdum[idx]) + end end end -@label compute_rt - ultimate_rt = Union{} - for idx in all_rets - bb = block_for_inst(ir.cfg, idx) - if bb != 1 && length(ir.cfg.blocks[bb].preds) == 0 - # Could have discovered this block is dead after the initial scan - continue + begin @label compute_rt + ultimate_rt = Union{} + for idx in all_rets + bb = block_for_inst(ir.cfg, idx) + if bb != 1 && length(ir.cfg.blocks[bb].preds) == 0 + # Could have discovered this block is dead after the initial scan + continue + end + inst = ir.stmts[idx][:inst]::ReturnNode + rt = argextype(inst.val, ir) + ultimate_rt = tmerge(typeinf_lattice(interp), ultimate_rt, rt) end - inst = ir.stmts[idx][:inst]::ReturnNode - rt = argextype(inst.val, ir) - ultimate_rt = tmerge(typeinf_lattice(interp), ultimate_rt, rt) end return ultimate_rt end -function ir_abstract_constant_propagation(interp::AbstractInterpreter, mi_cache, - frame::InferenceState, mi::MethodInstance, ir::IRCode, argtypes::Vector{Any}) +function ir_abstract_constant_propagation(interp::AbstractInterpreter, irsv::IRInterpretationState) if __measure_typeinf__[] - inf_frame = Timings.InferenceFrameInfo(mi, frame.world, Any[], Any[], length(ir.argtypes)) + inf_frame = Timings.InferenceFrameInfo(irsv.mi, irsv.world, Any[], Any[], length(irsv.ir.argtypes)) Timings.enter_new_timer(inf_frame) - v = _ir_abstract_constant_propagation(interp, mi_cache, mi, ir, argtypes) - append!(inf_frame.slottypes, ir.argtypes) + v = _ir_abstract_constant_propagation(interp, irsv) + append!(inf_frame.slottypes, irsv.ir.argtypes) Timings.exit_current_timer(inf_frame) return v else - T = _ir_abstract_constant_propagation(interp, mi_cache, mi, ir, argtypes) + T = _ir_abstract_constant_propagation(interp, irsv) return T end end diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index 0e2b99dced93e..362a14fefde20 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -43,7 +43,7 @@ function compute_live_ins(cfg::CFG, du::SSADefUse) use.kind === :isdefined && continue # filter out `isdefined` usages push!(uses, use.idx) end - compute_live_ins(cfg, du.defs, uses) + compute_live_ins(cfg, sort!(du.defs), uses) end # assume `stmt == getfield(obj, field, ...)` or `stmt == setfield!(obj, field, val, ...)` @@ -140,7 +140,7 @@ function has_safe_def( # if this block has already been examined, bail out to avoid infinite cycles pred in seen && return false idx = last(ir.cfg.blocks[pred].stmts) - # NOTE `idx` isn't a load, thus we can use inclusive coondition within the `find_def_for_use` + # NOTE `idx` isn't a load, thus we can use inclusive condition within the `find_def_for_use` def, _, _ = find_def_for_use(ir, domtree, allblocks, du, idx, true) # will throw since we already checked this `:new` site doesn't define this field def == newidx && return false @@ -595,16 +595,21 @@ function is_old(compact, @nospecialize(old_node_ssa)) !already_inserted(compact, old_node_ssa) end -mutable struct LazyDomtree +mutable struct LazyGenericDomtree{IsPostDom} ir::IRCode - domtree::DomTree - LazyDomtree(ir::IRCode) = new(ir) + domtree::GenericDomTree{IsPostDom} + LazyGenericDomtree{IsPostDom}(ir::IRCode) where {IsPostDom} = new{IsPostDom}(ir) end -function get(x::LazyDomtree) +function get!(x::LazyGenericDomtree{IsPostDom}) where {IsPostDom} isdefined(x, :domtree) && return x.domtree - return @timeit "domtree 2" x.domtree = construct_domtree(x.ir.cfg.blocks) + return @timeit "domtree 2" x.domtree = IsPostDom ? + construct_postdomtree(x.ir.cfg.blocks) : + construct_domtree(x.ir.cfg.blocks) end +const LazyDomtree = LazyGenericDomtree{false} +const LazyPostDomtree = LazyGenericDomtree{true} + function perform_lifting!(compact::IncrementalCompact, visited_phinodes::Vector{AnySSAValue}, @nospecialize(cache_key), lifting_cache::IdDict{Pair{AnySSAValue, Any}, AnySSAValue}, @@ -636,7 +641,7 @@ function perform_lifting!(compact::IncrementalCompact, if all_same dominates_all = true if lazydomtree !== nothing - domtree = get(lazydomtree) + domtree = get!(lazydomtree) for item in visited_phinodes if !dominates_ssa(compact, domtree, the_leaf_val, item) dominates_all = false @@ -723,40 +728,31 @@ function perform_lifting!(compact::IncrementalCompact, end function lift_svec_ref!(compact::IncrementalCompact, idx::Int, stmt::Expr) - if length(stmt.args) != 4 - return - end + length(stmt.args) != 4 && return vec = stmt.args[3] val = stmt.args[4] valT = argextype(val, compact) (isa(valT, Const) && isa(valT.val, Int)) || return valI = valT.val::Int - (1 <= valI) || return + valI >= 1 || return if isa(vec, SimpleVector) - if valI <= length(val) - compact[idx] = vec[valI] - end - return - end - - if isa(vec, SSAValue) + valI <= length(vec) || return + compact[idx] = quoted(vec[valI]) + elseif isa(vec, SSAValue) def = compact[vec][:inst] if is_known_call(def, Core.svec, compact) - nargs = length(def.args) - if valI <= nargs-1 - compact[idx] = def.args[valI+1] - end - return + valI <= length(def.args) - 1 || return + compact[idx] = def.args[valI+1] elseif is_known_call(def, Core._compute_sparams, compact) + valI != 1 && return # TODO generalize this for more values of valI res = _lift_svec_ref(def, compact) - if res !== nothing - compact[idx] = res.val - end - return + res === nothing && return + compact[idx] = res.val end end + return end # TODO: We could do the whole lifing machinery here, but really all @@ -764,12 +760,13 @@ end # which always targets simple `svec` call or `_compute_sparams`, # so this specialized lifting would be enough @inline function _lift_svec_ref(def::Expr, compact::IncrementalCompact) + length(def.args) >= 3 || return nothing m = argextype(def.args[2], compact) isa(m, Const) || return nothing m = m.val isa(m, Method) || return nothing + # TODO: More general structural analysis of the intersection - length(def.args) >= 3 || return nothing sig = m.sig isa(sig, UnionAll) || return nothing tvar = sig.var @@ -873,10 +870,15 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing, InliningState} = nothin end elseif is_known_call(stmt, Core.finalizer, compact) 3 <= length(stmt.args) <= 5 || continue - # Inlining performs legality checks on the finalizer to determine - # whether or not we may inline it. If so, it appends extra arguments - # at the end of the intrinsic. Detect that here. - length(stmt.args) == 5 || continue + info = compact[SSAValue(idx)][:info] + if isa(info, FinalizerInfo) + is_finalizer_inlineable(info.effects) || continue + else + # Inlining performs legality checks on the finalizer to determine + # whether or not we may inline it. If so, it appends extra arguments + # at the end of the intrinsic. Detect that here. + length(stmt.args) == 5 || continue + end is_finalizer = true elseif isexpr(stmt, :foreigncall) nccallargs = length(stmt.args[3]::SimpleVector) @@ -1046,13 +1048,13 @@ end # NOTE we resolve the inlining source here as we don't want to serialize `Core.Compiler` # data structure into the global cache (see the comment in `handle_finalizer_call!`) -function try_inline_finalizer!(ir::IRCode, argexprs::Vector{Any}, idx::Int, mi::MethodInstance, inlining::InliningState) +function try_inline_finalizer!(ir::IRCode, argexprs::Vector{Any}, idx::Int, mi::MethodInstance, inlining::InliningState, attach_after::Bool) code = get(inlining.mi_cache, mi, nothing) - et = inlining.et + et = InliningEdgeTracker(inlining.et) if code isa CodeInstance if use_const_api(code) # No code in the function - Nothing to do - et !== nothing && push!(et, mi) + add_inlining_backedge!(et, mi) return true end src = @atomic :monotonic code.inferred @@ -1068,83 +1070,163 @@ function try_inline_finalizer!(ir::IRCode, argexprs::Vector{Any}, idx::Int, mi:: length(src.cfg.blocks) == 1 || return false # Ok, we're committed to inlining the finalizer - et !== nothing && push!(et, mi) + add_inlining_backedge!(et, mi) - linetable_offset, extra_coverage_line = ir_inline_linetable!(ir.linetable, src, mi.def, ir[SSAValue(idx)][:line]) - if extra_coverage_line != 0 - insert_node!(ir, idx, NewInstruction(Expr(:code_coverage_effect), Nothing, extra_coverage_line)) - end + # TOOD: Should there be a special line number node for inlined finalizers? + inlined_at = ir[SSAValue(idx)][:line] + ((sp_ssa, argexprs), linetable_offset) = ir_prepare_inlining!(InsertBefore(ir, SSAValue(idx)), ir, + ir.linetable, src, mi.sparam_vals, mi.def, inlined_at, argexprs) # TODO: Use the actual inliner here rather than open coding this special purpose inliner. spvals = mi.sparam_vals ssa_rename = Vector{Any}(undef, length(src.stmts)) for idx′ = 1:length(src.stmts) - urs = userefs(src[SSAValue(idx′)][:inst]) - for ur in urs - if isa(ur[], SSAValue) - ur[] = ssa_rename[ur[].id] - elseif isa(ur[], Argument) - ur[] = argexprs[ur[].n] - elseif isexpr(ur[], :static_parameter) - ur[] = spvals[ur[].args[1]] - end - end - # TODO: Scan newly added statement into the sroa defuse struct - stmt = urs[] - isa(stmt, ReturnNode) && continue inst = src[SSAValue(idx′)] - ssa_rename[idx′] = insert_node!(ir, idx, NewInstruction(stmt, inst; line = inst[:line] + linetable_offset), true) + stmt′ = inst[:inst] + isa(stmt′, ReturnNode) && continue + stmt′ = ssamap(stmt′) do ssa::SSAValue + ssa_rename[ssa.id] + end + stmt′ = ssa_substitute_op!(InsertBefore(ir, SSAValue(idx)), inst, stmt′, argexprs, mi.specTypes, mi.sparam_vals, sp_ssa, :default) + ssa_rename[idx′] = insert_node!(ir, idx, NewInstruction(stmt′, inst; line = inst[:line] + linetable_offset), attach_after) end + return true end -is_nothrow(ir::IRCode, pc::Int) = ir.stmts[pc][:flag] & (IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW) ≠ 0 +is_nothrow(ir::IRCode, pc::Int) = (ir.stmts[pc][:flag] & IR_FLAG_NOTHROW) ≠ 0 + +function reachable_blocks(cfg::CFG, from_bb::Int, to_bb::Union{Nothing,Int} = nothing) + worklist = Int[from_bb] + visited = BitSet(from_bb) + if to_bb !== nothing + push!(visited, to_bb) + end + function visit!(bb::Int) + if bb ∉ visited + push!(visited, bb) + push!(worklist, bb) + end + end + while !isempty(worklist) + foreach(visit!, cfg.blocks[pop!(worklist)].succs) + end + return visited +end + +function try_resolve_finalizer!(ir::IRCode, idx::Int, finalizer_idx::Int, defuse::SSADefUse, + inlining::InliningState, lazydomtree::LazyDomtree, + lazypostdomtree::LazyPostDomtree, info::Union{FinalizerInfo, Nothing}) + # For now, require that: + # 1. The allocation dominates the finalizer registration + # 2. The finalizer registration dominates all uses reachable from the + # finalizer registration. + # 3. The insertion block for the finalizer is the post-dominator of all + # uses and the finalizer registration block. The insertion block must + # be dominated by the finalizer registration block. + # 4. The path from the finalizer registration to the finalizer inlining + # location is nothrow + # + # TODO: We could relax item 3, by inlining the finalizer multiple times. + + # Check #1: The allocation dominates the finalizer registration + domtree = get!(lazydomtree) + finalizer_bb = block_for_inst(ir, finalizer_idx) + alloc_bb = block_for_inst(ir, idx) + dominates(domtree, alloc_bb, finalizer_bb) || return nothing + + bb_insert_block::Int = finalizer_bb + bb_insert_idx::Union{Int,Nothing} = finalizer_idx + function note_block_use!(usebb::Int, useidx::Int) + new_bb_insert_block = nearest_common_dominator(get!(lazypostdomtree), + bb_insert_block, usebb) + if new_bb_insert_block == bb_insert_block == usebb + if bb_insert_idx !== nothing + bb_insert_idx = max(bb_insert_idx, useidx) + else + bb_insert_idx = useidx + end + else + bb_insert_idx = nothing + end + bb_insert_block = new_bb_insert_block + nothing + end -function try_resolve_finalizer!(ir::IRCode, idx::Int, finalizer_idx::Int, defuse::SSADefUse, inlining::InliningState) - # For now: Require that all uses and defs are in the same basic block, - # so that live range calculations are easy. - bb = ir.cfg.blocks[block_for_inst(ir.cfg, first(defuse.uses).idx)] - minval::Int = typemax(Int) - maxval::Int = 0 + # Collect all reachable blocks between the finalizer registration and the + # insertion point + blocks = reachable_blocks(ir.cfg, finalizer_bb, alloc_bb) - function check_in_range(x::Union{Int,SSAUse}) - if isa(x, SSAUse) - didx = x.idx + # Check #2 + function check_defuse(x::Union{Int,SSAUse}) + duidx = x isa SSAUse ? x.idx : x + duidx == finalizer_idx && return true + bb = block_for_inst(ir, duidx) + # Not reachable from finalizer registration - we're ok + bb ∉ blocks && return true + note_block_use!(bb, duidx) + if dominates(domtree, finalizer_bb, bb) + return true else - didx = x + return false end - didx in bb.stmts || return false - if didx < minval - minval = didx + end + all(check_defuse, defuse.uses) || return nothing + all(check_defuse, defuse.defs) || return nothing + + # Check #3 + dominates(domtree, finalizer_bb, bb_insert_block) || return nothing + + if !inlining.params.assume_fatal_throw + # Collect all reachable blocks between the finalizer registration and the + # insertion point + blocks = finalizer_bb == bb_insert_block ? Int[finalizer_bb] : + reachable_blocks(ir.cfg, finalizer_bb, bb_insert_block) + + # Check #4 + function check_range_nothrow(ir::IRCode, s::Int, e::Int) + return all(s:e) do sidx::Int + sidx == finalizer_idx && return true + sidx == idx && return true + return is_nothrow(ir, sidx) + end end - if didx > maxval - maxval = didx + for bb in blocks + range = ir.cfg.blocks[bb].stmts + s, e = first(range), last(range) + if bb == bb_insert_block + bb_insert_idx === nothing && continue + e = bb_insert_idx + end + if bb == finalizer_bb + s = finalizer_idx + end + check_range_nothrow(ir, s, e) || return nothing end - return true end - check_in_range(idx) || return nothing - all(check_in_range, defuse.uses) || return nothing - all(check_in_range, defuse.defs) || return nothing - - # For now: Require all statements in the basic block range to be nothrow. - all(minval:maxval) do idx::Int - return is_nothrow(ir, idx) || idx == finalizer_idx - end || return nothing + # Ok, legality check complete. Figure out the exact statement where we're + # gonna inline the finalizer. + loc = bb_insert_idx === nothing ? first(ir.cfg.blocks[bb_insert_block].stmts) : bb_insert_idx::Int + attach_after = bb_insert_idx !== nothing - # Ok, `finalizer` rewrite is legal. finalizer_stmt = ir[SSAValue(finalizer_idx)][:inst] argexprs = Any[finalizer_stmt.args[2], finalizer_stmt.args[3]] - inline = finalizer_stmt.args[4] - if inline === nothing - # No code in the function - Nothing to do - else - mi = finalizer_stmt.args[5]::MethodInstance - if inline::Bool && try_inline_finalizer!(ir, argexprs, maxval, mi, inlining) - # the finalizer body has been inlined + flags = info === nothing ? UInt8(0) : flags_for_effects(info.effects) + if length(finalizer_stmt.args) >= 4 + inline = finalizer_stmt.args[4] + if inline === nothing + # No code in the function - Nothing to do else - insert_node!(ir, maxval, NewInstruction(Expr(:invoke, mi, argexprs...), Nothing), true) + mi = finalizer_stmt.args[5]::MethodInstance + if inline::Bool && try_inline_finalizer!(ir, argexprs, loc, mi, inlining, attach_after) + # the finalizer body has been inlined + else + insert_node!(ir, loc, with_flags(NewInstruction(Expr(:invoke, mi, argexprs...), Nothing), flags), attach_after) + end end + else + insert_node!(ir, loc, with_flags(NewInstruction(Expr(:call, argexprs...), Nothing), flags), attach_after) end # Erase the call to `finalizer` ir[SSAValue(finalizer_idx)][:inst] = nothing @@ -1152,6 +1234,7 @@ function try_resolve_finalizer!(ir::IRCode, idx::Int, finalizer_idx::Int, defuse end function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse}}, used_ssas::Vector{Int}, lazydomtree::LazyDomtree, inlining::Union{Nothing, InliningState}) + lazypostdomtree = LazyPostDomtree(ir) for (idx, (intermediaries, defuse)) in defuses intermediaries = collect(intermediaries) # Check if there are any uses we did not account for. If so, the variable @@ -1184,7 +1267,8 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse end end if finalizer_idx !== nothing && inlining !== nothing - try_resolve_finalizer!(ir, idx, finalizer_idx, defuse, inlining) + try_resolve_finalizer!(ir, idx, finalizer_idx, defuse, inlining, + lazydomtree, lazypostdomtree, ir[SSAValue(finalizer_idx)][:info]) continue end # Partition defuses by field @@ -1231,7 +1315,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse if isempty(ldu.live_in_bbs) phiblocks = Int[] else - phiblocks = iterated_dominance_frontier(ir.cfg, ldu, get(lazydomtree)) + phiblocks = iterated_dominance_frontier(ir.cfg, ldu, get!(lazydomtree)) end allblocks = union!(BitSet(phiblocks), ldu.def_bbs) blocks[fidx] = phiblocks, allblocks @@ -1239,7 +1323,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse for i = 1:length(du.uses) use = du.uses[i] if use.kind === :isdefined - if has_safe_def(ir, get(lazydomtree), allblocks, du, newidx, use.idx) + if has_safe_def(ir, get!(lazydomtree), allblocks, du, newidx, use.idx) ir[SSAValue(use.idx)][:inst] = true else all_eliminated = false @@ -1252,7 +1336,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse continue end end - has_safe_def(ir, get(lazydomtree), allblocks, du, newidx, use.idx) || @goto skip + has_safe_def(ir, get!(lazydomtree), allblocks, du, newidx, use.idx) || @goto skip end else # always have some definition at the allocation site for i = 1:length(du.uses) @@ -1267,7 +1351,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse # Compute domtree now, needed below, now that we have finished compacting the IR. # This needs to be after we iterate through the IR with `IncrementalCompact` # because removing dead blocks can invalidate the domtree. - domtree = get(lazydomtree) + domtree = get!(lazydomtree) local preserve_uses = nothing for fidx in 1:ndefuse du = fielddefuse[fidx] @@ -1409,7 +1493,8 @@ end function is_union_phi(compact::IncrementalCompact, idx::Int) inst = compact.result[idx] - return isa(inst[:inst], PhiNode) && is_some_union(inst[:type]) + isa(inst[:inst], PhiNode) || return false + return is_some_union(inst[:type]) end """ @@ -1742,6 +1827,12 @@ function cfg_simplify!(ir::IRCode) end return idx end + function ascend_eliminated_preds(pred) + while pred != 1 && length(bbs[pred].preds) == 1 && length(bbs[pred].succs) == 1 + pred = bbs[pred].preds[1] + end + return pred + end # Walk the CFG from the entry block and aggressively combine blocks for (idx, bb) in enumerate(bbs) @@ -1758,12 +1849,14 @@ function cfg_simplify!(ir::IRCode) # If this BB is empty, we can still merge it as long as none of our successor's phi nodes # reference our predecessors. found_interference = false + preds = Int[ascend_eliminated_preds(pred) for pred in bb.preds] for idx in bbs[succ].stmts stmt = ir[SSAValue(idx)][:inst] stmt === nothing && continue isa(stmt, PhiNode) || break for edge in stmt.edges - for pred in bb.preds + edge = ascend_eliminated_preds(edge) + for pred in preds if pred == edge found_interference = true @goto done @@ -1779,47 +1872,62 @@ function cfg_simplify!(ir::IRCode) end end - # Assign new BB numbers + # Assign new BB numbers in DFS order, dropping unreachable blocks max_bb_num = 1 - bb_rename_succ = zeros(Int, length(bbs)) - for i = 1:length(bbs) + bb_rename_succ = fill(0, length(bbs)) + worklist = BitSetBoundedMinPrioritySet(length(bbs)) + push!(worklist, 1) + while !isempty(worklist) + i = popfirst!(worklist) # Drop blocks that will be merged away if merge_into[i] != 0 bb_rename_succ[i] = -1 end - # Drop blocks with no predecessors - if i != 1 && length(ir.cfg.blocks[i].preds) == 0 - bb_rename_succ[i] = -1 - end # Mark dropped blocks for fixup if !isempty(searchsorted(dropped_bbs, i)) - bb_rename_succ[i] = -bbs[i].succs[1] + succ = bbs[i].succs[1] + push!(worklist, succ) + bb_rename_succ[i] = -succ end - bb_rename_succ[i] != 0 && continue - - curr = i - while true - bb_rename_succ[curr] = max_bb_num - max_bb_num += 1 - # Now walk the chain of blocks we merged. - # If we end in something that may fall through, - # we have to schedule that block next - curr = follow_merged_succ(curr) - terminator = ir.stmts[ir.cfg.blocks[curr].stmts[end]][:inst] - if isa(terminator, GotoNode) || isa(terminator, ReturnNode) - break + if bb_rename_succ[i] == 0 + curr = i + while true + @assert bb_rename_succ[curr] == 0 + bb_rename_succ[curr] = max_bb_num + max_bb_num += 1 + # Now walk the chain of blocks we merged. + # If we end in something that may fall through, + # we have to schedule that block next + while merged_succ[curr] != 0 + if bb_rename_succ[curr] == 0 + bb_rename_succ[curr] = -1 + end + curr = merged_succ[curr] + end + terminator = ir.stmts[ir.cfg.blocks[curr].stmts[end]][:inst] + if isa(terminator, GotoNode) || isa(terminator, ReturnNode) + break + elseif isa(terminator, GotoIfNot) + if bb_rename_succ[terminator.dest] == 0 + push!(worklist, terminator.dest) + end + end + ncurr = curr + 1 + if !isempty(searchsorted(dropped_bbs, ncurr)) + break + end + curr = ncurr end - curr += 1 - if !isempty(searchsorted(dropped_bbs, curr)) - break + + for succ in bbs[curr].succs + if bb_rename_succ[succ] == 0 + push!(worklist, succ) + end end end end - # Compute map from new to old blocks - result_bbs = Int[findfirst(j->i==j, bb_rename_succ) for i = 1:max_bb_num-1] - # Fixup dropped BBs resolved_all = false while !resolved_all @@ -1838,8 +1946,24 @@ function cfg_simplify!(ir::IRCode) end end - # Figure out how predecessors should be renamed + # Drop remaining unvisited bbs bb_rename_pred = zeros(Int, length(bbs)) + for i = 1:length(bbs) + if bb_rename_succ[i] == 0 + bb_rename_succ[i] = -1 + bb_rename_pred[i] = -2 + end + end + + # Compute map from new to old blocks + result_bbs = zeros(Int, max_bb_num-1) + for (o, bb) in enumerate(bb_rename_succ) + bb > 0 || continue + isempty(searchsorted(dropped_bbs, o)) || continue + result_bbs[bb] = o + end + + # Figure out how predecessors should be renamed for i = 1:length(bbs) if merged_succ[i] != 0 # Block `i` should no longer be a predecessor (before renaming) @@ -1848,11 +1972,32 @@ function cfg_simplify!(ir::IRCode) continue end pred = i + is_unreachable = false + is_multi = false while pred !== 1 && !isempty(searchsorted(dropped_bbs, pred)) - pred = bbs[pred].preds[1] + preds = bbs[pred].preds + if length(preds) == 0 + is_unreachable = true + break + elseif length(preds) > 1 + # This block has multiple predecessors - the only way this is + # legal is if we proved above that our successors don't have + # any phi nodes that would interfere with the renaming. Mark + # this specially. + is_multi = true + break + end + @assert length(preds) == 1 + pred = preds[1] + end + if is_unreachable + @assert bb_rename_pred[i] == -2 + elseif is_multi + bb_rename_pred[i] = -3 + else + bbnum = follow_merge_into(pred) + bb_rename_pred[i] = bb_rename_succ[bbnum] end - bbnum = follow_merge_into(pred) - bb_rename_pred[i] = bb_rename_succ[bbnum] end # Compute new block lengths @@ -1886,7 +2031,20 @@ function cfg_simplify!(ir::IRCode) function compute_preds(i) orig_bb = result_bbs[i] preds = bbs[orig_bb].preds - return Int[bb_rename_pred[pred] for pred in preds] + res = Int[] + function scan_preds!(preds) + for pred in preds + r = bb_rename_pred[pred] + r == -2 && continue + if r == -3 + scan_preds!(bbs[pred].preds) + else + push!(res, r) + end + end + end + scan_preds!(preds) + return res end BasicBlock[ @@ -1903,8 +2061,10 @@ function cfg_simplify!(ir::IRCode) @assert length(new_bb.succs) <= 2 length(new_bb.succs) <= 1 && continue if new_bb.succs[1] == new_bb.succs[2] - terminator = ir[SSAValue(last(bbs[old_bb].stmts))] + old_bb2 = findfirst(x->x==bbidx, bb_rename_pred) + terminator = ir[SSAValue(last(bbs[old_bb2].stmts))] @assert isa(terminator[:inst], GotoIfNot) + # N.B.: The dest will be renamed in process_node! below terminator[:inst] = GotoNode(terminator[:inst].dest) pop!(new_bb.succs) new_succ = cresult_bbs[new_bb.succs[1]] @@ -1945,6 +2105,7 @@ function cfg_simplify!(ir::IRCode) ms = merged_succ[ms] end end + compact.idx = length(ir.stmts) compact.active_result_bb = length(bb_starts) return finish(compact) end diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 1ff2641c42a96..242e133cbd35f 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -157,9 +157,10 @@ function should_print_ssa_type(@nospecialize node) !isa(node, QuoteNode) end -function default_expr_type_printer(io::IO, @nospecialize(typ), used::Bool) - printstyled(io, "::", typ, color=(used ? :cyan : :light_black)) - nothing +function default_expr_type_printer(io::IO; @nospecialize(type), used::Bool, show_type::Bool=true, _...) + show_type || return nothing + printstyled(io, "::", type, color=(used ? :cyan : :light_black)) + return nothing end normalize_method_name(m::Method) = m.name @@ -497,14 +498,18 @@ function DILineInfoPrinter(linetable::Vector, showtypes::Bool=false) return emit_lineinfo_update end -# line_info_preprinter(io::IO, indent::String, idx::Int) may print relevant info -# at the beginning of the line, and should at least print `indent`. It returns a -# string that will be printed after the final basic-block annotation. -# line_info_postprinter(io::IO, typ, used::Bool) prints the type-annotation at the end -# of the statement -# should_print_stmt(idx::Int) -> Bool: whether the statement at index `idx` should be -# printed as part of the IR or not -# bb_color: color used for printing the basic block brackets on the left +""" + IRShowConfig + +- `line_info_preprinter(io::IO, indent::String, idx::Int)`` may print relevant info + at the beginning of the line, and should at least print `indent`. It returns a + string that will be printed after the final basic-block annotation. +- `line_info_postprinter(io::IO; type, used::Bool, show_type::Bool, idx::Int)` prints + relevant information like type-annotation at the end of the statement +- `should_print_stmt(idx::Int) -> Bool`: whether the statement at index `idx` should be + printed as part of the IR or not +- `bb_color`: color used for printing the basic block brackets on the left +""" struct IRShowConfig line_info_preprinter line_info_postprinter @@ -647,8 +652,8 @@ function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo, IncrementalCompact}, if new_node_type === UNDEF # try to be robust against errors printstyled(io, "::#UNDEF", color=:red) - elseif show_type - line_info_postprinter(IOContext(io, :idx => node_idx), new_node_type, node_idx in used) + else + line_info_postprinter(io; type = new_node_type, used = node_idx in used, show_type, idx = node_idx) end println(io) i += 1 @@ -662,22 +667,28 @@ function show_ir_stmt(io::IO, code::Union{IRCode, CodeInfo, IncrementalCompact}, if type === UNDEF # This is an error, but can happen if passes don't update their type information printstyled(io, "::#UNDEF", color=:red) - elseif show_type - line_info_postprinter(IOContext(io, :idx => idx), type, idx in used) + else + line_info_postprinter(io; type, used = idx in used, show_type, idx) end end println(io) return bb_idx end -function _new_nodes_iter(stmts, new_nodes, new_nodes_info) +function _new_nodes_iter(stmts, new_nodes, new_nodes_info, new_nodes_idx) new_nodes_perm = filter(i -> isassigned(new_nodes.inst, i), 1:length(new_nodes)) sort!(new_nodes_perm, by = x -> (x = new_nodes_info[x]; (x.pos, x.attach_after))) perm_idx = Ref(1) - return function (idx::Int) + return function get_new_node(idx::Int) perm_idx[] <= length(new_nodes_perm) || return nothing node_idx = new_nodes_perm[perm_idx[]] + if node_idx < new_nodes_idx + # skip new nodes that have already been processed by incremental compact + # (but don't just return nothing because there may be multiple at this pos) + perm_idx[] += 1 + return get_new_node(idx) + end if new_nodes_info[node_idx].pos != idx return nothing end @@ -690,18 +701,18 @@ function _new_nodes_iter(stmts, new_nodes, new_nodes_info) end end -function new_nodes_iter(ir::IRCode) +function new_nodes_iter(ir::IRCode, new_nodes_idx=1) stmts = ir.stmts new_nodes = ir.new_nodes.stmts new_nodes_info = ir.new_nodes.info - return _new_nodes_iter(stmts, new_nodes, new_nodes_info) + return _new_nodes_iter(stmts, new_nodes, new_nodes_info, new_nodes_idx) end function new_nodes_iter(compact::IncrementalCompact) stmts = compact.result new_nodes = compact.new_new_nodes.stmts new_nodes_info = compact.new_new_nodes.info - return _new_nodes_iter(stmts, new_nodes, new_nodes_info) + return _new_nodes_iter(stmts, new_nodes, new_nodes_info, 1) end # print only line numbers on the left, some of the method names and nesting depth on the right @@ -731,7 +742,7 @@ function inline_linfo_printer(code::IRCode) end # Print location information right aligned. If the line below is too long, it'll overwrite this, # but that's what we want. - if get(io, :color, false) + if get(io, :color, false)::Bool method_start_column = cols - max_method_width - max_loc_width - 2 filler = " "^(max_loc_width-length(annotation)) printstyled(io, "\e[$(method_start_column)G$(annotation)$(filler)$(loc_method)\e[1G", color = :light_black) @@ -813,7 +824,8 @@ function show_ir(io::IO, ir::IRCode, config::IRShowConfig=default_config(ir); pop_new_node! = new_nodes_iter(ir)) used = stmts_used(io, ir) cfg = ir.cfg - let io = IOContext(io, :maxssaid=>length(ir.stmts)) + maxssaid = length(ir.stmts) + Core.Compiler.length(ir.new_nodes) + let io = IOContext(io, :maxssaid=>maxssaid) show_ir_stmts(io, ir, 1:length(ir.stmts), config, used, cfg, 1; pop_new_node!) end finish_show_ir(io, cfg, config) @@ -830,6 +842,7 @@ function show_ir(io::IO, ci::CodeInfo, config::IRShowConfig=default_config(ci); end function show_ir(io::IO, compact::IncrementalCompact, config::IRShowConfig=default_config(compact.ir)) + compact_cfg = CFG(compact.result_bbs, Int[first(compact.result_bbs[i].stmts) for i in 2:length(compact.result_bbs)]) cfg = compact.ir.cfg (_, width) = displaysize(io) @@ -844,19 +857,22 @@ function show_ir(io::IO, compact::IncrementalCompact, config::IRShowConfig=defau end end pop_new_node! = new_nodes_iter(compact) - bb_idx = let io = IOContext(io, :maxssaid=>length(compact.result)) - show_ir_stmts(io, compact, 1:compact.result_idx-1, config, used_compacted, cfg, 1; pop_new_node!) + maxssaid = length(compact.result) + Core.Compiler.length(compact.new_new_nodes) + bb_idx = let io = IOContext(io, :maxssaid=>maxssaid) + show_ir_stmts(io, compact, 1:compact.result_idx-1, config, used_compacted, compact_cfg, 1; pop_new_node!) end # Print uncompacted nodes from the original IR + + # print a separator stmts = compact.ir.stmts - pop_new_node! = new_nodes_iter(compact.ir) - if compact.idx < length(stmts) - indent = length(string(length(stmts))) - # config.line_info_preprinter(io, "", compact.idx) - printstyled(io, "─"^(width-indent-1), '\n', color=:red) - end - let io = IOContext(io, :maxssaid=>length(compact.ir.stmts)) + indent = length(string(length(stmts))) + # config.line_info_preprinter(io, "", compact.idx) + printstyled(io, "─"^(width-indent-1), '\n', color=:red) + + pop_new_node! = new_nodes_iter(compact.ir, compact.new_nodes_idx) + maxssaid = length(compact.ir.stmts) + Core.Compiler.length(compact.ir.new_nodes) + let io = IOContext(io, :maxssaid=>maxssaid) show_ir_stmts(io, compact.ir, compact.idx:length(stmts), config, used_uncompacted, cfg, bb_idx; pop_new_node!) end diff --git a/base/compiler/ssair/slot2ssa.jl b/base/compiler/ssair/slot2ssa.jl index da8580be5d2a1..6a9a128104b30 100644 --- a/base/compiler/ssair/slot2ssa.jl +++ b/base/compiler/ssair/slot2ssa.jl @@ -216,7 +216,7 @@ function typ_for_val(@nospecialize(x), ci::CodeInfo, sptypes::Vector{Any}, idx:: end return (ci.ssavaluetypes::Vector{Any})[idx] end - isa(x, GlobalRef) && return abstract_eval_global(x.mod, x.name) + isa(x, GlobalRef) && return abstract_eval_globalref(x) isa(x, SSAValue) && return (ci.ssavaluetypes::Vector{Any})[x.id] isa(x, Argument) && return slottypes[x.n] isa(x, NewSSAValue) && return DelayedTyp(x) diff --git a/base/compiler/ssair/verify.jl b/base/compiler/ssair/verify.jl index fcbed694bc2db..ca460b10ca67d 100644 --- a/base/compiler/ssair/verify.jl +++ b/base/compiler/ssair/verify.jl @@ -1,13 +1,22 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +function maybe_show_ir(ir::IRCode) + if isdefined(Core, :Main) + Core.Main.Base.display(ir) + end +end + if !isdefined(@__MODULE__, Symbol("@verify_error")) macro verify_error(arg) arg isa String && return esc(:(print && println(stderr, $arg))) - (arg isa Expr && arg.head === :string) || error("verify_error macro expected a string expression") + isexpr(arg, :string) || error("verify_error macro expected a string expression") pushfirst!(arg.args, GlobalRef(Core, :stderr)) pushfirst!(arg.args, :println) arg.head = :call - return esc(arg) + return esc(quote + $arg + maybe_show_ir(ir) + end) end end diff --git a/base/compiler/stmtinfo.jl b/base/compiler/stmtinfo.jl index 966ee32338b48..2b0f453951ec8 100644 --- a/base/compiler/stmtinfo.jl +++ b/base/compiler/stmtinfo.jl @@ -197,7 +197,17 @@ object type. """ struct FinalizerInfo info::Any - effects::Effects + effects::Effects # the effects for the finalizer call +end + +""" + info::ModifyFieldInfo + +Represents a resolved all of `modifyfield!(obj, name, op, x, [order])`. +`info.info` wraps the call information of `op(getfield(obj, name), x)`. +""" +struct ModifyFieldInfo + info::Any # the callinfo for the `op(getfield(obj, name), x)` call end @specialize diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 5c51ca81a2fdf..32551df34eea2 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -25,6 +25,7 @@ function find_tfunc(@nospecialize f) end const DATATYPE_TYPES_FIELDINDEX = fieldindex(DataType, :types) +const DATATYPE_NAME_FIELDINDEX = fieldindex(DataType, :name) ########## # tfuncs # @@ -823,7 +824,10 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), boundscheck:: if isa(s, Union) return getfield_nothrow(rewrap_unionall(s.a, s00), name, boundscheck) && getfield_nothrow(rewrap_unionall(s.b, s00), name, boundscheck) - elseif isa(s, DataType) + elseif isType(s) && isTypeDataType(s.parameters[1]) + s = s0 = DataType + end + if isa(s, DataType) # Can't say anything about abstract types isabstracttype(s) && return false s.name.atomicfields == C_NULL || return false # TODO: currently we're only testing for ordering === :not_atomic @@ -863,15 +867,40 @@ function getfield_tfunc(s00, name, order, boundscheck) return getfield_tfunc(s00, name) end getfield_tfunc(@nospecialize(s00), @nospecialize(name)) = _getfield_tfunc(s00, name, false) + +function _getfield_fieldindex(@nospecialize(s), name::Const) + nv = name.val + if isa(nv, Symbol) + nv = fieldindex(s, nv, false) + end + if isa(nv, Int) + return nv + end + return nothing +end + +function _getfield_tfunc_const(@nospecialize(sv), name::Const, setfield::Bool) + if isa(name, Const) + nv = _getfield_fieldindex(typeof(sv), name) + nv === nothing && return Bottom + if isa(sv, DataType) && nv == DATATYPE_TYPES_FIELDINDEX && isdefined(sv, nv) + return Const(getfield(sv, nv)) + end + if isconst(typeof(sv), nv) + if isdefined(sv, nv) + return Const(getfield(sv, nv)) + end + return Union{} + end + end + return nothing +end + function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool) if isa(s00, Conditional) return Bottom # Bool has no fields - elseif isa(s00, Const) || isconstType(s00) - if !isa(s00, Const) - sv = s00.parameters[1] - else - sv = s00.val - end + elseif isa(s00, Const) + sv = s00.val if isa(name, Const) nv = name.val if isa(sv, Module) @@ -881,31 +910,15 @@ function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool end return Bottom end - if isa(nv, Symbol) - nv = fieldindex(typeof(sv), nv, false) - end - if !isa(nv, Int) - return Bottom - end - if isa(sv, DataType) && nv == DATATYPE_TYPES_FIELDINDEX && isdefined(sv, nv) - return Const(getfield(sv, nv)) - end - if isconst(typeof(sv), nv) - if isdefined(sv, nv) - return Const(getfield(sv, nv)) - end - return Union{} - end + r = _getfield_tfunc_const(sv, name, setfield) + r !== nothing && return r end s = typeof(sv) elseif isa(s00, PartialStruct) s = widenconst(s00) sty = unwrap_unionall(s)::DataType if isa(name, Const) - nv = name.val - if isa(nv, Symbol) - nv = fieldindex(sty, nv, false) - end + nv = _getfield_fieldindex(sty, name) if isa(nv, Int) && 1 <= nv <= length(s00.fields) return unwrapva(s00.fields[nv]) end @@ -917,6 +930,27 @@ function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool return tmerge(_getfield_tfunc(rewrap_unionall(s.a, s00), name, setfield), _getfield_tfunc(rewrap_unionall(s.b, s00), name, setfield)) end + if isType(s) + if isconstType(s) + sv = s00.parameters[1] + if isa(name, Const) + r = _getfield_tfunc_const(sv, name, setfield) + r !== nothing && return r + end + s = typeof(sv) + else + sv = s.parameters[1] + if isTypeDataType(sv) && isa(name, Const) + nv = _getfield_fieldindex(DataType, name) + if nv == DATATYPE_NAME_FIELDINDEX + # N.B. This only works for fields that do not depend on type + # parameters (which we do not know here). + return Const(sv.name) + end + s = DataType + end + end + end isa(s, DataType) || return Any isabstracttype(s) && return Any if s <: Tuple && !hasintersect(widenconst(name), Int) @@ -972,13 +1006,8 @@ function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool end return t end - fld = name.val - if isa(fld, Symbol) - fld = fieldindex(s, fld, false) - end - if !isa(fld, Int) - return Bottom - end + fld = _getfield_fieldindex(s, name) + fld === nothing && return Bottom if s <: Tuple && fld >= nf && isvarargtype(ftypes[nf]) return rewrap_unionall(unwrapva(ftypes[nf]), s00) end @@ -1116,7 +1145,7 @@ function modifyfield!_tfunc(o, f, op, v) PT = Const(Pair) return instanceof_tfunc(apply_type_tfunc(PT, T, T))[1] end -function abstract_modifyfield!(interp::AbstractInterpreter, argtypes::Vector{Any}, sv::InferenceState) +function abstract_modifyfield!(interp::AbstractInterpreter, argtypes::Vector{Any}, si::StmtInfo, sv::InferenceState) nargs = length(argtypes) if !isempty(argtypes) && isvarargtype(argtypes[nargs]) nargs - 1 <= 6 || return CallMeta(Bottom, EFFECTS_THROWS, false) @@ -1134,16 +1163,14 @@ function abstract_modifyfield!(interp::AbstractInterpreter, argtypes::Vector{Any op = unwrapva(argtypes[4]) v = unwrapva(argtypes[5]) TF = getfield_tfunc(o, f) - push!(sv.ssavalue_uses[sv.currpc], sv.currpc) # temporarily disable `call_result_unused` check for this call - callinfo = abstract_call(interp, ArgInfo(nothing, Any[op, TF, v]), sv, #=max_methods=# 1) - pop!(sv.ssavalue_uses[sv.currpc], sv.currpc) + callinfo = abstract_call(interp, ArgInfo(nothing, Any[op, TF, v]), StmtInfo(true), sv, #=max_methods=# 1) TF2 = tmeet(callinfo.rt, widenconst(TF)) if TF2 === Bottom RT = Bottom elseif isconcretetype(RT) && has_nontrivial_const_info(typeinf_lattice(interp), TF2) # isconcrete condition required to form a PartialStruct RT = PartialStruct(RT, Any[TF, TF2]) end - info = callinfo.info + info = ModifyFieldInfo(callinfo.info) end return CallMeta(RT, Effects(), info) end @@ -1754,7 +1781,7 @@ function arrayset_typecheck(@nospecialize(arytype), @nospecialize(elmtype)) end # Query whether the given builtin is guaranteed not to throw given the argtypes -function _builtin_nothrow(@nospecialize(f), argtypes::Array{Any,1}, @nospecialize(rt), @specialize(lattice::AbstractLattice)) +function _builtin_nothrow(@specialize(lattice::AbstractLattice), @nospecialize(f), argtypes::Array{Any,1}, @nospecialize(rt)) ⊑ₗ = ⊑(lattice) if f === arrayset array_builtin_common_nothrow(argtypes, 4) || return false @@ -1827,6 +1854,10 @@ function _builtin_nothrow(@nospecialize(f), argtypes::Array{Any,1}, @nospecializ 2 <= length(argtypes) <= 4 || return false # Core.finalizer does no error checking - that's done in Base.finalizer return true + elseif f === Core.compilerbarrier + length(argtypes) == 2 || return false + a1 = argtypes[1] + return isa(a1, Const) && contains_is((:type, :const, :conditional), a1.val) end return false end @@ -1839,7 +1870,7 @@ const _EFFECT_FREE_BUILTINS = [ fieldtype, apply_type, isa, UnionAll, getfield, arrayref, const_arrayref, isdefined, Core.sizeof, Core.kwfunc, Core.ifelse, Core._typevar, (<:), - typeassert, throw, arraysize, getglobal, + typeassert, throw, arraysize, getglobal, compilerbarrier ] const _CONSISTENT_BUILTINS = Any[ @@ -1858,7 +1889,7 @@ const _CONSISTENT_BUILTINS = Any[ (<:), typeassert, throw, - setfield!, + setfield! ] const _INACCESSIBLEMEM_BUILTINS = Any[ @@ -1877,6 +1908,7 @@ const _INACCESSIBLEMEM_BUILTINS = Any[ tuple, typeassert, typeof, + compilerbarrier, ] const _ARGMEM_BUILTINS = Any[ @@ -1981,7 +2013,7 @@ function getglobal_effects(argtypes::Vector{Any}, @nospecialize(rt)) return Effects(EFFECTS_TOTAL; consistent, nothrow, inaccessiblememonly) end -function builtin_effects(f::Builtin, argtypes::Vector{Any}, @nospecialize(rt)) +function builtin_effects(@specialize(lattice::AbstractLattice), f::Builtin, argtypes::Vector{Any}, @nospecialize(rt)) if isa(f, IntrinsicFunction) return intrinsic_effects(f, argtypes) end @@ -1994,6 +2026,10 @@ function builtin_effects(f::Builtin, argtypes::Vector{Any}, @nospecialize(rt)) return getfield_effects(argtypes, rt) elseif f === getglobal return getglobal_effects(argtypes, rt) + elseif f === Core.get_binding_type + length(argtypes) == 2 || return EFFECTS_THROWS + effect_free = get_binding_type_effect_free(argtypes[1], argtypes[2]) ? ALWAYS_TRUE : ALWAYS_FALSE + return Effects(EFFECTS_TOTAL; effect_free) else consistent = contains_is(_CONSISTENT_BUILTINS, f) ? ALWAYS_TRUE : ALWAYS_FALSE if f === setfield! || f === arrayset @@ -2003,7 +2039,7 @@ function builtin_effects(f::Builtin, argtypes::Vector{Any}, @nospecialize(rt)) else effect_free = ALWAYS_FALSE end - nothrow = (!(!isempty(argtypes) && isvarargtype(argtypes[end])) && builtin_nothrow(f, argtypes, rt)) + nothrow = (!(!isempty(argtypes) && isvarargtype(argtypes[end])) && builtin_nothrow(lattice, f, argtypes, rt)) if contains_is(_INACCESSIBLEMEM_BUILTINS, f) inaccessiblememonly = ALWAYS_TRUE elseif contains_is(_ARGMEM_BUILTINS, f) @@ -2015,10 +2051,10 @@ function builtin_effects(f::Builtin, argtypes::Vector{Any}, @nospecialize(rt)) end end -function builtin_nothrow(@nospecialize(f), argtypes::Vector{Any}, @nospecialize(rt)) +function builtin_nothrow(@specialize(lattice::AbstractLattice), @nospecialize(f), argtypes::Vector{Any}, @nospecialize(rt)) rt === Bottom && return false contains_is(_PURE_BUILTINS, f) && return true - return _builtin_nothrow(f, argtypes, rt, fallback_lattice) + return _builtin_nothrow(lattice, f, argtypes, rt) end function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtypes::Vector{Any}, @@ -2188,7 +2224,7 @@ end # TODO: this function is a very buggy and poor model of the return_type function # since abstract_call_gf_by_type is a very inaccurate model of _method and of typeinf_type, # while this assumes that it is an absolutely precise and accurate and exact model of both -function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, sv::Union{InferenceState, IRCode}) +function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, si::StmtInfo, sv::Union{InferenceState, IRCode}) if length(argtypes) == 3 tt = argtypes[3] if isa(tt, Const) || (isType(tt) && !has_free_typevars(tt)) @@ -2201,16 +2237,17 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s if contains_is(argtypes_vec, Union{}) return CallMeta(Const(Union{}), EFFECTS_TOTAL, false) end + # # Run the abstract_call without restricting abstract call # sites. Otherwise, our behavior model of abstract_call # below will be wrong. if isa(sv, InferenceState) old_restrict = sv.restrict_abstract_call_sites sv.restrict_abstract_call_sites = false - call = abstract_call(interp, ArgInfo(nothing, argtypes_vec), sv, -1) + call = abstract_call(interp, ArgInfo(nothing, argtypes_vec), si, sv, -1) sv.restrict_abstract_call_sites = old_restrict else - call = abstract_call(interp, ArgInfo(nothing, argtypes_vec), sv, -1) + call = abstract_call(interp, ArgInfo(nothing, argtypes_vec), si, sv, -1) end info = verbose_stmt_info(interp) ? MethodResultPure(ReturnTypeCallInfo(call.info)) : MethodResultPure() rt = widenconditional(call.rt) diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index e30e2fc9f7e2d..6db3c42a6ca54 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -391,8 +391,10 @@ function cache_result!(interp::AbstractInterpreter, result::InferenceResult) code_cache(interp)[linfo] = CodeInstance(result, inferred_result, valid_worlds) if track_newly_inferred[] m = linfo.def - if isa(m, Method) - m.module != Core && push!(newly_inferred, linfo) + if isa(m, Method) && m.module != Core + ccall(:jl_typeinf_lock_begin, Cvoid, ()) + push!(newly_inferred, linfo) + ccall(:jl_typeinf_lock_end, Cvoid, ()) end end end @@ -565,13 +567,13 @@ function store_backedges(frame::InferenceResult, edges::Vector{Any}) nothing end -function store_backedges(caller::MethodInstance, edges::Vector{Any}) - for (typ, to) in BackedgeIterator(edges) - if isa(to, MethodInstance) - ccall(:jl_method_instance_add_backedge, Cvoid, (Any, Any, Any), to, typ, caller) +function store_backedges(frame::MethodInstance, edges::Vector{Any}) + for (; sig, caller) in BackedgeIterator(edges) + if isa(caller, MethodInstance) + ccall(:jl_method_instance_add_backedge, Cvoid, (Any, Any, Any), caller, sig, frame) else - typeassert(to, Core.MethodTable) - ccall(:jl_method_table_add_backedge, Cvoid, (Any, Any, Any), to, typ, caller) + typeassert(caller, Core.MethodTable) + ccall(:jl_method_table_add_backedge, Cvoid, (Any, Any, Any), caller, sig, frame) end end end @@ -680,7 +682,7 @@ end # returns `nothing` otherwise function find_dominating_assignment(id::Int, idx::Int, sv::InferenceState) block = block_for_inst(sv.cfg, idx) - for pc in reverse(sv.cfg.blocks[block].stmts) # N.B. reverse since the last assignement is dominating this block + for pc in reverse(sv.cfg.blocks[block].stmts) # N.B. reverse since the last assignment is dominating this block pc < idx || continue # N.B. needs pc ≠ idx as `id` can be assigned at `idx` stmt = sv.src.code[pc] isexpr(stmt, :(=)) || continue @@ -804,7 +806,7 @@ function merge_call_chain!(interp::AbstractInterpreter, parent::InferenceState, # of recursion. merge_effects!(interp, parent, Effects(EFFECTS_TOTAL; terminates=false)) while true - add_cycle_backedge!(child, parent, parent.currpc) + add_cycle_backedge!(parent, child, parent.currpc) union_caller_cycle!(ancestor, child) merge_effects!(interp, child, Effects(EFFECTS_TOTAL; terminates=false)) child = parent @@ -976,10 +978,10 @@ function typeinf_ircode( sparams::SimpleVector, optimize_until::Union{Integer,AbstractString,Nothing}, ) - ccall(:jl_typeinf_begin, Cvoid, ()) + ccall(:jl_typeinf_timing_begin, Cvoid, ()) frame = typeinf_frame(interp, method, atype, sparams, false) if frame === nothing - ccall(:jl_typeinf_end, Cvoid, ()) + ccall(:jl_typeinf_timing_end, Cvoid, ()) return nothing, Any end (; result) = frame @@ -987,19 +989,19 @@ function typeinf_ircode( opt = OptimizationState(frame, opt_params, interp) ir = run_passes(opt.src, opt, result, optimize_until) rt = widenconst(ignorelimited(result.result)) - ccall(:jl_typeinf_end, Cvoid, ()) + ccall(:jl_typeinf_timing_end, Cvoid, ()) return ir, rt end # compute an inferred frame function typeinf_frame(interp::AbstractInterpreter, method::Method, @nospecialize(atype), sparams::SimpleVector, run_optimizer::Bool) mi = specialize_method(method, atype, sparams)::MethodInstance - ccall(:jl_typeinf_begin, Cvoid, ()) + ccall(:jl_typeinf_timing_begin, Cvoid, ()) result = InferenceResult(mi) frame = InferenceState(result, run_optimizer ? :global : :no, interp) frame === nothing && return nothing typeinf(interp, frame) - ccall(:jl_typeinf_end, Cvoid, ()) + ccall(:jl_typeinf_timing_end, Cvoid, ()) return frame end @@ -1007,13 +1009,13 @@ end function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance) method = mi.def::Method for i = 1:2 # test-and-lock-and-test - i == 2 && ccall(:jl_typeinf_begin, Cvoid, ()) + i == 2 && ccall(:jl_typeinf_timing_begin, Cvoid, ()) code = get(code_cache(interp), mi, nothing) if code isa CodeInstance # see if this code already exists in the cache inf = @atomic :monotonic code.inferred if use_const_api(code) - i == 2 && ccall(:jl_typeinf_end, Cvoid, ()) + i == 2 && ccall(:jl_typeinf_timing_end, Cvoid, ()) tree = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ()) rettype_const = code.rettype_const tree.code = Any[ ReturnNode(quoted(rettype_const)) ] @@ -1033,7 +1035,7 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance) tree.max_world = code.max_world return tree elseif isa(inf, CodeInfo) - i == 2 && ccall(:jl_typeinf_end, Cvoid, ()) + i == 2 && ccall(:jl_typeinf_timing_end, Cvoid, ()) if !(inf.min_world == code.min_world && inf.max_world == code.max_world && inf.rettype === code.rettype) @@ -1044,7 +1046,7 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance) end return inf elseif isa(inf, Vector{UInt8}) - i == 2 && ccall(:jl_typeinf_end, Cvoid, ()) + i == 2 && ccall(:jl_typeinf_timing_end, Cvoid, ()) inf = _uncompressed_ir(code, inf) return inf end @@ -1057,7 +1059,7 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance) frame = InferenceState(InferenceResult(mi), #=cache=#:global, interp) frame === nothing && return nothing typeinf(interp, frame) - ccall(:jl_typeinf_end, Cvoid, ()) + ccall(:jl_typeinf_timing_end, Cvoid, ()) frame.src.inferred || return nothing return frame.src end @@ -1069,17 +1071,17 @@ function typeinf_type(interp::AbstractInterpreter, method::Method, @nospecialize end mi = specialize_method(method, atype, sparams)::MethodInstance for i = 1:2 # test-and-lock-and-test - i == 2 && ccall(:jl_typeinf_begin, Cvoid, ()) + i == 2 && ccall(:jl_typeinf_timing_begin, Cvoid, ()) code = get(code_cache(interp), mi, nothing) if code isa CodeInstance # see if this rettype already exists in the cache - i == 2 && ccall(:jl_typeinf_end, Cvoid, ()) + i == 2 && ccall(:jl_typeinf_timing_end, Cvoid, ()) return code.rettype end end result = InferenceResult(mi) typeinf(interp, result, :global) - ccall(:jl_typeinf_end, Cvoid, ()) + ccall(:jl_typeinf_timing_end, Cvoid, ()) result.result isa InferenceState && return nothing return widenconst(ignorelimited(result.result)) end @@ -1094,7 +1096,7 @@ function typeinf_ext_toplevel(interp::AbstractInterpreter, linfo::MethodInstance src = linfo.uninferred::CodeInfo if !src.inferred # toplevel lambda - infer directly - ccall(:jl_typeinf_begin, Cvoid, ()) + ccall(:jl_typeinf_timing_begin, Cvoid, ()) if !src.inferred result = InferenceResult(linfo) frame = InferenceState(result, src, #=cache=#:global, interp) @@ -1102,7 +1104,7 @@ function typeinf_ext_toplevel(interp::AbstractInterpreter, linfo::MethodInstance @assert frame.inferred # TODO: deal with this better src = frame.src end - ccall(:jl_typeinf_end, Cvoid, ()) + ccall(:jl_typeinf_timing_end, Cvoid, ()) end end return src diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index d389b4cd399c4..5c57443d70656 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -78,7 +78,7 @@ InterConditional(var::SlotNumber, @nospecialize(thentype), @nospecialize(elsetyp InterConditional(slot_id(var), thentype, elsetype) const AnyConditional = Union{Conditional,InterConditional} -Conditional(cnd::InterConditional) = Conditinal(cnd.slot, cnd.thentype, cnd.elsetype) +Conditional(cnd::InterConditional) = Conditional(cnd.slot, cnd.thentype, cnd.elsetype) InterConditional(cnd::Conditional) = InterConditional(cnd.slot, cnd.thentype, cnd.elsetype) struct PartialTypeVar @@ -106,7 +106,7 @@ struct StateUpdate end # Represent that the type estimate has been approximated, due to "causes" -# (only used in abstract interpretion, doesn't appear in optimization) +# (only used in abstract interpretation, doesn't appear in optimization) # N.B. in the lattice, this is epsilon smaller than `typ` (except Union{}) struct LimitedAccuracy typ @@ -362,7 +362,7 @@ function is_lattice_equal(lattice::PartialsLattice, @nospecialize(a), @nospecial widenconst(a) == widenconst(b) || return false a.fields === b.fields && return true # fast path for i in 1:length(a.fields) - is_lattice_equal(a.fields[i], b.fields[i]) || return false + is_lattice_equal(lattice, a.fields[i], b.fields[i]) || return false end return true end diff --git a/base/compiler/typelimits.jl b/base/compiler/typelimits.jl index ccf9c5314566c..43ce57d6adb5d 100644 --- a/base/compiler/typelimits.jl +++ b/base/compiler/typelimits.jl @@ -304,7 +304,7 @@ end # A simplified type_more_complex query over the extended lattice # (assumes typeb ⊑ typea) -function issimplertype(@nospecialize(typea), @nospecialize(typeb)) +function issimplertype(lattice::AbstractLattice, @nospecialize(typea), @nospecialize(typeb)) typea = ignorelimited(typea) typeb = ignorelimited(typeb) typea isa MaybeUndef && (typea = typea.typ) # n.b. does not appear in inference @@ -315,14 +315,14 @@ function issimplertype(@nospecialize(typea), @nospecialize(typeb)) for i = 1:length(typea.fields) ai = unwrapva(typea.fields[i]) bi = fieldtype(aty, i) - is_lattice_equal(ai, bi) && continue + is_lattice_equal(lattice, ai, bi) && continue tni = _typename(widenconst(ai)) if tni isa Const bi = (tni.val::Core.TypeName).wrapper - is_lattice_equal(ai, bi) && continue + is_lattice_equal(lattice, ai, bi) && continue end bi = getfield_tfunc(typeb, Const(i)) - is_lattice_equal(ai, bi) && continue + is_lattice_equal(lattice, ai, bi) && continue # It is not enough for ai to be simpler than bi: it must exactly equal # (for this, an invariant struct field, by contrast to # type_more_complex above which handles covariant tuples). @@ -335,14 +335,14 @@ function issimplertype(@nospecialize(typea), @nospecialize(typeb)) typeb isa Const && return true typeb isa Conditional || return false is_same_conditionals(typea, typeb) || return false - issimplertype(typea.thentype, typeb.thentype) || return false - issimplertype(typea.elsetype, typeb.elsetype) || return false + issimplertype(lattice, typea.thentype, typeb.thentype) || return false + issimplertype(lattice, typea.elsetype, typeb.elsetype) || return false elseif typea isa InterConditional # ibid typeb isa Const && return true typeb isa InterConditional || return false is_same_conditionals(typea, typeb) || return false - issimplertype(typea.thentype, typeb.thentype) || return false - issimplertype(typea.elsetype, typeb.elsetype) || return false + issimplertype(lattice, typea.thentype, typeb.thentype) || return false + issimplertype(lattice, typea.elsetype, typeb.elsetype) || return false elseif typea isa PartialOpaque # TODO end @@ -356,10 +356,10 @@ end typea === typeb && return typea suba = ⊑(lattice, typea, typeb) - suba && issimplertype(typeb, typea) && return typeb + suba && issimplertype(lattice, typeb, typea) && return typeb subb = ⊑(lattice, typeb, typea) suba && subb && return typea - subb && issimplertype(typea, typeb) && return typea + subb && issimplertype(lattice, typea, typeb) && return typea return nothing end @@ -433,6 +433,8 @@ function tmerge(lattice::ConditionalsLattice, @nospecialize(typea), @nospecializ end return Bool end + typea = widenconditional(typea) + typeb = widenconditional(typeb) return tmerge(widenlattice(lattice), typea, typeb) end @@ -471,8 +473,9 @@ end function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(typeb)) # type-lattice for Const and PartialStruct wrappers - if ((isa(typea, PartialStruct) || isa(typea, Const)) && - (isa(typeb, PartialStruct) || isa(typeb, Const))) + acp = isa(typea, Const) || isa(typea, PartialStruct) + bcp = isa(typeb, Const) || isa(typeb, PartialStruct) + if acp && bcp aty = widenconst(typea) bty = widenconst(typeb) if aty === bty @@ -521,22 +524,40 @@ function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(ty return anyrefine ? PartialStruct(aty, fields) : aty end end + # Don't widen const here - external AbstractInterpreter might insert lattice + # layers between us and `ConstsLattice`. + isa(typea, PartialStruct) && (typea = widenconst(typea)) + isa(typeb, PartialStruct) && (typeb = widenconst(typeb)) # type-lattice for PartialOpaque wrapper - if isa(typea, PartialOpaque) && isa(typeb, PartialOpaque) && widenconst(typea) == widenconst(typeb) - if !(typea.source === typeb.source && - typea.parent === typeb.parent) - return widenconst(typea) + apo = isa(typea, PartialOpaque) + bpo = isa(typeb, PartialOpaque) + if apo && bpo + aty = widenconst(typea) + bty = widenconst(typeb) + if aty == bty + if !(typea.source === typeb.source && + typea.parent === typeb.parent) + return widenconst(typea) + end + return PartialOpaque(typea.typ, tmerge(typea.env, typeb.env), + typea.parent, typea.source) end - return PartialOpaque(typea.typ, tmerge(typea.env, typeb.env), - typea.parent, typea.source) + typea = aty + typeb = bty + elseif apo + typea = widenconst(typea) + elseif bpo + typeb = widenconst(typeb) end - # no special type-inference lattice, join the types - typea, typeb = widenconst(typea), widenconst(typeb) - @assert isa(typea, Type); @assert isa(typeb, Type) + return tmerge(widenlattice(lattice), typea, typeb) +end - return tmerge(JLTypeLattice(), typea, typeb) +function tmerge(lattice::ConstsLattice, @nospecialize(typea), @nospecialize(typeb)) + # the equality of the constants can be checked here, but the equivalent check is usually + # done by `tmerge_fast_path` at earlier lattice stage + return tmerge(widenlattice(lattice), widenconst(typea), widenconst(typeb)) end function tmerge(::JLTypeLattice, @nospecialize(typea::Type), @nospecialize(typeb::Type)) diff --git a/base/compiler/types.jl b/base/compiler/types.jl index 1e877fe1dedae..ac36475b8c603 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -23,6 +23,14 @@ struct ArgInfo argtypes::Vector{Any} end +struct StmtInfo + """ + If `used` is false, we know that the return value is statically unused and + need thus not be computed. + """ + used::Bool +end + """ InferenceResult @@ -63,11 +71,17 @@ struct OptimizationParams compilesig_invokes::Bool trust_inference::Bool - # Duplicating for now because optimizer inlining requires it. - # Keno assures me this will be removed in the near future - MAX_METHODS::Int + """ + assume_fatal_throw::Bool + + If `true`, gives the optimizer license to assume that any `throw` is fatal + and thus the state after a `throw` is not externally observable. In particular, + this gives the optimizer license to move side effects (that are proven not observed + within a particular code path) across a throwing call. Defaults to `false`. + """ + assume_fatal_throw::Bool + MAX_TUPLE_SPLAT::Int - MAX_UNION_SPLITTING::Int function OptimizationParams(; inlining::Bool = inlining_enabled(), @@ -75,11 +89,10 @@ struct OptimizationParams inline_nonleaf_penalty::Int = 1000, inline_tupleret_bonus::Int = 250, inline_error_path_cost::Int = 20, - max_methods::Int = 3, tuple_splat::Int = 32, - union_splitting::Int = 4, compilesig_invokes::Bool = true, - trust_inference::Bool = false + trust_inference::Bool = false, + assume_fatal_throw::Bool = false ) return new( inlining, @@ -89,9 +102,8 @@ struct OptimizationParams inline_error_path_cost, compilesig_invokes, trust_inference, - max_methods, + assume_fatal_throw, tuple_splat, - union_splitting ) end end diff --git a/base/compiler/typeutils.jl b/base/compiler/typeutils.jl index 303cc6bd711a5..d2992fc6113ba 100644 --- a/base/compiler/typeutils.jl +++ b/base/compiler/typeutils.jl @@ -23,6 +23,29 @@ function hasuniquerep(@nospecialize t) return false end +""" + isTypeDataType(@nospecialize t) + +For a type `t` test whether ∀S s.t. `isa(S, rewrap_unionall(Type{t}, ...))`, +we have `isa(S, DataType)`. In particular, if a statement is typed as `Type{t}` +(potentially wrapped in some UnionAll), then we are guaranteed that this statement +will be a DataType at runtime (and not e.g. a Union or UnionAll typeequal to it). +""" +function isTypeDataType(@nospecialize t) + isa(t, DataType) || return false + isType(t) && return false + # Could be Union{} at runtime + t === Core.TypeofBottom && return false + if t.name === Tuple.name + # If we have a Union parameter, could have been redistributed at runtime, + # e.g. `Tuple{Union{Int, Float64}, Int}` is a DataType, but + # `Union{Tuple{Int, Int}, Tuple{Float64, Int}}` is typeequal to it and + # is not. + return _all(isTypeDataType, t.parameters) + end + return true +end + function has_nontrivial_const_info(lattice::PartialsLattice, @nospecialize t) isa(t, PartialStruct) && return true isa(t, PartialOpaque) && return true diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 071b0b6089b98..e71597c68bdb2 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -128,7 +128,10 @@ function retrieve_code_info(linfo::MethodInstance) end if c === nothing && isdefined(m, :source) src = m.source - if isa(src, Array{UInt8,1}) + if src === nothing + # can happen in images built with --strip-ir + return nothing + elseif isa(src, Array{UInt8,1}) c = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), m, C_NULL, src) else c = copy(src::CodeInfo) @@ -235,9 +238,9 @@ is_no_constprop(method::Union{Method,CodeInfo}) = method.constprop == 0x02 Return an iterator over a list of backedges. Iteration returns `(sig, caller)` elements, which will be one of the following: -- `(nothing, caller::MethodInstance)`: a call made by ordinary inferrable dispatch -- `(invokesig, caller::MethodInstance)`: a call made by `invoke(f, invokesig, args...)` -- `(specsig, mt::MethodTable)`: an abstract call +- `BackedgePair(nothing, caller::MethodInstance)`: a call made by ordinary inferrable dispatch +- `BackedgePair(invokesig, caller::MethodInstance)`: a call made by `invoke(f, invokesig, args...)` +- `BackedgePair(specsig, mt::MethodTable)`: an abstract call # Examples @@ -254,7 +257,7 @@ julia> callyou(2.0) julia> mi = first(which(callme, (Any,)).specializations) MethodInstance for callme(::Float64) -julia> @eval Core.Compiler for (sig, caller) in BackedgeIterator(Main.mi.backedges) +julia> @eval Core.Compiler for (; sig, caller) in BackedgeIterator(Main.mi.backedges) println(sig) println(caller) end @@ -268,8 +271,11 @@ end const empty_backedge_iter = BackedgeIterator(Any[]) -const MethodInstanceOrTable = Union{MethodInstance, Core.MethodTable} -const BackedgePair = Pair{Union{Type, Nothing, MethodInstanceOrTable}, MethodInstanceOrTable} +struct BackedgePair + sig # ::Union{Nothing,Type} + caller::Union{MethodInstance,Core.MethodTable} + BackedgePair(@nospecialize(sig), caller::Union{MethodInstance,Core.MethodTable}) = new(sig, caller) +end function iterate(iter::BackedgeIterator, i::Int=1) backedges = iter.backedges @@ -378,7 +384,7 @@ function is_throw_call(e::Expr) if e.head === :call f = e.args[1] if isa(f, GlobalRef) - ff = abstract_eval_global(f.mod, f.name) + ff = abstract_eval_globalref(f) if isa(ff, Const) && ff.val === Core.throw return true end diff --git a/base/complex.jl b/base/complex.jl index 3d9997e5d772d..a9590328a8c56 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -195,7 +195,7 @@ flipsign(x::Complex, y::Real) = ifelse(signbit(y), -x, x) function show(io::IO, z::Complex) r, i = reim(z) - compact = get(io, :compact, false) + compact = get(io, :compact, false)::Bool show(io, r) if signbit(i) && !isnan(i) print(io, compact ? "-" : " - ") diff --git a/base/deepcopy.jl b/base/deepcopy.jl index 74c9d2b49c123..eae8974326d06 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -21,7 +21,7 @@ so far within the recursion. Within the definition, `deepcopy_internal` should b in place of `deepcopy`, and the `dict` variable should be updated as appropriate before returning. """ -function deepcopy(x) +function deepcopy(@nospecialize x) isbitstype(typeof(x)) && return x return deepcopy_internal(x, IdDict())::typeof(x) end diff --git a/base/deprecated.jl b/base/deprecated.jl index 8d07abc687bd7..87fc670cd594a 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -290,7 +290,7 @@ cat_shape(dims, shape::Tuple{}) = () # make sure `cat_shape(dims, ())` do not re @deprecate unsafe_indices(A) axes(A) false @deprecate unsafe_length(r) length(r) false -# these were internal type aliases, but some pacakges seem to be relying on them +# these were internal type aliases, but some packages seem to be relying on them const Any16{N} = Tuple{Any,Any,Any,Any,Any,Any,Any,Any, Any,Any,Any,Any,Any,Any,Any,Any,Vararg{Any,N}} const All16{T,N} = Tuple{T,T,T,T,T,T,T,T, diff --git a/base/dict.jl b/base/dict.jl index 750b98ea070f2..5f725f82ac57b 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -205,7 +205,7 @@ end end end - @assert h.age == age0 "Muliple concurent writes to Dict detected!" + @assert h.age == age0 "Muliple concurrent writes to Dict detected!" h.age += 1 h.slots = slots h.keys = keys diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 454d4b394e503..2286b3500ee0f 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -795,7 +795,7 @@ julia> f(2) 7 ``` -Anonymous functions can also be defined for multiple argumets. +Anonymous functions can also be defined for multiple arguments. ```jldoctest julia> g = (x,y) -> x^2 + y^2 #2 (generic function with 1 method) @@ -2899,7 +2899,7 @@ Base.setproperty! swapproperty!(x, f::Symbol, v, order::Symbol=:not_atomic) The syntax `@atomic a.b, _ = c, a.b` returns `(c, swapproperty!(a, :b, c, :sequentially_consistent))`, -where there must be one getfield expression common to both sides. +where there must be one `getproperty` expression common to both sides. See also [`swapfield!`](@ref Core.swapfield!) and [`setproperty!`](@ref Base.setproperty!). @@ -2909,9 +2909,9 @@ Base.swapproperty! """ modifyproperty!(x, f::Symbol, op, v, order::Symbol=:not_atomic) -The syntax `@atomic max(a().b, c)` returns `modifyproperty!(a(), :b, -max, c, :sequentially_consistent))`, where the first argument must be a -`getfield` expression and is modified atomically. +The syntax `@atomic op(x.f, v)` (and its equivalent `@atomic x.f op v`) returns +`modifyproperty!(x, :f, op, v, :sequentially_consistent)`, where the first argument +must be a `getproperty` expression and is modified atomically. Invocation of `op(getproperty(x, f), v)` must return a value that can be stored in the field `f` of the object `x` by default. In particular, unlike the default behavior of @@ -3088,7 +3088,7 @@ unused and delete the entire benchmark code). ```julia function loop() for i = 1:1000 - # The complier must guarantee that there are 1000 program points (in the correct + # The compiler must guarantee that there are 1000 program points (in the correct # order) at which the value of `i` is in a register, but has otherwise # total control over the program. donotdelete(i) @@ -3167,11 +3167,11 @@ but there are a number of small differences. They are documented here for completeness only and (unlike `Base.finalizer`) have no stability guarantees. The current differences are: - - `Core.finalizer` does not check for mutability of `o`. Attempting to register - a finalizer for an immutable object is undefined behavior. - - The value `f` must be a Julia object. `Core.finalizer` does not support a - raw C function pointer. - - `Core.finalizer` returns `nothing` rather than `o`. +- `Core.finalizer` does not check for mutability of `o`. Attempting to register + a finalizer for an immutable object is undefined behavior. +- The value `f` must be a Julia object. `Core.finalizer` does not support a + raw C function pointer. +- `Core.finalizer` returns `nothing` rather than `o`. """ Core.finalizer diff --git a/base/env.jl b/base/env.jl index 4fdc02e582a4c..41914c30e5c7d 100644 --- a/base/env.jl +++ b/base/env.jl @@ -117,7 +117,7 @@ if Sys.iswindows() m = nothing end if m === nothing - @warn "malformed environment entry: $env" + @warn "malformed environment entry" env continue end return (Pair{String,String}(winuppercase(env[1:prevind(env, m)]), env[nextind(env, m):end]), (pos, blk)) @@ -131,8 +131,8 @@ else # !windows env = env::String m = findfirst('=', env) if m === nothing - @warn "malformed environment entry: $env" - nothing + @warn "malformed environment entry" env + continue end return (Pair{String,String}(env[1:prevind(env, m)], env[nextind(env, m):end]), i+1) end diff --git a/base/errorshow.jl b/base/errorshow.jl index 2172ea029a796..2d9ada0ff29cb 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -107,8 +107,8 @@ showerror(io::IO, ex::InitError) = showerror(io, ex, []) function showerror(io::IO, ex::DomainError) if isa(ex.val, AbstractArray) - compact = get(io, :compact, true) - limit = get(io, :limit, true) + compact = get(io, :compact, true)::Bool + limit = get(io, :limit, true)::Bool print(IOContext(io, :compact => compact, :limit => limit), "DomainError with ", ex.val) else @@ -451,7 +451,7 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=() # the type of the first argument is not matched. t_in === Union{} && special && i == 1 && break if t_in === Union{} - if get(io, :color, false) + if get(io, :color, false)::Bool let sigstr=sigstr Base.with_output_color(Base.error_color(), iob) do iob print(iob, "::", sigstr...) @@ -495,7 +495,7 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=() if !((min(length(t_i), length(sig)) == 0) && k==1) print(iob, ", ") end - if get(io, :color, false) + if get(io, :color, false)::Bool let sigstr=sigstr Base.with_output_color(Base.error_color(), iob) do iob print(iob, "::", sigstr...) diff --git a/base/essentials.jl b/base/essentials.jl index f9a7abb774625..daee352b7649d 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -13,6 +13,8 @@ length(a::Array) = arraylen(a) eval(:(getindex(A::Array, i1::Int) = arrayref($(Expr(:boundscheck)), A, i1))) eval(:(getindex(A::Array, i1::Int, i2::Int, I::Int...) = (@inline; arrayref($(Expr(:boundscheck)), A, i1, i2, I...)))) +==(a::GlobalRef, b::GlobalRef) = a.mod === b.mod && a.name === b.name + """ AbstractSet{T} @@ -451,7 +453,7 @@ end """ oftype(x, y) -Convert `y` to the type of `x` (`convert(typeof(x), y)`). +Convert `y` to the type of `x` i.e. `convert(typeof(x), y)`. # Examples ```jldoctest @@ -688,7 +690,10 @@ end @eval getindex(v::SimpleVector, i::Int) = Core._svec_ref($(Expr(:boundscheck)), v, i) function length(v::SimpleVector) - return ccall(:jl_svec_len, Int, (Any,), v) + t = @_gc_preserve_begin v + len = unsafe_load(Ptr{Int}(pointer_from_objref(v))) + @_gc_preserve_end t + return len end firstindex(v::SimpleVector) = 1 lastindex(v::SimpleVector) = length(v) @@ -743,7 +748,7 @@ function isassigned end function isassigned(v::SimpleVector, i::Int) @boundscheck 1 <= i <= length(v) || return false - return ccall(:jl_svec_isassigned, Bool, (Any, Int), v, i - 1) + return true end diff --git a/base/file.jl b/base/file.jl index eaff9efae43d3..b449a68bfa5da 100644 --- a/base/file.jl +++ b/base/file.jl @@ -1062,7 +1062,7 @@ See also: [`hardlink`](@ref). !!! compat "Julia 1.6" The `dir_target` keyword argument was added in Julia 1.6. Prior to this, - symlinks to nonexistant paths on windows would always be file symlinks, and + symlinks to nonexistent paths on windows would always be file symlinks, and relative symlinks to directories were not supported. """ function symlink(target::AbstractString, link::AbstractString; diff --git a/base/float.jl b/base/float.jl index eb1cc36e6c215..5038238222e7b 100644 --- a/base/float.jl +++ b/base/float.jl @@ -135,6 +135,17 @@ i.e. the maximum integer value representable by [`exponent_bits(T)`](@ref) bits. """ function exponent_raw_max end +""" + uabs(x::Integer) + +Return the absolute value of `x`, possibly returning a different type should the +operation be susceptible to overflow. This typically arises when `x` is a two's complement +signed integer, so that `abs(typemin(x)) == typemin(x) < 0`, in which case the result of +`uabs(x)` will be an unsigned integer of the same size. +""" +uabs(x::Integer) = abs(x) +uabs(x::BitSigned) = unsigned(abs(x)) + ## conversions to floating-point ## # TODO: deprecate in 2.0 @@ -165,33 +176,45 @@ promote_rule(::Type{Float16}, ::Type{UInt128}) = Float16 promote_rule(::Type{Float16}, ::Type{Int128}) = Float16 function Float64(x::UInt128) - x == 0 && return 0.0 - n = 128-leading_zeros(x) # ndigits0z(x,2) - if n <= 53 - y = ((x % UInt64) << (53-n)) & 0x000f_ffff_ffff_ffff - else - y = ((x >> (n-54)) % UInt64) & 0x001f_ffff_ffff_ffff # keep 1 extra bit - y = (y+1)>>1 # round, ties up (extra leading bit in case of next exponent) - y &= ~UInt64(trailing_zeros(x) == (n-54)) # fix last bit to round to even + if x < UInt128(1) << 104 # Can fit it in two 52 bits mantissas + low_exp = 0x1p52 + high_exp = 0x1p104 + low_bits = (x % UInt64) & Base.significand_mask(Float64) + low_value = reinterpret(Float64, reinterpret(UInt64, low_exp) | low_bits) - low_exp + high_bits = ((x >> 52) % UInt64) + high_value = reinterpret(Float64, reinterpret(UInt64, high_exp) | high_bits) - high_exp + low_value + high_value + else # Large enough that low bits only affect rounding, pack low bits + low_exp = 0x1p76 + high_exp = 0x1p128 + low_bits = ((x >> 12) % UInt64) >> 12 | (x % UInt64) & 0xFFFFFF + low_value = reinterpret(Float64, reinterpret(UInt64, low_exp) | low_bits) - low_exp + high_bits = ((x >> 76) % UInt64) + high_value = reinterpret(Float64, reinterpret(UInt64, high_exp) | high_bits) - high_exp + low_value + high_value end - d = ((n+1022) % UInt64) << 52 - reinterpret(Float64, d + y) end function Float64(x::Int128) - x == 0 && return 0.0 - s = ((x >>> 64) % UInt64) & 0x8000_0000_0000_0000 # sign bit - x = abs(x) % UInt128 - n = 128-leading_zeros(x) # ndigits0z(x,2) - if n <= 53 - y = ((x % UInt64) << (53-n)) & 0x000f_ffff_ffff_ffff - else - y = ((x >> (n-54)) % UInt64) & 0x001f_ffff_ffff_ffff # keep 1 extra bit - y = (y+1)>>1 # round, ties up (extra leading bit in case of next exponent) - y &= ~UInt64(trailing_zeros(x) == (n-54)) # fix last bit to round to even + sign_bit = ((x >> 127) % UInt64) << 63 + ux = uabs(x) + if ux < UInt128(1) << 104 # Can fit it in two 52 bits mantissas + low_exp = 0x1p52 + high_exp = 0x1p104 + low_bits = (ux % UInt64) & Base.significand_mask(Float64) + low_value = reinterpret(Float64, reinterpret(UInt64, low_exp) | low_bits) - low_exp + high_bits = ((ux >> 52) % UInt64) + high_value = reinterpret(Float64, reinterpret(UInt64, high_exp) | high_bits) - high_exp + reinterpret(Float64, sign_bit | reinterpret(UInt64, low_value + high_value)) + else # Large enough that low bits only affect rounding, pack low bits + low_exp = 0x1p76 + high_exp = 0x1p128 + low_bits = ((ux >> 12) % UInt64) >> 12 | (ux % UInt64) & 0xFFFFFF + low_value = reinterpret(Float64, reinterpret(UInt64, low_exp) | low_bits) - low_exp + high_bits = ((ux >> 76) % UInt64) + high_value = reinterpret(Float64, reinterpret(UInt64, high_exp) | high_bits) - high_exp + reinterpret(Float64, sign_bit | reinterpret(UInt64, low_value + high_value)) end - d = ((n+1022) % UInt64) << 52 - reinterpret(Float64, s | d + y) end function Float32(x::UInt128) @@ -225,8 +248,8 @@ function Float32(x::Int128) end # TODO: optimize -Float16(x::UInt128) = convert(Float16, Float32(x)) -Float16(x::Int128) = convert(Float16, Float32(x)) +Float16(x::UInt128) = convert(Float16, Float64(x)) +Float16(x::Int128) = convert(Float16, Float64(x)) Float16(x::Float32) = fptrunc(Float16, x) Float16(x::Float64) = fptrunc(Float16, x) @@ -662,17 +685,6 @@ end precision(::Type{T}; base::Integer=2) where {T<:AbstractFloat} = _precision(T, base) precision(::T; base::Integer=2) where {T<:AbstractFloat} = precision(T; base) -""" - uabs(x::Integer) - -Return the absolute value of `x`, possibly returning a different type should the -operation be susceptible to overflow. This typically arises when `x` is a two's complement -signed integer, so that `abs(typemin(x)) == typemin(x) < 0`, in which case the result of -`uabs(x)` will be an unsigned integer of the same size. -""" -uabs(x::Integer) = abs(x) -uabs(x::BitSigned) = unsigned(abs(x)) - """ nextfloat(x::AbstractFloat, n::Integer) @@ -794,7 +806,19 @@ end """ issubnormal(f) -> Bool -Test whether a floating point number is subnormal. +Test whether a floating point number is [subnormal](https://en.wikipedia.org/wiki/Subnormal_number). A floating point number is recognized as +subnormal whenever its exponent is the least value possible and its significand is zero. + +# Examples +```jldoctest +julia> floatmin(Float32) +1.1754944f-38 + +julia> issubnormal(1.0f-37) +false + +julia> issubnormal(1.0f-38) +true """ function issubnormal(x::T) where {T<:IEEEFloat} y = reinterpret(Unsigned, x) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 4276ec0daecaf..b3db0f087d211 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -99,12 +99,12 @@ julia> round(357.913; sigdigits=4, base=2) value represented by `1.15` is actually *less* than 1.15, yet will be rounded to 1.2. For example: - ```jldoctest; setup = :(using Printf) + ```jldoctest julia> x = 1.15 1.15 - julia> @sprintf "%.20f" x - "1.14999999999999991118" + julia> big(1.15) + 1.149999999999999911182158029987476766109466552734375 julia> x < 115//100 true diff --git a/base/gmp.jl b/base/gmp.jl index 5d3cabac87e40..8e0c51e6259d6 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -668,8 +668,12 @@ function prod(arr::AbstractArray{BigInt}) # to account for the rounding to limbs in MPZ.mul! # (BITS_PER_LIMB-1 would typically be enough, to which we add # 1 for the initial multiplication by init=1 in foldl) - nbits = GC.@preserve arr sum(arr; init=BITS_PER_LIMB) do x - abs(x.size) * BITS_PER_LIMB - leading_zeros(unsafe_load(x.d)) + nbits = BITS_PER_LIMB + for x in arr + iszero(x) && return zero(BigInt) + xsize = abs(x.size) + lz = GC.@preserve x leading_zeros(unsafe_load(x.d, xsize)) + nbits += xsize * BITS_PER_LIMB - lz end init = BigInt(; nbits) MPZ.set_si!(init, 1) diff --git a/base/indices.jl b/base/indices.jl index c12d4fac69745..0584b32941132 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -476,7 +476,7 @@ struct LinearIndices{N,R<:NTuple{N,AbstractUnitRange{Int}}} <: AbstractArray{Int indices::R end convert(::Type{LinearIndices{N,R}}, inds::LinearIndices{N}) where {N,R<:NTuple{N,AbstractUnitRange{Int}}} = - LinearIndices{N,R}(convert(R, inds.indices)) + LinearIndices{N,R}(convert(R, inds.indices))::LinearIndices{N,R} LinearIndices(::Tuple{}) = LinearIndices{0,typeof(())}(()) LinearIndices(inds::NTuple{N,AbstractUnitRange{<:Integer}}) where {N} = diff --git a/base/int.jl b/base/int.jl index 73485520509c7..567b7022e8d21 100644 --- a/base/int.jl +++ b/base/int.jl @@ -578,8 +578,17 @@ if nameof(@__MODULE__) === :Base # Examples ```jldoctest - julia> 129 % Int8 + julia> x = 129 % Int8 -127 + + julia> typeof(x) + Int8 + + julia> x = 129 % BigInt + 129 + + julia> typeof(x) + BigInt ``` """ $fname(x::Integer, T::Type{<:Integer}) end @@ -772,13 +781,24 @@ promote_rule(::Type{UInt128}, ::Type{Int128}) = UInt128 The lowest value representable by the given (real) numeric DataType `T`. +See also: [`floatmin`](@ref), [`typemax`](@ref), [`eps`](@ref). + # Examples ```jldoctest +julia> typemin(Int8) +-128 + +julia> typemin(UInt32) +0x00000000 + julia> typemin(Float16) -Inf16 julia> typemin(Float32) -Inf32 + +julia> nextfloat(-Inf32) # smallest finite Float32 floating point number +-3.4028235f38 ``` """ function typemin end @@ -801,7 +821,10 @@ julia> typemax(UInt32) julia> typemax(Float64) Inf -julia> floatmax(Float32) # largest finite floating point number +julia> typemax(Float32) +Inf32 + +julia> floatmax(Float32) # largest finite Float32 floating point number 3.4028235f38 ``` """ diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 00632667f659e..823deee94f173 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -649,6 +649,9 @@ See also [`digits`](@ref), [`count_ones`](@ref). # Examples ```jldoctest +julia> ndigits(0) +1 + julia> ndigits(12345) 5 diff --git a/base/io.jl b/base/io.jl index 59bce5eb4de6d..c2d6ad592bf0c 100644 --- a/base/io.jl +++ b/base/io.jl @@ -1001,7 +1001,7 @@ function read(s::IO, nb::Integer = typemax(Int)) return resize!(b, nr) end -read(s::IO, ::Type{String}) = String(read(s)) +read(s::IO, ::Type{String}) = String(read(s)::Vector{UInt8}) read(s::IO, T::Type) = error("The IO stream does not support reading objects of type $T.") ## high-level iterator interfaces ## diff --git a/base/irrationals.jl b/base/irrationals.jl index b0af42e6e283a..3c4a422a74147 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -31,7 +31,7 @@ struct Irrational{sym} <: AbstractIrrational end show(io::IO, x::Irrational{sym}) where {sym} = print(io, sym) function show(io::IO, ::MIME"text/plain", x::Irrational{sym}) where {sym} - if get(io, :compact, false) + if get(io, :compact, false)::Bool print(io, sym) else print(io, sym, " = ", string(float(x))[1:min(end,15)], "...") diff --git a/base/loading.jl b/base/loading.jl index 72d4b5c237895..6df28abbd9dbb 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -232,12 +232,10 @@ end function get_updated_dict(p::TOML.Parser, f::CachedTOMLDict) s = stat(f.path) - time_since_cached = time() - f.mtime - rough_mtime_granularity = 0.1 # seconds - # In case the file is being updated faster than the mtime granularity, - # and have the same size after the update we might miss that it changed. Therefore - # always check the hash in case we recently created the cache. - if time_since_cached < rough_mtime_granularity || s.inode != f.inode || s.mtime != f.mtime || f.size != s.size + # note, this might miss very rapid in-place updates, such that mtime is + # identical but that is solvable by not doing in-place updates, and not + # rapidly changing these files + if s.inode != f.inode || s.mtime != f.mtime || f.size != s.size content = read(f.path) new_hash = _crc32c(content) if new_hash != f.hash @@ -347,7 +345,7 @@ There `where` argument provides the context from where to search for the package: in this case it first checks if the name matches the context itself, otherwise it searches all recursive dependencies (from the resolved manifest of each environment) until it locates the context `where`, and from there -identifies the depdencency with with the corresponding name. +identifies the dependency with with the corresponding name. ```julia-repl julia> Base.identify_package("Pkg") # Pkg is a dependency of the default environment @@ -460,6 +458,18 @@ function pkgdir(m::Module, paths::String...) return joinpath(dirname(dirname(path)), paths...) end +function get_pkgversion_from_path(path) + project_file = locate_project_file(path) + if project_file isa String + d = parsed_toml(project_file) + v = get(d, "version", nothing) + if v !== nothing + return VersionNumber(v::String) + end + end + return nothing +end + """ pkgversion(m::Module) @@ -477,12 +487,17 @@ the form `pkgversion(@__MODULE__)` can be used. This function was introduced in Julia 1.9. """ function pkgversion(m::Module) - rootmodule = moduleroot(m) - pkg = PkgId(rootmodule) - pkgorigin = @lock require_lock begin - get(pkgorigins, pkg, nothing) + path = pkgdir(m) + path === nothing && return nothing + @lock require_lock begin + v = get_pkgversion_from_path(path) + pkgorigin = get(pkgorigins, PkgId(moduleroot(m)), nothing) + # Cache the version + if pkgorigin !== nothing && pkgorigin.version === nothing + pkgorigin.version = v + end + return v end - return pkgorigin === nothing ? nothing : pkgorigin.version end ## generic project & manifest API ## @@ -502,7 +517,7 @@ function locate_project_file(env::String) end # classify the LOAD_PATH entry to be one of: -# - `false`: nonexistant / nothing to see here +# - `false`: nonexistent / nothing to see here # - `true`: `env` is an implicit environment # - `path`: the path of an explicit project file function env_project_file(env::String)::Union{Bool,String} @@ -1356,13 +1371,9 @@ function set_pkgorigin_version_path(pkg::PkgId, path::Union{String,Nothing}) assert_havelock(require_lock) pkgorigin = get!(PkgOrigin, pkgorigins, pkg) if path !== nothing - project_file = locate_project_file(joinpath(dirname(path), "..")) - if project_file isa String - d = parsed_toml(project_file) - v = get(d, "version", nothing) - if v !== nothing - pkgorigin.version = VersionNumber(v::AbstractString) - end + # Pkg needs access to the version of packages in the sysimage. + if Core.Compiler.generating_sysimg() + pkgorigin.version = get_pkgversion_from_path(joinpath(dirname(path), "..")) end end pkgorigin.path = path @@ -1671,12 +1682,14 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, concrete_d deps_eltype = sprint(show, eltype(concrete_deps); context = :module=>nothing) deps = deps_eltype * "[" * join(deps_strs, ",") * "]" trace = isassigned(PRECOMPILE_TRACE_COMPILE) ? `--trace-compile=$(PRECOMPILE_TRACE_COMPILE[])` : `` - io = open(pipeline(`$(julia_cmd()::Cmd) -O0 - --output-ji $output --output-incremental=yes - --startup-file=no --history-file=no --warn-overwrite=yes - --color=$(have_color === nothing ? "auto" : have_color ? "yes" : "no") - $trace - -`, stderr = internal_stderr, stdout = internal_stdout), + io = open(pipeline(addenv(`$(julia_cmd()::Cmd) -O0 + --output-ji $output --output-incremental=yes + --startup-file=no --history-file=no --warn-overwrite=yes + --color=$(have_color === nothing ? "auto" : have_color ? "yes" : "no") + $trace + -`, + "OPENBLAS_NUM_THREADS" => 1), + stderr = internal_stderr, stdout = internal_stdout), "w", stdout) # write data over stdin to avoid the (unlikely) case of exceeding max command line size write(io.in, """ diff --git a/base/logging.jl b/base/logging.jl index f60a9a1a80eab..809a9368d95bd 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -671,7 +671,7 @@ function handle_message(logger::SimpleLogger, level::LogLevel, message, _module, remaining > 0 || return end buf = IOBuffer() - stream = logger.stream + stream::IO = logger.stream if !(isopen(stream)::Bool) stream = stderr end diff --git a/base/math.jl b/base/math.jl index 7f812f82a419e..968eb0eee8bc0 100644 --- a/base/math.jl +++ b/base/math.jl @@ -930,18 +930,27 @@ end ldexp(x::Float16, q::Integer) = Float16(ldexp(Float32(x), q)) """ - exponent(x::AbstractFloat) -> Int + exponent(x) -> Int -Get the exponent of a normalized floating-point number. Returns the largest integer `y` such that `2^y ≤ abs(x)`. +For a normalized floating-point number `x`, this corresponds to the exponent of `x`. # Examples ```jldoctest +julia> exponent(8) +3 + +julia> exponent(64//1) +6 + julia> exponent(6.5) 2 julia> exponent(16.0) 4 + +julia> exponent(3.142e-4) +-12 ``` """ function exponent(x::T) where T<:IEEEFloat @@ -1162,7 +1171,7 @@ end n == 3 && return x*x*x # keep compatibility with literal_pow if n < 0 rx = inv(x) - n==-2 && return rx*rx #keep compatability with literal_pow + n==-2 && return rx*rx #keep compatibility with literal_pow isfinite(x) && (xnlo = -fma(x, rx, -1.) * rx) x = rx n = -n diff --git a/base/methodshow.jl b/base/methodshow.jl index 9e815765dc382..4bd29f75c361d 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -11,7 +11,7 @@ function strip_gensym(sym) end function argtype_decl(env, n, @nospecialize(sig::DataType), i::Int, nargs, isva::Bool) # -> (argname, argtype) - t = sig.parameters[unwrapva(min(i, end))] + t = unwrapva(sig.parameters[min(i, end)]) if i == nargs && isva va = sig.parameters[end] if isvarargtype(va) && (!isdefined(va, :N) || !isa(va.N, Int)) @@ -247,7 +247,7 @@ function show_method(io::IO, m::Method; modulecolor = :light_black, digit_align_ end # module & file, re-using function from errorshow.jl - if get(io, :compact, false) # single-line mode + if get(io, :compact, false)::Bool # single-line mode print_module_path_file(io, m.module, string(file), line; modulecolor, digit_align_width) else println(io) @@ -268,7 +268,7 @@ function show_method_list_header(io::IO, ms::MethodList, namefmt::Function) if hasname what = (startswith(sname, '@') ? "macro" - : mt.module === Core && last(ms).sig === Tuple ? + : mt.module === Core && mt.defs isa Core.TypeMapEntry && (mt.defs.func::Method).sig === Tuple ? "builtin function" : # else "generic function") @@ -472,6 +472,8 @@ function show(io::IO, mime::MIME"text/plain", mt::AbstractVector{Method}) push!(last_shown_line_infos, (string(file), line)) end end + first && summary(io, mt) + nothing end function show(io::IO, mime::MIME"text/html", mt::AbstractVector{Method}) @@ -484,4 +486,5 @@ function show(io::IO, mime::MIME"text/html", mt::AbstractVector{Method}) end print(io, "") end + nothing end diff --git a/base/mpfr.jl b/base/mpfr.jl index 97e4535c065d2..119b0dd67b79f 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -1026,7 +1026,7 @@ string(b::BigFloat) = _string(b) print(io::IO, b::BigFloat) = print(io, string(b)) function show(io::IO, b::BigFloat) - if get(io, :compact, false) + if get(io, :compact, false)::Bool print(io, _string(b, 5)) else print(io, _string(b)) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 487be1d9b42a0..ae69b13c2f9ad 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -325,7 +325,7 @@ module IteratorsMD convert(Tuple{Vararg{UnitRange{Int}}}, R) convert(::Type{CartesianIndices{N,R}}, inds::CartesianIndices{N}) where {N,R} = - CartesianIndices(convert(R, inds.indices)) + CartesianIndices(convert(R, inds.indices))::CartesianIndices{N,R} # equality Base.:(==)(a::CartesianIndices{N}, b::CartesianIndices{N}) where N = @@ -1348,7 +1348,7 @@ end # Note: the next two functions rely on the following definition of the conversion to Bool: # convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError(...)) -# they're used to pre-emptively check in bulk when possible, which is much faster. +# they're used to preemptively check in bulk when possible, which is much faster. # Also, the functions can be overloaded for custom types T<:Real : # a) in the unlikely eventuality that they use a different logic for Bool conversion # b) to skip the check if not necessary diff --git a/base/namedtuple.jl b/base/namedtuple.jl index 70ebba34abe87..3e9f1272d588e 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -111,7 +111,8 @@ function NamedTuple{names}(nt::NamedTuple) where {names} types = Tuple{(fieldtype(nt, idx[n]) for n in 1:length(idx))...} Expr(:new, :(NamedTuple{names, $types}), Any[ :(getfield(nt, $(idx[n]))) for n in 1:length(idx) ]...) else - types = Tuple{(fieldtype(typeof(nt), names[n]) for n in 1:length(names))...} + length_names = length(names)::Integer + types = Tuple{(fieldtype(typeof(nt), names[n]) for n in 1:length_names)...} NamedTuple{names, types}(map(Fix1(getfield, nt), names)) end end @@ -148,7 +149,7 @@ convert(::Type{NamedTuple{names,T}}, nt::NamedTuple{names,T}) where {names,T<:Tu convert(::Type{NamedTuple{names}}, nt::NamedTuple{names}) where {names} = nt function convert(::Type{NamedTuple{names,T}}, nt::NamedTuple{names}) where {names,T<:Tuple} - NamedTuple{names,T}(T(nt)) + NamedTuple{names,T}(T(nt))::NamedTuple{names,T} end if nameof(@__MODULE__) === :Base @@ -318,8 +319,8 @@ values(nt::NamedTuple) = Tuple(nt) haskey(nt::NamedTuple, key::Union{Integer, Symbol}) = isdefined(nt, key) get(nt::NamedTuple, key::Union{Integer, Symbol}, default) = isdefined(nt, key) ? getfield(nt, key) : default get(f::Callable, nt::NamedTuple, key::Union{Integer, Symbol}) = isdefined(nt, key) ? getfield(nt, key) : f() -tail(t::NamedTuple{names}) where names = NamedTuple{tail(names)}(t) -front(t::NamedTuple{names}) where names = NamedTuple{front(names)}(t) +tail(t::NamedTuple{names}) where names = NamedTuple{tail(names::Tuple)}(t) +front(t::NamedTuple{names}) where names = NamedTuple{front(names::Tuple)}(t) reverse(nt::NamedTuple) = NamedTuple{reverse(keys(nt))}(reverse(values(nt))) @assume_effects :total function diff_names(an::Tuple{Vararg{Symbol}}, bn::Tuple{Vararg{Symbol}}) diff --git a/base/number.jl b/base/number.jl index 04205e06831e3..c90e2ce4a3875 100644 --- a/base/number.jl +++ b/base/number.jl @@ -4,7 +4,7 @@ # Numbers are convertible convert(::Type{T}, x::T) where {T<:Number} = x -convert(::Type{T}, x::Number) where {T<:Number} = T(x) +convert(::Type{T}, x::Number) where {T<:Number} = T(x)::T """ isinteger(x) -> Bool diff --git a/base/operators.jl b/base/operators.jl index 7d68761eace3f..6523b3716d1d1 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -185,7 +185,7 @@ Not the inverse of `isless`! Test whether `x` is greater than `y`, according to a fixed total order compatible with `min`. Defined with `isless`, this function is usually `isless(y, x)`, but `NaN` and -[`missing`](@ref) are ordered as smaller than any ordinary value with `missing` +[`missing`](@ref) are ordered as smaller than any regular value with `missing` smaller than `NaN`. So `isless` defines an ascending total order with `NaN` and `missing` as the @@ -658,9 +658,9 @@ end >>(x, n) Right bit shift operator, `x >> n`. For `n >= 0`, the result is `x` shifted -right by `n` bits, where `n >= 0`, filling with `0`s if `x >= 0`, `1`s if `x < -0`, preserving the sign of `x`. This is equivalent to `fld(x, 2^n)`. For `n < -0`, this is equivalent to `x << -n`. +right by `n` bits, filling with `0`s if `x >= 0`, `1`s if `x < 0`, preserving +the sign of `x`. This is equivalent to `fld(x, 2^n)`. For `n < 0`, this is +equivalent to `x << -n`. # Examples ```jldoctest @@ -699,8 +699,8 @@ end >>>(x, n) Unsigned right bit shift operator, `x >>> n`. For `n >= 0`, the result is `x` -shifted right by `n` bits, where `n >= 0`, filling with `0`s. For `n < 0`, this -is equivalent to `x << -n`. +shifted right by `n` bits, filling with `0`s. For `n < 0`, this is equivalent +to `x << -n`. For [`Unsigned`](@ref) integer types, this is equivalent to [`>>`](@ref). For [`Signed`](@ref) integer types, this is equivalent to `signed(unsigned(x) >> n)`. @@ -842,7 +842,7 @@ julia> x == (fld1(x, y) - 1) * y + mod1(x, y) true ``` """ -fld1(x::T, y::T) where {T<:Real} = (m = mod1(x, y); fld(x + y - m, y)) +fld1(x::T, y::T) where {T<:Real} = (m = mod1(x, y); fld((x - m) + y, y)) function fld1(x::T, y::T) where T<:Integer d = div(x, y) return d + (!signbit(x ⊻ y) & (d * y != x)) @@ -887,13 +887,21 @@ widen(x::Type{T}) where {T} = throw(MethodError(widen, (T,))) """ |>(x, f) -Applies a function to the preceding argument. This allows for easy function chaining. -When used with anonymous functions, parentheses are typically required around the definition to get the intended chain. +Infix operator which applies function `f` to the argument `x`. +This allows `f(g(x))` to be written `x |> g |> f`. +When used with anonymous functions, parentheses are typically required around +the definition to get the intended chain. # Examples ```jldoctest -julia> [1:5;] .|> (x -> x^2) |> sum |> inv -0.01818181818181818 +julia> 4 |> inv +0.25 + +julia> [2, 3, 5] |> sum |> inv +0.1 + +julia> [0 1; 2 3] .|> (x -> x^2) |> sum +14 ``` """ |>(x, f) = f(x) @@ -1306,7 +1314,7 @@ Some collections follow a slightly different definition. For example, use [`haskey`](@ref) or `k in keys(dict)`. For these collections, the result is always a `Bool` and never `missing`. -To determine whether an item is not in a given collection, see [`:∉`](@ref). +To determine whether an item is not in a given collection, see [`∉`](@ref). You may also negate the `in` by doing `!(a in b)` which is logically similar to "not in". When broadcasting with `in.(items, collection)` or `items .∈ collection`, both diff --git a/base/ordering.jl b/base/ordering.jl index e49102159c962..d0c9cb99f9c72 100644 --- a/base/ordering.jl +++ b/base/ordering.jl @@ -122,7 +122,7 @@ lt(o::Lt, a, b) = o.lt(a,b) @propagate_inbounds function lt(p::Perm, a::Integer, b::Integer) da = p.data[a] db = p.data[b] - lt(p.order, da, db) | (!lt(p.order, db, da) & (a < b)) + (lt(p.order, da, db)::Bool) | (!(lt(p.order, db, da)::Bool) & (a < b)) end _ord(lt::typeof(isless), by::typeof(identity), order::Ordering) = order diff --git a/base/pair.jl b/base/pair.jl index b5dffbb4e7e86..28a9f981080ec 100644 --- a/base/pair.jl +++ b/base/pair.jl @@ -28,6 +28,11 @@ julia> for x in p end foo 7 + +julia> replace.(["xops", "oxps"], "x" => "o") +2-element Vector{String}: + "oops" + "oops" ``` """ Pair, => @@ -55,7 +60,7 @@ last(p::Pair) = p.second convert(::Type{Pair{A,B}}, x::Pair{A,B}) where {A,B} = x function convert(::Type{Pair{A,B}}, x::Pair) where {A,B} - Pair{A,B}(convert(A, x[1]), convert(B, x[2])) + Pair{A,B}(convert(A, x[1]), convert(B, x[2]))::Pair{A,B} end promote_rule(::Type{Pair{A1,B1}}, ::Type{Pair{A2,B2}}) where {A1,B1,A2,B2} = diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index ea1863de8b708..80685332a85dc 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -132,6 +132,7 @@ julia> size(B) julia> size(A)[perm] == ans true +``` """ function permutedims(A::AbstractArray, perm) dest = similar(A, genperm(axes(A), perm)) @@ -275,11 +276,21 @@ end P end -function Base._mapreduce_dim(f, op, init::Base._InitialValue, A::PermutedDimsArray, dims::Colon) +const CommutativeOps = Union{typeof(+),typeof(Base.add_sum),typeof(min),typeof(max),typeof(Base._extrema_rf),typeof(|),typeof(&)} + +function Base._mapreduce_dim(f, op::CommutativeOps, init::Base._InitialValue, A::PermutedDimsArray, dims::Colon) + Base._mapreduce_dim(f, op, init, parent(A), dims) +end +function Base._mapreduce_dim(f::typeof(identity), op::Union{typeof(Base.mul_prod),typeof(*)}, init::Base._InitialValue, A::PermutedDimsArray{<:Union{Real,Complex}}, dims::Colon) Base._mapreduce_dim(f, op, init, parent(A), dims) end -function Base.mapreducedim!(f, op, B::AbstractArray{T,N}, A::PermutedDimsArray{T,N,perm,iperm}) where {T,N,perm,iperm} +function Base.mapreducedim!(f, op::CommutativeOps, B::AbstractArray{T,N}, A::PermutedDimsArray{S,N,perm,iperm}) where {T,S,N,perm,iperm} + C = PermutedDimsArray{T,N,iperm,perm,typeof(B)}(B) # make the inverse permutation for the output + Base.mapreducedim!(f, op, C, parent(A)) + B +end +function Base.mapreducedim!(f::typeof(identity), op::Union{typeof(Base.mul_prod),typeof(*)}, B::AbstractArray{T,N}, A::PermutedDimsArray{<:Union{Real,Complex},N,perm,iperm}) where {T,N,perm,iperm} C = PermutedDimsArray{T,N,iperm,perm,typeof(B)}(B) # make the inverse permutation for the output Base.mapreducedim!(f, op, C, parent(A)) B diff --git a/base/pointer.jl b/base/pointer.jl index 70be6b1797eed..62b34dd06d368 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -20,14 +20,14 @@ const C_NULL = bitcast(Ptr{Cvoid}, 0) # TODO: deprecate these conversions. C doesn't even allow them. # pointer to integer -convert(::Type{T}, x::Ptr) where {T<:Integer} = T(UInt(x)) +convert(::Type{T}, x::Ptr) where {T<:Integer} = T(UInt(x))::T # integer to pointer convert(::Type{Ptr{T}}, x::Union{Int,UInt}) where {T} = Ptr{T}(x) # pointer to pointer convert(::Type{Ptr{T}}, p::Ptr{T}) where {T} = p -convert(::Type{Ptr{T}}, p::Ptr) where {T} = bitcast(Ptr{T}, p) +convert(::Type{Ptr{T}}, p::Ptr) where {T} = bitcast(Ptr{T}, p)::Ptr{T} # object to pointer (when used with ccall) diff --git a/base/range.jl b/base/range.jl index 4b2bf18e9f634..b9625aac3c443 100644 --- a/base/range.jl +++ b/base/range.jl @@ -252,7 +252,7 @@ abstract type AbstractRange{T} <: AbstractArray{T,1} end RangeStepStyle(::Type{<:AbstractRange}) = RangeStepIrregular() RangeStepStyle(::Type{<:AbstractRange{<:Integer}}) = RangeStepRegular() -convert(::Type{T}, r::AbstractRange) where {T<:AbstractRange} = r isa T ? r : T(r) +convert(::Type{T}, r::AbstractRange) where {T<:AbstractRange} = r isa T ? r : T(r)::T ## ordinal ranges @@ -283,7 +283,7 @@ abstract type AbstractUnitRange{T} <: OrdinalRange{T,T} end Ranges with elements of type `T` with spacing of type `S`. The step between each element is constant, and the range is defined in terms of a `start` and `stop` of type `T` and a `step` of type `S`. Neither -`T` nor `S` should be floating point types. The syntax `a:b:c` with `b > 1` +`T` nor `S` should be floating point types. The syntax `a:b:c` with `b != 0` and `a`, `b`, and `c` all integers creates a `StepRange`. # Examples @@ -1396,14 +1396,13 @@ function sum(r::AbstractRange{<:Real}) end function _in_range(x, r::AbstractRange) - if !isfinite(x) - return false - elseif iszero(step(r)) - return !isempty(r) && first(r) == x - else - n = round(Integer, (x - first(r)) / step(r)) + 1 - return n >= 1 && n <= length(r) && r[n] == x - end + isempty(r) && return false + f, l = first(r), last(r) + # check for NaN, Inf, and large x that may overflow in the next calculation + f <= x <= l || l <= x <= f || return false + iszero(step(r)) && return true + n = round(Integer, (x - f) / step(r)) + 1 + n >= 1 && n <= length(r) && r[n] == x end in(x::Real, r::AbstractRange{<:Real}) = _in_range(x, r) # This method needs to be defined separately since -(::T, ::T) can be implemented diff --git a/base/rational.jl b/base/rational.jl index 782b05e587e1b..26746ad0b4bc2 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -551,7 +551,7 @@ function hash(x::Rational{<:BitInteger64}, h::UInt) end # These methods are only needed for performance. Since `first(r)` and `last(r)` have the -# same denominator (because their difference is an integer), `length(r)` can be calulated +# same denominator (because their difference is an integer), `length(r)` can be calculated # without calling `gcd`. function length(r::AbstractUnitRange{T}) where T<:Rational @inline diff --git a/base/reduce.jl b/base/reduce.jl index 64ea4293c9893..a7f821a73be92 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -989,7 +989,7 @@ _findmin(a, ::Colon) = findmin(identity, a) """ argmax(f, domain) -Return a value `x` in the domain of `f` for which `f(x)` is maximised. +Return a value `x` from `domain` for which `f(x)` is maximised. If there are multiple maximal values for `f(x)` then the first one will be found. `domain` must be a non-empty iterable. @@ -1041,7 +1041,7 @@ argmax(itr) = findmax(itr)[2] """ argmin(f, domain) -Return a value `x` in the domain of `f` for which `f(x)` is minimised. +Return a value `x` from `domain` for which `f(x)` is minimised. If there are multiple minimal values for `f(x)` then the first one will be found. `domain` must be a non-empty iterable. diff --git a/base/reflection.jl b/base/reflection.jl index 94c6c9eeff0fe..d6c044103d0bc 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -265,6 +265,11 @@ Determine whether a global is declared `const` in a given module `m`. isconst(m::Module, s::Symbol) = ccall(:jl_is_const, Cint, (Any, Any), m, s) != 0 +function isconst(g::GlobalRef) + g.binding != C_NULL && return ccall(:jl_binding_is_const, Cint, (Ptr{Cvoid},), g.binding) != 0 + return isconst(g.mod, g.name) +end + """ isconst(t::DataType, s::Union{Int,Symbol}) -> Bool @@ -547,7 +552,7 @@ end isprimitivetype(T) -> Bool Determine whether type `T` was declared as a primitive type -(i.e. using the `primitive` keyword). +(i.e. using the `primitive type` syntax). """ function isprimitivetype(@nospecialize t) @_total_meta @@ -648,7 +653,7 @@ isconcretetype(@nospecialize(t)) = (@_total_meta; isa(t, DataType) && (t.flags & isabstracttype(T) Determine whether type `T` was declared as an abstract type -(i.e. using the `abstract` keyword). +(i.e. using the `abstract type` syntax). # Examples ```jldoctest @@ -1413,7 +1418,7 @@ function infer_effects(@nospecialize(f), @nospecialize(types=default_tt(f)); if isa(f, Core.Builtin) argtypes = Any[types.parameters...] rt = Core.Compiler.builtin_tfunction(interp, f, argtypes, nothing) - return Core.Compiler.builtin_effects(f, argtypes, rt) + return Core.Compiler.builtin_effects(Core.Compiler.typeinf_lattice(interp), f, argtypes, rt) end tt = signature_type(f, types) result = Core.Compiler.findall(tt, Core.Compiler.method_table(interp)) @@ -1833,7 +1838,7 @@ as well to get the properties of an instance of the type. `propertynames(x)` may return only "public" property names that are part of the documented interface of `x`. If you want it to also return "private" -fieldnames intended for internal use, pass `true` for the optional second argument. +property names intended for internal use, pass `true` for the optional second argument. REPL tab completion on `x.` shows only the `private=false` properties. See also: [`hasproperty`](@ref), [`hasfield`](@ref). diff --git a/base/refpointer.jl b/base/refpointer.jl index cd179c87b30d5..290ffc51cbf2a 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -101,7 +101,7 @@ IteratorSize(::Type{<:Ref}) = HasShape{0}() unsafe_convert(::Type{Ref{T}}, x::Ref{T}) where {T} = unsafe_convert(Ptr{T}, x) unsafe_convert(::Type{Ref{T}}, x) where {T} = unsafe_convert(Ptr{T}, x) -convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x) +convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x)::RefValue{T} ### Methods for a Ref object that is backed by an array at index i struct RefArray{T,A<:AbstractArray{T},R} <: Ref{T} diff --git a/base/regex.jl b/base/regex.jl index 27e0391f8a6c8..7c4c780ba0a7c 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -801,7 +801,7 @@ end """ - ^(s::Regex, n::Integer) + ^(s::Regex, n::Integer) -> Regex Repeat a regex `n` times. diff --git a/base/set.jl b/base/set.jl index 3b5635ccb5a33..c1c9cc91d29c1 100644 --- a/base/set.jl +++ b/base/set.jl @@ -548,7 +548,7 @@ function hash(s::AbstractSet, h::UInt) end convert(::Type{T}, s::T) where {T<:AbstractSet} = s -convert(::Type{T}, s::AbstractSet) where {T<:AbstractSet} = T(s) +convert(::Type{T}, s::AbstractSet) where {T<:AbstractSet} = T(s)::T ## replace/replace! ## diff --git a/base/show.jl b/base/show.jl index 5ac50ec3526e9..1e281fbd6d6d1 100644 --- a/base/show.jl +++ b/base/show.jl @@ -4,7 +4,7 @@ using Core.Compiler: has_typevar function show(io::IO, ::MIME"text/plain", u::UndefInitializer) show(io, u) - get(io, :compact, false) && return + get(io, :compact, false)::Bool && return print(io, ": array initializer with undefined values") end @@ -24,7 +24,7 @@ function show(io::IO, ::MIME"text/plain", r::LinRange) end function show(io::IO, ::MIME"text/plain", f::Function) - get(io, :compact, false) && return show(io, f) + get(io, :compact, false)::Bool && return show(io, f) ft = typeof(f) mt = ft.name.mt if isa(f, Core.IntrinsicFunction) @@ -109,7 +109,7 @@ function _truncate_at_width_or_chars(ignore_ANSI::Bool, str, width, rpad=false, end function show(io::IO, ::MIME"text/plain", iter::Union{KeySet,ValueIterator}) - isempty(iter) && get(io, :compact, false) && return show(io, iter) + isempty(iter) && get(io, :compact, false)::Bool && return show(io, iter) summary(io, iter) isempty(iter) && return print(io, ". ", isa(iter,KeySet) ? "Keys" : "Values", ":") @@ -131,7 +131,7 @@ function show(io::IO, ::MIME"text/plain", iter::Union{KeySet,ValueIterator}) if limit str = sprint(show, v, context=io, sizehint=0) - str = _truncate_at_width_or_chars(get(io, :color, false), str, cols) + str = _truncate_at_width_or_chars(get(io, :color, false)::Bool, str, cols) print(io, str) else show(io, v) @@ -242,7 +242,7 @@ function show(io::IO, ::MIME"text/plain", t::AbstractSet{T}) where T if limit str = sprint(show, v, context=recur_io, sizehint=0) - print(io, _truncate_at_width_or_chars(get(io, :color, false), str, cols)) + print(io, _truncate_at_width_or_chars(get(io, :color, false)::Bool, str, cols)) else show(recur_io, v) end @@ -303,7 +303,7 @@ function IOContext(io::IO, dict::ImmutableDict) IOContext{typeof(io0)}(io0, dict) end -convert(::Type{IOContext}, io::IO) = IOContext(unwrapcontext(io)...) +convert(::Type{IOContext}, io::IO) = IOContext(unwrapcontext(io)...)::IOContext IOContext(io::IO) = convert(IOContext, io) @@ -434,9 +434,10 @@ Julia code when possible. [`repr`](@ref) returns the output of `show` as a string. -To customize human-readable text output for objects of type `T`, define -`show(io::IO, ::MIME"text/plain", ::T)` instead. Checking the `:compact` -[`IOContext`](@ref) property of `io` in such methods is recommended, +For a more verbose human-readable text output for objects of type `T`, define +`show(io::IO, ::MIME"text/plain", ::T)` in addition. Checking the `:compact` +[`IOContext`](@ref) key (often checked as `get(io, :compact, false)::Bool`) +of `io` in such methods is recommended, since some containers show their elements by calling this method with `:compact => true`. @@ -495,7 +496,7 @@ end function active_module() isassigned(REPL_MODULE_REF) || return Main REPL = REPL_MODULE_REF[] - return REPL.active_module()::Module + return invokelatest(REPL.active_module)::Module end # Check if a particular symbol is exported from a standard library module @@ -615,7 +616,7 @@ function make_typealias(@nospecialize(x::Type)) env = env::SimpleVector # TODO: In some cases (such as the following), the `env` is over-approximated. # We'd like to disable `fix_inferred_var_bound` since we'll already do that fix-up here. - # (or detect and reverse the compution of it here). + # (or detect and reverse the computation of it here). # T = Array{Array{T,1}, 1} where T # (ti, env) = ccall(:jl_type_intersection_with_env, Any, (Any, Any), T, Vector) # env[1].ub.var == T.var @@ -951,13 +952,13 @@ function _show_type(io::IO, @nospecialize(x::Type)) if print_without_params(x) show_type_name(io, (unwrap_unionall(x)::DataType).name) return - elseif get(io, :compact, true) && show_typealias(io, x) + elseif get(io, :compact, true)::Bool && show_typealias(io, x) return elseif x isa DataType show_datatype(io, x) return elseif x isa Union - if get(io, :compact, true) && show_unionaliases(io, x) + if get(io, :compact, true)::Bool && show_unionaliases(io, x) return end print(io, "Union") @@ -1170,7 +1171,7 @@ function show(io::IO, p::Pair) isdelimited(io_i, p[i]) || print(io, "(") show(io_i, p[i]) isdelimited(io_i, p[i]) || print(io, ")") - i == 1 && print(io, get(io, :compact, false) ? "=>" : " => ") + i == 1 && print(io, get(io, :compact, false)::Bool ? "=>" : " => ") end end @@ -1570,7 +1571,7 @@ unquoted(ex::Expr) = ex.args[1] function printstyled end function with_output_color end -emphasize(io, str::AbstractString, col = Base.error_color()) = get(io, :color, false) ? +emphasize(io, str::AbstractString, col = Base.error_color()) = get(io, :color, false)::Bool ? printstyled(io, str; color=col, bold=true) : print(io, uppercase(str)) @@ -1838,9 +1839,10 @@ function allow_macroname(ex) end end -function is_core_macro(arg, macro_name::AbstractString) - arg === GlobalRef(Core, Symbol(macro_name)) +function is_core_macro(arg::GlobalRef, macro_name::AbstractString) + arg == GlobalRef(Core, Symbol(macro_name)) end +is_core_macro(@nospecialize(arg), macro_name::AbstractString) = false # symbol for IOContext flag signaling whether "begin" is treated # as an ordinary symbol, which is true in indexing expressions. @@ -2720,7 +2722,7 @@ function dump(io::IOContext, x::Array, n::Int, indent) println(io) recur_io = IOContext(io, :SHOWN_SET => x) lx = length(x) - if get(io, :limit, false) + if get(io, :limit, false)::Bool dump_elts(recur_io, x, n, indent, 1, (lx <= 10 ? lx : 5)) if lx > 10 println(io) diff --git a/base/some.jl b/base/some.jl index 8dc726e5c0022..e09a926ab931b 100644 --- a/base/some.jl +++ b/base/some.jl @@ -35,7 +35,7 @@ end convert(::Type{T}, x::T) where {T>:Nothing} = x convert(::Type{T}, x) where {T>:Nothing} = convert(nonnothingtype_checked(T), x) convert(::Type{Some{T}}, x::Some{T}) where {T} = x -convert(::Type{Some{T}}, x::Some) where {T} = Some{T}(convert(T, x.value)) +convert(::Type{Some{T}}, x::Some) where {T} = Some{T}(convert(T, x.value))::Some{T} function show(io::IO, x::Some) if get(io, :typeinfo, Any) == typeof(x) diff --git a/base/sort.jl b/base/sort.jl index 6bbe43c61b0c7..f6f737ac2082e 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -516,7 +516,8 @@ const SMALL_ALGORITHM = InsertionSort const SMALL_THRESHOLD = 20 function sort!(v::AbstractVector, lo::Integer, hi::Integer, ::InsertionSortAlg, o::Ordering) - @inbounds for i = lo+1:hi + lo_plus_1 = (lo + 1)::Integer + @inbounds for i = lo_plus_1:hi j = i x = v[i] while j > lo @@ -1161,7 +1162,7 @@ function sortperm(A::AbstractArray; min, max = extrema(A) (diff, o1) = sub_with_overflow(max, min) (rangelen, o2) = add_with_overflow(diff, oneunit(diff)) - if !o1 && !o2 && rangelen < div(n,2) + if !(o1 || o2)::Bool && rangelen < div(n,2) return sortperm_int_range(A, rangelen, min) end end diff --git a/base/special/log.jl b/base/special/log.jl index d868071818a18..5e20cdbaa06a6 100644 --- a/base/special/log.jl +++ b/base/special/log.jl @@ -556,7 +556,7 @@ const t_log_table_compact = ( end # Log implementation that returns 2 numbers which sum to give true value with about 68 bits of precision -# Since `log` only makes sense for positive exponents, we speed up the implimentation by stealing the sign bit +# Since `log` only makes sense for positive exponents, we speed up the implementation by stealing the sign bit # of the input for an extra bit of the exponent which is used to normalize subnormal inputs. # Does not normalize results. # Adapted and modified from https://github.com/ARM-software/optimized-routines/blob/master/math/pow.c @@ -575,7 +575,7 @@ function _log_ext(xu) t, logctail = getfield(t_log_table_compact, Int(i+1)) invc, logc = log_tab_unpack(t) # Note: invc is j/N or j/N/2 where j is an integer in [N,2N) and - # |z/c - 1| < 1/N, so r = z/c - 1 is exactly representible. + # |z/c - 1| < 1/N, so r = z/c - 1 is exactly representable. r = fma(z, invc, -1.0) # k*Ln2 + log(c) + r. t1 = muladd(k, 0.6931471805598903, logc) #ln(2) hi part diff --git a/base/special/trig.jl b/base/special/trig.jl index e3033aab6c272..817d073d0cc48 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -255,7 +255,7 @@ end # # Note: tan(y+z) = tan(y) + tan'(y)*z # ~ tan(y) + (1+y*y)*z - # Therefore, for better accuracz in computing tan(y+z), let + # Therefore, for better accuracy in computing tan(y+z), let # 3 2 2 2 2 # r = y *(T2+y *(T3+y *(...+y *(T12+y *T13)))) # then diff --git a/base/stream.jl b/base/stream.jl index 6c81f5f44ea6a..0d8676885fa0c 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -1361,7 +1361,7 @@ julia> io1 = open("same/path", "w") julia> io2 = open("same/path", "w") -julia> redirect_stdio(f, stdout=io1, stderr=io2) # not suppored +julia> redirect_stdio(f, stdout=io1, stderr=io2) # not supported ``` Also the `stdin` argument may not be the same descriptor as `stdout` or `stderr`. ```julia-repl diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 306ecc5cc214a..c2666898243b0 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -229,7 +229,7 @@ Symbol(s::AbstractString) = Symbol(String(s)) Symbol(x...) = Symbol(string(x...)) convert(::Type{T}, s::T) where {T<:AbstractString} = s -convert(::Type{T}, s::AbstractString) where {T<:AbstractString} = T(s) +convert(::Type{T}, s::AbstractString) where {T<:AbstractString} = T(s)::T ## summary ## @@ -715,7 +715,7 @@ julia> repeat("ha", 3) repeat(s::AbstractString, r::Integer) = repeat(String(s), r) """ - ^(s::Union{AbstractString,AbstractChar}, n::Integer) + ^(s::Union{AbstractString,AbstractChar}, n::Integer) -> AbstractString Repeat a string or character `n` times. This can also be written as `repeat(s, n)`. diff --git a/base/strings/io.jl b/base/strings/io.jl index d1bf7a763e93c..e800002076d54 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -201,7 +201,7 @@ function show( ) # compute limit in default case if limit === nothing - get(io, :limit, false) || return show(io, str) + get(io, :limit, false)::Bool || return show(io, str) limit = max(20, displaysize(io)[2]) # one line in collection, seven otherwise get(io, :typeinfo, nothing) === nothing && (limit *= 7) diff --git a/base/strings/substring.jl b/base/strings/substring.jl index b8a0de1948326..baaea038b2cfe 100644 --- a/base/strings/substring.jl +++ b/base/strings/substring.jl @@ -55,13 +55,13 @@ SubString{T}(s::T) where {T<:AbstractString} = SubString{T}(s, 1, lastindex(s):: @propagate_inbounds maybeview(s::AbstractString, args...) = getindex(s, args...) convert(::Type{SubString{S}}, s::AbstractString) where {S<:AbstractString} = - SubString(convert(S, s)) + SubString(convert(S, s))::SubString{S} convert(::Type{T}, s::T) where {T<:SubString} = s # Regex match allows only Union{String, SubString{String}} so define conversion to this type convert(::Type{Union{String, SubString{String}}}, s::String) = s convert(::Type{Union{String, SubString{String}}}, s::SubString{String}) = s -convert(::Type{Union{String, SubString{String}}}, s::AbstractString) = convert(String, s) +convert(::Type{Union{String, SubString{String}}}, s::AbstractString) = convert(String, s)::String function String(s::SubString{String}) parent = s.string diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index 36af24bda857b..821e186501d1d 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -468,7 +468,7 @@ A character is classified as numeric if it belongs to the Unicode general catego i.e. a character whose category code begins with 'N'. Note that this broad category includes characters such as ¾ and ௰. -Use [`isdigit`](@ref) to check whether a character a decimal digit between 0 and 9. +Use [`isdigit`](@ref) to check whether a character is a decimal digit between 0 and 9. # Examples ```jldoctest diff --git a/base/sysinfo.jl b/base/sysinfo.jl index f0852f32fc17d..62241457f8954 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -20,6 +20,8 @@ export BINDIR, loadavg, free_memory, total_memory, + physical_free_memory, + physical_total_memory, isapple, isbsd, isdragonfly, @@ -246,19 +248,44 @@ function loadavg() return loadavg_ end +""" + Sys.free_physical_memory() + +Get the free memory of the system in bytes. The entire amount may not be available to the +current process; use `Sys.free_memory()` for the actually available amount. +""" +free_physical_memory() = ccall(:uv_get_free_memory, UInt64, ()) + +""" + Sys.total_physical_memory() + +Get the total memory in RAM (including that which is currently used) in bytes. The entire +amount may not be available to the current process; see `Sys.total_memory()`. +""" +total_physical_memory() = ccall(:uv_get_total_memory, UInt64, ()) + """ Sys.free_memory() Get the total free memory in RAM in bytes. """ -free_memory() = ccall(:uv_get_free_memory, UInt64, ()) +free_memory() = ccall(:uv_get_available_memory, UInt64, ()) """ Sys.total_memory() Get the total memory in RAM (including that which is currently used) in bytes. +This amount may be constrained, e.g., by Linux control groups. For the unconstrained +amount, see `Sys.physical_memory()`. """ -total_memory() = ccall(:uv_get_total_memory, UInt64, ()) +function total_memory() + memory = ccall(:uv_get_constrained_memory, UInt64, ()) + if memory == 0 + return total_physical_memory() + else + return memory + end +end """ Sys.get_process_title() diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 0852fafe192ec..6c8ea35cfa373 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -199,7 +199,7 @@ microseconds). `:static` scheduler creates one task per thread and divides the iterations equally among them, assigning each task specifically to each thread. In particular, the value of -[`threadid()`](@ref Threads.threadid) is guranteed to be constant within one iteration. +[`threadid()`](@ref Threads.threadid) is guaranteed to be constant within one iteration. Specifying `:static` is an error if used from inside another `@threads` loop or from a thread other than 1. diff --git a/base/toml_parser.jl b/base/toml_parser.jl index 323f954cf8b11..d9579e17ce990 100644 --- a/base/toml_parser.jl +++ b/base/toml_parser.jl @@ -326,7 +326,7 @@ function Base.showerror(io::IO, err::ParserError) str1, err1 = point_to_line(err.str::String, pos, pos, io) @static if VERSION <= v"1.6.0-DEV.121" # See https://github.com/JuliaLang/julia/issues/36015 - format_fixer = get(io, :color, false) == true ? "\e[0m" : "" + format_fixer = get(io, :color, false)::Bool == true ? "\e[0m" : "" println(io, "$format_fixer ", str1) print(io, "$format_fixer ", err1) else diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index a8611b21052b5..edbce928f527c 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -164,7 +164,7 @@ div12(x, y) = div12(promote(x, y)...) A number with twice the precision of `T`, e.g., quad-precision if `T = Float64`. -!!! warn +!!! warning `TwicePrecision` is an internal type used to increase the precision of floating-point ranges, and not intended for external use. If you encounter them in real code, the most likely explanation is @@ -268,10 +268,10 @@ TwicePrecision{T}(x::Number) where {T} = TwicePrecision{T}(T(x), zero(T)) convert(::Type{TwicePrecision{T}}, x::TwicePrecision{T}) where {T} = x convert(::Type{TwicePrecision{T}}, x::TwicePrecision) where {T} = - TwicePrecision{T}(convert(T, x.hi), convert(T, x.lo)) + TwicePrecision{T}(convert(T, x.hi), convert(T, x.lo))::TwicePrecision{T} -convert(::Type{T}, x::TwicePrecision) where {T<:Number} = T(x) -convert(::Type{TwicePrecision{T}}, x::Number) where {T} = TwicePrecision{T}(x) +convert(::Type{T}, x::TwicePrecision) where {T<:Number} = T(x)::T +convert(::Type{TwicePrecision{T}}, x::Number) where {T} = TwicePrecision{T}(x)::TwicePrecision{T} float(x::TwicePrecision{<:AbstractFloat}) = x float(x::TwicePrecision) = TwicePrecision(float(x.hi), float(x.lo)) diff --git a/base/util.jl b/base/util.jl index e1fef49d20f01..f26ed0717a1fd 100644 --- a/base/util.jl +++ b/base/util.jl @@ -119,7 +119,7 @@ or an integer between 0 and 255 inclusive. Note that not all terminals support 2 Keywords `bold=true`, `underline=true`, `blink=true` are self-explanatory. Keyword `reverse=true` prints with foreground and background colors exchanged, -and `hidden=true` should be invisibe in the terminal but can still be copied. +and `hidden=true` should be invisible in the terminal but can still be copied. These properties can be used in any combination. See also [`print`](@ref), [`println`](@ref), [`show`](@ref). diff --git a/base/version.jl b/base/version.jl index 978abbba1a8aa..67377c86a8493 100644 --- a/base/version.jl +++ b/base/version.jl @@ -289,7 +289,7 @@ function banner(io::IO = stdout) commit_date = isempty(Base.GIT_VERSION_INFO.date_string) ? "" : " ($(split(Base.GIT_VERSION_INFO.date_string)[1]))" - if get(io, :color, false) + if get(io, :color, false)::Bool c = text_colors tx = c[:normal] # text jl = c[:normal] # julia diff --git a/cli/Makefile b/cli/Makefile index e5298a8da7619..274877ecaf12a 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -28,6 +28,14 @@ endif # Build list of dependent libraries that must be opened SHIPFLAGS += -DDEP_LIBS="\"$(LOADER_BUILD_DEP_LIBS)\"" DEBUGFLAGS += -DDEP_LIBS="\"$(LOADER_DEBUG_BUILD_DEP_LIBS)\"" +ifneq (,$(findstring MINGW,$(shell uname))) +# In MSYS2, do not perform path conversion for `DEP_LIBS`. +# https://www.msys2.org/wiki/Porting/#filesystem-namespaces +# We define this environment variable for only these two object files, +# as they're the only ones that require it at the time of writing. +$(BUILDDIR)/loader_lib.o: export MSYS2_ARG_CONV_EXCL = -DDEP_LIBS= +$(BUILDDIR)/loader_lib.dbg.obj: export MSYS2_ARG_CONV_EXCL = -DDEP_LIBS= +endif # MSYS2 EXE_OBJS := $(BUILDDIR)/loader_exe.o EXE_DOBJS := $(BUILDDIR)/loader_exe.dbg.obj diff --git a/deps/Makefile b/deps/Makefile index 6c0bc6de86c54..4f0cc48b01971 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -88,6 +88,10 @@ ifeq ($(USE_SYSTEM_LLVM), 0) DEP_LIBS += llvm endif +ifeq ($(USE_SYSTEM_LLD), 0) +DEP_LIBS += lld +endif + ifeq ($(USE_SYSTEM_PCRE), 0) DEP_LIBS += pcre endif @@ -168,7 +172,7 @@ endif DEP_LIBS_STAGED_ALL := llvm llvm-tools clang llvmunwind unwind libuv pcre \ openlibm dsfmt blastrampoline openblas lapack gmp mpfr patchelf utf8proc \ objconv mbedtls libssh2 nghttp2 curl libgit2 libwhich zlib p7zip csl \ - libsuitesparse + libsuitesparse lld DEP_LIBS_ALL := $(DEP_LIBS_STAGED_ALL) ifneq ($(USE_BINARYBUILDER_OPENBLAS),0) diff --git a/deps/blastrampoline.mk b/deps/blastrampoline.mk index 2e9a14cd6b7be..bd1cb65c6ae2d 100644 --- a/deps/blastrampoline.mk +++ b/deps/blastrampoline.mk @@ -6,16 +6,25 @@ BLASTRAMPOLINE_GIT_URL := https://github.com/JuliaLinearAlgebra/libblastrampolin BLASTRAMPOLINE_TAR_URL = https://api.github.com/repos/JuliaLinearAlgebra/libblastrampoline/tarball/$1 $(eval $(call git-external,blastrampoline,BLASTRAMPOLINE,,,$(BUILDDIR))) +BLASTRAMPOLINE_BUILD_OPTS := $(MAKE_COMMON) CC="$(CC) $(SANITIZE_OPTS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" +BLASTRAMPOLINE_BUILD_OPTS += ARCH="$(ARCH)" OS="$(OS)" + $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/build-configured: $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/source-extracted mkdir -p $(dir $@) echo 1 > $@ +BLASTRAMPOLINE_BUILD_ROOT := $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/src $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/build-compiled: $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/build-configured - cd $(dir $@)/src && $(MAKE) $(MAKE_COMMON) CC="$(CC) $(SANITIZE_OPTS)" + cd $(dir $@)/src && $(MAKE) $(BLASTRAMPOLINE_BUILD_OPTS) +ifeq ($(OS), WINNT) + # Windows doesn't like soft link, use hard link + cd $(BLASTRAMPOLINE_BUILD_ROOT)/build/ && \ + cp -f --dereference --link libblastrampoline.dll libblastrampoline.dll +endif echo 1 > $@ define BLASTRAMPOLINE_INSTALL - $(MAKE) -C $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/src $(MAKE_COMMON) install DESTDIR="$2" + $(MAKE) -C $(BLASTRAMPOLINE_BUILD_ROOT) install $(BLASTRAMPOLINE_BUILD_OPTS) DESTDIR="$2" endef $(eval $(call staged-install, \ blastrampoline,$(BLASTRAMPOLINE_SRC_DIR), \ @@ -23,6 +32,11 @@ $(eval $(call staged-install, \ $$(BLASTRAMPOLINE_OBJ_TARGET), \ $$(INSTALL_NAME_CMD)libblastrampoline.$$(SHLIB_EXT) $$(build_shlibdir)/libblastrampoline.$$(SHLIB_EXT))) +clean-blastrampoline: + -$(MAKE) -C $(BLASTRAMPOLINE_BUILD_ROOT) clean + -$(RM) $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/build-compiled \ + $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/build-configured + get-blastrampoline: $(BLASTRAMPOLINE_SRC_FILE) extract-blastrampoline: $(BUILDDIR)/$(BLASTRAMPOLINE_SRC_DIR)/source-extracted configure-blastrampoline: extract-blastrampoline diff --git a/deps/blastrampoline.version b/deps/blastrampoline.version index 7a153431bafbe..9d124df6490b9 100644 --- a/deps/blastrampoline.version +++ b/deps/blastrampoline.version @@ -2,6 +2,6 @@ BLASTRAMPOLINE_JLL_NAME := libblastrampoline ## source build -BLASTRAMPOLINE_VER := 5.1.1 -BLASTRAMPOLINE_BRANCH=v5.1.1 -BLASTRAMPOLINE_SHA1=bac2f810d523003fbb431ecc6e9ea81c8b86e2d6 +BLASTRAMPOLINE_VER := 5.2.0 +BLASTRAMPOLINE_BRANCH=v5.2.0 +BLASTRAMPOLINE_SHA1=4a934fd00056c6d351e9b9a445c3b05bf8a0669d diff --git a/deps/checksums/NetworkOptions-4d3df6445bbca0556a7a9f2abb0e48ba7d774f5a.tar.gz/md5 b/deps/checksums/NetworkOptions-4d3df6445bbca0556a7a9f2abb0e48ba7d774f5a.tar.gz/md5 deleted file mode 100644 index f1a62f3d38760..0000000000000 --- a/deps/checksums/NetworkOptions-4d3df6445bbca0556a7a9f2abb0e48ba7d774f5a.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -47be3a2c46e5279714bcb7837127c08a diff --git a/deps/checksums/NetworkOptions-4d3df6445bbca0556a7a9f2abb0e48ba7d774f5a.tar.gz/sha512 b/deps/checksums/NetworkOptions-4d3df6445bbca0556a7a9f2abb0e48ba7d774f5a.tar.gz/sha512 deleted file mode 100644 index 27b5e2397013c..0000000000000 --- a/deps/checksums/NetworkOptions-4d3df6445bbca0556a7a9f2abb0e48ba7d774f5a.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -df45c5fa22619da686481b78de76b60573c798c14a9bbf3a9dd449f52ffca1f2b8dd3b247e2a7679d3dd55ba115787f3734cf03d29a10eba8fecdd78890891b5 diff --git a/deps/checksums/NetworkOptions-8ce1e104eeddcf9c7ccb387dc4811ddb1c750cc2.tar.gz/md5 b/deps/checksums/NetworkOptions-8ce1e104eeddcf9c7ccb387dc4811ddb1c750cc2.tar.gz/md5 new file mode 100644 index 0000000000000..4f4a11a34cbb5 --- /dev/null +++ b/deps/checksums/NetworkOptions-8ce1e104eeddcf9c7ccb387dc4811ddb1c750cc2.tar.gz/md5 @@ -0,0 +1 @@ +a86ceac14b0ddc0dace2a5b30c3c0e2a diff --git a/deps/checksums/NetworkOptions-8ce1e104eeddcf9c7ccb387dc4811ddb1c750cc2.tar.gz/sha512 b/deps/checksums/NetworkOptions-8ce1e104eeddcf9c7ccb387dc4811ddb1c750cc2.tar.gz/sha512 new file mode 100644 index 0000000000000..3fb8797a10eb8 --- /dev/null +++ b/deps/checksums/NetworkOptions-8ce1e104eeddcf9c7ccb387dc4811ddb1c750cc2.tar.gz/sha512 @@ -0,0 +1 @@ +0554193fbad941b0b9f88a3fced366c4b066207023736f628f6623266de113a546aa883b9fe1c46cd1d7cf64ad2e7992471c1b76e3894aa401c27227828dcaa3 diff --git a/deps/checksums/Pkg-3cbbd860afd4c2a50a80a04fa229fe5cd5bddc76.tar.gz/md5 b/deps/checksums/Pkg-3cbbd860afd4c2a50a80a04fa229fe5cd5bddc76.tar.gz/md5 new file mode 100644 index 0000000000000..8480935cba812 --- /dev/null +++ b/deps/checksums/Pkg-3cbbd860afd4c2a50a80a04fa229fe5cd5bddc76.tar.gz/md5 @@ -0,0 +1 @@ +f164cc7c322b2bd3f9a1ed49882d9a8c diff --git a/deps/checksums/Pkg-3cbbd860afd4c2a50a80a04fa229fe5cd5bddc76.tar.gz/sha512 b/deps/checksums/Pkg-3cbbd860afd4c2a50a80a04fa229fe5cd5bddc76.tar.gz/sha512 new file mode 100644 index 0000000000000..2f3164077b8a9 --- /dev/null +++ b/deps/checksums/Pkg-3cbbd860afd4c2a50a80a04fa229fe5cd5bddc76.tar.gz/sha512 @@ -0,0 +1 @@ +5d1d8acfed6e432033473f083860cdbefafcc0f0b8d8aa99fa445288a3064ca72da8fc4dfa1a3459347e1d512adba252bc5d468305fa4a74e4e8f25ae0628c87 diff --git a/deps/checksums/Pkg-f22fa37dbc97c67e69a1dda2a3afd088c45702ce.tar.gz/md5 b/deps/checksums/Pkg-f22fa37dbc97c67e69a1dda2a3afd088c45702ce.tar.gz/md5 deleted file mode 100644 index b1f5164581731..0000000000000 --- a/deps/checksums/Pkg-f22fa37dbc97c67e69a1dda2a3afd088c45702ce.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -2c06962f1284651aea7d2169adb291b2 diff --git a/deps/checksums/Pkg-f22fa37dbc97c67e69a1dda2a3afd088c45702ce.tar.gz/sha512 b/deps/checksums/Pkg-f22fa37dbc97c67e69a1dda2a3afd088c45702ce.tar.gz/sha512 deleted file mode 100644 index 2ec622f6de7a8..0000000000000 --- a/deps/checksums/Pkg-f22fa37dbc97c67e69a1dda2a3afd088c45702ce.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -d9b9b798aebfa423f9f600eeefd9b2bd2af73cb8cb9edd4f1e631f1b24aab3bc599f0436ab5ad93bfb35bcf2779273ce84d603dbde9d1d74e990f7c4829a4ae0 diff --git a/deps/checksums/SparseArrays-1bae96dc8f9a8ca8b7879eef4cf71e186598e982.tar.gz/md5 b/deps/checksums/SparseArrays-1bae96dc8f9a8ca8b7879eef4cf71e186598e982.tar.gz/md5 new file mode 100644 index 0000000000000..c30fb0af82a8d --- /dev/null +++ b/deps/checksums/SparseArrays-1bae96dc8f9a8ca8b7879eef4cf71e186598e982.tar.gz/md5 @@ -0,0 +1 @@ +88144ed473b0ca6154ec55a8977c281c diff --git a/deps/checksums/SparseArrays-1bae96dc8f9a8ca8b7879eef4cf71e186598e982.tar.gz/sha512 b/deps/checksums/SparseArrays-1bae96dc8f9a8ca8b7879eef4cf71e186598e982.tar.gz/sha512 new file mode 100644 index 0000000000000..1808b81c26624 --- /dev/null +++ b/deps/checksums/SparseArrays-1bae96dc8f9a8ca8b7879eef4cf71e186598e982.tar.gz/sha512 @@ -0,0 +1 @@ +1c8c27f6b74c60dedecd6dd58de6b4b400bf3b942104e3ba7319a10a111ebbab0be03f98f072c073f43ca454d187674737dd34c1c9acb92adf3c8b76b3c400ac diff --git a/deps/checksums/SparseArrays-91814c1e84421a9c43b2776fc9dc96ec25104ac8.tar.gz/md5 b/deps/checksums/SparseArrays-91814c1e84421a9c43b2776fc9dc96ec25104ac8.tar.gz/md5 deleted file mode 100644 index 470e121636cd1..0000000000000 --- a/deps/checksums/SparseArrays-91814c1e84421a9c43b2776fc9dc96ec25104ac8.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -da78690de5f015cad4419b2c68e8b242 diff --git a/deps/checksums/SparseArrays-91814c1e84421a9c43b2776fc9dc96ec25104ac8.tar.gz/sha512 b/deps/checksums/SparseArrays-91814c1e84421a9c43b2776fc9dc96ec25104ac8.tar.gz/sha512 deleted file mode 100644 index 72a6bf1ce9731..0000000000000 --- a/deps/checksums/SparseArrays-91814c1e84421a9c43b2776fc9dc96ec25104ac8.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -c4045aeaef8094644a36b6d1f80fa62de33146f90bf18e23369a7234752d39fbdf5822c556cf81242109031b08ab6f5354facc5ede3f45215e68cc10421abf42 diff --git a/deps/checksums/Tar-56062695b92920c8b75e997fb0c8c3b015d04b78.tar.gz/md5 b/deps/checksums/Tar-56062695b92920c8b75e997fb0c8c3b015d04b78.tar.gz/md5 deleted file mode 100644 index 3be44f2d90718..0000000000000 --- a/deps/checksums/Tar-56062695b92920c8b75e997fb0c8c3b015d04b78.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -2e6f1656df70500842c4de4d0f941f89 diff --git a/deps/checksums/Tar-56062695b92920c8b75e997fb0c8c3b015d04b78.tar.gz/sha512 b/deps/checksums/Tar-56062695b92920c8b75e997fb0c8c3b015d04b78.tar.gz/sha512 deleted file mode 100644 index 7c1626b841ee0..0000000000000 --- a/deps/checksums/Tar-56062695b92920c8b75e997fb0c8c3b015d04b78.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -2d2ed113bb9e9469b29a680172d1ab06b2ad8e0574788c3eb16467e621b9127c6159afbddd1014694d46bf9945cfcecbe8cbc315448e0a06fe14b45a4b10ae83 diff --git a/deps/checksums/Tar-951955b7fbe0d79e4e8a1405b6816e4081a6976d.tar.gz/md5 b/deps/checksums/Tar-951955b7fbe0d79e4e8a1405b6816e4081a6976d.tar.gz/md5 new file mode 100644 index 0000000000000..f9aa140eccc97 --- /dev/null +++ b/deps/checksums/Tar-951955b7fbe0d79e4e8a1405b6816e4081a6976d.tar.gz/md5 @@ -0,0 +1 @@ +b49a74404daa5575b82f89082ff35af9 diff --git a/deps/checksums/Tar-951955b7fbe0d79e4e8a1405b6816e4081a6976d.tar.gz/sha512 b/deps/checksums/Tar-951955b7fbe0d79e4e8a1405b6816e4081a6976d.tar.gz/sha512 new file mode 100644 index 0000000000000..1519b88a7a53e --- /dev/null +++ b/deps/checksums/Tar-951955b7fbe0d79e4e8a1405b6816e4081a6976d.tar.gz/sha512 @@ -0,0 +1 @@ +33280360d106269922c95c5cd3289babddf85f5031047a93a583b465f4c78ec41d800a025c3ab9e69817144390b206b6c2fdac181476b7fcbce91c55ee5b134f diff --git a/deps/checksums/blastrampoline b/deps/checksums/blastrampoline index 0276f885e5768..ee10c4a624386 100644 --- a/deps/checksums/blastrampoline +++ b/deps/checksums/blastrampoline @@ -1,34 +1,34 @@ -blastrampoline-bac2f810d523003fbb431ecc6e9ea81c8b86e2d6.tar.gz/md5/070218f52aee906ebebb035e6c504aef -blastrampoline-bac2f810d523003fbb431ecc6e9ea81c8b86e2d6.tar.gz/sha512/eff4c34f19fd444cf3379c81836db82848287aca6106d952127565a0ee2d36797fa36b9f48b77db6a9a0c27dd307400385236ed335d7e58ecc7ec92de32af2c6 -libblastrampoline.v5.1.1+0.aarch64-apple-darwin.tar.gz/md5/a6475f23420c26d97b1baf1e37cc13b5 -libblastrampoline.v5.1.1+0.aarch64-apple-darwin.tar.gz/sha512/96386a4e0b57bc50cbefbb0eb75b037571e3d9ae3900122bb8d4f7f14db017b9e8a6dd2eceff07c9880dda2e072b89df7d21432fd5a08bef87a282cfc3bfbb82 -libblastrampoline.v5.1.1+0.aarch64-linux-gnu.tar.gz/md5/c28450dc1999d9304414288b267d72f2 -libblastrampoline.v5.1.1+0.aarch64-linux-gnu.tar.gz/sha512/19303d32b316cbce29f93dfb713987d6567946262158f1aa5f447a86197843d2875915fc6282264f49747237844f8cf32f9e5b2a0d6f67d514474823e7929de5 -libblastrampoline.v5.1.1+0.aarch64-linux-musl.tar.gz/md5/a40854c55588b88c57994fc8e3d3247a -libblastrampoline.v5.1.1+0.aarch64-linux-musl.tar.gz/sha512/c2fbc67fd8ab61bc854722949ac87d19fb7ae3e732f01e9ed855204605ef1b2756db4272688807a9928eba3cfe949099a3e74ea68c432219c023216d82e44b1b -libblastrampoline.v5.1.1+0.armv6l-linux-gnueabihf.tar.gz/md5/2d564a40dafc6e3001bcb13f2460306a -libblastrampoline.v5.1.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/2ba59a5ea48bb4e9fafc5a34b8bc09fda9f4aa15917e41a87410d888ff69832fbd54a6ed6a401e0686dd2fd46e90603969ee42497691270921cf5688c8a1d2f7 -libblastrampoline.v5.1.1+0.armv6l-linux-musleabihf.tar.gz/md5/41cd8967ea13f76301e2760ce20b16b9 -libblastrampoline.v5.1.1+0.armv6l-linux-musleabihf.tar.gz/sha512/40f69ae9e352215e8faa65ca8451d5850090cafc3b71207df2f588ebd06d247fab4af02a544e5389a9e5a89a38d5a89f71ad8d1bf7bc695d9cf8903e9654ac87 -libblastrampoline.v5.1.1+0.armv7l-linux-gnueabihf.tar.gz/md5/a689ed70eba7f191a32508c5e266952a -libblastrampoline.v5.1.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/47e5e1f1ef3f7dbf22c48bc9a09c0abb5abb967885c288c74b51249a22aab0cf475887e612f219e5abb905eab3018d5b5225682bfcc908debd6ff8d509e1a23c -libblastrampoline.v5.1.1+0.armv7l-linux-musleabihf.tar.gz/md5/ed08534ca3f065d391c2484c5fe6fd6b -libblastrampoline.v5.1.1+0.armv7l-linux-musleabihf.tar.gz/sha512/014d10a154ce3d35dd428dae52d4d52445d1cc1d501aed5f490332b663438a000b02992946b0ce18bf2e829339a35e163f684568f3484c83ca4f8584da4cc405 -libblastrampoline.v5.1.1+0.i686-linux-gnu.tar.gz/md5/b5f315c6e3b719991f4750d0451ac13b -libblastrampoline.v5.1.1+0.i686-linux-gnu.tar.gz/sha512/b67a478b532b664c1729a151d62f070308806476a2ca38bde3d20648676f1ed7f41ada42650641f98eb165beba984d40ddbe667b49b99213321c54d72c2f0f81 -libblastrampoline.v5.1.1+0.i686-linux-musl.tar.gz/md5/69b0b2128c7b482bc6f7b769d30322cc -libblastrampoline.v5.1.1+0.i686-linux-musl.tar.gz/sha512/97621e6f17deb137ba63af5a413efa67bc60ccd6a6776ff6fad8b1393e8a4b9a4586b5a4015471a64314b85e81e8421d5fa85b55f7bc48f4affd30d89a5d4082 -libblastrampoline.v5.1.1+0.i686-w64-mingw32.tar.gz/md5/b16bdd51b0d3336bca03374cd23884da -libblastrampoline.v5.1.1+0.i686-w64-mingw32.tar.gz/sha512/f323fae462a4d1210fbab1f6b253224b385c5a3c5e259cd4ce57fc4f77ba53293b8f14a3cd9db1f7c8ee2dab461aa36d62a8ec8e9693f3c257b8401de6550cc1 -libblastrampoline.v5.1.1+0.powerpc64le-linux-gnu.tar.gz/md5/d8f0d6980b97ae48a9d97dbfa28e6d1c -libblastrampoline.v5.1.1+0.powerpc64le-linux-gnu.tar.gz/sha512/f1137c5357153c0c309277d39398c2338297be73de995ae083397da5c170c4b1bec6939b6e160601b98ea40c42f9b563ac5ac1625341cde1ece6b1b5f5ec01f5 -libblastrampoline.v5.1.1+0.x86_64-apple-darwin.tar.gz/md5/088b8d27b76be56fcd7ed4383e5912d3 -libblastrampoline.v5.1.1+0.x86_64-apple-darwin.tar.gz/sha512/52741282b55f1ee0ded1aa63e4313a84be0862209f8a4439ef2076a03010c0d91083ca35cacbf187de77817ad864625a3dfd2769881764e3d9434ae387405778 -libblastrampoline.v5.1.1+0.x86_64-linux-gnu.tar.gz/md5/562215ad47d93c83c6587051ef201f0c -libblastrampoline.v5.1.1+0.x86_64-linux-gnu.tar.gz/sha512/9217f6afa0f3ef534c361fc09d14bfdf8322a8942c5e2ca0fc9234839e48d56339f03126aa9706b2ef067f88433d79f7d6f8824bb5763b99f64ef42919c3ab0b -libblastrampoline.v5.1.1+0.x86_64-linux-musl.tar.gz/md5/bd9b17ebc05ae50fc125c3cf1df8f990 -libblastrampoline.v5.1.1+0.x86_64-linux-musl.tar.gz/sha512/68b0ea95d404508038ca84b426c3ec02ae98b129e92a0f661766ab08bf38750f92a8aa41c53327bc2f6787b42504025011eaf79bb98febace4c41e628caf2094 -libblastrampoline.v5.1.1+0.x86_64-unknown-freebsd.tar.gz/md5/0308d4a7312bacc62446438f4d4b6894 -libblastrampoline.v5.1.1+0.x86_64-unknown-freebsd.tar.gz/sha512/d4085d81e85b9c1ffefd5a6147deea9f04436e1145eca73e5b63dba048aeaab9c497df725dc3104a77c834597363b7205ef7270f96ae94f06c950f7574e25d07 -libblastrampoline.v5.1.1+0.x86_64-w64-mingw32.tar.gz/md5/2a883d986c884be08ef332bcdc3ab52e -libblastrampoline.v5.1.1+0.x86_64-w64-mingw32.tar.gz/sha512/dacbcbe09910b7965448b22f3dbd55945bbe22d06c60a92d2c97da83f0b08d00278ff870eada470213fe22fa3c8acfcc0be8b753a885d98898d048e896c909ad +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 diff --git a/deps/checksums/clang b/deps/checksums/clang index 3b9c1210d73f1..3cb8e59b6791a 100644 --- a/deps/checksums/clang +++ b/deps/checksums/clang @@ -1,116 +1,116 @@ -Clang.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/6b348a17486a0341ce5d29b46676ffe9 -Clang.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/0a136ee170831c5c8f94b817560e62cb6e74cc45bdff25628249adce6e9c92554348fbfad5a015b0bccd7d455d6cfa96205529c5557d9a9918b5937246f91c80 -Clang.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.tar.gz/md5/6cb40666812420e480be0e852d0afcd1 -Clang.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.tar.gz/sha512/e9371fe5d4b74301d56f90910d996571ad40f9fd4c516a1153d171b0b7195ea4483700f37a0ed5dce8e4a134ead82017b19caf7f0283dbb832667ea465e70a60 -Clang.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/c39b5813f31efde2643a2f1fcfff0712 -Clang.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/921a18a32b2d816b0a7fa64df603a2d6ac4dd7eef38be1a6251e521869cce44637a8df79f2f20064a60135e7b648cc9be72f49e1ed09a7b104149e97adebf398 -Clang.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/ff04b2f629fbfe52c0bfcf1c01c1e899 -Clang.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/9038dadfbc21973c12ecbb2ae87598bf7c288b2c663f2d46395a481e66d76f2b892ac0b322d2b303e779d0350732aa62782401b340b95ff5581af578af1bd938 -Clang.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/efd9661ceffd24d140ce673e273541db -Clang.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/df0d28e126d4a9a635ca036ffd4379f6d6025a5e59e684f7889510655436ec66b335bb6bb5b57a62eef418443a27404ea2a904e366b591bcd155128b743ff958 -Clang.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/30ac4ddab7485ef3d4e9a16972273c00 -Clang.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/f24d6d8c9af0b383004170f831c14ca3e3c2b10d5622d195723c058254cae6711b24b849cda001887ec9e984a66cc72facac032456c3302f6dc681f79607e2e9 -Clang.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/dd663eebde360c4f9ce38b5379549582 -Clang.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/3ab857dfac603bddaa430a8210dc16f05d8a3e4a9cdd72ebd007c995fa3380eec0b5e9421372b1fd17dcd438ef283ad7583e006a28b99f693d2028e5f7701c90 -Clang.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/0b5d792aa94c2a33688a5c5ed71f790d -Clang.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/e450a439c065322c3320a1a11eadf9e607139ae813e75e6b3f775016b8f24eb61d6beeef4f6d0ec55aa5b5ec5eb217ca38b2c18c0ca274030c7834024de82b14 -Clang.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/c81da32893f11dc7ff9e955fa7631bcc -Clang.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/c016f7c29206f3faeabb2d3e18433f8b994e3040c41ab221628e5c26dc64d5068ef7100ecc035bae821718ded60ac628dd92d968d67e957ae01cc7129ff8e47b -Clang.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/51b94d2d6ae77d7bc09e9660f469e61f -Clang.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/fcf9b4dfac45999ad342100e76a9da4eb25e7cdddff1bba8871522300679d74fc033421cac3e2d86347cd78252fc03f7fecff86f1d9d9e673ee88e58b9ef53e2 -Clang.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/65d16924c1ac4f5a4193b4c4df19015a -Clang.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/fae2b3f4268f167124d359c3eb18c5686859e50e9b438b583ce89c3e9d3db43143479c6d39bd1e66789d06d964d91d11d4970ee7f28655e644b2cecbf40722c4 -Clang.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/81816305c782f9af31bab7119af32950 -Clang.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/4c0fe2d65d0943e9cc5402a386665037c5c0feb6152389c9910d96ebe64fa14f8d5d92a96066783ef782210ffa8c411dcf62b521067c33a3a34ad49a22c75ddb -Clang.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/23a56e77348f0ae60149ffdc8a983d85 -Clang.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/b0cc6d1acbf202cec1ce09b00d45894020f735e655740511af8c19eca78e2121130c9026192b2b54bf4c68f01db9548fd9f6905a62196d09668513776dd074ff -Clang.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/3a5ffdc6c2e6dd0d9d88af425993acea -Clang.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/f031b1d65472d388280a58dd7ecc75e65de73b1d324dc03c3521a3ada64f87f53d9c54816132468c996139b7043c762eb38999e6adb84d880be479065adab1d4 -Clang.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/12525f36fbc291df84db549e4daf385f -Clang.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/bd693fd7cd61df4c3af3ae37e3765cf1fca2e1bcc7c7e3e72497baed8a671d77c7d0bf9d9279d336ed7321b80b16a2a2bf976078aa023d4abba2a46c1d2cec37 -Clang.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/96307b773837849115b6cc399a832767 -Clang.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/684e45564f8fa7539249607b9b8ec63adc21e06678933e0aacf891729ccf449face0abb9c897c6076d1f262ba5f9b784048258342336ef93c89bdf0fa480a656 -Clang.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/c2824237dd39ad3163fbdc58250a42e7 -Clang.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/eacb660fdfe4127607f6fc867bbb09b30182ac6d0d0ef7258b0ceccdfc3199a0ae5c1b61192346adbf9956f751a6f0181ecc42cf0945d366c03c625c957b5f99 -Clang.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/24f878973b45178ebbeb09ceca56e96f -Clang.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/d1daeddccc5ffcbb869778171d5ac87e30793e04bbae0bc25c3ce41ca16e1b2161f1cc98e15b81a6cdee4fbf5433f02c698628e8a7401b3ce36982e798b62f36 -Clang.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/9945e9b6104a402df030f3412bc642e0 -Clang.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/c1b9764908bc61fd6ea9a17db70388d1cc0c0f75797ce1be8d07a24784cfedde8553b5dc5606d5c395e3385da5afa0abb607cca0a7deeed8eb6ff5818e8edfe2 -Clang.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/1a6f00390e04a56cb89f7f1afb9abba6 -Clang.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/e9e4bec30cd77cfba29b9258ddfa5994d312750b901a91fca0fbfc6bc66f3c4df19cb609149755306c650dc4f3c815cd44dbb83db5ef61fb0d2fc31c6fcf27e8 -Clang.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/a2ac0220a521ab80718b2cfbc2d35d4c -Clang.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/f618c040d5fd18efff280e4da6a8fcb343732cb6beff93f868a7735c4b88fb38ed6b6f09aac598db876aacd1f1e5379d134d30e604e0af1c37aaac29f8b725a3 -Clang.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/25dfb136ef52be7f1147dcedfb622b96 -Clang.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/2d291b8100a17b992bd88963bf211d61948f13130af868ce63da08f6c224e9f2f4b5aca69ed212f4b8795d830d1e03562997f57bb1dfa13e23e8c606e63a5b05 -Clang.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/fbd4ddda6f632de4af29d765b2ee91f0 -Clang.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/83a6038e248b3639a5f9b5621d269103f2baeef86ba32c47787e9c8125e04af9e573653f3ff870856c7bc71afc30ec7598b6d6e503d0994b8a2d6597802a4a72 -Clang.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/6b94bc6e9dab2a70dcd7282cc39ad191 -Clang.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/14fdccdc50bab738cae3b62084726e49124616c16b8281103ee50c362270ef63014bf8d3254c9baa555397425fd26ff567013104c3adfa6e2448c7de5ee0b2e3 -Clang.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/1fe19241bd62b9ecfdf4334b9ed4e2fc -Clang.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/cfe7e01f1eabdc978107ba72b5624321d64e73a5464591db22926cc277d0c1834ac1720e9aee14c262c2e9627fb7c34541d62fef6ec9af68f094fce603f1b394 -Clang.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/5389b937980be57c27437a3f2f900d56 -Clang.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/d30ff5ed29a74a2253910c103819784bccfed0e0b49d0ab5aef77dabf71e4a217500619980d875b9160bdab82d90163000107b4757add76fa662c97badf9f966 -Clang.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/8419b95dc44b7ad5f751eda96952e5e9 -Clang.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/1807c96d89d680cb311149085623e8469454ac56a2610e97f47dd1429dadb06de19ea02918796a1c35ffbeb921b23d2d4465dc6deaa5f7e26e763d4afdd55581 -Clang.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/8860012f4b975b3848df84e08a5500e3 -Clang.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/f1f4cdad2b72494d8bf4223a4aa7da8f4e2942f0796f31cbe2676e58066c645a4ba8fb23f89929712866c899f438d803a6b92c523f4de992512de33b344e0646 -Clang.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/051bfaa5ceae32ea086bd2c72e09719c -Clang.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/3f8b92120cc14aac086da4bd8c2a77efa20884180a2864243144498173ea8076b3104588586dc5d7b563863e7a7390c0ac8ef57978a6c7a823ecff40d9da95db -Clang.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/9f16f0dae9e3dc41db7a46e20ed3f79a -Clang.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/e8378d2c55920479599c13ce7620a16b48c46d81c94dfd343d046aabd0e704a8c8a1945ad796127964b975591168bbbeb01dd32a261835f6eb085d902031fb03 -Clang.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/f8f86030559207fcf8c90d163e62fa18 -Clang.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/451beee73d75f768a85df3de916c919354bf2d014351fa29b1e59cadec847db73db98b1d37c6ba3e3066df0774b00dfde260702b2cb3ecc27dec32dda4e93783 -Clang.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.tar.gz/md5/2bb39ac53b8391ab94cc9c868333d29f -Clang.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/888237c27ae9279186241797f100a3cfc240f3b38259f6d289fa1e991516d8633c81c16147788668a9cc2eac6135e4a7b4f2159a7ff7387bb871e7f8217f0404 -Clang.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/a4b047860c7a1fb8a257dd91b2c87656 -Clang.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/05685415eb7a2b862a5124935315c91b438a4ae0bd73b9d06cbf2f03b72a98f25008fff1cc2fa36c89c367993ea222354331b1dd347f0e4d272f5d0f2af83677 -Clang.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.tar.gz/md5/8a98cb86849be3f2ad297f869dc53561 -Clang.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/5357f852a417ea6ecb2427fb337c37d721720e00e07e22ad1f7fc7fec2e62688165dc70220f031ec642758ccd27942527388ff5141ee245dcae895870b34d420 -Clang.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/eb10067716599b5917923f90f7a888eb -Clang.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/83ca40047b329208c93ee274a7c3c0db73642b8a09004f085393a613651f3503028fdd036163c68b572dec47031e7a1b28d9fefae5d37cc5561fba1941acb303 -Clang.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/545673dc4cfb337e56329117821e3717 -Clang.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/55121566bd6ab6b83f4c3313b220e7d9ce56a63107fff8165070a7e41f41527f0ad536c53a114a88139d356de4f2b52cfbfe57b9995b90da3fd9edfd1c264ade -Clang.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/3d11d3939a04a0a0c7b90ae2822ceabe -Clang.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/9a88fc418fadb960b3de4401685a1650a56f1b2e46e227b43a193d2b9679abe2f7bd5278f8975e62f48e9aa9d6d042843b78c97bef75d7960d8098d55eb53653 -Clang.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/058442685a6b3c429ebd0b6b9a2742e0 -Clang.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/df8ae6cfae9d4cdb6a9e0abf173c2b8e568e10d37dd909fbb810a39dfa5ac44df22c1951f93f0a850dbc68ca83a9fbff0ec2589dcabf76ab71ab9623b12ef818 -Clang.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/cff98d9d2260a25237c92ad577457bbe -Clang.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/2d31b8636d21f0f000961d9c34d41ff175054786b4641819c058c3d221816be8256750fa3191a4e6e1533b76d5e11fc491e43f3dc974228ae1cfceb3fb08123c -Clang.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/3eb63cb369d56d5c8d280f30c841c892 -Clang.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/902194f729e17ac8dae4c5d57d39e58d7e59730b3ba98bf6724875b032a63731f657440268a5dff94c5c7384ef15dc2e39e0778d7b84d8dbbea51a2920050a15 -Clang.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/aa66e3089b7d0647039645c12beaced5 -Clang.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/f2d4b6f7fc7b58dbb7684139650ead99fe46e1e5034fba3323e96f12f5dff1956fc195a47120317b641bc04c02e9649a56fcf43d45e456bc1404c4274fd96631 -Clang.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/7bc16298c40c0a9b114972c6610480de -Clang.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/6901d2d397890e2519c3cc56f937b221341e3eec6c9ecfecac975ac7d06222fd6a2574e301eca8fb863ec956f77f8b0c0e95e389fd1c1c6d07056023cbe22fca -Clang.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/be6bcea66978ace05e009bfe1d590ee6 -Clang.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/1cba06ceb02d20d8e19b388ae5c90bf136bb5095cdcae1b27c0c960d2b549aa05b64e59f3d004e380d1891d874eb4dc9d6a425a43ef50a6b57f0839234b79bbb -Clang.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.tar.gz/md5/99b330190daa88537ed35958ec8c4f99 -Clang.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.tar.gz/sha512/1f7d9c49f5478e7a3aec8286b7aa1f6077d5629b5370d4277cdd6f80b7ea577236ff43fe24f293a72e14641a84dad5a9ad63192169b7c28ade2adcd7a765664d -Clang.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/350edd25403a292f2b6eca1f91f5b52b -Clang.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/bbd8f8624b59e673b676a1fd102975a1aec91043ef6ec6ccedf28aee871463eca4d83e806734cbbab2b447f85e17c9b86e15ca6c8bd55bafa50f36d4bbc69a6a -Clang.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/f22125e4a1ba212fe08562a29b3cbb7d -Clang.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/90241eed7c38360ab408e6a78be99816d388994ffb066544647e0f457295d5ac2031513cce0dc1ec69f95a5779c3850184e0d7e15cf8ba38ec9252d4164aabad -Clang.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/067ad4d5aefdf1e9e89df440b1fbb051 -Clang.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/ae06851a5228ed4fec4cf5dc66f5cebb230e2c7c8fb3fa81d543f2a08c52d506349fad51d79ae66182f0aab68278cb7cb3109a267ffdf7e110dce51aced4a0ef -Clang.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/971aaea160fce64d68d32c37ae6fd863 -Clang.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/01e19e7308e6a50bf35fda31c04dc1fb4a8934ebbb6a269931b5ace4880ec1b6aaa4cc5bf122b0cb18ce30e6fc8581cabfa287a3d3e9eb528cb36aa12fb6ce08 -Clang.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/320b165946061b8564d6aa31b40715ad -Clang.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/603889c6dd5ffc5deec75c0f9c48f495453f48e27e9e2c7ad8c434c36c4ed2f8b0a831735dc1c99ec0617386b066c79309c4166e56c65d1ce9408c0b6987fc36 -Clang.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/5cc0f317469cd86392702d57f1768ae3 -Clang.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/1abe71a898caf744aaffd1c4562f650af7aae3d91b3c0f337de73e921fa63ba5d03b2910bf135752dca63e11bfcefcee32526d359b9e4e9dcda968e6fe3c8efd -Clang.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/5b7f51888a61c29747e89b2622f26818 -Clang.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/074b97f2905f055b6aab61e545417efc42fd1be925693c777b2368c7b7ccc0ad618fb5388c719c7c70c9ffacd94f299874c4b394323d1a40dc2177cef4037f81 -Clang.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/6db48866b5edce638a863724b4b15eef -Clang.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/472f90471616add503bb5ebd51090e5f0c590b1b32e5d2131fd2335793a85211ca17cc4b43f765348e64effc81c346abebb9e495b0486651a56e490acf0dd82a -Clang.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/md5/22b547e88104604c404dfd81c619bbd9 -Clang.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/sha512/48fbc5fdefbb1c8810f5ef990ea469e87f8393b30bbc88063a8c8d54d4203d1b121617d96aab03080d978ca02537ce0585941cbc72d4e7dd24ecedf455588c1b -Clang.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.tar.gz/md5/863aa1416d79961eda02bb3dfd104651 -Clang.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.tar.gz/sha512/052863f2ce7a994d32b6cec7dcbe2c0f0d22293a2d423cfd254686ec056fa0c25095777a6c572443fcece8b664808da5f545e3c9426f7a39ab9c62f3b63b943e -Clang.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/6bfb96ff317c27ef402d3148adcd6d61 -Clang.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/84d7ed38825e5d758d0220ba1ef24c57489415dbee0ad4f8474ce2dcea1cce28b621ad87890558fc620bbf60ef56e513cf682f2776a590ed48511ac9af9e01ba -Clang.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/6b9a1896ccc89f0d5cfd53f6585bc685 -Clang.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/882f3aa3635498890c3722b57127530d731e93ea488861f2aaabd32c00ed99a68ce8b113a6e671d9b0f54dbcfacfb291dd6c862ff2cac4208b25e855db2a15af -Clang.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/cd5c163a984f82c91e8563da7dc2433f -Clang.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/9e14e95a3e7442362b4e71c8d9c04408cf05f0b6ea2f7cb10ca0f006d8f4bea432f1e398205ea59fc18db7a7fd7af588e45a9c6a49f48d982b0cd5d3fb80fcfd -Clang.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/a9e07a08622f6a515a015ca80299646d -Clang.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/cb2be324c2da4f75dae7431520455e1dfd1ca3c0d63470131e2bd569d646302615be2bebb6326022d9edbc77c282f605886f9429802c9671cce6bc45f4e25c91 +Clang.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/298e05bc189e33877b76a7a6c9ed9478 +Clang.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/c460899d649982b6cc6c79ccfdebdc98257f7077e2f2f04597f86f3be98f2643400258035614ff7d434639c5861671ca1410945662d00ba1be8f3a887e2e0f59 +Clang.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.tar.gz/md5/7189c71fa493fa40253a7b0644869c55 +Clang.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.tar.gz/sha512/5bca9174562f8f1388321e501c9ae36389a7b07a112bddac3c25184b535dc5324b8c7c56f40c5b6a31772dcc87c411054d6817d9348e2d38375887c339426bdd +Clang.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/a170c242afd649b37bfe17196baa1455 +Clang.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/e77f0a8a268297d9bc7c164f7c89e351c1c839fc7ab52265552171d7d73b0c974b8a1c2ee200d7773a331293127b869d635b7cd6273e2db58bc4d60bc163296a +Clang.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/8234f867f72c39bd04cd47a4659a22a1 +Clang.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/accae8bef10e8499b86073d0d50b5dbc2accca7a5a0acccc214d55049da882d705ffa936627a339713fe1aab29e9078888fd474ee41c820316efedca1f35463e +Clang.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/42423636e6a7a726477cf86399227c88 +Clang.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/8cee8754ac597861ffd54b7a0f261efbe44ed3d3ed56711355b3c9f14a21fa0883b5665e4f55f82eabb2eea20a03ab738eaf32589322dce06f3788fbd943ee39 +Clang.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/0151cd8dcc8784154a51a333aa1dc4bd +Clang.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/b2cc6fbeb2ff4079596c09ced2b856ec7be2db64420b09f3b52b80cac1ba900967af611709834940ae3118adf82bdbcb2d5a90d8b9d5b5a1c1aded8e1b604dca +Clang.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/8ed62616ef3e1a583e9095130ebf2ce8 +Clang.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/0ffdae3ec39068e56749da47636dffc21a601df9c2bfc7421c97c6924c6107fe10d2eb641b660fde50ba5fc0a4ceb922041a0adf32cc8aa553d0ab9aa374f11f +Clang.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/a3518f44e475e1ac8b9fcd6fdf470bf3 +Clang.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/2fd3a8524f627a4d7967b6646a9ad9d973301d060883e2b488a67c2b4bb3242c44e46f78a63257cabbca000690e3659e7420173a40af6439106dc1806ce9cfa4 +Clang.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/598475afb9320f81dffd8c2af89564b8 +Clang.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/6a360ea886eca3c7a60bda7a41b305afdcef00593f7084c50a44456b1ccd079c2d6990e90c081c716eafb2c5226d880a9f1bb855e61941fa4acd0590b63dd2fd +Clang.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/22bdaa9b14a7ab40cc0de4c5fb174f20 +Clang.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/96f45265f947357cd3f79d42bc05c891570f62cfa4a84fef6c99a8db14a845a444d857d4e84985a2b741377798861e714252b61f7676269b98caa5e304e63ff6 +Clang.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/70f47a6695b81d157c87668ce3b1e453 +Clang.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/e1ef1e288aa7fad7dccc2bc4bdd0cbef0d134e97b41f85e5e85fc56e6a276beb358aecfe0d0791d745d2e3834ffba269b7bb289716d39ad3260568cc10e9b3da +Clang.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/3141a42822b55f86d0f075ded553be8a +Clang.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/cfae9ff35702119c0cc5de6cdde4640629d020512b086280c26c974b71c024f0555b910a29c95f00a9ffb602f12512f21dbaae10278dc15e6ff6546f66ad1a97 +Clang.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/8b1f2da8ec4768c9426b15cfeed00dbe +Clang.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/ca4efad2aea4339fda792e8ad3cff7ad891ff2ed4a2647d466a6aeab67d61054da79fb39c1f3bd0456226dac5eb8ef1306ff70f795e21725d3611846bdd124d3 +Clang.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/468e0f231d30f64f40866a719d281e5e +Clang.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/91e205aa53337a150d6c3c84edfb06e408aba0c39843db5c3defa18c6684055139c4c40c7714355cb6d7530d40c720a13d59e9a7f99ffbf2ee389ef090687845 +Clang.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/a4006665b5c955df38a251281429dd94 +Clang.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/f67892698dfee1861c0837b6439ad897502e3441f534b4027eb5fda6a73eda616343a8d8d8273f08b7cda0ecebf88eadeea1c2b9df96bc807767dbb455144e17 +Clang.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/6662732339b55dd2aac965b12db07969 +Clang.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/b66ca56ce67b653f903bf85a274b11077f4967946719b71a306ae249867cf22d2f22e8fe7adf67be29b4cff87ca54a8dc910aebcc8325f9188854da5907b3b2b +Clang.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/392e4b35796cd085840345d1078b6c43 +Clang.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/78aa79f0ede37280acd504ff32cad3ea862ee20118e00b65c53d6eb2c0a99d307be7961abc3e53b01a4e44a4a26541c62bc3ba6c1213f17335beee71e905f6bb +Clang.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/679b0cffef21e3e8a3ac41f9c0d1758b +Clang.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/3df8edf277753d5a27826d0614a7e359d44a48f5b086641998d9b0b1f4bf575c03cff03ff59b7dc3ca773af3b91a487755561a5964c7884896a885b40d5c40f3 +Clang.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/5a7526421f59c8626b84fbe3c7adb686 +Clang.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/ea8230025f212b081696dcdd094c7f44f86413c5b6547a31e166b05e119a82fc4afa811fb6907037c07de309f21e1b36c266a65d6f4fed49d815036ff578bcf1 +Clang.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/a385cf886ebf1036e465c54575ee45a8 +Clang.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/2c53f5c1bb19f33764c0c65d7e337fa0f96213fd98527db1680ab2f036ccdef0a51c008667892300413f7ede68b7220da9f36420c1188fb58164497aad41e22e +Clang.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/7c19b127843bfad76f981534395e9b2b +Clang.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/d5ebc8f781f1147a5e459856a2888dc0525f1f63f6f3e53599faaba20c5b6ef75ca01261c8cf8c6917178658e2f38a70720299c5bbbb316b4ef631a8129ed7d0 +Clang.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/5877d43223bb2629934394bcc803c580 +Clang.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/1ebeeb1f491463acaf12d2f1ba10220ed215df80ad79e392f99989466f34d395fdce87fa3502bfdaaca1e4feae7998d861bacd4fcfc12b5e23467d1608cc27cb +Clang.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/b277b57e63f1025bef77786400c30909 +Clang.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/fbf0eb469dd91f9d480417e86ce341215758c48adba98b4eb3b53d9321e2ed81cb551549614da722bdf62eefb8145b55d160a2563cd4523c43ff71276fd45f45 +Clang.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/d973a878a00a38fd892c9e697e4aefac +Clang.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/6557bc7ea57a09ae6dca45cf90f925983f30afabe4af597aa2a397a9a3182b61d0408bf16c4cee5ccab3907a644d6ad5542d30fa28cf3fb5b790f66f43031b91 +Clang.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/79284554223c4866f204bb7704e99bfe +Clang.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/b78b1c7234096d88f061253866300a8db94928ddb8867d9d5a03f263c32fb3ade36f77c351b04ef3ebfd07131e9dfef7afa0d81cf5cb88e87848cbea354f15ce +Clang.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/e9235c729a76570ad2a919f2c4cb2415 +Clang.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/651b512a8cae627cb30575f0907ad1488e3838fa106fe583962e8399883b5b02138e29bcfdb30456ec3e30360efce7283018005ac6352fae4e2564db3b50aac1 +Clang.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/7a7e56421b13e36ddda5119def5cf104 +Clang.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/fd45e46f44bfe2e6346e4795cd1e08bb775c243ba015394e5b9acda2fa0db704cf96191a79cd48c5bbecfc87118c6165ddc3b74f91ef1fa651e71df6f610042e +Clang.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/f59a37a860a38dbdd6f422d9eaf24642 +Clang.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/4e1eca8784e42ff1ac1fcb810579746f49bd54559ca9cb20776fb84e7e42f5fc924a975d4941c1e061b31901f3f9522fca3e8bbeac45fd8717556e5e70fb4b05 +Clang.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/e3c0338c9b592c67562afecaee5eee8e +Clang.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/0dda3627cfec247825103ce25d51457893eb699a6176151dbc0874ef1e087dcbad98790ba6400e2a8c5187b742d2e7a2671b15f3c63b9c17b9eaa8777795eb01 +Clang.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/2359790c7f6de7fbfe8208c3f3cddf34 +Clang.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/c4032bb8322f9daeb7d838ca66868bd5487242ac2e3854d47a789f17211a9255efe79e3893511099ea77f61e85550b56b8c2c3b206fb632c95527ad391584e51 +Clang.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/e8321015b108eace4abceedc289bd6fe +Clang.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/a760c2e1a6ff33225a42ee4beb566d38c78ccc333d58129635e96009ef92d8c96740e164e0305215542bdc3ae0339e698a899c7cc53c260411f1ff22b60d3dde +Clang.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.tar.gz/md5/985f7225c38a5e7f68d759b2929d3fa1 +Clang.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/f74921af797ef0d3d1ec394ce1b672b72d4b25225207f2c7f7f227f0f033647afce139f710e6d4d23d474528d9f1e223f286d0c2b1b1bdf82c38b273bacc838e +Clang.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/9ab44ae551b230e83232de13e2a63203 +Clang.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/f017dfec0f088c7e0fb714164ca4e4f73cc290e8bfc4fa1838bfb5bc8f13d2cbddc1294863febefbf83dfdabf72b6b6493cf8b816b6a7c25d6a29b658d757e80 +Clang.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.tar.gz/md5/d772e714293d4f4a49652413783ad4e4 +Clang.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/b45610cdb1907d9b1aabe6dabf2a6e7ee1e2e796caf5c62f504f17f098a61d2913b02f30570bd7ca62005276c2a2861f6eb347bc93c78e4878e433f13eb187b8 +Clang.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/a91febe6ea0dc6e45a1972084cfd9b55 +Clang.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/cbd826d9843db662e5ab74172380a7d1000822c9c5a821fcc54746909dca2fcdccc7190f723e6aca60d73fb204422c95edd01bbcbe0b355d998f84f40d899ccb +Clang.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/15dfb79ac059279303528fb9bd60417f +Clang.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/15236f71d74448a81f08e9cd9ac503e17e6e8ef679b11219f6d42b8b4a74a8fcb0093f3d3bdc36b8041ec67f1ab30754dc73bb54d498ee3ad52c519cd260cf09 +Clang.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/035734a134fd46a5fe558f264f838299 +Clang.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/2cb35b0907129d1d8d6468d8f9a981839afd829cd16fe5fb539fe50f79560e852e5f0873b577ef0827211a51b07e26bd6090c98cde24fadda58ed28735095fbc +Clang.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/262c482c5af85f15cacd7d63f645589a +Clang.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/ba70b123c105edd4ea1906f988582c8daaf0e625d645ad881976b68b98cd57717143f4b4bf35c3ca90f582ebfdc07c1ca208aa7c7aec330347f1baec74a79262 +Clang.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/935168f2b01f3fc9ab11396ed2d4a0bb +Clang.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/e602720c37e841f67ce2810908943a1bb68d59a2f17ca0ecf772de4a94880459a467fff263c15e310189c12bc573d1d3d2a0264274965d4c5f2957fd36daefee +Clang.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/76275a214835cf423b53bdb2d5d483ba +Clang.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/e231f87d73f32b9f08c1dfc5a7f6407b6a214b28c77d4604c1358ac0ffccb7391e005e4f4e88c03dc5fbe7decac6df77e5d9ec60cdfa18f47bf51c70b0ce3d32 +Clang.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/dd6eb853ba155972322f4f92cd019146 +Clang.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/c48026d655f5a8f896866299e8cbd4841bf3a1a2d00957309cbcdcf137bfd6e41bbbd8bfaae51265127e7922c3384512f6c086060e03e9bb1bcd22586969c9db +Clang.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/a8d6871f004cdca531abcd14a783f418 +Clang.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/e9e33eaa5af1485715fabf281cdf4c45f985904012db4f31a4d6ef70611a2ddecc13cc0dc4deb1ed75a6dd4da4b29b1cfae761c108f661e9df46f04ad9e011ed +Clang.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/12d3c0d8d84a41630198eb69a06651f5 +Clang.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/1ed2de110db980e6daaad2e821fba6653cf1e72ed3b69d41a423cd597eac5ac18f88cd83c2afcc000c41effd268bf8b545c292096449630ab2c091474be42261 +Clang.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.tar.gz/md5/a5b6ba0d493b4542e3c5374e982b60ab +Clang.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.tar.gz/sha512/d65a6a6adc6a47be6dbc53b1b74e8ee0065cdc5e593a99f9fe40fdb8d23741146720c89de4dad9388dab801f4797e1524a39d778400e622bb9c03f23622d0708 +Clang.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/c7f5a6766b5f9aeeeff2a10748b35627 +Clang.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/1717d54c6328fd27a87aab0f120d85c066e74cc19f6e77f57f138d75d5da02ca9fc9956e620173385b89badfad12dbb6d5b90d676d000323024060b14a4a2212 +Clang.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/3e415c55a918b9fb20e7a9159f2a302f +Clang.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/be58bacc8fcd1f0cff745d8c7e555feba3e059274925b9361005603f93348d8c2d88c7f9249bc7d422e2bce52cdb280a2f1c5dab93044235cf8959ccfb193f95 +Clang.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/65b32b4dc28112dc57a1d62f5cd8740e +Clang.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/497eb5cfc826424468b3e53af7be3c0ee9c1d7a9ee85f30660dffbc728319301373617f9f7d9d09a300132fc93df8038fe2f099846d6b55ad07263afa2334b96 +Clang.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/066451584d69234c5096edf29421a713 +Clang.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/1e3c7dd8387cc5e5e0b1bc248c6d4dd7ca67bba2c681708593f395158546a305f9f7ea9a12be35376f020c768db834a3458625abe7c7ff3edfecb3b1425506a1 +Clang.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/51d8ed30230760dc228e3f4350cf8527 +Clang.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/37b0a003eaa618782f3ecf660829a1da8ec5d06bff9bdefdc6371a99156f0ab9778cc841c03b6ed1cb6e97e66123ce9f6d91b8c260a27f55e1d5d3371869d45c +Clang.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/4cac304533ee927f818f6f2e8804c6b4 +Clang.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/7f642a1da1074683ac8023d1f2bffeb7ae06d09bbdf31d6cfaa089ba44c459f71326585fce3587f0b1c98df122f635de46b3a2dcc9cd245449e453d47dd3f0f5 +Clang.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/33daf6fbfc468f3e0b013cc43b1482ba +Clang.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/1aae2a79622e821e6a8743786a0191ccafa7fe11c71741cb8cc41029890def518d41973f74568c6d8d4a6c8e3ddb37cbb29413c79517e4cc0458c2b636f92171 +Clang.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/debb98a67dfbac8e7f57ef6ab242816e +Clang.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/ed85d0a7d880193421f132082f46facfb9750da60c7860c611c37947212b7c7bd5393899906b0e21f58d98056f8d0611dbf25e06c6d6021acb4f79a7b6956100 +Clang.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/md5/1456cf6c22c78537bd3feb556319a05a +Clang.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/sha512/0cd46d6e0e135db0f2961d614faa59b8442e56f7507f07a27675dd400078d6556060ac13ad40b55f41393ab5be6d1db027038e97d3fd32c833ca1ec64ea3dd4d +Clang.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.tar.gz/md5/8b3ae4d75b49ce372f64011af803c32d +Clang.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.tar.gz/sha512/2de4e4521887d6dc951ab29bd25cbaf5d8dbd55630b63682acfb0929ea8a378e051f61f3d1b4cad127b8f67f65848dfd5aaa2ad38dcdee39a0c3f0d0a2962dbe +Clang.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/89f575a07f9b42b659af895d66d36dc0 +Clang.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/cd3a201eedc0c685d6f11537b050bbc8aa29583391790a4d54ba8662a4ddb27574bc588bba52cac899a45733807a879d57f1caac380c0cb6401a7012602aa345 +Clang.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/5f3acbfc31fc032a18799b9738643f44 +Clang.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/ee631163849ac5b8755477c0b485b3bc9a24ca07270e68b374beb5c2ae10aab1a44586ac4f40fcab80a08a3fdccee66584688e98859bf9a07d23c1e14e4a4ca6 +Clang.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/450e2f2c49f97fbc0e18ab3e0daa183d +Clang.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/4ef4adbef50c5bb77699c8aec3f29a8faffbf5114c3b45e6530b4180e97443133d19f02358de99feed58cee37c88830c76600d2bc81fdd0318c3f41540f3190c +Clang.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/ef9b53f0fbf0a71c45277a49104a3939 +Clang.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/326db9bdc978940e36580e3478bd64473bcf157840c9d6eff67ebc1f2452e00d41acc1fa6489c7ac536b000c3c6fa2e86198077d3f95bab32d71cfde6fc1a368 diff --git a/deps/checksums/libuv b/deps/checksums/libuv index 99b328f0dc9b5..844b063287c6d 100644 --- a/deps/checksums/libuv +++ b/deps/checksums/libuv @@ -1,34 +1,34 @@ -LibUV.v2.0.1+8.aarch64-apple-darwin.tar.gz/md5/c6123b5807b457a7b171b9060bcafa19 -LibUV.v2.0.1+8.aarch64-apple-darwin.tar.gz/sha512/bfbf31fde87e8a4bbb9cde72fba98c562a66a5c64cb2a9998dce4f94cc955fd6afa0b54757682499da483baee9c78c30bd685a60ef6419d2b7383fd313f7eee3 -LibUV.v2.0.1+8.aarch64-linux-gnu.tar.gz/md5/97274d22abb4c3674508732907d74b47 -LibUV.v2.0.1+8.aarch64-linux-gnu.tar.gz/sha512/2adbfaaf690d928b7d32b2e4d48a53c4ffdd94cb699db8e46d93dde496a33b29feb3f0d1c62df42b2dfaace9941a79829d54fd68900632f9cec5da71015de28f -LibUV.v2.0.1+8.aarch64-linux-musl.tar.gz/md5/0eaec69cc9b40d99c23182b7a20c4b81 -LibUV.v2.0.1+8.aarch64-linux-musl.tar.gz/sha512/224156e8fb287d45060445dbbc2dedafebee0cd44923b541c13d6688c8e8f7a86fe608fe6235c9459a2f07eac9e4b0d38577164674238f89033c3ab8c76e6e05 -LibUV.v2.0.1+8.armv6l-linux-gnueabihf.tar.gz/md5/2ddd26fac1ec25faa44be79a95ea52e0 -LibUV.v2.0.1+8.armv6l-linux-gnueabihf.tar.gz/sha512/123a1faf182e4e757b96faf2f4981f4985246780796e0be9239872dbcc76631f2d028171a6e40150b532b4840de83c36e274e9630c2474ed50e9c150efaf2dd7 -LibUV.v2.0.1+8.armv6l-linux-musleabihf.tar.gz/md5/bf474e3faa0a8dafdc3c37eef1f22133 -LibUV.v2.0.1+8.armv6l-linux-musleabihf.tar.gz/sha512/9a4e4b0af14e5e16e654033f2b77910a5004dbbd52eaad844429af7f521233a8a352d3f12e96a5d6dc6b709b578146d9bb34e12ba959b0cc111b8a6667fc88d9 -LibUV.v2.0.1+8.armv7l-linux-gnueabihf.tar.gz/md5/a10c8d87b4cc631e85d93c3e0ea0e882 -LibUV.v2.0.1+8.armv7l-linux-gnueabihf.tar.gz/sha512/65ebe30c7e14a4d72e0489cfcc299a45a6313102b540b2c245df0d098ec9c79c1037517c9a341b095912fe81c36fd6d5c308dfb090169dea76c04105c871e790 -LibUV.v2.0.1+8.armv7l-linux-musleabihf.tar.gz/md5/d77772d6330ae6692fd1295f3dfea8a8 -LibUV.v2.0.1+8.armv7l-linux-musleabihf.tar.gz/sha512/c21ab143bb5262fb09a8d457ef53f639e3040802abd128bb49b300015bba857fe3adaa0181e277b7a79ca20e02aaafc644f1297cfc18a1e1ca8af8cf1af711be -LibUV.v2.0.1+8.i686-linux-gnu.tar.gz/md5/54bb6813c26a7e0ea2518de5faa243a5 -LibUV.v2.0.1+8.i686-linux-gnu.tar.gz/sha512/cef37e6b164a66135bb5eb3742827575a41e0723fa66e037b030833461bec681054c70684d0ab3b30e52a5b0a16eb003cc9a67003652f0865b7e0d504af2e7a8 -LibUV.v2.0.1+8.i686-linux-musl.tar.gz/md5/515fbd2e524ae8bff39520fa50ebe792 -LibUV.v2.0.1+8.i686-linux-musl.tar.gz/sha512/5b5679937c4aef39fc22bb8681440a33bd53eb6115315f8b169f65a9f59d632f3d774b0cd3fe14d9a2f74db64a459f0e81ceb94648c6c464e0d275567c87dadb -LibUV.v2.0.1+8.i686-w64-mingw32.tar.gz/md5/7f0fedba47d432c48b26757348b1eb5d -LibUV.v2.0.1+8.i686-w64-mingw32.tar.gz/sha512/3d3fe9bbd210896d68d3de2748a013a59e11fa42360c186fe7a461e2aa4b8c26fa7bacd1a04cd22e86c8600b2d764cb5c66a0cacbf956df8df04aa6cf26503f7 -LibUV.v2.0.1+8.powerpc64le-linux-gnu.tar.gz/md5/feac1f65834f86b0f1aedf002431fbd4 -LibUV.v2.0.1+8.powerpc64le-linux-gnu.tar.gz/sha512/f78b55da9ee0c9cd13c4824e07d4b96f7b47dfbc2d7abc5d09210cfff3c659f46ebb3dc733f8eeb9c6464c8252927e89f76540b48cdb370dd89e8ea1eabc6cb8 -LibUV.v2.0.1+8.x86_64-apple-darwin.tar.gz/md5/930a03b3cb44a2a42ff20be4c5bb388d -LibUV.v2.0.1+8.x86_64-apple-darwin.tar.gz/sha512/5398264f42707c35cacb68ba5dab84e49efcb5571e01b16055030dd11f5b8ea4371972b419e2087a1daf9565b4b578633fce13d1e050adb23f91b7ac16ad1937 -LibUV.v2.0.1+8.x86_64-linux-gnu.tar.gz/md5/3a3346f4e91123d49bf41a124303a670 -LibUV.v2.0.1+8.x86_64-linux-gnu.tar.gz/sha512/d81951bb396e5116d80127a69546844ec99f9b19b229a0344d3f9051e2f08c13f3abb0650bc314ca5be0fc556f0a655dba960e2513de590db0bfaae4575d6f54 -LibUV.v2.0.1+8.x86_64-linux-musl.tar.gz/md5/603fec3ba7efb51be040c22803784ded -LibUV.v2.0.1+8.x86_64-linux-musl.tar.gz/sha512/345fe3f0cedf7404345d49e9eca7032787d758b3d5e2e0af2b59836a1fc2e5b71738c8389eb31738c161527a717c7f6f30af123e3a9056785bcdbcb9a1b18057 -LibUV.v2.0.1+8.x86_64-unknown-freebsd.tar.gz/md5/ec6df758c4b27a495adb97820b5a8b22 -LibUV.v2.0.1+8.x86_64-unknown-freebsd.tar.gz/sha512/16d3c39d8fd2e4c9035cff99433c5f5a9150da18fac3ed9639e22a38715ef51f30d28f83674c68be69d1305f4b53b785f3a8f89d28253fe254bd2515fc49d5ea -LibUV.v2.0.1+8.x86_64-w64-mingw32.tar.gz/md5/0dff06ff0a42ac3404f78f7eccf08f1b -LibUV.v2.0.1+8.x86_64-w64-mingw32.tar.gz/sha512/4884c6cd7c29eee725b0d9f6eab091086665b3070f3cd33854f482c9b2ec55924ab560bd5d27b46c5e0ed6a7af08bffb5beb0e75fef6aa82b4f90bd7599ee691 -libuv-3f7038d62e43c3682394a6ea7b4ccc46be0fa0bf.tar.gz/md5/fe6957e2603df688a40605134505052b -libuv-3f7038d62e43c3682394a6ea7b4ccc46be0fa0bf.tar.gz/sha512/28f13b8d927e0663bff26e9ab829538947754046088a42fc85d772d62c28fb47f8f3075d1a884bbbae6ce0ba294eb8f3b5f9cb95be14d7ae1f467b713b4a14a7 +LibUV.v2.0.1+11.aarch64-apple-darwin.tar.gz/md5/60c0a26acbd9c6d35743c19ac917f9b9 +LibUV.v2.0.1+11.aarch64-apple-darwin.tar.gz/sha512/4f62658c10486040ffe04e8e694fbcdb2a07340d8f1d18b703598141f5b377c421e06b7896dc0be8472c6c9f748ff44be109db99304b0442f10eb878bf2af1df +LibUV.v2.0.1+11.aarch64-linux-gnu.tar.gz/md5/215a204f1fb13a8d1fc9b26106814bee +LibUV.v2.0.1+11.aarch64-linux-gnu.tar.gz/sha512/3f20dc865a1ebae98ac75581585c5057b6c27bbfe084580274089f3103b4ad5fceee7dd5822b6f1cee4dfdfe027a379ea5116e37ca331845108380d6c2ecf63f +LibUV.v2.0.1+11.aarch64-linux-musl.tar.gz/md5/b618837c1c2ff1e64578ae043c0a00c3 +LibUV.v2.0.1+11.aarch64-linux-musl.tar.gz/sha512/7a82709a183977237f76cc0048034522466843d583519cec95fc7dd39cab1891b397052c6deb69b8d6fab6d0f57c91b642431b579bfb6c790881509b8daaa24c +LibUV.v2.0.1+11.armv6l-linux-gnueabihf.tar.gz/md5/f09464b716b779b6cccc8e8103313acb +LibUV.v2.0.1+11.armv6l-linux-gnueabihf.tar.gz/sha512/7c39685bbb9beb39670c94a3dea0cfac8685c9ff1116026784e68610d9314c281690f87bba918dfcc60f39e3f5c54ce432ab7365f785510be4108fa2454905dc +LibUV.v2.0.1+11.armv6l-linux-musleabihf.tar.gz/md5/6a483f49e053a1d796c2280a165e5cdd +LibUV.v2.0.1+11.armv6l-linux-musleabihf.tar.gz/sha512/16d6ade651018b20e2b465ee9beab6d6442a8d3942249a90def2797ac2b2c0376173eb9411f26cdd3f82ae9798640f819e139dd3cd70ce7e4684f6154f68fbfa +LibUV.v2.0.1+11.armv7l-linux-gnueabihf.tar.gz/md5/d3c6110ba03be6136d0c0a3740b2bc21 +LibUV.v2.0.1+11.armv7l-linux-gnueabihf.tar.gz/sha512/a41c26cd52c82804bf14d783965ebf4893db0cae7319d9840777485a328237e9f7c54aa3c2dc9a0ee39f98db430b8616de6f60906fbd00771f9a50e989e68fde +LibUV.v2.0.1+11.armv7l-linux-musleabihf.tar.gz/md5/a302e22ac3bc6d0909cd1b2a90c712ac +LibUV.v2.0.1+11.armv7l-linux-musleabihf.tar.gz/sha512/dd0291b86e11dbf7a8cf5b22f862bb0a93dcfd0d5ae009fe0c53f569d012bc2ea4895976c699aabd79ce05f4ae6161ce56263859c1994ea696e50f918fc2f51b +LibUV.v2.0.1+11.i686-linux-gnu.tar.gz/md5/d3b8cfaee74da3f4ba58c6845345ebfe +LibUV.v2.0.1+11.i686-linux-gnu.tar.gz/sha512/9623b84f6411f9b7c5a67f5e346d6661f00103a8417e22018b513efa3b8904268c57c7de21cc2f66a55727060436159f70727beed49b7efc882befd4d399332d +LibUV.v2.0.1+11.i686-linux-musl.tar.gz/md5/0e04697b85d2798c19f56e437eb55e56 +LibUV.v2.0.1+11.i686-linux-musl.tar.gz/sha512/75373bb5a5e3dd8f3fa4a85664bcfa0c651a793d8b104264eafa9626520cfb936025d4b1540c8e6d16a73468b7a1068a5ab4fb3b37762404d1ef7225a85e1664 +LibUV.v2.0.1+11.i686-w64-mingw32.tar.gz/md5/617dfd4290517837ad4c709dc4301733 +LibUV.v2.0.1+11.i686-w64-mingw32.tar.gz/sha512/7069f8bbb876ab5e2a7f0d79f4a297cd7984e1a83eadb1f91f5de86afc951b38e5bf2641883a4b7f327eabbc2f25434453b855ff7d537d30cc5ae6c8a00341d4 +LibUV.v2.0.1+11.powerpc64le-linux-gnu.tar.gz/md5/70f16a63097a353fa45971d3e4313da4 +LibUV.v2.0.1+11.powerpc64le-linux-gnu.tar.gz/sha512/ecc9f39fef7e9917dbadf4a7fd7966d06fb240f73cc2df021d9b8fa1951655d078782f17948abbfb5a21f2b7fcd9c7390af0a05610a9b952d55d53b6826ec312 +LibUV.v2.0.1+11.x86_64-apple-darwin.tar.gz/md5/17fee1aaeb6947614705120a62a21fa4 +LibUV.v2.0.1+11.x86_64-apple-darwin.tar.gz/sha512/cf4c80e797e3d68f54916bae6163d948f0a300f201f2b8209310970751d68eef6c29da571721aa98794c9ae30f7dc655385a5091c716e0402d3241342a1d9544 +LibUV.v2.0.1+11.x86_64-linux-gnu.tar.gz/md5/7e2cfbd1d4cdf2afec2ab18f0f75e812 +LibUV.v2.0.1+11.x86_64-linux-gnu.tar.gz/sha512/8551dbaf242c859010481e12864d75e8df01c69a90b94293402881b50e32105add7f7fdae455144076a2169f37e5796eb528d8ef6fc02226fbbb9d0f1bc6f6d3 +LibUV.v2.0.1+11.x86_64-linux-musl.tar.gz/md5/3879f86977865ceac0ea36e3f563be73 +LibUV.v2.0.1+11.x86_64-linux-musl.tar.gz/sha512/0831c0606e9bed4f819cb8f2abba464c9e0034533abdb5bf6e6e92b9f37644103c39adc4498db5128395dc65da28c93d7cd01bfc474985fa5dd660b04ca14cc1 +LibUV.v2.0.1+11.x86_64-unknown-freebsd.tar.gz/md5/288d9ab3dd95028568880838462c1f35 +LibUV.v2.0.1+11.x86_64-unknown-freebsd.tar.gz/sha512/ac0366d8eb4d0908d5ea55105dc608418455bc601fc22058512e228225cbd1ad2c778f7838b9d2374a6f1661e386f4121bae0f4cecaa18a4ba70a3a743318e24 +LibUV.v2.0.1+11.x86_64-w64-mingw32.tar.gz/md5/2b390151d13474968444b0f07adc92c0 +LibUV.v2.0.1+11.x86_64-w64-mingw32.tar.gz/sha512/6c56a7ab3e28ebcc7e55917b5ba051b4725ca77752b5206f865b306e905d119170cd0bb4e117c7352a95aa13b814ec5e15547ec3904615b561775a17e6993741 +libuv-e6f0e4900e195c8352f821abe2b3cffc3089547b.tar.gz/md5/c4465d7bff6610761cf37a1e8e3da08c +libuv-e6f0e4900e195c8352f821abe2b3cffc3089547b.tar.gz/sha512/3347668b2b377704f3188e8901b130e891d19ac944ab3b7c1f4939d7afa119afff7dc10feaa2a518ec4122968147e31eb8932c6dfc1142a58a4828488f343191 diff --git a/deps/checksums/lld b/deps/checksums/lld index 230f499a9e0e2..588522e1cdb62 100644 --- a/deps/checksums/lld +++ b/deps/checksums/lld @@ -1,116 +1,116 @@ -LLD.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/8c0016fc3456a734169bf24aa11bdfc5 -LLD.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/9e8497beb3b472e458e00608ca5d40bb366a0f6c4fbb5a063d4b284ef4707faac1587014a373990b10f759f3162a62f5b237ceef57d2c1700bd28f547d95965e -LLD.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.tar.gz/md5/3da8ca68c84ac618660ab8668c63582c -LLD.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.tar.gz/sha512/4fc102cb31475b10d9bff8d9896d5cff117ad60c657c8e5bf0c66fd2bdf8e67604d044a183c77d6d53fe9ca8b6d1ec7e5fd1aff837f0ca2377d27c62648eddae -LLD.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/633d14891f40cb9b58ee7bde0f5b9f1d -LLD.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/338a63a3b31f5a04aafbd57405045ff464ddc3f71360df13b6e6910a344f68159f6e59ff7df27b740bd936e9b2ea49cf6ca21b06bb69d720a1d27d88d44987ba -LLD.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/055b955d19b96fbca731017cfa7eb73e -LLD.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/cbabf2ba59b157e7527bb6482211d1870237b2b557fa187a160397061810b2729d2e990ec01245be6c2272cfbf8ba60c36d2ef4a752a94486ddb393134b6a5b2 -LLD.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/65edbd6af9e0417922d4007851face45 -LLD.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/35c19a995f77b8afede866254aee5d8cc19bb037a7bfaeefd0700428b85b3134fd523206167180afcc6894b96c34eea449c0c84201ebea261e1c2773a6e584e6 -LLD.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/5c2785601c943e7cdf3dbc76c7d9eb48 -LLD.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/788cac1ed36b3ddb657e4627ee9fcd10a59bfe839d8e8b3ef8d49bc2cd9b44f0a71988ddb8d96b64686f4ca4d7979f2e48c17a7d785125da6a1e47ee80c13d91 -LLD.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/8bdcdc8960edb1ed08b0493073deef29 -LLD.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/54ef85a02de3b4f9272587504ff9f3a6e1780b3d57a51bfbcdb8bf24df74b92891aba18aafda1a98e911304e9d8e3b3c0140dc22cafe3cf6d37ae9fa23ffea9e -LLD.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/07c152bb41599901c48735b5c2da6a56 -LLD.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/d30a6e6b1579be50b37ecf26c04db1885f838fb68f8036cddc2ad840a98b0ad1a62a965db43f4dbc5de63d00c6ad5e1bd92144e7e4d83ca0efaab995f4ac92dc -LLD.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/8787b8326cb0ae92afc01322565d219a -LLD.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/a84d70118718f433933ef4dcfdb0bd215b108bc9f038db92d4e16985557b668c1b0d70accaaa64b1a7f843c46f75eab4e98795ac1e34ee48a1b1e2b2d1c968a2 -LLD.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/8f2bbf8e2dbc0d90d027a76e6a961f7d -LLD.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/0b0405417bff2bdefde9de5309cc84b72b9d4d2a2b8244855ec995b7b6c3d493427b9564aa662b1122686064bf5eb1950cd3998173d3722d6b16b9e9eb9832a4 -LLD.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/b26e0155aad5cecf1fde8ac911306c48 -LLD.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/8dc10f854f51f889869537747e4ea41323eb321bd1ff2b8337d66a24e05534b215d90bf59881edb20bf8f6b186902f30b2119f67caeedaa6b8e98b95a263004b -LLD.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/0648cfef90754fc542c590cd077c5e6f -LLD.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/e8153e56e5a6e39cfd1f8a72148d3fd4a1c40db439a84072e614553a87a2275c66e61099583b8ab633829a40509fe52f761d7f6077baf9ddff86651bf42b8a8c -LLD.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/ddc750ef2d97f46e4e45c8b4e671543a -LLD.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/e0bbbe411fa89eb6c8bda39d9037888839795cf9e6b3a8372e86cf1076c7d5dcbb93a8e471680800b86605359f5c6a5972529cd99b41d008c50e00cd263d5e3c -LLD.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/e38753a9b2e8f4c19672c6573e8e7920 -LLD.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/f1ebcee236bdc22101e64e6adb71c44aad060968419f2e0849c4994db3f2d011b5e405a3086148e5d8c3c1158f506df27beff9fbdf2b487369dc6ba973a03134 -LLD.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/3435af737a9fbfb244331bca84c9d11d -LLD.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/9cfa3e9e86af94f1159cc3a3899ff41e8a2eb454a7218ae271e513140e08f17b3e9f8fb5a30819f3120f10b2abca624c69b01dfaa5d0e7c0395a80567978beb3 -LLD.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/cb404fa26289e4bccc0720e76c8fb078 -LLD.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/c92a9b1e217568725b479a81ad9ef0b35a74fad5a6a79ccaf19e7b4b074aea12fbc34e088fcf0b231f15ee1e1169e5f9b4e8bed94ab5fb5f7e93438702eca247 -LLD.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/9a523734040f9fba7ccdf5260e60049f -LLD.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/556cc3d916acbb137936509b25c05ccf0f1e60dc7777008a3c1b716de3c30318b0a7d3b185e201f4def73d1054ac51876a7a5f3d95b72f0f1a1dddf1e6b5ee16 -LLD.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/48b87ff6fabf1cb33b7363e0b913cd34 -LLD.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/6b3f0e0c206bed61e4ad41cf8a73aca6a810483a71a6db98cae83781aba7d35ac75a55e72c34d6ec4836059a726c713996988f3dfe225c026fc61ec076cac5e2 -LLD.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/d5fa0da63d7d3dd17e0449299497a1c5 -LLD.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/41044992cc2c43bfa5765601a40a899d63a4b44bb2c59fe551882a08e3e721856e2a4c68d90c079ddfde8545ae6b5b429942d7fefa5f37858ece94e88385aff0 -LLD.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/3eb042a2a789832122d9d4991814761f -LLD.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/903c09ce9a63ab5c8ffcfa657c640ff09dfec1c5eacafb6f1cdb4264a7ba388a829c1fd5b0c3fc519ca4bbe631cdce57908906688c92f20cc04ef6e14ba744f4 -LLD.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/7a13e91c5386e2308a84f31cd9295ebb -LLD.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/712d193701486204e30fa6dff834ffc0f7e826629badbac1fb8ea0ec96f772289d95aa7ea74e0a8e98e571a34adb3624e64da6329b560c165d5af096e989a2fa -LLD.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/91a525ca556b551e0902580465fd99e7 -LLD.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/3e1e266bcae6aca8e8c3369e19efa0d24906485a158e327591dae63ee1237cdbe2974fbd0d8bf4c6148a11c1c25a79861406a35cb94471ca43cd50e870003859 -LLD.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/75f7d46a7cd00e07cc31984689cd17ab -LLD.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/558329e1981d2e029a1062ec49bb18b328967145e5e38efee60b8c091e03cea9ea68ab8977b20d08075531e3336df9fd9f8512bcfe91196de9005e0ee14a645f -LLD.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/f7bdfd3ff9e61b5fd2a8ad06d9af611d -LLD.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/155489ebbde4ac0e12aed8e5e8cf9826dce96956d2c909a7da3708140d89357498edec91e313dccc544b671e31b0eb7af231180a069c7480f32a2f72a2f614e4 -LLD.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/30789fd05c27f647c880f69f2df0f20d -LLD.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/71c07a66faa5247ce5d390a14f5c201a6b80d47b7412b397f216ba4cd299b35e7227f486f20122e262d8f560ec1d76e64232d367c2e64f47b566c06c19969900 -LLD.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/1380b42774d9c13b0c5134f62678a8e4 -LLD.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/05512c332c53dae65176feb23e33417e40ff2778a3b77d123f58e5883253021d209a5885e45bd69c51cc9bbaf6f42673679632534103ef897610b4664beb6453 -LLD.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/258826be140b444cced264228781e948 -LLD.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/c2a28edfdbce5475837a44615e7fa06a710424d06d770cf8cbf4d10bb4767d25a3df88497b4f57b117da65510a15a4acdc9749d03aa8ec50f0e1e645130298d6 -LLD.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/f40992df694ec2cea6bd783a7b19ccbd -LLD.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/58ce6366150391afac7968509bb66b325f69c7331cded7e9c61f936d22c85c2366d03d61f4ea845d1de76eeb513205604c98ba69bbbe6892073d71bc8f0fbc5e -LLD.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/2f62cba6c73201daf6c43276bcca0744 -LLD.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/ebc66d5a287caf6c2940bce79e43c245a37a37bb3eee7c142481a4857b23d17359ec7115d20c87551bbcc8d82a1ca9d91372bc3a0b037d52938f564922e58718 -LLD.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/882caac603615101ee64b7b670c6a46b -LLD.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/a86e6fb28e6fc936caef4c73e4686f7adb1161ac55a90669663c4674c771830d4c0728c13b9fd22a5601b3bc251d8ad407b2a1cbee6bf1b6af6bf53ee32dd67b -LLD.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/e3c0e1bbbe0774f932d53fe1c4d9573b -LLD.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/9dda268461e0fb2ad84bd40ac780cc9214ebd4237b4cdd3004a73d489a1f6e83384975e93301604209f8e4642828c73c4a71b61c82fe424edb3d5596d6f133d1 -LLD.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.tar.gz/md5/90d7ade44ba297e6b3721712240a8955 -LLD.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/206ac75651e0d5d862a79564d7ae5357419c56ba621530d4eaf40fb4e95b30a780066348d53bd879149939dd8b07d8b9abe734f0a9cdae2ed61166a8e084f460 -LLD.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/e94a9a5d81b1c4dc8409dfd4134b03ae -LLD.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/4abf942bf6615aff9168468037a4e1bd22c52c979d3869b6e7bf3049c10ffafbe729159983cc340cf5505060da8c352c517ed429978962f270a1fa6469c98b5f -LLD.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.tar.gz/md5/b81db5633a1447d15f7f2985cba01802 -LLD.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/90dd363eccd0c59047b67af8c6bc5496db6cbacc6f91b37fdf3f03814cd8711a3ccc08ac7a1c38d5f1e2397082572b54be55f0900f40d2e026f7c4123547d98b -LLD.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/cc6e74bebe78565d230cfdf5b0196579 -LLD.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/0a715195926640ce6fae478f1ad3e8f50f1071c0dc5303610c0515da9c66c2604bf07c322a98e7085a8f7b42f6923118b644e11f35ad9da33fd854787e0cd7c4 -LLD.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/ee62c3e2744fb7a14fd7011adada8cb0 -LLD.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/afe03d46d4174ce7f43786f34d6e6842183a72ba04e0658d0bc38c23c0d17761f79f392b80d70a49e6138584ae5aa8d5668420e16f6f38460dd505b763578886 -LLD.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/5763a00670b797e5b0c6ed2548792d6c -LLD.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/3c84c0e5b6ddf1e34f2a755175df2152d3daa1cbcaa53910081ee9a23d7f998ef1b476d232fcd27ad485c8d687b1adec253323faadb555041d9ef35853204691 -LLD.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/06c8a03d9c9393498340646f817addc8 -LLD.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/1058f00d2571f11a3084c2861ff0822df969c82a7f82a517c0d704568667d67c3f93cac5b17ad48bbcfe62cca15199033f0c9de3d48dffe5df80c6ccef2bf7b2 -LLD.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/e62195d4962e6a6d502c6856be1d3688 -LLD.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/72ffab279fe535cd2c0a8ea40afae73abb90ae0e3824812dc1b716ffa6038ad8b26eaef69d06b6b3c29687e901c14ef534ee6c64bb5a4390646b4c704c675d52 -LLD.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/719ef46fcf4ad428a52d7dcb051d9e41 -LLD.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/ce89e0cc4a5d841d6d97f6d80bdf5336fef56328e618a38e880f7dace01d0bf9ada73e5eaa821f884a1a505d6353672b86ba90fccdfd095dcdc0ac93f35949fc -LLD.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/ad2f242f1df03516ebe98e4dd8f90abd -LLD.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/c2c6a3b8f7dfdb7652b80f95c9eac85d74e6a94e814337a6d6ae9ca2c33b47c90aab63171550a043c523a09d0f6eea9f2341ebc3708cafdb184a04588b0bc5c1 -LLD.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/a6280227759f48538a6bcf9666502a14 -LLD.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/2e3d5a541ad42f3558dc0a8f9112f61bb7c06ed2d4a1aa6f8e3611841e7e2874add76cc88fa8b76b3e491a1c1dc9a8ed1939f6931d334731c5d7c4e1a6b083e4 -LLD.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/8248779068eddc7e43978e71e76977b8 -LLD.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/feb45385c8ca2df0bde4d8ff409f70bed3512ffdbbfc07b769a68c324a5296354f35163ac92b980632e7cf17c4169c22ac9e64a5c6f0e6d58ee028ff95e0314e -LLD.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.tar.gz/md5/155546aa504931073f59a8a63b3e7ebd -LLD.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.tar.gz/sha512/9263c32e0761104011be32bd333325da5a8c2bf4f2448fd8a8117fc0ffb7a85cbd93f18849767f2ffee561476d2e249621128bc98dd0c50b0973ab3829cf1c7d -LLD.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/76cfa361fe1f4719dbb70f0e14780521 -LLD.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/9461db4f7825701c1aaf0c71ca34f8ccbb5389c5af04651454160bbc2f3051710efe689ee3d09790e12d4a3daaa8ae98e5c12785e31b776037d727b8364c1255 -LLD.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/757d098a263dba872eb595b5718a3e63 -LLD.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/625bbc787a9efb2bf455eb98ea2e41c9d6479ee0b5b009fe16194451fa95ffee2f9e82e12d1aeb7fa0ec0b314c5d7c0d533fd750e7f6dc51b12a00182b3e7be8 -LLD.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/1d011209db860a6a37ddd9a7c5a82378 -LLD.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/85e08dd3067f6cf6620ad20cacbefd474a49465588261975f122dd32fb629dac36c72dc10f632a9988878c0ccdd27af76ac6056e8d14c6beb4cf15ebba1841a4 -LLD.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/dd57f567e35654be4bd26ceeb4b0a468 -LLD.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/f42e7c4c4bc17eced803643499a89e07107175d5c244dbd998bfc7acba34dc7546bf94fc34c71fc291bff4fe731213306a1a3ecd4e8bad7f5d94fe4d413fb014 -LLD.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/4a38b8dae3c80ba6154c25273ae08101 -LLD.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/1fb2f40b209eb903578d7d6b2527ba124baa0219c517c4fb573645fdfaa61b2abd27926a4c0b32da9c40202df68c543dbcf9e53de5948446b8f589c1feed35c1 -LLD.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/eb668ceb4878a4747ef95337f20c7e6c -LLD.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/10eb872f0cdf72b1a206c8a08a6f9289a2205bd468cae802a7606f406cd20011b6149db2dafa944582b3a4a6746030d43d9e3cf1cf9a25a42db7de56f21831d6 -LLD.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/4ed84dc932b5e6e65d22c5e8e5c83ab9 -LLD.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/8c3db5d56afffb136b206ed5e1f9ee60814d441013c5d0996783fcce7052fedbd2efccbacd7b6bafbe4536020e52a1e5bf2b026ff52bd380203760e2a6f03b7c -LLD.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/91aa6ae667d0e1f3f44587619b3762ff -LLD.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/9c45d4a295f6a1a7ec7e855673977773f1617e6d880708eb7f6c5fdb505d8849538f59e1c92f383530bb8c5c1ed438be442f50df9f157242cb493614d423d6eb -LLD.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/md5/9344e0cae0899f671173bf2c5121ba62 -LLD.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/sha512/879858cce846728465c96f3edfd00bc0d0646236d08ee7ec0d2f7566ccd1ffab73d4cb820d2724374c39556122ca0c3defb4ff1c5be9b1ff85a9cdd8d1f2bfdf -LLD.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.tar.gz/md5/378f8b32cca5d88eb029598ebaf3076f -LLD.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.tar.gz/sha512/2fb6c177a1009d0e09119888f7785e041ba3fb023a55d66eeec643bab01db60c4ddf6f026637ada6cbc69544ef3ab30922cc978ef4c60077dc813f6fe951cbb5 -LLD.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/a107c199ef47fa47d4e0fd4c86f057ea -LLD.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/ad212fcc21e421da9b90af5fb8f547127eb7ab477f8ac816543410411ef227421c0aadb49cf944babe5dec22d24468953fe5e52e797c59669c78dd0630dc72ed -LLD.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/d3360e9403172778432fff5d650b0159 -LLD.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/503dc5eb26364522a6a49c892c8e470de7985064485a1f04ddf909184e355b679ed8410741123108156f8ea696af3be286119d816f14713cf121ea007546871b -LLD.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/2c42b2e72c6507082815457511370450 -LLD.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/99a049e1c2fb3927bf06741f8b54d6a9222d0518668c4c06f90c9d8836d8227c206d81b9c9f6bf8c56489ed4e359abfe463630e83dcd4a6c7f632716987eac74 -LLD.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/da5e8dc90a901cc405bd31a3fcb10793 -LLD.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/92b66e2f45c368ab736603c06daf520ffda444a09e80368d37d57994183f228854d84ce3efc7a2f03fa5567feb7ed3a28679a4bf42a5dcf3bd37e0b7503f6182 +LLD.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/fc262d76d2c8b848713b39fda7d55544 +LLD.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/86d584699333feeb574e9c00116a9bcfb728ecd905e983ebf02eaeded052c03a148fcaed1b655c07edaebbfb256f376f6451e1167503b235bf557836a9ddf7f1 +LLD.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.tar.gz/md5/cdf439f1bb444adc506fb844230709b7 +LLD.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.tar.gz/sha512/9cefd451e0282d9d787fb79d70430bf811297a81c045af386a0b685f34627a31631d036d1b67dd32360dfffc51450d0498e71a03302e0cbba3e60d45cbd3112b +LLD.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/0e2d3659de3c546073a52db675b2f00d +LLD.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/6d52a3b56f3bdbb59addca2c7d4b0776f8f414191579b59938c5715b14b1d1cc1e76b873c098ce98a28bed57a0a97974805f158ec952a83551adb61dbac3891b +LLD.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/c319caffaf1ae4271e86354661eac133 +LLD.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/f908988258050f06e4022b44dc9e49fd66221abe0c205a92e0fd270705b9b78ad7892ffc9adfc69b9c2a70f955e98678ca65dbcc3ebdd748d08ec1c414e90892 +LLD.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/69fd74156fd9d4c32596f8ec8743f24f +LLD.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/04220b61f3a9a93be147a8e73f044233bda56dce7500c2225089c1fd1e64092f8af7d91b9fd41b4f347950d787194e9ecda0fa3f09e9f0dd3f1f0836d39bcc95 +LLD.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/0848225be33d9f436d6cab9fe0b1a6ca +LLD.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/d1bf4cdb1f47c28f0ceb86606cdf073141e2e5a249756bbc4fb862aa4e3476b9b6c436e994c5702019b82b773c2c3d2f0e78d22a3cdd905e159c9ff753d2619c +LLD.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/8abd66714f15f7db949da104a1ad0fa5 +LLD.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/9edb1dcb32e5133634db932dbd04d29256a4ee636e44933f63c1585113b06dfa6b38eaf87b72a4b3efd044a25f0f173083360cdd15bb964d4f8ff3b4d5125d32 +LLD.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/4c8249e6976e75c7790b8a120a57d8f8 +LLD.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/405552d7d102a393c44d3386cef9a2a85916cdcab88b52bf3918f131b860bead5f6aadefb6794a879e9ae553a6b3a6d6444bb900c33acc77c1f79d60c024e772 +LLD.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/e86955bfda5ae339a22b959d1c97b7f0 +LLD.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/0cfb78274857b1f5f34ec0407dc52a5ec6083a00d9e9b959099839d7467f5ba304dda8a974ba4f3281b66ec3aee5d7ecf0cc774f26a6d059aeca39d850cdd17e +LLD.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/b17725f5c189699eb325506325ad7cc9 +LLD.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/cf7393cb10d023c7d1a04eee85e706c383ed8fe03b66b2e6a46f5a7cd0e76ef5cf065b94e612f6b46f4e2dade6782f8f2ea2b0885fa7dad2d2c83b049b376ce4 +LLD.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/73e8e847ec3126fadec0a6ba79974ec1 +LLD.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/7daface02ef1b12bf738ecc026c33b7568b415b91c452c64125d74db24f97f640a888c313156363de30b78d2c6a2593e3b4d683783b0a63d057b58ebd2a29047 +LLD.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/d141277d0d02d820c17634331bf0a40e +LLD.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/d0e0f145852fbd971ffbab7a92c24e435c581e6945d49588701f9e930d2d16bd6bd598b638b23f473f764bc57248ee9fa5bd725c35249a298ae30063d26ab0b3 +LLD.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/bfb86c885380c9bf0430ae21c5202057 +LLD.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/f5d7fc12102e8c728adf271b2ddddc67d766d1ef7477b57f8788c218f568bf93947137c0607008e9b8e8e7ec5c4ba9cc92688b0b8a15af96b3a54574b6d9f3a3 +LLD.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/054302b380b9b91d0ddfb09426ce44d3 +LLD.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/354c10a4705fad5c32a16140eba579603c077e725c35b1085e8d99a7b766b4a732b5b26f44bf4877f7bae477543f38c2222c3e4b610e901bcf70fa54828ea4e9 +LLD.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/50f02bd884e32ec088f279f99c4536ed +LLD.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/d0094821adc5254ca279f664199c76fc4754c5b1c4d676053acbd490ce1d84808817218b5e20c0e5a07243eb62e3876ab0b5cbfd1c3e80e0b0343153f0d85bd9 +LLD.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/ceb31cf8a3315a2d1c9ec314848ae5d7 +LLD.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/c83f85f36d61076c366ced1b03009e5695b7fbf77dedafbb5efa42e8a167a7841ad6e5c946d5d614e38f259bbc564bb24edf6a041b85ac52e12a4025d9cebc0a +LLD.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/2f51541d7a59b166d5c875c14ed9b5be +LLD.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/a092db3050dbae96a8e85dc5078c13fc415bfaf68800ed8c27871a04da19ac96ed5263366bdcf3f75b42d2c329ba473f1df6a38af3d3968bd1b165f9bdb50e13 +LLD.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/f2e13021c00a2ce98de6a153a3661944 +LLD.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/b1273890b740d9a9fe194d5351b74db261b7c1077e02c02bc6be47b4e61f5b069df248c140e46f5e4a8c735503ffb84dc7ea23f673f3b0943af1667cab836381 +LLD.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/4ded55f6eae1fa6a54e5765af6b99df9 +LLD.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/772c087814ba18418357799737ebf650ea5944e9c1a8f6b4c10770cf14f3ed8ea152854532b7975f6326b81d640021a63f8e0334e64ece776e41c5741591ae52 +LLD.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/bff02de59314ad554f2fd01924a80693 +LLD.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/114519b9ee153a495bedd174b42df227e1f41375511c8a4010a06013c73a3aa5db0938d764e0e639ceb86f9f13513c6416b3291f53eadfe0e1ef5b4a93b4ca03 +LLD.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/70e16637af23ce7f6c33b061e073dafe +LLD.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/2f3afd0cf1ae8a0c0f331a9dcca0e1e69d7b49397c226f1260ed38b2b5a2d400673578be0371cbb2a028827d9e22e6a8890e34110967250ef0f0f907f63d59f2 +LLD.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/b00c58a756363edfa9bcc6e26991ec74 +LLD.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/6e5d9448272aa69ec72a201f5d4b90b0a4804f654b510c4a6d98393cad3c1b352d6bb9f47b909ecf46a8afb4fc582176f0c26c028203cfc72ed6635255a1da4a +LLD.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/955be6224e721378e90a5c78c7c0557f +LLD.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/74c4bb8419a75782721c97d4af893ae4f976ddc7b159937bd6b3a1e00aa63708a227bd02b95685d681afe2955c7bec080873b1fc1fa4507bca24a09edf7adfb1 +LLD.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/5e3394ef7debe390219a4ce95df29741 +LLD.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/17b8f0a257f857093fc70c16821797107b5b1ac62239f28998d4c355e1d0e5541628e917464ad30ffd07f4c8ec3ce262125bcbabb0d39044fad73acdf96ef1e8 +LLD.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/9de7aad1857b8fffe7bd6476b0ce881f +LLD.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/876963d34b883ddfa13e59286d08ae7a6aecdf6a35f77b0d12867435e48468b65008d8c8b1f5bd931196076fffde615971efdb3774b5c7aa68ec08b1d6f0ebf2 +LLD.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/b9ac0071ec9b36819c77529559635998 +LLD.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/c6f7112b680c80d35feb633bfba3910405b0fc0914e05fbf5cf8fad001c5868973b7269b467aa1724d6c2b15278ff54a14aa09808b26104f54eb5452e3f78c43 +LLD.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/e387441aeaecb5f587f2e1edef3717c9 +LLD.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/e9b6e42dd132eff9f539108f9329ce29821d8101879d880e7cff587d3c7982c57eecd6e33d1af18edeb18664e77e6b5bca8f62d69fad57a176f7edcd43a51adc +LLD.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/70aea168615be9cf0868e9a504b2e572 +LLD.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/1a555b1c354ee690718ce08b1f736140925b06cee1b9533962ce7eb7f6332bbdb9e25e1281423772e0fdec8d34b5b690eccb6835cf6b764ada492ab20ad5088a +LLD.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/ca1e12e88613e2fa5f70a9b932306a5a +LLD.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/e2b669f1d5f24673f85f95dc53a041c3b5a34b05f3113803f53fddc9f8637cb92867a79fc02b19ce5e6cd99f0c0a7b6d351fd68994b244c1c35a1ed7058cb0d9 +LLD.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/b6833e7ca5dbf8c46ef536ec834b8f23 +LLD.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/995915b3cf655618176a98c41b54a3345797fb5ace72771ce963644dec67060ca84ba20779b94fc4bc48e8688d1f911b20abfeb459832b279ddcfc5afc998776 +LLD.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/ca9848c652737d4119d6f2f1b83bc807 +LLD.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/465c88336259a472fa49c6ce88d7965e44aaf34d0260e38a832f27ed5b99d77d9653c2390dc12f15db549325170c59be108eb9f41f99ef88d5fae47edd538abf +LLD.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.tar.gz/md5/07c8437e8af4e120268242fe1ceee853 +LLD.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/ead33174285f85e4d8f40baf2f18c88ea51894dfac528be47db16a4885ad658ac5b92431693ef24690d9a8f7a9de7d3fdc348ea1f505e29f8e8455f1a4e57ca8 +LLD.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/13395b2c3c4077899229e5b7dec5e535 +LLD.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/a3f95af4b499f0b4426a109cafc1c9bb4fcf2a600d6aaedc8472d26aa61b04b1aaa3a801d39e165a9e7253eddca6009006e2b8030dded6e592cae7a477015d64 +LLD.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.tar.gz/md5/02f86c3d3e21b8e4de49ee5632d42c1c +LLD.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/ec796d467089ebbb0e5a6085c0f5b15e5f43247335661b22fc95d7656b860ad34bf5dcbc3d3c14898bec871347eee565c18100a872f1150d25120e25702d5613 +LLD.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/055a29a5b3e7bfc69cc4455150d2a765 +LLD.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/0a51cf1f1b1c825cf397279916a0bdda789dc9f8917a9cca70e10050bd253f286fc296725ccc17651d72c304458356c9e0c7744e85ea0961fd5a895a2300eb26 +LLD.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/357377a9b28dbe542141528ff21df505 +LLD.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/199182506961dbb552cdb7a40bd53dd613f9a15bf824d96813bfcd26e0cce1081651314211f99dbeb7145d250ee90eaad760bdfee27ce8e14cc40561ff8e3028 +LLD.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/50e1465dfdd73cb4892dbc84dc2bd407 +LLD.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/bac02215501595510bd92f59bc5d6f707a79faa360823afc82893e7eb64b42ddf035ac3083dbe37f87b3dded5c5f06269b3fdedd2ea1eca0a41738178492fa46 +LLD.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/c86e047af65383a802f9f40f0366486d +LLD.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/24dc600035ac9fc7fc94dd47e3bcb197ea64557565a962bffe683ee040a089a4f0a6618e6ff06c9225ec0961adbfc810706d016a0dab659d77d2fcc73c1e302a +LLD.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/463c8a2b34c01c1964f9090d476ee1b5 +LLD.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/a2d8da10ad2b81b9fb5563ac98e992a7500d35c4999ff51e30dabf662199b4bf47c3b8191a87c6dcbd6fd3fb7917f680ca9d9dfcab92fc66afda42d93bfe7a1c +LLD.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/02871a4b77f564a1562fd1b8766341ec +LLD.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/acf16625e34e0f686bbd02da34515ab9ad1cebbc03fc2cc4793728d153c3d30d5e684179293e0df333bec54c35c02f63b4e8b39373c4a78b4dc496cb84168953 +LLD.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/6ccd870609a949083245a0a469a256c6 +LLD.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/e79381809dfbbb457f6ab542aef7bd20e758f92c6306d8efa900f3d951cc37857170fb41d6e264d8fac903aab6b1b3c2cb6cd7b29b12db05df23a3f0136d3149 +LLD.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/a26d060376eec9f52ca65cc9117de48d +LLD.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/b7ec3789ae9afa900a332e7d545576995de14ebb31b00ef9f8d16d6f8eabdb8d35a508c283b9dc49cbd2cbf0aa99c0c081750ac9d4d80a1fbff71e044361cf72 +LLD.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/c4063d74231b368d5e4dec1f8a110187 +LLD.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/0cedd30610c042e58a91e1f4a46fc973a781a0f432292d40fd87b4907dde868574dfe7cd372d8a05f7e56e73d507b20df8c89d49b1bcb5edea161365aaed04e5 +LLD.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.tar.gz/md5/09f1070e327911a6eb38e4d7481be776 +LLD.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.tar.gz/sha512/47236e8449a479599dc03d198c28da352139cb62d08b7def13328a32b5209a29985d7f0044c74d716a3458adbeb8ce2845a760bfe3923a50a4d4eab1f832dbcf +LLD.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/214314e0359316fa00e5a770b55daacb +LLD.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/b25ef3505996442b5e4d4c20e3cd9b9fdf385b8e86a8f5598616943fc8aef8b96307206d6aa836f3f8d65818806eec6901b1d26fb339320f538e3ef7568b6859 +LLD.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/32760e37872e2353c33c175cf42fab39 +LLD.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/6b38c31a34cf4b1384f3b24cbf7e4ebb20a112465293bbb37e33bcf06d998f2ccc0393c94a95a1b39147c8e6eba84b107ae934f207aa56512f16e992a642714d +LLD.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/1e935c8f2b36fb537574c2c14baf51c6 +LLD.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/ffaeb5160830e5859b2f650d818422b80ca187f0cc43422915bdf1dc0b4ccc4b6d0cc8caaf570105ee531169fc494a6fbc9656ea4ba9f9cade8e38b7ee339fc9 +LLD.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/ceeefef634d597e201047041ac330f43 +LLD.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/f4b4ba04f2a72744f59dc26d894956f8af267e7b26a34a658fbf6ebf681b5d414775aa7137e2641ef0e9a0600269926c1a45d98d9ea2087677901c62b94cb414 +LLD.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/a9dbcac1935a74f3bb3ad3a879098ca6 +LLD.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/7975edea6954b6168de5d05f7fdd5d95bcdd3c826b5b098baff86c93928eb3d9b169b3948fd94f9194f01f859cef1f1bd3db7fb470c7296b0194c37adca1de71 +LLD.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/b9690d75d244393b4990c68ff9e4196f +LLD.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/d062cf3d89bbee1597871e2d7921cd4fef31e955434005f300a87fdb6d1245e399e417da7a1093f99ccf816f22873c517937bf7a139efce350e66a01368c0c7a +LLD.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/9c5651ed5d643dd3db02a7183453d3f6 +LLD.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/a6e99cb649cf7d6c81958ba1f2bc8460e3164e0cee4fd5a62bf62bd3040b8641b5665f0eb47933a4f13e1b1034ff6a167938088bac4b9b2eb75dc1060d53fe40 +LLD.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/6fa5219c6a38dffb193ff53d5b3a3d1d +LLD.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/f7191d625f35d8e8a147426c004b1c7bb327e3394b047478c8d003bdbcb1b2da492cfed0c71ca123fea68c500c17d10cb6f157080228ef1517d88a6a2c8103a8 +LLD.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/md5/de8e66dcda15ce77c82350a0c708358f +LLD.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/sha512/ead4dd1b926ad903c99a3ca5280397f1f866356a3c2e0c92143165593288af8e29796cc0909e72123b64c58cc522bc49703f5039f731e8805944f8bc8f318104 +LLD.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.tar.gz/md5/fb78f5da88875c423fe9c4e897db7547 +LLD.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.tar.gz/sha512/9a667f0d6d1436dcd61e6d83dbd749b5d156cea5b7286667f723d835a93db6409f5c3df3b77e8816707c8d779d9571a7ed1ad764409204a45cd4ff01df252e79 +LLD.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/ac4c0898727e017239bce35420ad80b1 +LLD.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/7e80a8b7583c28b3e92c7f0d1c8b8d5b3ffbe00d5df87e3a2c4a4877421f28e4a9b658672684d0f37164209a9e74191be687571db6c498edc902bd104bc2dc4c +LLD.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/b70020b2b3065478ae37e309cf4e9e8d +LLD.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/56b99742fc2ae442d3d3e3a80339fa016c4b6f53699798aed0351b1e6bf75c8300b18ce2e67416443f7eb8f110f98d3aefadc140d2c9f906e77b69ca349f954a +LLD.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/6ec819571dc37ca63d590bc0a3cb4e54 +LLD.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/e0acd7b407f8dd88572dab34e30d385fe23a8c98dcc4550811db5667e182f2ddbe773b992e4f83015033b0ab6c38071ffe0b6f68e0a01e8f9b9d627a233c46fe +LLD.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/0668a79e8d23e48aa5380fff43436d82 +LLD.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/bd78a518126c715861d7f27993ae26e8082452d4ad18a9d3a0fa39ef46fca8b6e98ca14ec715470161a1c9d64ee71c7ed4c815be1b3c480f1d003ed3377895d1 diff --git a/deps/checksums/llvm b/deps/checksums/llvm index 1dd4bf8d25b2a..905a88f80a2e3 100644 --- a/deps/checksums/llvm +++ b/deps/checksums/llvm @@ -1,119 +1,119 @@ -LLVM.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/0c76e71a19a34674d60b16d6e4ee05e8 -LLVM.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/a2ff10102f3d815fac59cf9deadc7fac4d80119448faa586c8b4b18065395d6c01afdb033cf4df0ee9b6a1b47cfca64a7abf3e516ba53c1b511bd3163e849b72 -LLVM.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.tar.gz/md5/d1a4470e03d01d334fef19961207f904 -LLVM.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.tar.gz/sha512/27cb2bc0ffa2c2a900d82b2a022ab08fadd51049a41e7c4384124f3206dce8ae21dd166ada134097cb62eed1cc6b126a5f1fdb05a7a6618090c1fd4f057057ed -LLVM.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/b0c4e4f118661a8067c54d942a3b5484 -LLVM.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/4c03b578fce13debcb9c41279b3e0368f7e8050e4e5706df5981990f5f7cb23a127318c832c45951ddfbdc75b30505312fe0ffa18eb78d8071b6c11ee5715001 -LLVM.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/ef2ef9ce8f464714105b110849ddaa05 -LLVM.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/ab9f5be73cafa7b25873ddd00554c954e6614ba3a89e8bab5524715a4263994ff9f2294d94bff6967649b21873d46fea39fefc05ae861df05885bb0515103dd0 -LLVM.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/1e8d31bae456e9f09bd5cc4a31dd2222 -LLVM.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/1d767fa39a244e84697b96d7f2a8b74838e42f34dc920c49dfa0b90653973dbcc3550d73e49c42da58ececf3e24081257eb3e5a3ddd03218285bada6e226c756 -LLVM.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/10256df67e8b054c3eb9265fc0bc6e4f -LLVM.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/88bdd4fef3168ed59f3d7c8863ccd7a83d8e22e885cfc0a8dc69900743b30dd3d4d1f20e1d73a1d010cb4fa8fe08e5ec0a226dfcbe4f60f67c9ee26e7778f40c -LLVM.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/c59f8d15b7b0aee8f05b948d55ec8669 -LLVM.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/f1d2cf8b039036fd55eb5b8d01d2cd18729b4a8fdbb76c76b8ec4ba7f761ec9b6b350c3dc8dcf9acc1a51419bf401fab16fe8debbab795fc170b01234b85cde3 -LLVM.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/ef5c22089fbea6a2b3c90aec0b9dde71 -LLVM.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/092de108c28788ebb49e757dcc4aa1bb049af91c37bd5b705382fb93c52e0ad8f4d068d1e344ef559c05e8f12333067c423dd175e101145754e68ec730887a4d -LLVM.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/8f273421d7315363170c4848004110cc -LLVM.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/6fd617a95efcdc9f8236e1c978a80f560ea5f079bacaee8a9f16938ee13e7d3bab3dbd6d9cbde985c9f0ace866cb2130e7196ce5c2aa29a45561fd32175f4f43 -LLVM.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/b77f7e2ebdf97535e6c51ecbef5fd15e -LLVM.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/27b351d494e2b13aad7bc32555beadf4445740a438b1965a01947dbf616249cf4b91a094b787617660f8d1e4391cd4b8d00770c0127b1c483441be6367d1151c -LLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/88cab2df0359568e5b0a1c94cd4bc232 -LLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/849e8bf2faeb6e8d9b1fc49991cdcddcdcd708b0c264134daf6793019eefff2c0f8d8fc9bcc81aa3a0af7c5e3f2879da4dfaf9b6735b4992f0b1d7b63cbe713c -LLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/2127bde6c442ecd8eb0d4803e15f2350 -LLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/dcdd9ae023bba72fc65f01eae537e34b3927e6486a4b2817a26a2ada393645747e4472dcc9df1c9d7b647d463efa2eada9338f3f996caaca26ae835f6a89006c -LLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/3dc3024b888b8950f2e4515f58932724 -LLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/35be20253565312b6536c520c003586d6437ad8001da112788a9ba521d7df58d7ebb03385fd11df7af87a77523795f84b37728433f9fa0eb9851e1634662bc73 -LLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/a75cb433050232df0121a6eee4a8f181 -LLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/f55b4d87b6297e3cc6aba4475b2faea80afb924cbbcc0a3006a85d1e1381e1fe9222c3216734692546db8ab66ed77129e963a633d9eec0b07cafc4d63ee07622 -LLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/292972ee70f04cd9d924dbf978fa2e8a -LLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/e9e8a38109d7a7e3591ea62c86cdeda0a35bd7e1bb66ea751e120025477144b335b14cebbaa7bbebfde4a6272d77fb0d7725c4affd46f50e042a01e98c95bf20 -LLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/3e858809fb4e06ef103f5168855552f1 -LLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/eeeaa836ca57af5fbf3426d2670dc1828d34f47102ac0a7e360a56649570d98d8a6d062392c69fb25c67a99001c389e5f81536e272cbe64d3645244ca60b1ec3 -LLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/1dc5de23222aa4ba4d1f47bbf95dbe9d -LLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/e7fbfda31bab79ebfba178218f7bee4adedd5876d9bd8a9a1f90e6ada5fdcf6256f91fa7bb78682f6ce21ddc690f7fa1e13a7e23d95b3c23260b724da3a31060 -LLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/dfeb1654bc02f28565d1161a944c0769 -LLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/dea0d20a138df2e6a846bb57008b7304b370c22cad62ebb8e2a35c184a7797f6e33e1b05ae9178e9220827c15d6539ea289581462d96f59379ab87aa361d48be -LLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/c5e72e611913355c3ef38a930d4303aa -LLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/44fbd792f6923c03000d5b37f9f5a64fa1dda34f0648ca4814fc5a9ba8afd44cb9d20712837a4d6913968a44a277828d0a46c3da78985f659dab55297ee3d449 -LLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/b63f687a5c91f961a3f4fcab9c0fd672 -LLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/a6c0b58d9b1d30fd447397148b2c413d2dd0e203ef9b3a7c018c0456b5558f0b45cc2a9c01ef87bb07335b23ed03add7f2fa557e1b36a38d6792a74521896965 -LLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/905c8b326ed7953e9acd9472d492d97a -LLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/39a143eb2f9a5066a756026bef2bf91de43179a3ed255d8420ef202ac4a330baa6637d6dee755bd07a1b30c0f486d1b30a9b1e9e04c4315413b581459390508a -LLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/e9d641263761ec8470bc5b0eede79f7a -LLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/480f31a162cdbd74c2ace36632b5a430549823d37250609480ae871bfbb90fa7f229606266dd30f2d12546472689e83f2ee1d2cb48e3590c101526b79a14c750 -LLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/edc201b7e4f6d4c450fbfe489a5fe11c -LLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/a8420dab1d8ad2a4a91c9bcf3563e862bbf9830fc86fda54b79840f54fcb1f76bd89267a708302539480b2e5d070028e27297d2a39a8507e8059116b918f67d3 -LLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/783e3fed63e7281f8a18e732a5c93b6b -LLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/354588e793d5a2127178a4477d01a09200a83e4d4687c6d696ecccd61df9181f42767fb997bdee44be8bb68200a4addeaf6d2ea1b63e4aadf2f43c70bfbe2fb1 -LLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/529bebf43cd44d1b7106c2aeaa18cb86 -LLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/c5b92133becc3195e60d8bff69df3aa2e63815a59af847a742cafe862caf7a76bdb615e10c20682962110fa93528d3d4019ea7281356d203e362b2a8c334ea79 -LLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/60e7e6513b72f8cce04461e1048dc005 -LLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/e3ba84c9caf7589497ac8f2ea7a9a0036895a64d0a558acf001d6741cdd3e37f9a94478b7af0f3e71c445d1e7bc006f66bcc7d0e4a1ecceac5114f9517ea63b4 -LLVM.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/bf95645be89d8399fe4897d265130207 -LLVM.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/939ef321b24fa8161c79591eb94de0b3a4b7979456eab9822f5f15772133b8676fbe845705adf51a62d294ab1966e96a377f73911b27aac4f8ad40f1b33d2ed6 -LLVM.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/e36e10322d8157829ba56b8aa5b99a69 -LLVM.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/6a9487ebd384ceba767e52c257a783fd9251f9ce549690dac36f225a4a2d0f4e429077fb68a8e04629ff8e7d9c2134933e73ca4590d9c617b0768f69eb044efa -LLVM.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/347157000cca1eef2f7d56401f0be7a4 -LLVM.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/c664e665c1955efe90a8bd56bd56674886b68e989a166e8c7b2c5bb193e72eea09722eb0a349c2be3e6df288de69ab913a3461bd5be518e75e58d243817bae53 -LLVM.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/6704e2a7d209e5b145be3d9ea0c74ec1 -LLVM.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/534617d76e709e61f97e0f4ca513cd41675eda967b917fd54fa04a9a078b23f056a4283ce22cedce774eb1130944074e630b03797a2f80510b3a84e6b02ae5b4 -LLVM.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/667e01bafb504c62c221bd4fa25c78aa -LLVM.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/f2dc5ced205f20b4cd1ce071139c3ae920a4de42908b2fe76fd260f53cdfd792d77fe34208fa8748f35429a568e3b029b887281738f8d0ec461fe66ede7703de -LLVM.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.tar.gz/md5/be3b05de2011f7c2580fb374288cf1e6 -LLVM.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/1da5e45e5ccf42e6367dd087615fafc32d8140605afd237fad6f290afc461cc1bfe2d518cd9d158c3dfa7aac16585d291d598f4c76ff33ec55317fca4b7933dd -LLVM.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/a66b362d166d7f7b8f0d6cfd80849caf -LLVM.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/057ab8545e642c99c2bd9b3a83d2a186afd274187beea0e7fa4f4d09dd52aa742eafc43ee3d1a3ee47714a5cfd52b81e84244a4dd9024c8fc0d312bc29440ab1 -LLVM.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.tar.gz/md5/645da8a4129e8e46ea6068553ed5c55f -LLVM.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/4fe7a3e2a64759eddc58d12dee35e3ec338f005d1e228194a7cf80498c3f668fc947b0a759b3c36a245beccb1d050dad6e0775749d1c815752113f7b8459179a -LLVM.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/803b19a812efb8345edb98ec4f86edc5 -LLVM.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/2075907c0e7a58420e9086639fd07eb8c3197c13a0fcbc6d2306c4f19825601f76634c286e3aef144864749de50b9851a5f7e272fc4ca52a736d58f5c066532b -LLVM.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/435649f806f37134ac1e6e7ea70fd0d0 -LLVM.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/dddcce930128f9ef274c9e395b9993a8930498ca97ef3154ff9545afea4bc694b17fa195e80b2b12580adc759ff37d6d9532c4a76e83e61f95b2601a63068de2 -LLVM.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/0ffb561e2bf17abce26ba75995b0cb27 -LLVM.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/8a7c127756f9e7af5372a85002399d9ed13712a35ce229b1c2e652a96e2364b83d531bf5c9b5074515b669a72a72a0aecc3ed3be4c5eeda6af440f2d334467b3 -LLVM.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/08e59f959b5c470695b532d1ee4af51b -LLVM.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/dce6729c536dc6ddb0e370eb52f21d99b5b4bb3c2003992ae6d9bb680a9a15eddf6fcca3cf03f47e624e50a4dd4256a6eb51a6aa59773cca78282553b10c8387 -LLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/13a027a2025374f75d35c88b6c2bac5c -LLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/2ad96dbcb650edbe61068632822a431c840989b38b2c3d679589f10dc3a51db79b769417f2f3a6cbb940a944151e71750c743304c82e448adf7638ab54bce0f6 -LLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/30b3a22c2838a716ec4effdf39b5afdd -LLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/6e365b80dbfc405bf6959ee95097a2bd387f348891722dc9ed1a3f9643576e80cdd0847fc201b964dce91ef7da707a64fc43c9ab2649da83a6c289b570ab57fe -LLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/6cf789c4993e19f4e718e30e01e9cbe0 -LLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/021363778e23cad4257bf298ee8cd986e0d2476f7d4ee13262b5227178736df576a69d70aafa5f9c784a0276dd76135d16ac7801eda74b8c908a2e14252f5861 -LLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/ca941c607ecf5441b8572649270f7a76 -LLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/d6ef6940b758a53ab5d3982f30454cc6ecc71e57125de951b31cd42399a11bb612a7d7911a3512783bb511805f4a37d14a25f8263e503f720bf1926ef1cf1694 -LLVM.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/671d4de96672fc9488ecca751efaf318 -LLVM.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/160f9e7fb22ded234b2c6256571f25b21d99569baad48aea0723bfcef1481a561f2ba61368502c2b7e716d9d0fbcd3592528fa3e14b83184eea6c8c2d15131ed -LLVM.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.tar.gz/md5/d544e7712b13260c8bc9e6937b6a3d37 -LLVM.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.tar.gz/sha512/cb87e0d4c7bf1802e67d2c27824a45955c69bca02ccd200a3b54f940e5a99a59775a141137374df1afa37a0699de21c8d82268229c16afc7e2da162aca30dc86 -LLVM.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/7f7301f4de89c4c58fb3a842541594ff -LLVM.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/9c4087a21960ea392340e0ee8be33fc550459c5890df8d2c4badee4be8b77a88a4830979aacc20d589d1ef030732c7731440331a45c1fbdea247fe18bafcad9b -LLVM.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/7fb4d43c3609f96e92eb99a86224cce6 -LLVM.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/508238cf0d109d7650f5b16dce1fda03b682ef12de1ada4f691fd72b3da8d82fd594af40c779698cbcc6f3dd8d462ec8eed8c267f850b3ee388a48e8b0772d32 -LLVM.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/6bf1d3ca75d1301448741628ec0fbcd5 -LLVM.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/a1dca79ca42dc42b3beb953ae314921646c37f2c0e151d50e4ffadc2ee8145afe8ae3f1a110ce1b73779f649cf4db1e46f03724eaee5e5915cc724997de6a09b -LLVM.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/88d2dbb17a5993969cb17cfd72249ae9 -LLVM.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/3eb5002bed0f844cf154a6503ee7076bd94aa7989341a0087924d8a211cd73b2c7ab6dab9e9bf09c4b5105a32d8ab8bc39b29f51ed44d7bb0c031242bde00b88 -LLVM.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/608113f3d254e13acdd4bdbd26e582a3 -LLVM.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/1b50f6b33915b5661140bc954d619f9e570f54e15d642d66e88fcd06c77a393d246d6556bf1c153612a05b82ac9d335a0d2ce096f77f04f48b60457ea849abf8 -LLVM.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/1798a3087f3a047f40f3a27bc0628315 -LLVM.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/252d35e5cf75b884d5cd274c7f27620e00592f038f87b3ffba83f5e98d28a306f39835be4a108f47418f5707f1f0ef80bb32264cd94cb1ed570beecc622d1513 -LLVM.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/0f39f76b4885151193d7493a52c42229 -LLVM.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/817f583ebc4bff25bdeb62e7a12c8536474f84cd77829031b8775f98927beaeacebfc8a38b505b8d0d77127a189dc417624904b85270d1185b0b56c527a97537 -LLVM.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/89ee73f869ccdf82ebba65d4bc73205d -LLVM.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/1fe90e766bc2a024f30bfe59998ec7c4b5424896dabf779e66bbf6e1b1ba624e127625943dddba30657d6c2869d8f5b2ba10fef84f59e3f7bb9c50c683d8a963 -LLVM.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/md5/72b0dfd9e3365203d2bdfbaa43f30d87 -LLVM.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/sha512/054559d7837a05389fe072d5180809da033ba20b06e493aad3c53485a78006f1e7a1d97e764243d6e98d35f15158f4593f64634c79457c56048b70b8a8cd62aa -LLVM.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.tar.gz/md5/67656fa6c09567f970d75bcdea7688e3 -LLVM.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.tar.gz/sha512/339ccf2096e4284dec118c5c894761b19c38b28c804a65ef279af74269ff7679edc4beb73bb030f52a540bc244697f5e70f5886d72b7c0eae55f756b23e274f6 -LLVM.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/3bf399051f7988c3ef75bb8f9fdfb6a0 -LLVM.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/0ec48eca8e98db4abea62d5f44da2a7a2975e6c750533a977ab83eb364cbd190a8708b5eb92305fad4962ddd908bd03d9dd78e3370f1ffa3e52b1a0a7c54b44d -LLVM.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/5de65422f1d56f8db6f57163479f78df -LLVM.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/0cbbc58ad1261779f0d6d2a81279cb6b9782c0c4100d82b32f83a296c0a009f003097c623e380bfd8f930ef02d032357a627208a9896c177724f754cced4e987 -LLVM.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/144d30f32962338e9a7f83d155dd4fcf -LLVM.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/0a6d4e7b0caf941c44b41f5ec32d128e89e8dc77aed09fbe62933683e3757d345ca96df7a0c31bd7efee925150663c4869f183238ce83a64efa22f77f6e6726c -LLVM.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/908b83a1cc9c08796716516b2921be73 -LLVM.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/07e61338e5d4a0707b6d620a661676aa6ade753fb54ddb913669990a7fff32fa380e6697d04fcddbb7f0c19b437178ee80f63b28b0ab3e58e0e8c5d9a23aee68 +LLVM.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/533cdc265cf2625457f3655b8589b43f +LLVM.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/3a0c96b2fc7c16fc33741933654a564574a5059d806a3999f0c0c0af31f99acc5948ef09edb21eae9f6d4362a7968af55781048029a875ea92a981669c6e8cda +LLVM.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.tar.gz/md5/4fbb96de11f9f64d5bc3f467a36b5584 +LLVM.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.tar.gz/sha512/bf08ae144e7fdc7f5055f98ff2a4e8d5b46670db00ed498cd3323e10df86506172ff41aa6f0815259018168bdee40a73775b962c5f0ba8639c28b18d65cbf927 +LLVM.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/73e92eaf551cc50ba8b1072ea5a177d8 +LLVM.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/691090c34cb5fe5217c44f1f7f0a411b733bd8197baab7c5cf2eadedb4a6838bd39935795a7715521c8edcf0e611c6555068b49e17c4b2465201aa1772010bab +LLVM.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/3f0783b752b25d2d47b557c3504f35fb +LLVM.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/ffce30b3286ddf0c09328b66876bf3c2f2330ec0adf5bccb4039be3f09cd55acead7c34feb6f9473892338768da4fbc3ee8589197f420d89fcfb2039ff15d889 +LLVM.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/3ec4084b5dcad58981a701fbeaab02e3 +LLVM.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/cf95a368f5a6b9ddcc368ca91631546a92ab374d9da74aa6e2036d61ac788f8348b50465c241853c37f64608bc2d067b96d17990c03ad71ce69032cc012ec433 +LLVM.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/cb4072b14022490456636e0fda20e569 +LLVM.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/1750a2be132a0db76db43b91592c5144ede76c5b205693d5eccc2fd340534fd5d90ab358a8c1af08deab8138e6c82d382e3e95c13ba027b1b92b6f955da1ced5 +LLVM.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/f2f7f1b86007e297c8827d5ab58f5c7d +LLVM.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/49a9efe8cb1352ae38169a3545ce1cb719d0f7fefc29a24b40fd3d59f99c98483ff33e869e283463f17fb63b883cca792f618296a840eeae82a5855a9dc67e86 +LLVM.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/24c659a871de64c3f8d54e7bea029e84 +LLVM.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/3e4487be7762672a4dfd5f7675945d2b640e81660153036ec2b5cf44fd278266233a94a0cfa337ec11c5b4ad6fd46f80406806bdd3a1f1eb9e3da43184af83d6 +LLVM.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/39412690e1c3da7fcf4416184feea3be +LLVM.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/142eaaf10bc19b5e786bd2f8edbab31cd5dfd6045e86c6244239fd7288b7556347adbede12cb40fff02da52295edd85c172fe17ea27126246ff4c8fec05b29d2 +LLVM.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/0fa28f8c44961f43899886a6b6b0c0dc +LLVM.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/9dae70462e8fab0fdb0cd589470bb058569c5640e60bf74e600821344561afbcbf1191e47df9d2117ff5934bf707e57e67fcb9d889e470531505bc18d996b2fa +LLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/1de340a831cbfcb7d026a77d6f91070e +LLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/a36758040ca5d84a514b4764dc60c97e4cb8ff7737d1ffeace3b9f0b0c73716ee7202672291d7bf24da03e193b52292b0c2cb74e200b2eb15b3b982c8f67c3ee +LLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/03042210289cd06ead94a0d84234d99e +LLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/7b16eff41381880a42c6c13f6241aae4184ebd9a5fd696afad4c030f815a210ef54eb877a4e375d9eaa31e53ba71594174edb4c17e60854034e190a6a6ad084f +LLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/c2de107822fb76243378e9de06278775 +LLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/e04a608ba0c7ea6bf827aef2f060241c0891908dd495dbdc675db81114f07c7ecaa27c0df630aa1118f56c71b59ec3f81e96e84336cfcf4cfc16464da0871675 +LLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/58766a44a4f74bba6204c20a6a00a10d +LLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/5776b898b4b988d1fc44a7961fd759646aad17d0f4b5a3544857183ae5e863a1f42e632cbbb7712b95fd418a2c680497ba2c23dc8fc5d6080e25ff94ae289646 +LLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/4a78da7a5b639353e61e47559072e190 +LLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/82dde74099a64b35e94f53765f2748eb65e815a7ccd51a8d288c37ecc306eded95cc4b424812e9e59f247f3f9183c3a1bc7f244ea51f2d1912445db4611c030f +LLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/c49efd85a0273ad684d13101f4dcfff3 +LLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/af25f90527744970458792697027250f543d8ab1ea068767cd1c240a251492ce33b2211e6850a7cf36f16f6b65ba11ccb799f6bbaa777fc92c51785d0188e101 +LLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/167f874b6eae226e02f32c7ac5859b2d +LLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/1a3b0b128b5b8fa26509d3b814f03ed1f1a6cfbc0017e5751761d0aa3b3821dfd4165e7687b09ba03d11c29ea533d866bc435e7187c1816405df37f897ae6d2d +LLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/29f396d657b0e5340443c71d59faf366 +LLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/d43fcdded977428b5938aaa6b6443326cee9b522ceaf5d871c0ef783773e20cd955baf95d0639db7273a8fcccaf17259b05d77a347aa6ac481c446969b436f24 +LLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/c17e06330348f30d3f74f26db2499612 +LLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/ce308261d0be8f4cdf3c639085a38779a214abfe6bfa38626810f9e99c696b133af20a592ccf9a301edd2a05a99195154a76910d8a120178764c8692ec9dc4fa +LLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/203772b8f6063cf6d8d4a7c249fba457 +LLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/ed7574ab6915db25c0b9675be8ab8db04f71cfd775626cf67142d82a2b32f73ba5e3689108bc10872863bcb6672b2cce3502e1bd941ef602559d7fe2c9d8d4e1 +LLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/6a08b5cec8c3147ba678db787fc4d2e1 +LLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/9e8c77bddb64c0bac8326750e81cecc38d54168e1d7760f69d17a1bab4b4b69305c2a75e03f5f10e40a2b2bdc0f07eb2cd5e48e3f8630722e7a30940091c7a69 +LLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/b018658105b8ff058a1c8aa04654e895 +LLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/a182645261fba4d41e89473fa18510778c236c27ac8bc5db1cebdfc1da2617e9b4b940f08045b057c271d44b9a61caee24f4204e1a98cac2c2f40284f14c3e05 +LLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/7100005784dc8202c966c4d9b0f8b4ff +LLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/f38e939bb1cdbb4d895cd8300022094e16b1940eaa450b4098c6822126e83389f52235dbbb22fa776930ef508770db074f5f378848057c693ad1690337ae43ca +LLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/4c8003cb2fac076627ec325340792f5e +LLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/cdb25936c38077b0b486821158a06a0d182e756cb7567cc9e0b0e696fcb10bc2597c41e7ae6316f4945771ddb18a03864ea2ee6ca93cd1eb737eb365933e3a4a +LLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/f6e0156ce3a0dd264668aeea0b6acfef +LLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/01c31900e79786b719d535bb1f57a36e54d56f0690361771ede98f2806fa30f825dcf6d4c176b33d73940c838d8e69440dd49180d3d29954ae02e1525ad05708 +LLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/5ed27717d90e862b22226a11bad4696c +LLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/47a8e6aadc5e736f4b78ff059c628488a685ad3d97a0ac2b8c5d048b116dd0116514399d66983f3f519e8701ea4a851986b94b17405ab31480f09acbd0edf9c0 +LLVM.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/7d154fd2adb1cba4312fa2ee20d2147c +LLVM.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/4a26b459baf5ba801ced522b4575c81328c9212cce9dbd1af233931c95c9b6d869e81964778dffb5d376dc4a258adb8f2986c868d9c90f480d6fdc021f252187 +LLVM.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/0deb9f1cb47d683fc4250071bd9490fe +LLVM.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/2717b2c15b715de323d4a7d914f191e017aaf38224e41554f60c68885b1aad625fa8fa8b3e305e8703e8772407284d03d229cb2d2f9ff219d7dbe5f91366ee9b +LLVM.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/4d9a0d826ea67ab20769999783641abc +LLVM.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/7cf33e40f6672703d88e8a0ce656e955c4a7d010b857cef89f7dc56291b1af1003c0dbb5ab32e0285260216b58e30a38cb78da28d1bf08ee66cd7a8218a835c9 +LLVM.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/54736c04b06b3e1f27673c5b552fd8de +LLVM.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/942f8f4c4191b9ab75e2a03174c0c1241c4c6af06b6f5833fd0c56d57ad195b45374af80089fdb1e2e431f9cbf256a7856ede7e8f76712e0d3189009cae5995b +LLVM.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/9738446d7d909cfaed0658cb104526b8 +LLVM.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/8c8db654a9d2da00195ec1e1beb89f10447a0a73e8d3e055b456f0f7d8e1dd90d7873ef9da2e2b27528b316b334166f2286755abb33acfc0a9eca06b23a26b0e +LLVM.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.tar.gz/md5/16134c865661a0f29d9cc693ed3d5510 +LLVM.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/173407929822c567e7841f24040b82d9981c6bf176717df6942d14ad00757871c1d2a81ccc4467abcad59a1d874d611b7cb5f0cff83898a74fed637781ae0a5e +LLVM.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/d9a7eda0ebfd108c6a1cf435674be3ba +LLVM.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/381bae57c71c387c4608de3cc8a3477b826461a8df1b98fe06259c4a595066a816e96c6731565ea1c3166377a0d9aff722a483e47c76ba01293d408f2eb3b577 +LLVM.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.tar.gz/md5/0d312cbea5545a03a49dabcf7519191b +LLVM.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/39c86e52d6298408fee6ab3de6416b710b782ec0810602ec76eb76a87facab57abdc9d8a60be9522c0665766a24ef0af8c83437493b778f028012577188572a5 +LLVM.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/bf5eb915b604825b04ca84b1ec3e9f1d +LLVM.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/0907a5bfb790c34a8acdd28aeb28ac36a6bec25210b85e2f617f7145ebd80a3d6d4718c633d45411218a5d49545c0adf69c922c19c4674b2db527ce7e7a0d084 +LLVM.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/0972a1aa6efa0accbdb1be9b799aaa6c +LLVM.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/4bcfd7cabdd5ce119cd848d8838644c8f4ff189e2998b4d3ae69193cc9c64ccffb31d08d66b2f81f86876b19266c6d2c362314f539f0612efb69b6b6df981469 +LLVM.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/df4f0d07cdf26759104686d4f36e2818 +LLVM.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/5983d1e9c1a072045c773dc438da13715faad6e0999fa9a3405821a4922ed8fab666186bf1a8dcc45743e27e5065825df8bc92a06cf3321354aaf022191f35c8 +LLVM.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/216857bad881f6a50678e2079d93f9bc +LLVM.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/17cec3034d17551eca798b6e6fc355f746ef71ce2337439b55c2f55b63f0f89168cdadfea578d7971bb1f6eb096bee47e94e34f85ae99d88e39d2052d2a51a6a +LLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/a2b9db6135bafc8f80d275d676859d13 +LLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/bb98b51aa3a3e2f4f58ab6ff0ad36536e4455a602045f811cf30e04e87efc4be4be27b905fc1716b4ed3e2971a5d9b4bd41c438541288ed4240e608adbbbddec +LLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/a3a189210c2b6e2bd32ad7ee6d353a82 +LLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/3304170ea4c369f24a99e6249401a2ed078693c9e6444a03c65dd033bd539326f0444e0ea71e4d8e84dda9cecefb46b7fba87a302365497115e4359370b5fd76 +LLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/dc0be3ad6e188d471bc1b0f7a07aba35 +LLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/0d9eef5b33ce0bd2bd6d7467d198e2f00f6c31ea0cf116491e368c78882f8437442cc18663d96f72e99fe201041d08e79d61c13b3998fdecffb1a7d6f2843a35 +LLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/2563d77bfb2317192f5cd0a00148b6cc +LLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/d0572501e91cce51d662a1a6c780adf148f34e0f4a151c1fb7bb55bc064f7f6f29a6423715f9e2332205e50f076a561ca4b0992e834b234a77f7709ab4c92786 +LLVM.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/a096186819d3f06c70d40498aafc5879 +LLVM.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/67c83539c0272d090e1a2221748eacb4fad15350bfc84f7839227d623ed234878752c38f412f0396b1dacae1543dfa9323e184b98cdec3fb9b436aa8a907bce3 +LLVM.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.tar.gz/md5/c5402ce51e61f4aa46dc56942c374746 +LLVM.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.tar.gz/sha512/f9072dab2ee52b5d8116cefbc32b023745860af644de867eef658d0fb9308d5868a5a871489c399cd95efcef9075c7a20b877933e9a243454f0819b4b0cf5213 +LLVM.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/ec70c50570a56b50df05b140f320c475 +LLVM.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/df598d58bb083634b298edc0e4e9006ebfe76029206fda10a58481be1872ea42ee441ebd3c36dd59490c66e89d9db0f610799be4b5d4c96dc315099e2f19728c +LLVM.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/4688e7cb1c73e5957e0ecd0cc14ed53e +LLVM.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/b825067f87d3bebf6e50a472ca6629cce7272579d473e36231bb2b765e509d4fd23cb899ad14489ace12f5ba8531089392d5fb9f3541351b162664eb63ab1390 +LLVM.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/d9762bedfee132f62012b31c3cc4719b +LLVM.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/29a2f8b5e4084d1c10aa15ab7d25812508233cc53c1dedac89d5951bf6488641461507fd769be6e4449fe435c17e933c6a295b00093f158dac97b92b448cb149 +LLVM.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/c68eaa7c015201a8292e1f1d8cc65fd6 +LLVM.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/ccda3083ec0246969824d8c5cfdcb965585fcd1d38306ea160024259e54a433e421d058b6ac2a924f091e0042010ee0512e51af928a6b0762bda0cdb7f99f120 +LLVM.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/853391923e6372c3ec18ff5a44c338aa +LLVM.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/166189bc0b81ca270bb017e68cdb05d4c9d1d1664bd9fd24b9bc49e14dc1d811fc6565958628a062b509f8784d42632603de31df1d4bf1b1e9ef9ab9c5656122 +LLVM.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/2907097b73dcc8d8999b1df921c4b75b +LLVM.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/6574d330914a1535b6e1be83f889c6a2cdb474e83ddf00315662a146f1e29657bddcbbf261315446f749c9859d8fc496be084f3dc56572367b0ad8d25f09f06c +LLVM.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/33e00eb48fba5be418d76f1c1d0ace78 +LLVM.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/10908824a5dda3e69aedd03d0c7695379f465b284b78681d6f8419e7304702ede9c721ae0b54169716abbed429db199450e3fba5b0e5d56e21867defd9573cc1 +LLVM.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/6f8bc1a92fe8f3e85991739fdefaf1a8 +LLVM.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/4ff992b094a6d03256b4eaeebbcbd023a22b54b49976471c16ded0542e1a79e46da43cf0346d54760cd5d18e9b3f108f42f3caa37593a6c1037bcdb4d4461923 +LLVM.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/md5/a3b82c7e8e9af0e7431d7b3a6b3e62a2 +LLVM.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/sha512/8fc9c0d2ae985d4da89734aa4b49fb368d245819c1fd4a345baf354d58a4a0b85d6390e1d6979b5ae757e29fdff58579cb7ab6388c596d9923e80d34fac4766d +LLVM.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.tar.gz/md5/9bc7eb74f530e71a3d2dca02a200363d +LLVM.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.tar.gz/sha512/3beb680621d3862f18441471cb9318d38da108bb7114423475ca67d3e8998652e4046bf7ffa40692dbb63f377c506e41d3f6c621bc3b1f88366ff0fc6cefe59a +LLVM.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/ba22b4e204e585ff18c3cb57b8e2c87d +LLVM.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/037bcf1c9e0fe5faf40c4c5f8a06b9f90fd8ea36d3649f4faa6927df8615819a2231b4393963a8f29070b0dcef6e755106b12f9cdb2a9a61610dab35fa5aa4bb +LLVM.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/e33235975b1a6ec8f69d40ae91d0e4ef +LLVM.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/1ccbddc51c6d9df883ddb75257fc42ed95c8b3d3fc99d6bbe9aba508e142865bf96678272719f60cb28a3b6f49adf68d390ec50abce47b139e6f7db653537ef0 +LLVM.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/a620552217c5b3b5318be75a3ebe31fe +LLVM.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/5703664ffe0587035cc12de3bace722e7c93cb920810a36beab49d456ddc6d285abab70172f95a83e952f5c5254dbe4825e465d2efc905c6798d7c4cb258ebea +LLVM.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/4d90ccd98213c482f202034d16442be3 +LLVM.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/ba41bc5f229e61a87f517f552fce604ef4fce17523b6b1b856ae7aeba4827f114a0eea73bf05262fd58604fad3e746c8aa54e9fb87cd97aafa50cd9d3396126b LLVMLibUnwind.v12.0.1+0.aarch64-apple-darwin.tar.gz/md5/b95ad4844e649bf46db43683b55b9f4f LLVMLibUnwind.v12.0.1+0.aarch64-apple-darwin.tar.gz/sha512/15e0996aebe6db91fe58121001aa7ea4b23685ead3c26b5d89afae34b535e34b4e801a971f4854d8e1a1fbc805cece06272470622eef863e225358113a127913 LLVMLibUnwind.v12.0.1+0.aarch64-linux-gnu.tar.gz/md5/6d8783dc9b86c9884e0877f0d8ac4167 @@ -146,123 +146,123 @@ LLVMLibUnwind.v12.0.1+0.x86_64-unknown-freebsd.tar.gz/md5/54ac594b4c8e7f261034a8 LLVMLibUnwind.v12.0.1+0.x86_64-unknown-freebsd.tar.gz/sha512/a43756afd92081e6dd7244d162862fc318b41ca110a5e8be6e4ee2d8fdfd8fb0f79961ae55e48913e055779791bd1c0ecd34fd59281fb66b3c4f24a1f44128f0 LLVMLibUnwind.v12.0.1+0.x86_64-w64-mingw32.tar.gz/md5/83cf8fc2a085a73b8af4245a82b7d32f LLVMLibUnwind.v12.0.1+0.x86_64-w64-mingw32.tar.gz/sha512/297a5c7b33bd3f57878871eccb3b9879ea5549639523a1b9db356b710cafb232906a74d668315340d60ba0c5087d3400f14ab92c3704e32e062e6b546abf7df6 -libLLVM.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/98edfd392bd87c1e4389635dcf6c9b03 -libLLVM.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/abc559339a504bb32018ab7204afb4ef20e7b95bc6124dffb45566204242b4b1300131f4ad64f51b03cfd13576c5203785209e26c64d3c82b79fcd1ce2469ae1 -libLLVM.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.tar.gz/md5/c3435bf375e6f9cf8a07264fe17a4fcb -libLLVM.v14.0.5+3.aarch64-apple-darwin-llvm_version+14.tar.gz/sha512/b5facd69b211d021333690b17832dc7812309981c3b0f09219dcecff17dce73df9a4046ace64136ea1900b518fbb87e072cf966ab1dd6be397607461281994d9 -libLLVM.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/55176f53121207d7aaf5faf15cc73498 -libLLVM.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/108fe4218d70acb25048401b5f1d3edec28822ec977d11320f0d3efdbb9227552ff13edccccd8049f31939c889c09209d0dd7f4938fc90c3c93eddd686af498c -libLLVM.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/c054098b8593c603ca8138ddd1ed7acb -libLLVM.v14.0.5+3.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/39fde9044e69af75fff847e22eac3724ecfd88f72af5cb3c98bfd2d89af5c908db128f0f459381cffed1389b596a6e125e83e9fa3597bea364ee2462b0ec3b1e -libLLVM.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/74c000d9a6bc3d532ed221d193ca8a86 -libLLVM.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/d2ded5aff1a4ab6fe7274dc75f64cb1d75ffa25bfe18488d73db442628febca2ef518aeb8aed8486a6f5ae3f8fb4ecc401391f47976eeead371cd927fd771def -libLLVM.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/29e86e90b883e46cde67f1c402155ebf -libLLVM.v14.0.5+3.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/c5cd3b1db10bedaa4f945b6f734dab54cfb6cfee49609a755aa1daab4ca952a29f7306d2c323547462c9fe400b920ba574e8d15e67fab1855bf4933151f84b56 -libLLVM.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/4ef8699f83cee4f3d6e842d6ba36f9d4 -libLLVM.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/92b3d20b643e5e9c478bdbd1d1ca8e472385b70b812ad8289d8c5cf605ec213a1c06a7f323aa04ac869be0f5e397979f1981254a58a672c890f8bf45426ca4ab -libLLVM.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/afbd401226eed8618834863cfa05d04b -libLLVM.v14.0.5+3.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/0cdcc194bf01f2e89e759b1074203a9d9a944c263818c7edf4be5ec72bb9864eaca1418f1056144a77f23fe578d368184cf840f0a6f2672713d5260e9d4a198b -libLLVM.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/a88f7b74c5d3d7a67cf9a2d4b45a0e10 -libLLVM.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/092fbe034a12494d18bc0c21b3b9d8a43034d1899d216d97a530d3f42c27706599ac3e5fd657ed46d1e8a6dde78e32c5647085b18a046578b17c00f8bca2b7bf -libLLVM.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/952a6d4749f12b1f8a14362bef24b8e2 -libLLVM.v14.0.5+3.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/d292ea3b49ee5ed7cd43ab4ddad2d326e8ff17b7ed231aa2c3b653fb49178729ad4f54693e9d54295fc27020627fe3d098083c95dff71f03b0d8682ccbcfc8d3 -libLLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/7a0b6016f18d3b50b37ff71d95400fad -libLLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/943df3aa4b25e62e90aae0a2cbca9ae85060af7407d2aab5d303878070b27636d99eeda39abedb49d3ecd69a032b4ef27da73bf829b4bafb318f2ce27357b6a4 -libLLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/5cb1f95a46295e7d7456a715ef6eac50 -libLLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/c5c2e62a53a8c0adfb1d836dde2c504379f92f091e0ebd763850ef7c0fa4ff90aed9609a2f494fd8b6480552d948a700bf8b53997fa175d78647bea59bd51505 -libLLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/411025a357d1f8bdacda85dd40984c48 -libLLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/405242c828bf90b82e34b997e5dde1131c361d640f2c3e1a9b0b6870b5120821e096eca546acfdddb0b03233e6f28fd8b09182e124d8b4556e8ef3046d721c0a -libLLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/4546ed395724295649ce9b82f5eb3101 -libLLVM.v14.0.5+3.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/8335a08f1a84d468b8c3b127b75a2863b39c1623ece869d449f41da79d2c8a24538b97233acc09fee1a6c0d03270ecc7dd6476ef3603709df0b1ba0243269a68 -libLLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/8880495fa4d6494e38953c754743d563 -libLLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/d6dcf72ff6d1321edd2675c198a62956de450a9860bce113549abd47855532bb2b7bd7975a0f7acc78c6a965189d6a056ad1d5522f6ac52a4a82cd2eb2db2b22 -libLLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/5464991f7e0ea0503bace24ca2a64e31 -libLLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/3dcf8ee623a5ace0e16b9e6ec37bdd5808639aa740ce9aaee9bd51f2d80855b33bdbfb52d38f4fe0e0eb42a749f814353a23c1e61756863706ae3afee0611d52 -libLLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/98b6d4a58baeef735e0a6faa3ad69848 -libLLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/5b17e63010b274ebac1b48804bd81bdd2f229096d164a6d2d3ddce6eef8dbab6e51e598d054d5bf70eb2109d654fa4b1558b4b700837f7d7a5d434f5a752bbe0 -libLLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/23ff52793b4c9397919735929479bcbd -libLLVM.v14.0.5+3.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/16e0d0c3cdc0581b5d80504ed358375bd527027bb9d3ee1d795eea2b4ab2467ef6eb4d960f148d5e26297eb42ab6f5e73300899a9d855c019cf932c7482e02f9 -libLLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/946cc89e0fa89c19bcfd15adfdbb7970 -libLLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/4bc0ac1d02f59611683c499371ab1c18f41a1c97ee36653ebd35f7bdb3af8e7701f2c7f5b0975d6584727e9a9e0fce8df5d2d6e1bf0fee8612a950fe47e1c060 -libLLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/0d46f869321786989a6118a82c3ea66e -libLLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/943655c29786deb0c0a19118fd2d26a8213fb030723a5ec099b841630ecf9b28e3ab2de041361f7c38cab8daa81a7e4b594aa6002fd45a38d47345cb4cd0ba5f -libLLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/9e48541f09174d8b0bf061304afa54cf -libLLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/d6696877af61426f9c76b717490839762ff3efee2a315c5a0da8a36c3110bb38140bd1e82f09612c33a2682d4d7a056ea2945e2d53a68a1937bb1497f4a60d0e -libLLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/8a44877e943b6584cc0f4e4aac6d21a4 -libLLVM.v14.0.5+3.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/f40f5210a9ecf848a13567933417f92060a1b6c6f42decbfdcd721b38cc24989deea0a2e8276ad1e5611a6e68574aa60b20344ac3f9da862a4c155468d7628c6 -libLLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/3590738ad44189751814531aa0336050 -libLLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/f7eb97571370ce5aa5949825cef3139901d7388413d33e654ac8dcfed06fb760cfbcb3d26c87cb2cd8e463bf690db0fedece6c77f270d569a5e549cf326ba84b -libLLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/0328c1d212e57289448324e5279672d4 -libLLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/8d6ecc77db25b437464930d04c6b700702fa245ca32986ecb356551ec9d27c3711195be7e688b5f76c777c08447e931364a2a0f5c652b8e74ef2e589d9dad77c -libLLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/fc6ef6cffb62cccc308f0af543d23807 -libLLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/20605f1fdfb4013f79519d03c43b6670cbdb695cf20a886f6c887711acc24f1a3d809ecb71138c9627018fb9bcff32de61a5047e02ed9d87938c002980eeeeaa -libLLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/6c12380bb7550b57cb5588d0d0f8c9ec -libLLVM.v14.0.5+3.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/96a2cbede4243f9805b7aa5140f59a87ed79ceb51870ad6ac2688fa8b99dee1994dcd36e3b4a4187b090ff89e53a4918ee142eea2585b551e1c5868fb1684141 -libLLVM.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/a059315d68524fd58c0dcf5a9769c9f9 -libLLVM.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/94aaf46334f66258f8d0b0f26d7f64d42b14902f85b734b4e5b4c89a3b2ecb0d28a7401f2631be6feb9a7dd5ed84cf0ae6772c80d4e7d2f02824fa5cdaea0b5f -libLLVM.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/8f41556d6404a2056a83731f061ba0df -libLLVM.v14.0.5+3.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/dfac5dbac822f99281d504eaf9cd16859b86640e273a50e309fcdbdd8937169485e6d80cc0cd65d1d6cb33f921147cff3a797ddecfdbdcb41355f07d30652741 -libLLVM.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/82453196fe362154bde0293929c209d3 -libLLVM.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/284621f221c14903a23d495d3df5d930c0b8669b53b5ce728f2eb6f5450ea3aef0c2f31bddaf4dee99eef664dea8e5a212d8febdaccfc87841e525acbd0d18c7 -libLLVM.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/1a34fb25985d6c2121d0b2830fb0ec21 -libLLVM.v14.0.5+3.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/f1a3f93d4c72f9d91f59d6bb34952d803d36386b3deb7909e04151a50d69eb79b3a8cb143ded8c80d02af2defc06cf2b7f317c066ceb56e0a0d36c6d4504909e -libLLVM.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/b6586ebd74d597b00fc8f8c3befc5115 -libLLVM.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/92e18e7f99e31c20aed2034bac9a7a4326d49301e84364d27f6bdba6c10e21e2b232f698d1e3c2eb4763dfb22c243deaec27f94859e37467405054062c0181eb -libLLVM.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.tar.gz/md5/8017dc361866f3dcd6e23493196063de -libLLVM.v14.0.5+3.i686-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/ee911d814735ecf1d7d0263dc065b9ab4906cda9ce798def8cf2488b623f28b86b4be44aaddac3d5303277e12ecd5009846c28a918bd466015c7a03649d20b32 -libLLVM.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/06688205d76cb96b2271376b9b12a318 -libLLVM.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/7b81cea8e2ff8532ce205bfbcf01785df82e526373daecb33af13a42cfbea5cf13905f898828b59066231d8985b4e31f49e6cb58342b3c29017e77de360b6f3f -libLLVM.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.tar.gz/md5/e9d98d4193600f5fbf41cd473d29422d -libLLVM.v14.0.5+3.i686-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/88237005968960213c7df83dcdc1fc3c383176b04edf352fc5bdbe1a1163e6024290243e2611d3bbb803749a1b74016092510d7b77e8bb7c3fb42ba9cf34a0ad -libLLVM.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/33b3d78789bfc1ee47a9bfc336b63822 -libLLVM.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/1247c576b4c974ce51f123bab6637e9315a27ae3e0ed0778b18842207a0a9be1a7c321227e8605c88abf4f87b4bd9b5a46c5fcb6b220356f2a4d1044001e99d6 -libLLVM.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/31048ebd14145c38d3c52954813eb91d -libLLVM.v14.0.5+3.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/7057154a2e81ecce0cf32de3db3868d665c6fb07ab42a3aa1070cdd8991e56ffa26b84f44fd94ebf400175d477960e11e6f9ddda3d11529f7ea973d3045a08c2 -libLLVM.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/6e6f02827a77f469306f66187cf5e347 -libLLVM.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/f3b0e42b72d2fc7ae4ddf413ed00d8cabc62bda54f0159b47735262e8474d95db78da0a0b15ae54566b4b293f744e91060a83187f6b19c41529ed4ee6fe67054 -libLLVM.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/549c582ceee2ca5a99fd51b947a99c92 -libLLVM.v14.0.5+3.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/a159f59a308c67d4d06f74d51696c2301a174a45415f0e6e2426e4df6d5f638b245e95a0038e6c9192c5e2ff59e4e24899ffbc1d2437e4ef226c9a2ace840d12 -libLLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/c40b3e7c3d61136a622c9fdeb1b91c46 -libLLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/33720015a37d455e95c9529f0c2f4d8c404e173007072a7ffe8b76e1384e923183f2c8d4347f599478c3d02041e95ba79da87ace2a35ec273b413aefe656a340 -libLLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/a14b32952d56547d845645d10c8a87fd -libLLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/c533195eba3b03007985dca7b250a8d283e7948bbde7bad352bfff701e318e383e719d773666d7857a88d90291246889ebb9fde7f3b89de5a5fabe7d640dd8f5 -libLLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/cdff86b8390e64f6060b629f96c1ce78 -libLLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/8d964e32c9a4b819aac4ca9ceae4965891c0fa26a8761794e30292a4125ea9cb0d198222509179a9aeaf44ced89b4a3d9ab30a733605b344cd5ed288463000aa -libLLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/28f3c8d502ca7a0ce0da3bf9e150dba0 -libLLVM.v14.0.5+3.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/b5ef97031e963b1fc2263a8f0f416b4e8f1dcfb05b908ffd685c9d7f0900dc02feb660c1a59f3c33fc262f373593b13502a55726dfbd5f73b4317132bebb81e0 -libLLVM.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/70ec5ce09b401585fc01c27746abb524 -libLLVM.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/3807a85d3f3ce7a6c8a12765c4e96fdcfb9cbf131e3259c654a34406c06ad81e3cd0ba4230860f0bc070247f6b8ba6318ef1c63c52ddbf83b6a7dca0fe80605e -libLLVM.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.tar.gz/md5/de4258e6b353f38871dbc4a544570b55 -libLLVM.v14.0.5+3.x86_64-apple-darwin-llvm_version+14.tar.gz/sha512/0fcd9052b4fb0e31cdf73972858d9d604dcd30b17e964b4b44e6f99d24e55f46d9539cee45ac390dba2276cd4193fe78d092a620d37f51ff6ce383b0ff098e6f -libLLVM.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/dd4f9f8c134d7ac1841302de76afb56a -libLLVM.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/3216ba16930bbf666ad184010eee5f09246066bb5395fe88a0d56c36b309c652321a1b30a50a8c5fee3ec91dd70182f79feeaeb31bd35559325dd2a430225164 -libLLVM.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/c9820b7d75a5708227c5431651dfd9ea -libLLVM.v14.0.5+3.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/2c78534892429dc064799657d77337d8b253946a955ef3213f052c1422a6f581adf63e6851a51327081bc0172418cbe8d1ce5972451ed062387de495789b176b -libLLVM.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/fdc36b08e9527c8cc95b042a7ac5879a -libLLVM.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/3ca6902e487545adc5aa94d64015552f4f899e6fc32ff7387fcad652c32e4c05ed57ed1a51e209066b06692f1f7b3301abf29cea67bda4b06c7488ab1bc3d18f -libLLVM.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/8d69f636a36247461dda2bbbdf0435f9 -libLLVM.v14.0.5+3.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/f3b110b5beec01208adc3397ec84e2ef867559e4d3d70d2eb2427a26fcc40f42639eabb342d50924093bedde511f27cc51922c47aee3ed42d4bf05bd39ce3129 -libLLVM.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/ddbeaf2b2a56983d1563fcdc484a75e2 -libLLVM.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/55136c26c3a8c4c12d328bb2457073138ed747d711ccf46f3c102979bf9b98c9fef28b2c71755972ee4eb70544f3a6ba848643d97b9a01710a03aee56d9fa4bf -libLLVM.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/c1125ccfc89f68a66c943b06a74c5272 -libLLVM.v14.0.5+3.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/42c11d63632d16987ba0d092d255e141ce99a3e2015a371cb886dc5f2e4e376fc6b3cfb9aede106f00c88555a675abd343d1cc737a00cd145d1d19f00d4ae368 -libLLVM.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/4e7b0cd8d695ee65c984f4c61ad0957c -libLLVM.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/654b46a1f4c5e0cae0fdd5e4a2da361d72af761a95a33f077f1f9b3216c8a509c2ece0726a4c6954a315d2b85e177e03d8ae7af20bbddb236b02f3b3bd67b836 -libLLVM.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/b1638db0af4915b809fc68f378ee7faa -libLLVM.v14.0.5+3.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/375992b170781b0fee3ecdf06b6b260a6ac93b31bb273fecc44605cc1b1be717f78e494b7b391db239d5ec28b04908ee7fb0de9bf8d2c2d9880588cb15b59e6e -libLLVM.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/md5/d1fd699c1b8c86eb9de58bc7db1fba19 -libLLVM.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/sha512/b06a651189a69395505246eacc64e47fec13b772aedd7773cc5ad27a66babc610396cca108535b00a35c689b59d68450272cca6e63de0121c84ede48280423f6 -libLLVM.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.tar.gz/md5/37538a4f484a8732c2a14517aebf6b15 -libLLVM.v14.0.5+3.x86_64-unknown-freebsd-llvm_version+14.tar.gz/sha512/0942865d8a1af33a414b1e6c8f920c629ffaf1de64c030be231404945319d5eeff4df9803d4026af9ee3cc7a141d6c960818880ac21308d8b49d4814b2922eb6 -libLLVM.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/90ffc0702fd94f58ae48d2f83221b314 -libLLVM.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/c662b80994a2a9564b625d795a30227864c54f61e3e800b7f3d80711f873fed18eac51dc1a4ee471669694a036d66b2366aba3eced81bcfb8868386485a680a3 -libLLVM.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/a8ef0684805b4e284758db4c68dd12de -libLLVM.v14.0.5+3.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/ee324ad0db2a1c7e068cfa3d2172cb0e1231005f92a0cec188c5b339e63b28d15053f6703d7230235e4e03853a9b37b5628ddd8dc202e2ffd8243e98f08f794e -libLLVM.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/fb4303d8ade17ea5780979e805668ea7 -libLLVM.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/18adc37903181e75af95c6e72d66958e575a0e131e23fae1868b976291a1d340555593292a45e2adb254814125467fe95cd1aebb3ead116afc21f1b468c62a35 -libLLVM.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/ac44022f0b2679433121d745bc76b283 -libLLVM.v14.0.5+3.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/37fd4f54b6b63dd48664f0b7c3d11de9b14011d66e358d4ad5875bc24ebd707e2bec468814bc40feb174e83846b5e3795f80b6235c57cce9d46afcefb0af5b13 -llvm-julia-14.0.5-3.tar.gz/md5/e774d56d136b7aaadfeca00d9e5ae780 -llvm-julia-14.0.5-3.tar.gz/sha512/1e9d859417838f2705c8a800556f3e4f51355b9e5d954331cd1efda8f5906060d55a28ed20d56d88f0927f86e3137168c244f7ee20c2ddcb0e119d6a69f1d60b +libLLVM.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/6c5ee2a38d4ea9eedb10ddb182f99e1b +libLLVM.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/471559396c160f7c69e39aa027955eeaa585382feccec79efe63e89d63ca2af0008d20fcd73b67444fca8ae17d48f9324f0d5d207eb1b3661f9562f7aeb4534a +libLLVM.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.tar.gz/md5/12d98767b737c33206b8f06923932f7f +libLLVM.v14.0.6+0.aarch64-apple-darwin-llvm_version+14.tar.gz/sha512/08babffaa18e40c0df47d852bc063f6a1bd77ba0a3a73e77e4717c71ddd255ca6ed29924fb78fd61bfed64f29b343818d27da44f43400eb83da391d863473533 +libLLVM.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/c879bdb130e8a068a8474969ca7f23d7 +libLLVM.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/2fa94870a8e72222a72491efa584014d06185ee5c9ff7aef75ae02be246cc438f124020cbe6820023ba5cc823fa60188e054c171cfb80d240db7e0414c63c3f5 +libLLVM.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/bd13bcfb024f72a2df65afc61a305862 +libLLVM.v14.0.6+0.aarch64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/999f6199577362a9e607265cab518d8b0b0a9455e6bd7ef4fc80d77f57d81e6cca8ff3f6651eb3b8541d451297c9d85e38a09cb1bfb2960f1d2ffdeda4f657f7 +libLLVM.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/717afe277d8447cc8c9c354d31541ea0 +libLLVM.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/5ce37884f45f128fcf814b54b5b7d8cfc0ef2f4ab5dd38cf6bb8acad3d9accd568cdbcfe32f445890a11ddad4614c57e88a9d6c39787f4ee0738c781637811d8 +libLLVM.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/dbbd454cc983cfee2fbfd7861117ed4f +libLLVM.v14.0.6+0.aarch64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/81ea01a7f4d4da96e10abf027e8a2baa2ff8086bf923a9bac82af02416deb543c3528692bd8f470e137669ca58ad05c2224243afca8213cdcf794bb65ed0b452 +libLLVM.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/0b9e93cfc2e6a72aa3e7f1dee03c831e +libLLVM.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/f796a029452a6af689b06d0a7b2b746d49d4a95a0edb6b064baa41614c2f16f843cd613f29ced45f1e42d4c600b5ebc435f564adb2ac52632abb397b97517189 +libLLVM.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/2b259c04529102c161910fcc38ac79ea +libLLVM.v14.0.6+0.aarch64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/26f97b72b63bd93f71fc1b4dc56cbd66e05f6633bb35f4f033b10a150773e6550127a13bf49a67cc0492b6140ebf01c02254678eb4af9e2832f2c757ba89b7c2 +libLLVM.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/89e0c9030216fc05b932326ca1d065ec +libLLVM.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/b35b869afff05ecad66e102b1374b9e51a05284684d01a80259a08496bcd1b0d208b4015e64bb55c24f105bcbae0eaeadf188d76daac9bf0800e446782230ff4 +libLLVM.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/f61852a29c7f30562b6b9cb660fbb968 +libLLVM.v14.0.6+0.aarch64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/dd7adb9b8b7a7c8a667a3e021032ef601b459f6afff198853dead00879008d24cc67f6785d6ce1ff284ad9c7279e77e817613af40aef86fa1bb4a57c20006a36 +libLLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/91c9fc7bfec64c0309c1f3b7126bba76 +libLLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/d3b03c50a3d6b56b333efca03f7ba0f4633d2a12acf4685fc30cfcedf3d0483e34784aa1715973ace6ed12e0c2bf1a35645b931afa34adfd75f04959509d9218 +libLLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/8a4893e1a088c02f1af8171dbf1e8be9 +libLLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/606861d316759450060eaf81e924b8805494e0303cc8ce8e5b03e09e5c09294ceec274edaacb628eec1ac614ed68f64983b574841f56878b9e308d231ef363c5 +libLLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/1ed600f5af67def3fadac97fb008ad83 +libLLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/12b17d567f426260b6d9dc5c352a609d93a2c81c94287163d67628b3b227410920836a01292718052929f22028cc737cbe7885e430164e5b9bad7aa5fe048d46 +libLLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/7ef417149337a8ef1819dbbaf9ce0d67 +libLLVM.v14.0.6+0.armv6l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/031ceb1b9928429674f9c28899c6a0b66eb6f517af0760227587101ba0645e31a772619d8145301a10402784763c07a20046a7e455c4b912e3788e192017cf3b +libLLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/abc563cdf8e7cd16000b0ee872b8aaab +libLLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/45159941d6c9c7fd4e392e500f96dd7ee74fbda9dd29026463bae7d542bb3eb71ea8c4fca49c1738effc1439e54c166fb72962f3d96e351e811efa7aa1770a7f +libLLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/24f6b603f9a4ceb4939a662d212249fd +libLLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/3ebb6c078939191acd90560d1cdc3ba35d7c1d5b77ea699acb9a739b99fe8a2b832af3f9c98337ce435fca31dc7f267cb287a48ef12ca793fec4ffd1ff98e5f2 +libLLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/2cbdd592ab2d5a9ee5ccc68f730ef783 +libLLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/f976047b12cc6f0c09d6996f1986dd03014ae2848ef8287a9889bbc69fbb1e16118af682f83d1f33548ffbaddb6edf557f8b49639d4e63b8d0782dcfebde4420 +libLLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/f627500b3b0340b3510c105e5c26bdd1 +libLLVM.v14.0.6+0.armv6l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/3e60bd5d43996ddba4a8bab4e03f3a29370e3bfe147edd61bc26f82b5019e464e8131c20d336be104dfd067e80955f7fbf610e79550394011803b4a941628edb +libLLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/0eed22f302a580a21105b6111ece2760 +libLLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/e14ac2bf1b5087b904e453ab18bc5750f6a8b17a0e247b4e791bea967b288cd5890af748608ef4dfe74a6fbc588841c4c8c7b58587ba6088cff737f19b15af0b +libLLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/md5/4f6f3bded0d4fde726cd2e8e90efcb31 +libLLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx03-llvm_version+14.tar.gz/sha512/a112057ae5b44373101a744ac6d65b4561f76435d7990961f0df692f4b44b792811a96df6d6307dd0abc3c35856ae456ca8f1fabfcc564d8f3c0e812f2793940 +libLLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/e922fe5db388a4493ea2c19bfb468931 +libLLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/9fa3b3956ac18d1735fc6b78c874415405d808754e96da3bd1a4e43cee7c0f7e6a65fc982f4868c47caf155d4f0f9df5dfee46bdddc6769b641c046d9fdd88af +libLLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/md5/3f1d64de6acd05aaa93efb2c36fa0d6e +libLLVM.v14.0.6+0.armv7l-linux-gnueabihf-cxx11-llvm_version+14.tar.gz/sha512/fbf7e4d53bd052eee794de903cf17bd3abd570a0a4a98d14a5fcbe4fd2bc121a7ebcf04110a9c1c7907c61ef13b0d972ef085b7c5a294cd9613c23ac14079b1f +libLLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/md5/9ef224e893cfef52494dc43787963aaa +libLLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.asserts.tar.gz/sha512/8b8678c14cafe937f3cd4619486c96fee651503571f552d77da9be49f77530d9df98db1863b3970ab3f400b5ca76df538887c2488ba4f6876b0f9853f3edb5ff +libLLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/md5/307a2e7c5689ed7fa05aac413e932aaa +libLLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx03-llvm_version+14.tar.gz/sha512/8ef7ff87f11c3e6f0daabeab8e4b15e47bbfe3296b7d99aa15a4f2debca7527c5f8dec193bde4d96e0b979bf7438a75c4a6e8faed23acf08debac0ede679f493 +libLLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/md5/881fd88344cf429e78519c48794e2118 +libLLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.asserts.tar.gz/sha512/2dae579a7c90d3528aaa30892c0f6f0d7c82c16eaf011bb460602cd80f7b806d114c3417664635919b28ee9c15ef4035cdefed047348472fe8d2190db4af41a1 +libLLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/md5/ab01cffaabf4c788355e7cb25b51af45 +libLLVM.v14.0.6+0.armv7l-linux-musleabihf-cxx11-llvm_version+14.tar.gz/sha512/c2cd6a426728a5b0dbdcdf7f67e4621aab0f89da1187bc9447d4e5a7cc6c716b649fc1dc957ab3fcc82d2287712ce9d1c1116dea85e0a9324909a68c12484e0c +libLLVM.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/ded7afb1e8c5be1189adcbf84a169475 +libLLVM.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/7013d0d414917cd38144afd7ea90d1718a9084d1b8702bb911060a24a106e3fb9e584094f541aff71dea4961b25698d15c1f9515cb44b137ce855defa5e47197 +libLLVM.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/abb91475af33c6a97948d4af2693d2e7 +libLLVM.v14.0.6+0.i686-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/64b8ae8f399bac84ac092e20597767c79e3427e09b8a8ed8d3292c4d1a233bdef00d2b27b578d1192850b72480e8e9e9fe025cca8aae54208122b492cce1cf48 +libLLVM.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/df2c50462c36e9e3647cd6ac98f4f395 +libLLVM.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/bbd20df4071e221417724091527a54dede73490af03357b79db7a63c2d925a7b2126dd967eff4bec14b27ebe263f9d88d212eed82d7260f693c67ddf0839cfb2 +libLLVM.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/3844c7dd6f9d2e033bb5b98744a23213 +libLLVM.v14.0.6+0.i686-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/380d56a1b872070a79c37c4d02948a008312a6ce262a38a94206d5b4209d9ee07cddc2536adb8c6dd109e4554ba16c490c96dae8307a1f7699d562b0d686d333 +libLLVM.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/294cae70e45a6a28d31dd524ca950976 +libLLVM.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/79cadf16603e388d9d0f9f925403ff7c34a04acdbd02f33dd4e823249f3dd02b6e37edfc247088220b8b333e3a8fd64c4ee267cff9d073c231109ea51514407e +libLLVM.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.tar.gz/md5/fff69236c97a34f0fe9d50ed93b82fc3 +libLLVM.v14.0.6+0.i686-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/4f7b03836bae2767ff910c5c7c79dccaae1c8478de597fb81e2b686f6e7dd195acf2140e3be72cae77509be9f25092fe8c19bd64af041469e45cf948a0baeff7 +libLLVM.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/527c35f304ab42a39df7e1fcecec26f3 +libLLVM.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/7ed37d57cf4f61bc29d7eec25579b17f449c734e658ce779fea923ccf997732b4d07c9d8bc68962fa42c0f66d739b8a9abafe0c5efb940e36c4bcf2bf6a1f0da +libLLVM.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.tar.gz/md5/504a55204bb0f8b57debd377788aab7d +libLLVM.v14.0.6+0.i686-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/03c3bd280c77356d168fcf5837dbe984f1be225a3576032de76dde1d9bb151e3b63efbd35542dff315999b1113c74ae466cc8d7e52ce12cb5d195b4bd24fca2a +libLLVM.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/3a6e6fa8ad2ea6665b184ecfb8e3f8d9 +libLLVM.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/21131866e0c4355e9de01c32415b337babf113386c293e55191070bf5b08d64c7cf00d15407e78a01f3a25d557c208774df99d46c9a858e35ce27c5609bf30c8 +libLLVM.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/ab3b323eee3d22829a74d966ec464196 +libLLVM.v14.0.6+0.i686-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/cc297c791c7367756da76b2f0aa4b272a48d4bbd563f50b6e9d9f6c741b1a060bd3d1637838233a67dd12976d27b1d2e9a041cbdbcc42a23f7ca5da73e38db3d +libLLVM.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/0e8c5a7d07c21fa9070e3c9fdeade6ad +libLLVM.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/3306216a8edb2c91f7bec2fa65737e264fecbb5fa9b6431b493e5e42c9637f52d43018c3126e53d9963c88fc095de26b258e50e3f0a9ca5dd68d1530368e3776 +libLLVM.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/81922f4a88c94409b117e6fe1f8e9832 +libLLVM.v14.0.6+0.i686-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/265aa30a53a68432bc254164598fba8fcd4909b07cfb2a8e80a6d3a71434d1851728329354c8c6b1a5da91559ca0da9718d49b711fb94ec9b974ea5efd97cc3d +libLLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/cd1ce9719cbcaca2ddf6bec9cb34c2eb +libLLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/849bce21013282edd2e32e4b6ab98f8586c2d986656498d6efd0092d4db9358a05f2a33c2200c17b1fb6cff2714318f7f322a5cf1ecf9a16c6bac5cac3517627 +libLLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/0d44242a7516c2808eca52cb54b5d01b +libLLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/3cea355f8d754cc712f16ad87f24f637381313f18963c8382cc79b3cf0237c4829f9c7d498d57d28c7aef5106ae7dafdfafabe90351ffb307adeb01e43bcf722 +libLLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/7b93f9f33beee190dbaa71508ef4d562 +libLLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/55eeba37a5b0724cbe813d5d9ec8e3b61f988c953896cc767866059c8d01e77163526935f16a8e30c6dde17999b2d6ea4088980ac118f6720f4bad8183debfcc +libLLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/24b8b6e559ea15a6bf90c39e2040f852 +libLLVM.v14.0.6+0.powerpc64le-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/180307a7e17edd2ce4758595afa784cccdfc2b09d9a1c601a69ca3a0ac1be420bc1990b8773209410e8da5c5fc81bc3a2e54687898a6d3ef0d496a27a8b27222 +libLLVM.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/md5/a74e1d380cde9950179a4b6a8e28ca61 +libLLVM.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.asserts.tar.gz/sha512/8f8ff44ed42b5315949d076b73abe91fdf958fd82a337dd15dd71182038e1643337159652e5fd911323af21a4668e46d3a401d85774f6d33fac982945d77022f +libLLVM.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.tar.gz/md5/85b65eef488ec075920048bfa6d9a7a1 +libLLVM.v14.0.6+0.x86_64-apple-darwin-llvm_version+14.tar.gz/sha512/cf865396678dc95b9d514c286fdbe85ea2a74715f5888e4392250770eb9556e354ecd9e52fc28864df88f87e06b8b39c6b403eda2bf9efd46d205f4c982e1551 +libLLVM.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/md5/411a28efef112b63a7e2cc5a7fa79432 +libLLVM.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.asserts.tar.gz/sha512/7d5eb694dd50f9f02d2cf0b2787c66f6b824c3928616759509326c7d85578f984d29ca888d3366cec9584466fcee063f236dcf0a353df280f7abb79352930f96 +libLLVM.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/md5/1fa0b4eefa8a57c858dbd9788d222741 +libLLVM.v14.0.6+0.x86_64-linux-gnu-cxx03-llvm_version+14.tar.gz/sha512/8c1b075ea01b661da518e309d521636c8e0dbeeaad688e9220db8b22965172050b9a0edb3b1098c3191873a516d03ab86b495550933ac680300ec0b42d3f31b3 +libLLVM.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/md5/b4f68d0b04db7c8021a180fe1df14768 +libLLVM.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.asserts.tar.gz/sha512/5c43368be28fc7cfa14ba03cb76b3a30f854e2c34d6b2ba3b9d7887dd2f0e4944f16b6380617bf080fc7bd760629b87f1292b49c07c684bfaf33ff9a48ba22ce +libLLVM.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/md5/e3b764196550adc33db2c15a74402dc4 +libLLVM.v14.0.6+0.x86_64-linux-gnu-cxx11-llvm_version+14.tar.gz/sha512/1822f35862887d00c162a8fc39e70d9fbf73ff6f2fd5bed44b678a1f983bf20f7a11d524e7bdbd3774d919392b061d1f980dcc12b306fc95cd456e984e81d2ca +libLLVM.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/md5/2d7837e11d7e65ca30878c25b38ff171 +libLLVM.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.asserts.tar.gz/sha512/62be4f20d35aa6efa2d52858d66150205f2b5fc1fc5faa2a49a48b27e78fd1587ed4b62123cdb25486d6a6f87951e628a45356df4263b7bdee820c850b727fe2 +libLLVM.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/md5/65d72c92bbbedb202c5e26fb4bfab6be +libLLVM.v14.0.6+0.x86_64-linux-musl-cxx03-llvm_version+14.tar.gz/sha512/2ec91bc32d89d390d104ff248440435df9cc73d7df79892f93b800feede8bb8d43f2a3e6d4682d72850b038ca75a256d24c7e9e34a751288f89cf5a8d69dcba9 +libLLVM.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/md5/f2eb226ef29f4ab2fa303f65253dac66 +libLLVM.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.asserts.tar.gz/sha512/61e2a4d02d113ea9df863a268268d3bdea5a9c9f481b9d4ae6c96a553e7516fdfb23896d4c17bbcfef931689d67daca61ef53f307713f3a583988420dc839af5 +libLLVM.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/md5/d8cd2760cb5a2a332488a6d8170ce82b +libLLVM.v14.0.6+0.x86_64-linux-musl-cxx11-llvm_version+14.tar.gz/sha512/a11764fb22d64831ce97315877d10c760697b0aa8fd667c6f3763038037fbe220285db20c981aa63f028b4dd13a8b0b57b32be6c792c1afa93dc531aff297621 +libLLVM.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/md5/33343f2e7fa1169eef570305a4d8837f +libLLVM.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.asserts.tar.gz/sha512/49b8189e8cac264f0d7cae54d78e65913f4dc047cc51f074a557073662203a96d15ef64452afb8069018f523bafd724951531d6b03c9034cdf16d359eeb9a850 +libLLVM.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.tar.gz/md5/3d211319807cdbfb6e405f47ec2a1d42 +libLLVM.v14.0.6+0.x86_64-unknown-freebsd-llvm_version+14.tar.gz/sha512/0173f80d5d6912543b2c3932a47d667449a579aed7f2b291f49bba6dcd0b680705a8f10be6175517fa4e8aecf2cfd027ef15d526bae76c99893f7203b7cf620a +libLLVM.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/md5/9018ceb966b33afecd3f9440e75393f9 +libLLVM.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.asserts.tar.gz/sha512/4bdc0e93f7d6be18c3522acbb016dc2e770d96be60a665f118866263366f1d6bc7702046d65e962d063b41b0d24f5a4fd0d4cfa5c4a9758052538e1404801708 +libLLVM.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/md5/f15cfe02c92f22187b71d5f8508a1bca +libLLVM.v14.0.6+0.x86_64-w64-mingw32-cxx03-llvm_version+14.tar.gz/sha512/b73f4932df6c36b0e943d6c6048f7a238aa1d28347ee97b2a7daab622d173c23fbf452a026bdbb26eda102f99cd96a3d09a751a462f201d207dcffdafc4be429 +libLLVM.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/md5/dfb780878726fc582a56ff433c27818e +libLLVM.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.asserts.tar.gz/sha512/59b7a0ecb36288149d19d72e79ab4cb27eba5e873617ca4ae020f281a764345aa9a9226c51ad6dbf8e5de3735ef73cbdd6a0447f7d7c58850fafba3c675695af +libLLVM.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/md5/49fb02433cb908da55ab0413eb91b0ab +libLLVM.v14.0.6+0.x86_64-w64-mingw32-cxx11-llvm_version+14.tar.gz/sha512/f411737f06e3927b199a855802bb840d33471f7d9a011d49fb299916e313ddba10f635ce58080787345f387a9dddd18b368e9f45a233e5ff84426d101434e298 +llvm-julia-14.0.6-0.tar.gz/md5/b262d8da6940024a9f0f717d26023f31 +llvm-julia-14.0.6-0.tar.gz/sha512/19af997a93dee55fd7d53c73d85c29f479ec81343266a81a81fef5321c88455eb3a315c03664f1d9763f2cb3f286f202d77629cf528b3f7ae77d369dc3d2c8a4 llvmunwind-12.0.1.tar.xz/md5/4ec327cee517fdb1f6a20e83748e2c7b llvmunwind-12.0.1.tar.xz/sha512/847b6ba03010a43f4fdbfdc49bf16d18fd18474d01584712e651b11191814bf7c1cf53475021d9ee447ed78413202b4ed97973d7bdd851d3e49f8d06f55a7af4 diff --git a/deps/checksums/openblas b/deps/checksums/openblas index 1523372d709fa..5c9194f5dd404 100644 --- a/deps/checksums/openblas +++ b/deps/checksums/openblas @@ -1,94 +1,94 @@ -OpenBLAS.v0.3.20+0.aarch64-apple-darwin-libgfortran5.tar.gz/md5/036acd7c7b68432f01f2a980bc4958be -OpenBLAS.v0.3.20+0.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/db2c995b09b5ab046491257b44a8806fd5e254bbf4b4df6e9281ffc8d199745a3d6fea912da2fdd657447e194c73db52cf7acb348b49fd37758b6fbbbdfd3a93 -OpenBLAS.v0.3.20+0.aarch64-linux-gnu-libgfortran3.tar.gz/md5/7c5de800082f39fea05d1fdf9cdf2e79 -OpenBLAS.v0.3.20+0.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/78775b01c1f24848da6111d9f4746f0b44f5966aa202af00182c4da649e4b4cf630cd1bb90e8ed32f54dfdbee0f6d03b87c171f03fee9b37886634a20546d627 -OpenBLAS.v0.3.20+0.aarch64-linux-gnu-libgfortran4.tar.gz/md5/eefc198718aa837a04e0f8e6dbdc8b0f -OpenBLAS.v0.3.20+0.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/cdc351d992b795732e02698df8f5f31c301dbcd6d995d2a35790461b08f3c942d70e8f7c031a943873eead4fcbd1e73649aafdfdb7450b955f4848be2e9a43de -OpenBLAS.v0.3.20+0.aarch64-linux-gnu-libgfortran5.tar.gz/md5/8d9ced4a8e441713ceb0d79b72b43ca5 -OpenBLAS.v0.3.20+0.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/b1dfc3f4a539d01266e3e5d400864cd445c4bc561de464e2f6c9eb5704541aa436944f6bfc89be1948e9675f1a83098d77fe52f70886dc90d54206c81f350277 -OpenBLAS.v0.3.20+0.aarch64-linux-musl-libgfortran3.tar.gz/md5/fa63d8009ac2605208ceea9f6183acdd -OpenBLAS.v0.3.20+0.aarch64-linux-musl-libgfortran3.tar.gz/sha512/92b8e2fd2bc45c60aaf8d79c59f96b721d969cd3320c0b04989a5a48099cae213fd4a6aa9dca45910d881e495d87863513b23ee7c433c894655cf72c7b009323 -OpenBLAS.v0.3.20+0.aarch64-linux-musl-libgfortran4.tar.gz/md5/68672f9cbcd9bee92c89b19599897034 -OpenBLAS.v0.3.20+0.aarch64-linux-musl-libgfortran4.tar.gz/sha512/4c19f3cb7afb52cd54c3852fef3815a23e57b5c2ebd9b647ad43ee62191b74474c787b22d6213555f38b8233b96d479631881d522c7bdd544954a9f04b51c509 -OpenBLAS.v0.3.20+0.aarch64-linux-musl-libgfortran5.tar.gz/md5/7fd9458e1482d46f761d6a519999a648 -OpenBLAS.v0.3.20+0.aarch64-linux-musl-libgfortran5.tar.gz/sha512/2e20c845deb5c87c6e02a3512728a27204193a764f8ead1a66ce053b66d03bb853bbf40289727b1b635b17423416a7a69c633242c12f98d3ec1eae5e82a88613 -OpenBLAS.v0.3.20+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/0868668b73c84e14edb634482d59eddc -OpenBLAS.v0.3.20+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/c87f91120db8d3b32cc12077b1e36110f89253fde22aae9de88945fc731ee74271acf31cabac9971635725f586b65cf6b1b9badebcbba5408b0ff4c68b580ccf -OpenBLAS.v0.3.20+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/9e84b7585acf2bb71781002b2238d888 -OpenBLAS.v0.3.20+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/14b57f9d5691997cf01bc6187a1a1d58d07d162ab8eb2a480e7c42f0cff1583161c8b1a059c9eeb83e7ed276c8ffe2e193db001a3b51724e5af24c72f5e33572 -OpenBLAS.v0.3.20+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/a4768ea555e68fc755da169f1c7eb21c -OpenBLAS.v0.3.20+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/490ce2b60cda0b5ed40df103e79b83ab75dd03779ea88b0ae5d3b76acadcf4810b35f69566e396b438d881130e43fd0dbff1672d0383dc7fe275f44574d8830b -OpenBLAS.v0.3.20+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/1a4e7e7cfdefcd878c18bab39b9c80cc -OpenBLAS.v0.3.20+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/15b512728b49782717770f044958ed3afcd54d6cc70b362a7c96dbadf7599bdcdd157ee021287a70e45957d0a856417540e64e2399cc392b9de55036d607fa29 -OpenBLAS.v0.3.20+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/63ce4aa67d1d56f2cf456285546d3eeb -OpenBLAS.v0.3.20+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/ac0bd761ef574d3533fa7f6110b9ecf992edf7a68c20fff4faf4b7372d3de4c5ed558119dcdb669296aab5c0da5ce0f51f54abfe998958e1924cfa0eb958305e -OpenBLAS.v0.3.20+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/581bcbd14328d82258511f8b91d8bf84 -OpenBLAS.v0.3.20+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/be66567c762f70885b187dc8912f83003c69dd5000387b5b82162ba9f47acb17d855f8f5bda2f31d3fc7e01d2aae3cd6b2392632d70ec34f2d648010a8b11f38 -OpenBLAS.v0.3.20+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/30dfd96f7f3d35df95e70d506f35c9f2 -OpenBLAS.v0.3.20+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/84213bbff84899882ab43599f3aeab1c6e3ee8f7158a3873ec2d6a3166e69036c16d742d25c476468f64b6644a2f798485e50427139880f1ae933ad507a2952c -OpenBLAS.v0.3.20+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/4b82a4e68a43d29538a318763004aa94 -OpenBLAS.v0.3.20+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/94d35902c34e6fa68a0648cab65db49650c73ed21d69ee667350cbbb81028413b92fc30e16504648a6b42039f483d327264a3ff39d546cd30241f4672f9300a2 -OpenBLAS.v0.3.20+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/7e290717c23a468383bd66b46eb58fac -OpenBLAS.v0.3.20+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/432cf42a320a265b9259d743eaca75b884663877858149b0feb83948436a941940955c0c89c6de9ca114f0bbf153127a046813195f4669a81cab1ce244cc5a6b -OpenBLAS.v0.3.20+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/f72bf36862607c57fc9cee5dc3f94dac -OpenBLAS.v0.3.20+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/caecc044e25d2939eec45924d69e64d3854fc54626a56126454fb3855ae2dabf36fc248d7ef9d240f15e8883787a43539e2a0d8dc68fc5c93a094ded94f3b976 -OpenBLAS.v0.3.20+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/66bfd606fc80e02999ad44243d3b686a -OpenBLAS.v0.3.20+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/b3d76ccf40af1de018e829f5dd696c6d18ad1fd96657a06d190a9d4e939cad5062a3a2ffaeca2ce7f75e822694ae0b817568dd8f115e089a59590bb34af264f8 -OpenBLAS.v0.3.20+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/ef7aca842a623246b4e2876ff28c53ef -OpenBLAS.v0.3.20+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/a59feb34806d651a2a3614bcc5203407db626e96dabeb6bb12b8d73915cfd87dc02b0e54704c5d0f1b8ab984d85ee64509a934884640d2522fc4a9835989aed8 -OpenBLAS.v0.3.20+0.i686-linux-gnu-libgfortran3.tar.gz/md5/f2ba9ed0f68447aeddfcf3ac883cf83b -OpenBLAS.v0.3.20+0.i686-linux-gnu-libgfortran3.tar.gz/sha512/1b6f300febf5ceeb0045c46cc3d6e9f2481cba2ceb97dcafff1667f06b8b96a2ad4975853e6bc2e3e6715ade28be5fb569fdae005f4fca2140a5557d4a0845ca -OpenBLAS.v0.3.20+0.i686-linux-gnu-libgfortran4.tar.gz/md5/b39347f487b46996de98d9a453ae804e -OpenBLAS.v0.3.20+0.i686-linux-gnu-libgfortran4.tar.gz/sha512/a923a92467b4582f69ec9d96556c8f2ef55a3f99dacecf0491da9740912d14d09a9ba86bdb5fcfbaab87250c57a0c077c2f6ccc08bf3236ba5c7d98822e9c32a -OpenBLAS.v0.3.20+0.i686-linux-gnu-libgfortran5.tar.gz/md5/6d9b4adf3fa54151c45b832b5869409e -OpenBLAS.v0.3.20+0.i686-linux-gnu-libgfortran5.tar.gz/sha512/f15583c15fb4e4b6a38353fbbce2aa57c8f46d58e6c5464a685e5fb0afd76f1bf9b3986c1d34af643a8c9b3a8a24ef63389982c2e8ffbf91a63e8f1ccca2cce5 -OpenBLAS.v0.3.20+0.i686-linux-musl-libgfortran3.tar.gz/md5/fa46f28f624e8c0752bb76abc04a41d5 -OpenBLAS.v0.3.20+0.i686-linux-musl-libgfortran3.tar.gz/sha512/76018ed804f25212760f1128f7d3823a1c8ba72b8cf5d83aa5be5c5f6e3de8076b04be9d5b659af75e3c2fd5cb9a0654dba59651f010534faf174a6c7d836cd3 -OpenBLAS.v0.3.20+0.i686-linux-musl-libgfortran4.tar.gz/md5/48411109935a2ada9d2e336515f36b6f -OpenBLAS.v0.3.20+0.i686-linux-musl-libgfortran4.tar.gz/sha512/9be06c11fb248d6da47dab21f60d1eec6b486a137048f79f2138b5fe6818846ac198da7d73ab93ec161e8861d7e670b587b6eeb846c571497e96023934127903 -OpenBLAS.v0.3.20+0.i686-linux-musl-libgfortran5.tar.gz/md5/b0a81e44dd4a216c60b6ff139512d7b5 -OpenBLAS.v0.3.20+0.i686-linux-musl-libgfortran5.tar.gz/sha512/1b1c3cc5e62af6af8e106c60c59d7ff685d567e93dce19643ba8c0547200000bae96a3473573619ab235c34ff8e65745266001cdc868e948ff3ecaa9ba93389f -OpenBLAS.v0.3.20+0.i686-w64-mingw32-libgfortran3.tar.gz/md5/18988c19ea5bdb81d97f8ce4456319f6 -OpenBLAS.v0.3.20+0.i686-w64-mingw32-libgfortran3.tar.gz/sha512/466d6b05dcf00b6f09c1a8b8fda97a0035838d73d77954f6cd499358e8160af6cf3e8aac97d0f7ba7ced144db1362a9ba126fb113a4469c232a6b9706dc3dc32 -OpenBLAS.v0.3.20+0.i686-w64-mingw32-libgfortran4.tar.gz/md5/d0aa399c07712e9a520a6cb8067bda63 -OpenBLAS.v0.3.20+0.i686-w64-mingw32-libgfortran4.tar.gz/sha512/7c3e0b1c18812719be4d86a641d25d927c9c8cbc6e1571c7a46ca27672ada00cbe3879faf0b5aeaaa0454907551953a20a56be0bc24b651df117532ace2f9067 -OpenBLAS.v0.3.20+0.i686-w64-mingw32-libgfortran5.tar.gz/md5/90d51a2f41c11fc8d1896597dd106cd6 -OpenBLAS.v0.3.20+0.i686-w64-mingw32-libgfortran5.tar.gz/sha512/683c40193ec7a4612c4a36e9d9f6d9443bfb72dbfed7fa10b200305c94589fd75362670d9b4d7646f24b4f7933cfc55a2496030907e2d3fd30b0eed8b6a2d10b -OpenBLAS.v0.3.20+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/30d5022d6f52adccfaf6b3dd837b6151 -OpenBLAS.v0.3.20+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/433a520458d6804eccf69c74fe357e6d819223b0398007f17420a6aa77a466177d9dcd4f467821b4d99f4397f5e0c1dc0864512a7f69c43f23bc40b6414449b6 -OpenBLAS.v0.3.20+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/2848232be1646333d6d413a588519d99 -OpenBLAS.v0.3.20+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/edb51d55f602d2a271109dbc12e59e23c232e58833bcc34dd857858d10d318eac99ba300fe4c6480b995e152ff036ff175218a2f4b29910a27f1861543d1e978 -OpenBLAS.v0.3.20+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/8bd4f4d571dc382eaf0084000596276e -OpenBLAS.v0.3.20+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/f9507f6dc53c632e0f26de074bcd312956b2fb492e9f1d32e3cdf1a6099d6f2b17eea09ae825b2414a28dfbd6958813cffa289fde0a15cf7cba4e6b3653d2a28 -OpenBLAS.v0.3.20+0.x86_64-apple-darwin-libgfortran3.tar.gz/md5/c644f00642c69946d12b8f1f96a8e766 -OpenBLAS.v0.3.20+0.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/2bd51e9adda3e0955ab26c5c178e9a75a8d9c1b4cd2fd221bbb7b9eb72337cd5034f42b53aaddcf97a807e01f2b9836f9be95a5c6517c831374a3b5148b6e380 -OpenBLAS.v0.3.20+0.x86_64-apple-darwin-libgfortran4.tar.gz/md5/cea0d5ad3528298e4512c900a13f21ec -OpenBLAS.v0.3.20+0.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/379ad13b723acde1d2239335c2611a9ebd2abe1432931d4c2395fce9f50bbd5d830a23fd5ea5afc1fc251704e4ed880468abde42bb0ea75b6bb0abb9a7753c5b -OpenBLAS.v0.3.20+0.x86_64-apple-darwin-libgfortran5.tar.gz/md5/bc726288a19a8bdcef3205de12b5f172 -OpenBLAS.v0.3.20+0.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/3e26b8a2075f997ded8750d84e3257b895e7e05adac77d836e66fa7478b43368b7d4b7a458c6991cb642ce0d135b1b507dade7302c4f5a44aabe637849bc1acb -OpenBLAS.v0.3.20+0.x86_64-linux-gnu-libgfortran3.tar.gz/md5/d162add49c7ee74dfc23b820bbd363b6 -OpenBLAS.v0.3.20+0.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/70bcc15f37e4cd822c2f95d8fd23e912829450825399d31c29c00a4ea219ca37f8831d3132ae4b5972fe9ec95c304bd1274a12ec8a8b289b1830cfb7ca0392d7 -OpenBLAS.v0.3.20+0.x86_64-linux-gnu-libgfortran4.tar.gz/md5/f036c51e0954b8b76e3023280144b5ff -OpenBLAS.v0.3.20+0.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/2101747ec254f51fe5c2cfc49ce9599aeacf0d3e7bcb14c9ccaa59d8b0f7e9dcda98ab3ff38973817b736a33ddf654e17748d8a9c3b40e5352a198278484a2f0 -OpenBLAS.v0.3.20+0.x86_64-linux-gnu-libgfortran5.tar.gz/md5/143d8e7cf2fb615ccab6617bffa4acf7 -OpenBLAS.v0.3.20+0.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/6e72144f83cb329301feedea02581a100d137f3b209af4983500c432b6d23cc7473c85a7b1ba90e24965508e74a191b49cea8820b5899793440c3ce067acbe06 -OpenBLAS.v0.3.20+0.x86_64-linux-musl-libgfortran3.tar.gz/md5/871863002d0053784a81409b4581c8cd -OpenBLAS.v0.3.20+0.x86_64-linux-musl-libgfortran3.tar.gz/sha512/908936494c981e14bcd7818043efe979d9522ae1c9ebcd69feb853c46a2249da1cb5292844d0de7276762a21ad8680a1117229f3ad53332b536233d8722c4d85 -OpenBLAS.v0.3.20+0.x86_64-linux-musl-libgfortran4.tar.gz/md5/ce4897980b12374801095fadfad11196 -OpenBLAS.v0.3.20+0.x86_64-linux-musl-libgfortran4.tar.gz/sha512/ba551942563a58fd22d182a29cee83ce5f51db10e52bc8cb27d979dc71632484e1acb713d4304d773c3111d5dba532bd65651374e91a364f8125295acacfffd4 -OpenBLAS.v0.3.20+0.x86_64-linux-musl-libgfortran5.tar.gz/md5/301ae23724b44c1d10e4febdc6738df3 -OpenBLAS.v0.3.20+0.x86_64-linux-musl-libgfortran5.tar.gz/sha512/2f1479b1f1d10682751b025493bc38cd5eb9854620024b1f0ac45ba0f7a7621b4795c4c2f89eece5c80b671387d095b118d58d8ba201214f45bcea1ac64fca91 -OpenBLAS.v0.3.20+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/51088d57d2a9e9e50259128a0ac48727 -OpenBLAS.v0.3.20+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/c88b1eb662c16b75c46a25959f6fff22de2cfb2a97ff1c0cd482528e83d54a4d8bbf33c3e7d6a79ad75998d0c6d46ef6f245e8ad406d1a072907138d7ca4a34c -OpenBLAS.v0.3.20+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/06167501fc4cc7b6587ead3696ef72af -OpenBLAS.v0.3.20+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/a853a4c5163e0bc0266e75df0b208794e8439a008b625b520b51e7891825a355960f62fe2275e4f849c345862fabf0339d0d22d4bdcd87acfb17ffd65627f74d -OpenBLAS.v0.3.20+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/73a43356c9bf374765a2bc8910e2eb49 -OpenBLAS.v0.3.20+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/0c2092789f4eeab1725cdfd7d308a2ede054b993d6d1a83f671c5c8e9f651565c282af7371c958c61a57679a233d3f62a287afb44225498dc31249f6821ddf98 -OpenBLAS.v0.3.20+0.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/46bd5ef0708671aeb2a533476a04591b -OpenBLAS.v0.3.20+0.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/1b0a3f9e61101cbf455da70056dea75637f3008df727072a22150072e7bfc773294378fc42a492b2351f9af2d6b7866503c0039f8addeab07d4f4b5d0f42b5fb -OpenBLAS.v0.3.20+0.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/7e412c9961e4762c40cca9c27e5c9aa2 -OpenBLAS.v0.3.20+0.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/6a275bd153bb0ba227f39ffbfe95ee1f84f42f79361f7d3a7b1a5c29ca253b8d8b2427ce389f10cf2b95fb87d91dcdf1144f24c82d11320a0aad7dfb8d3c0498 -OpenBLAS.v0.3.20+0.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/2a24ea7c7a9bdf8069d7f62c55d09bb5 -OpenBLAS.v0.3.20+0.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/7f9134df42be432199119b2a5ef5df2552247cca8647546fb755901d5903030fd5cb565c711248f173c71409cd3b30609a2adadf0213c9a096a9b70298b29a87 -openblas-0b678b19dc03f2a999d6e038814c4c50b9640a4e.tar.gz/md5/4586a405791fb16775eb9aecdd7daa59 -openblas-0b678b19dc03f2a999d6e038814c4c50b9640a4e.tar.gz/sha512/c34a498f2f1ecf65c5174a198022558bf6626eb6da0c4191762a35fd9d335c67dd17246cee3ef503301738a202650aaefe5e0073d8abefd3d1b8ba19cc953304 +OpenBLAS.v0.3.21+0.aarch64-apple-darwin-libgfortran5.tar.gz/md5/a89e1eeae1d9539c21598c98da5ac91c +OpenBLAS.v0.3.21+0.aarch64-apple-darwin-libgfortran5.tar.gz/sha512/181334363669482ac78b17ed9797ecc62ead35c07348eddd674c06252a7b36a356db48c62da77e73072df4cc21d0c25e0fb568c4dc7fe98e5db8e0f76eed7183 +OpenBLAS.v0.3.21+0.aarch64-linux-gnu-libgfortran3.tar.gz/md5/7ed3100359f9ed7da4959ecee3b4fd1e +OpenBLAS.v0.3.21+0.aarch64-linux-gnu-libgfortran3.tar.gz/sha512/329e26dae7f2e5ba81ba2271257c03426a349b89831147458a71d91da062bd11fab1b846f77922f3bc65a9f7d3b1914f15aaa0c14f696ba7bf43b55628a5464d +OpenBLAS.v0.3.21+0.aarch64-linux-gnu-libgfortran4.tar.gz/md5/ae71b44c62d42c246a21385d0691dcfa +OpenBLAS.v0.3.21+0.aarch64-linux-gnu-libgfortran4.tar.gz/sha512/0598da4b6410f59a69690e6908c80724df4a8c4761194993c1b127f84418f046d8fa0d367fda8a7faed5cec2d6c57bd8872ba216e38b5418bc9ff20af27528c6 +OpenBLAS.v0.3.21+0.aarch64-linux-gnu-libgfortran5.tar.gz/md5/fff9e118d250bebd55723e77c492280c +OpenBLAS.v0.3.21+0.aarch64-linux-gnu-libgfortran5.tar.gz/sha512/29d831f773cb6a75119c7cc2363fd72d38e32eaef6124505f8b5a1b64fa3ae7a6ffe199aae851de0893259d3bdc480aa377294688ee55d20f0da7dfc49fce747 +OpenBLAS.v0.3.21+0.aarch64-linux-musl-libgfortran3.tar.gz/md5/e93af05f98be926b3000dac3accf5f56 +OpenBLAS.v0.3.21+0.aarch64-linux-musl-libgfortran3.tar.gz/sha512/de3e9cee786d1a37dd5807aca81728d67d60fdace68aa17c69efcc7ebfe36dd3a240dea16f7cd3c5021f0f967f15f1154a3d32350f91165a9fcdd08285917196 +OpenBLAS.v0.3.21+0.aarch64-linux-musl-libgfortran4.tar.gz/md5/5a0226c6781c748a8f4d144b0ae4609b +OpenBLAS.v0.3.21+0.aarch64-linux-musl-libgfortran4.tar.gz/sha512/83d9ff97a5651b682ee1839cf0e1aa8dcd7c2e2d32b6cadb184b8d71123649a31519516b1c7d98c329ab9902538a01ffc14ec28f95ada35ba8da77241d74c2d2 +OpenBLAS.v0.3.21+0.aarch64-linux-musl-libgfortran5.tar.gz/md5/f09c8409b0f4e5e3ee9d471538289e45 +OpenBLAS.v0.3.21+0.aarch64-linux-musl-libgfortran5.tar.gz/sha512/b41234be953779db6601d5bffe43ab9ea23bb542583b16af48fe3a3400b1e50b45d3c91152895c92f6a1f4844ac018c8003f0fd10e9473c503e70e9fc4ad11b0 +OpenBLAS.v0.3.21+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/md5/78ea013e0ba52d289c919df3d5b79946 +OpenBLAS.v0.3.21+0.armv6l-linux-gnueabihf-libgfortran3.tar.gz/sha512/50ffb9d99d283db2880e767a3ebedbdc7ca67b18782717f5085e0cfc9f6cc55bdeb112e8dca0011e31954a22272936043ca538204fc9be81cb7a0f22d6726f12 +OpenBLAS.v0.3.21+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/md5/47d016b3a50c0c9b2ed1eb5e49904169 +OpenBLAS.v0.3.21+0.armv6l-linux-gnueabihf-libgfortran4.tar.gz/sha512/d38fe6df24d658a0f54ab007ac6f9b30c0a02fbf86c0592f2e5cf5a8375b654a7428b75f74c20d97d6c953ae9998664c82800813dfa806a5f16dfc20c798c419 +OpenBLAS.v0.3.21+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/md5/17f22b32a0715f82fd48cc5d82f6512c +OpenBLAS.v0.3.21+0.armv6l-linux-gnueabihf-libgfortran5.tar.gz/sha512/d9318a4cd232abc58907522c20ac666e6db2a92e6a25c9ddd1db0f0169be6f94aadc808014545e92e6168eaa7fa20de4235072186c48ade2e7fc672a700485ad +OpenBLAS.v0.3.21+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/md5/d5a83c8835ad8553d304bf5260b53985 +OpenBLAS.v0.3.21+0.armv6l-linux-musleabihf-libgfortran3.tar.gz/sha512/3b506824730c7269eb49e90dc11bfde2b17338ef1504da63e84562433c68586a71b022ad37de3096e06ac24e98828b48638c672789320f76cb33eda4c8e8c9eb +OpenBLAS.v0.3.21+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/md5/59cc4a5aeb63dd84c0dc12cbef7d37af +OpenBLAS.v0.3.21+0.armv6l-linux-musleabihf-libgfortran4.tar.gz/sha512/1e9cadcf65232d4a4fba9cda0226e5a5450227e16bf2c27a3268452d5c4e4d5d1321601fd6e1a5c5d92fbc3fc4de21c92e231b5ad3b25dd71eb49d5940fcf243 +OpenBLAS.v0.3.21+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/md5/c04f400d9aca82aac956e94d9fc6fc51 +OpenBLAS.v0.3.21+0.armv6l-linux-musleabihf-libgfortran5.tar.gz/sha512/8751300546ccb059fb7755e3f745e7e195cfaf90daf28b151ea2a3d540edf8910c97351d428dda196707599361a200f1a647098fdf5d7163380b4ad2b4a4f733 +OpenBLAS.v0.3.21+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/md5/f251abd323b6bc463ae4a1989670aefb +OpenBLAS.v0.3.21+0.armv7l-linux-gnueabihf-libgfortran3.tar.gz/sha512/4f179ed09a5f5b71033d09db3894ad78d58a4429d65203225ab7a2a8c887222924910756a5fc4e3974a7cc6f9d994af287490f53cd05fe90f86c4bd4c4023b6d +OpenBLAS.v0.3.21+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/md5/f8ffa30a958448028d1294da9d15f3b2 +OpenBLAS.v0.3.21+0.armv7l-linux-gnueabihf-libgfortran4.tar.gz/sha512/0a2d9a73be439d78b4af7c70345bdffd531d5687adeea28049adba3c8c9ab7b6ed221703f2a8aff9e7391305355a596dc9a846c84d36d1b4cdfda521f7c05e8c +OpenBLAS.v0.3.21+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/md5/56a4aa4f3eafff290d38dc251a5966cb +OpenBLAS.v0.3.21+0.armv7l-linux-gnueabihf-libgfortran5.tar.gz/sha512/fce03b1c1becdac66208de20e66949aba113ce2695217d34703a9ba4fd79d364cdf05424282b9d1f25ad9c315baffca3a8bd0af239f6284bd37cbdb2ec3463c6 +OpenBLAS.v0.3.21+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/md5/aca7ef7f854cfe45bedbf1f6b5a97aaf +OpenBLAS.v0.3.21+0.armv7l-linux-musleabihf-libgfortran3.tar.gz/sha512/16821728c7a0e56589b60176a06543240f2a061b437dc1cf38723dc56910c6add114a4a5e65eda051e5e88ff7b82b8613ffaf5dad7864f1208eb381159bacc8c +OpenBLAS.v0.3.21+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/md5/9f2c39eef42e5c80f56d36aee156e2b0 +OpenBLAS.v0.3.21+0.armv7l-linux-musleabihf-libgfortran4.tar.gz/sha512/441a7833e4e2d1334aeda58d87560e613244138005bc54c74af00d81c26e1e508ce874fccdcd3b3114a74f5e2a102eb520a2e4165b461861ba79fbaff81e4ae3 +OpenBLAS.v0.3.21+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/md5/bf1a9f3e553d6855133b4de3ffc841ee +OpenBLAS.v0.3.21+0.armv7l-linux-musleabihf-libgfortran5.tar.gz/sha512/2002b305ef3f3721287ed839d6d08f34127058e6295233f8280cc3ebd06d91cb326ea83f13c0158820c381fa8a2cc74ec1360a65c99bc525f492be561b15cc09 +OpenBLAS.v0.3.21+0.i686-linux-gnu-libgfortran3.tar.gz/md5/6051a0545d272bf19988e2a889531acd +OpenBLAS.v0.3.21+0.i686-linux-gnu-libgfortran3.tar.gz/sha512/21706d2fd8dde6e1e938b0c7a53c6073d52d830d7672702d828d5606582e2c98bdb39fc7ff1fa67188942713e9d718fdf5f014812115d0d0853066c2df21f297 +OpenBLAS.v0.3.21+0.i686-linux-gnu-libgfortran4.tar.gz/md5/4fc17cff9c7a4512245ffead4d75c678 +OpenBLAS.v0.3.21+0.i686-linux-gnu-libgfortran4.tar.gz/sha512/5a28c5a587be439cd2bdf4880caf967cdec14945d26c978fa5c59ce251d5811d460bebc038808e0e8dd2eb4b6a0fdfcaacca4718e2aeb7855f466bd13d1974a7 +OpenBLAS.v0.3.21+0.i686-linux-gnu-libgfortran5.tar.gz/md5/06fa8dff91cff8ba91e2b4bc896e776c +OpenBLAS.v0.3.21+0.i686-linux-gnu-libgfortran5.tar.gz/sha512/493110d06c4361df13ba8e0839b9410551b0bba4fe6e3cdcb53c0dff41a03b3e34ec1c2e73cd4671516631492a16b8dd140a59fa3ac71c348e670858654f2d8a +OpenBLAS.v0.3.21+0.i686-linux-musl-libgfortran3.tar.gz/md5/1b16814a10900c96537b5bfed19e71c2 +OpenBLAS.v0.3.21+0.i686-linux-musl-libgfortran3.tar.gz/sha512/603b2a2fd92286143cb0cb573e3c085db485cf3c4f54987d255efedaea2a8a3d84b83e28f6b2db9dbf05cd31f061845a749b8402d145cc5e8cc2eb369b38e3f5 +OpenBLAS.v0.3.21+0.i686-linux-musl-libgfortran4.tar.gz/md5/20ec87e486f1154d253bc251c1ec0bce +OpenBLAS.v0.3.21+0.i686-linux-musl-libgfortran4.tar.gz/sha512/a2d1736e0f632bddc5140ea88840113b80fedcad51bf5ea93445053eb07c1ae304a1510a85cf964d3a0e087390b8526a0df2bcd24e356b4693a41e5dfc8a671c +OpenBLAS.v0.3.21+0.i686-linux-musl-libgfortran5.tar.gz/md5/df9f4898d550130b0c0c5cede6dd4db3 +OpenBLAS.v0.3.21+0.i686-linux-musl-libgfortran5.tar.gz/sha512/c4c3133904e7b401c5d3013d0ef38b13d7a9804fb4ba38a2c0a062f1badb4d9150214bfc2a1bf55df1299e4151d71a6dbfce7063d9d80a19fe321878c0e59309 +OpenBLAS.v0.3.21+0.i686-w64-mingw32-libgfortran3.tar.gz/md5/3d83d839f80abbd17f84631fbb8f6624 +OpenBLAS.v0.3.21+0.i686-w64-mingw32-libgfortran3.tar.gz/sha512/e51680b4b97f404f244b4d943148f506f84a21f0f59f4d41a3a0cf81d545658d9cc59592a2538c4c077606fc1e6f87eda23063e49828f066e743205c5e6aee8e +OpenBLAS.v0.3.21+0.i686-w64-mingw32-libgfortran4.tar.gz/md5/2ca3ebd61038a5e422a946ede3d17535 +OpenBLAS.v0.3.21+0.i686-w64-mingw32-libgfortran4.tar.gz/sha512/c692b7c00aa0eda4a3fa989f84c797126b1596e13514117ad898166f941f040df67826ba33d0af93673c7a0b478fe4392f9a53d7859b7371878b6608dcb0556b +OpenBLAS.v0.3.21+0.i686-w64-mingw32-libgfortran5.tar.gz/md5/55995848e4bc9ef739e8ba17962787d3 +OpenBLAS.v0.3.21+0.i686-w64-mingw32-libgfortran5.tar.gz/sha512/e274dcfc6593786ac4c32c3f49ec69ab3a0c7278c67bbd04373d4845bff2dfaf17300d4a71e48ebd508e299fa629190ffe70ce074a68e83bac0eafa51f4db2a0 +OpenBLAS.v0.3.21+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/md5/2a3d5f0240a27cf1617d9d4abba6df78 +OpenBLAS.v0.3.21+0.powerpc64le-linux-gnu-libgfortran3.tar.gz/sha512/489128c884a0c2b9eb5145b18c68f9c7de9a9cc4131f4635689dc67765f87bec852b0547ebea4ecfdad4eec38063aabe8f6c3e96e5856e08c0c26130c2f11897 +OpenBLAS.v0.3.21+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/md5/bb3501965c26519ecf30830465b12672 +OpenBLAS.v0.3.21+0.powerpc64le-linux-gnu-libgfortran4.tar.gz/sha512/bcc78c10f7aba973f1159443e8d408465833ef43530c1c2514715db5a1bb84c0f48510c12b2ac1211b2777328ec682e01ab668818025651f00db7ca747f5674e +OpenBLAS.v0.3.21+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/md5/dc6192b5130e114b3cb1183690c7e398 +OpenBLAS.v0.3.21+0.powerpc64le-linux-gnu-libgfortran5.tar.gz/sha512/95d69ace7b145c02acbe13c52d1e7835fdb1e8788c0b03f0f967d88575b322988e4f4acef3b6ad3e505c895f8d19566b8eb9add02f0250cf2d4a14c9f1428f3f +OpenBLAS.v0.3.21+0.x86_64-apple-darwin-libgfortran3.tar.gz/md5/27a9117002f96c41c7907be0475a8d86 +OpenBLAS.v0.3.21+0.x86_64-apple-darwin-libgfortran3.tar.gz/sha512/2247f3691cc552f65a353412c46a76c1ac4b4d994a5725044ba300f0944f15b37144ceff438d77022b441c25eaf530709a4d3ed4523b97d292991b6407a72970 +OpenBLAS.v0.3.21+0.x86_64-apple-darwin-libgfortran4.tar.gz/md5/30dea9ca8b658ff6a9db9245d8ad7500 +OpenBLAS.v0.3.21+0.x86_64-apple-darwin-libgfortran4.tar.gz/sha512/3289e766bfad456b35efae6d341a77698d4d36908ac8d802f47777feed5eef224fde1cb4799b5bd4e8e216c28c78ab4407b92906ddac0bdd1cfb674136c69aaa +OpenBLAS.v0.3.21+0.x86_64-apple-darwin-libgfortran5.tar.gz/md5/ed820c420a67b32df0a9f34760ce605c +OpenBLAS.v0.3.21+0.x86_64-apple-darwin-libgfortran5.tar.gz/sha512/63f43eb0b1c037849fd5addda66d818c0b8188f9758391cd9929e78593c69ec61729be0efce6a9f943ebac178c634cdddffe172ad681ad1c4717949b075a1de7 +OpenBLAS.v0.3.21+0.x86_64-linux-gnu-libgfortran3.tar.gz/md5/a5393eb8e1799b6c089a82d8dde39fb0 +OpenBLAS.v0.3.21+0.x86_64-linux-gnu-libgfortran3.tar.gz/sha512/8ce9ad2f55f131592a87789ec6a824cbe1d23c3be32fb2ba59e107045f75c34684b85d3bab2913923f5a19414a072b5e855c86fddd44a4319a9b5e7b28d5c169 +OpenBLAS.v0.3.21+0.x86_64-linux-gnu-libgfortran4.tar.gz/md5/652aa333440219a4ec17d94dd4e6d358 +OpenBLAS.v0.3.21+0.x86_64-linux-gnu-libgfortran4.tar.gz/sha512/89d7740b462d4216e920dcd5c7867520b2f49c3cb74bd8424efd287927c92a08492c9fa413506248207f9532c7bb9ea2af587a4f70d7db8ea42ac1bc144e8a12 +OpenBLAS.v0.3.21+0.x86_64-linux-gnu-libgfortran5.tar.gz/md5/9e0831544d02a39565a2d0714b1e121a +OpenBLAS.v0.3.21+0.x86_64-linux-gnu-libgfortran5.tar.gz/sha512/9e57a08a09d5fc47d881f9f7ed2e52fbdc7301908cf1be384fe767e6b7771a5980827417049dd37df4d71a861b2cf2a05f25df892b15ed03458910b0bc53101a +OpenBLAS.v0.3.21+0.x86_64-linux-musl-libgfortran3.tar.gz/md5/dde15d3a2f26601cd7ac0a803efbe503 +OpenBLAS.v0.3.21+0.x86_64-linux-musl-libgfortran3.tar.gz/sha512/fa48e51a59b6fb213f88ce8b2778ca5eef73f0721a5c71e27cd8952a34a5003d69710571deb5c0c06526fa8016cfdacabdc2b343342ad0d1e523903fa94a8d42 +OpenBLAS.v0.3.21+0.x86_64-linux-musl-libgfortran4.tar.gz/md5/55b80d13104f4ddc9eefa0424d71330b +OpenBLAS.v0.3.21+0.x86_64-linux-musl-libgfortran4.tar.gz/sha512/fcd816e4dcd767963ae555846cee846c19f0b7d666042d59757eb2eebe115d30af60072c134c3025049712520705dbe9d2862a1f07c955780f9a0de69e6e00b5 +OpenBLAS.v0.3.21+0.x86_64-linux-musl-libgfortran5.tar.gz/md5/e22e46b304962a1edb550e19914cc5e6 +OpenBLAS.v0.3.21+0.x86_64-linux-musl-libgfortran5.tar.gz/sha512/38f8ce1baee4082fd2432dbc1905fd03d8efbcc378aefc9312e90b6054341717ea46bc4d33f9f517e67af0fca2da55b5c5b112850e6071ba18753a4936d78da2 +OpenBLAS.v0.3.21+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/md5/b8b7a9f9aff94b154e8479a84d7abe4b +OpenBLAS.v0.3.21+0.x86_64-unknown-freebsd-libgfortran3.tar.gz/sha512/afe4c45d4bf4e38fdbbf00b9e86a65244aadaa2b74e59f9a43f1860c130f721bba2f36186519b2573ff0819bd2b30414cc23800634847db2ecd2107f985495ad +OpenBLAS.v0.3.21+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/md5/8fceea42a8524fef29a54b88ea0a721b +OpenBLAS.v0.3.21+0.x86_64-unknown-freebsd-libgfortran4.tar.gz/sha512/e8195597057ab6de0aa5978b4d13b3248ac6acde3f86fc55d9e1c76ec39d464fc2eefea1096cfb5dffbd623f47b06be163c4c74981d2eb13387bc8499b9053fe +OpenBLAS.v0.3.21+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/md5/6f88d96c05663b4aeb81ba8a63882066 +OpenBLAS.v0.3.21+0.x86_64-unknown-freebsd-libgfortran5.tar.gz/sha512/f1f516d8d16a2f86bfb26129e0530146de3a4bcb62abcd2c7b9bf64cc09c069e5eeb66658b1cc0cdcc665de98246ad8ed20a7d8b132fe0f0e4d0651d3b4516d4 +OpenBLAS.v0.3.21+0.x86_64-w64-mingw32-libgfortran3.tar.gz/md5/4fb99984ec612a090b294c6b349a7cdb +OpenBLAS.v0.3.21+0.x86_64-w64-mingw32-libgfortran3.tar.gz/sha512/81bf55c6398a6cf4a61add084332e7cb79e6d550737641f6c0bc77aa61bd8187603a6100b78c2ef80109c3c5b21f7ba618a4780a5b68e5168a461af521f26c52 +OpenBLAS.v0.3.21+0.x86_64-w64-mingw32-libgfortran4.tar.gz/md5/a1a2c3623d583ab995ac86df07ab73bb +OpenBLAS.v0.3.21+0.x86_64-w64-mingw32-libgfortran4.tar.gz/sha512/ec5fab349607862c9e0badaa1fd433e057ac7d056008af683bbb37bf43fef5322e598cd71a6d9c3dd55ef857b39ca634e64572e9ae6e263022dc7f89083f9bca +OpenBLAS.v0.3.21+0.x86_64-w64-mingw32-libgfortran5.tar.gz/md5/05ef0ede7d565247a936c3110c25c83c +OpenBLAS.v0.3.21+0.x86_64-w64-mingw32-libgfortran5.tar.gz/sha512/34d2812bc0c6605558cbd6244c41d0805fc9a943cd91a74994bcacdd5ff19612eac8751832e3ee761089a853cf16069e67e13507ca75bbe4b7dc4517e41515e0 +openblas-b89fb708caa5a5a32de8f4306c4ff132e0228e9a.tar.gz/md5/716ebe95d4b491253cdde8308b8adb83 +openblas-b89fb708caa5a5a32de8f4306c4ff132e0228e9a.tar.gz/sha512/00e7bde49525c2c28bf07b47290e00b53bff446be63f09e90c51724c6350e5ddc90f5a071ae6de057b3fbb107060e70bf16683fcefcf48ae37ba1d0758be553b diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index a21755c79c895..7d6196f40951a 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -1,7 +1,7 @@ SuiteSparse-5.10.1.tar.gz/md5/68bb912f3cf3d2b01f30ebafef690302 SuiteSparse-5.10.1.tar.gz/sha512/8f85c6d63b76cba95707dfa732c51200df7794cb4c2599dbd92100475747b8d02b05089a47096e85c60b89bc852a8e768e0670f24902a82d29494a80ccf2bb5f -SuiteSparse-ed89e0fe3d8908cede058f42f872ba60159af0a6.tar.gz/md5/3019404c83511b5aab962559c2924072 -SuiteSparse-ed89e0fe3d8908cede058f42f872ba60159af0a6.tar.gz/sha512/06fa991da05376ee7e55a30f6fa29ab60ed2cec79818e217290e0e256233ee321fb25a764cbe834c3e94755b02d5326c93c8f1b686c53da28023778787e6d57f +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 diff --git a/deps/clang.version b/deps/clang.version index 182714fbb391e..2fa84f679cb19 100644 --- a/deps/clang.version +++ b/deps/clang.version @@ -1,4 +1,4 @@ ## jll artifact # Clang (paired with LLVM, only here as a JLL download) CLANG_JLL_NAME := Clang -CLANG_JLL_VER := 14.0.5+3 +CLANG_JLL_VER := 14.0.6+0 diff --git a/deps/libssh2.mk b/deps/libssh2.mk index e27a57a4078d1..d0174c0c090e2 100644 --- a/deps/libssh2.mk +++ b/deps/libssh2.mk @@ -36,8 +36,15 @@ $(LIBSSH2_SRC_PATH)/libssh2-userauth-check.patch-applied: $(LIBSSH2_SRC_PATH)/so patch -p1 -f < $(SRCDIR)/patches/libssh2-userauth-check.patch echo 1 > $@ +# issue: https://github.com/JuliaLang/julia/issues/45645#issuecomment-1153214379 +# fix pr: https://github.com/libssh2/libssh2/pull/711 +$(LIBSSH2_SRC_PATH)/libssh2-fix-import-lib-name.patch-applied: $(LIBSSH2_SRC_PATH)/libssh2-userauth-check.patch-applied + cd $(LIBSSH2_SRC_PATH) && \ + patch -p1 -f < $(SRCDIR)/patches/libssh2-fix-import-lib-name.patch + echo 1 > $@ + $(BUILDDIR)/$(LIBSSH2_SRC_DIR)/build-configured: \ - $(LIBSSH2_SRC_PATH)/libssh2-userauth-check.patch-applied + $(LIBSSH2_SRC_PATH)/libssh2-fix-import-lib-name.patch-applied $(BUILDDIR)/$(LIBSSH2_SRC_DIR)/build-configured: $(LIBSSH2_SRC_PATH)/source-extracted mkdir -p $(dir $@) diff --git a/deps/libuv.version b/deps/libuv.version index 5cffc1898842f..e4b277e36b099 100644 --- a/deps/libuv.version +++ b/deps/libuv.version @@ -4,4 +4,4 @@ LIBUV_JLL_NAME := LibUV ## source build LIBUV_VER := 2 LIBUV_BRANCH=julia-uv2-1.44.2 -LIBUV_SHA1=3f7038d62e43c3682394a6ea7b4ccc46be0fa0bf +LIBUV_SHA1=e6f0e4900e195c8352f821abe2b3cffc3089547b diff --git a/deps/lld.version b/deps/lld.version index 89b6829a99df9..2b34a5d3012ad 100644 --- a/deps/lld.version +++ b/deps/lld.version @@ -1,3 +1,3 @@ ## jll artifact LLD_JLL_NAME := LLD -LLD_JLL_VER := 14.0.5+3 +LLD_JLL_VER := 14.0.6+0 diff --git a/deps/llvm-tools.version b/deps/llvm-tools.version index 522bc8a466ed5..5da312d32f0af 100644 --- a/deps/llvm-tools.version +++ b/deps/llvm-tools.version @@ -1,5 +1,5 @@ ## jll artifact # LLVM_tools (downloads LLVM_jll to get things like `lit` and `opt`) LLVM_TOOLS_JLL_NAME := LLVM -LLVM_TOOLS_JLL_VER := 14.0.5+3 -LLVM_TOOLS_ASSERT_JLL_VER := 14.0.5+3 +LLVM_TOOLS_JLL_VER := 14.0.6+0 +LLVM_TOOLS_ASSERT_JLL_VER := 14.0.6+0 diff --git a/deps/llvm.mk b/deps/llvm.mk index f0312ed6decda..5d297b6c369bf 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -56,6 +56,9 @@ endif ifeq ($(BUILD_LIBCXX), 1) LLVM_ENABLE_RUNTIMES := $(LLVM_ENABLE_RUNTIMES);libcxx;libcxxabi endif +ifeq ($(BUILD_LLD), 1) +LLVM_ENABLE_PROJECTS := $(LLVM_ENABLE_PROJECTS);lld +endif LLVM_LIB_FILE := libLLVMCodeGen.a @@ -309,6 +312,6 @@ $(eval $(call bb-install,clang,CLANG,false,true)) $(eval $(call bb-install,lld,LLD,false,true)) $(eval $(call bb-install,llvm-tools,LLVM_TOOLS,false,true)) -install-lld install-clang install-llvm-tools: install-llvm - endif # USE_BINARYBUILDER_LLVM + +install-lld install-clang install-llvm-tools: install-llvm diff --git a/deps/llvm.version b/deps/llvm.version index 969134091759c..2dbcd0f510f81 100644 --- a/deps/llvm.version +++ b/deps/llvm.version @@ -4,5 +4,5 @@ LLVM_ASSERT_JLL_VER := 14.0.5+3 ## source build LLVM_VER := 14.0.5 -LLVM_BRANCH=julia-14.0.5-3 -LLVM_SHA1=julia-14.0.5-3 +LLVM_BRANCH=julia-14.0.6-0 +LLVM_SHA1=julia-14.0.6-0 diff --git a/deps/mpfr.mk b/deps/mpfr.mk index 1bb3ff32c302f..36a4f77c6a929 100644 --- a/deps/mpfr.mk +++ b/deps/mpfr.mk @@ -7,28 +7,23 @@ endif ifneq ($(USE_BINARYBUILDER_MPFR),1) -MPFR_OPTS := --enable-thread-safe --enable-shared-cache --disable-float128 --disable-decimal-float -ifeq ($(USE_SYSTEM_GMP), 0) -MPFR_OPTS += --with-gmp-include=$(abspath $(build_includedir)) --with-gmp-lib=$(abspath $(build_shlibdir)) -endif -ifeq ($(BUILD_OS),WINNT) -ifeq ($(OS),WINNT) -MPFR_OPTS += CFLAGS="$(CFLAGS) -DNPRINTF_L -DNPRINTF_T -DNPRINTF_J" -endif -endif +MPFR_CONFIGURE_OPTS := $(CONFIGURE_COMMON) +MPFR_CONFIGURE_OPTS += --enable-thread-safe --enable-shared-cache --disable-float128 --disable-decimal-float +MPFR_CONFIGURE_OPTS += --enable-shared --disable-static - -ifeq ($(OS),Darwin) -MPFR_CHECK_MFLAGS := LDFLAGS="$(LDFLAGS) -Wl,-rpath,'$(build_libdir)'" +ifeq ($(USE_SYSTEM_GMP), 0) +MPFR_CONFIGURE_OPTS += --with-gmp=$(abspath $(build_prefix)) endif ifeq ($(SANITIZE),1) # Force generic C build -MPFR_OPTS += --host=none-unknown-linux +MPFR_CONFIGURE_OPTS += --host=none-unknown-linux endif + $(SRCCACHE)/mpfr-$(MPFR_VER).tar.bz2: | $(SRCCACHE) $(JLDOWNLOAD) $@ https://www.mpfr.org/mpfr-$(MPFR_VER)/$(notdir $@) + $(SRCCACHE)/mpfr-$(MPFR_VER)/source-extracted: $(SRCCACHE)/mpfr-$(MPFR_VER).tar.bz2 $(JLCHECKSUM) $< cd $(dir $<) && $(TAR) -jxf $< @@ -42,23 +37,24 @@ checksum-mpfr: $(SRCCACHE)/mpfr-$(MPFR_VER).tar.bz2 $(BUILDDIR)/mpfr-$(MPFR_VER)/build-configured: $(SRCCACHE)/mpfr-$(MPFR_VER)/source-extracted mkdir -p $(dir $@) cd $(dir $@) && \ - $(dir $<)/configure $(CONFIGURE_COMMON) $(MPFR_OPTS) F77= --enable-shared --disable-static + $(dir $<)/configure $(MPFR_CONFIGURE_OPTS) echo 1 > $@ $(BUILDDIR)/mpfr-$(MPFR_VER)/build-compiled: $(BUILDDIR)/mpfr-$(MPFR_VER)/build-configured - $(MAKE) -C $(dir $<) $(LIBTOOL_CCLD) + $(MAKE) -C $(dir $<) echo 1 > $@ $(BUILDDIR)/mpfr-$(MPFR_VER)/build-checked: $(BUILDDIR)/mpfr-$(MPFR_VER)/build-compiled ifeq ($(OS),$(BUILD_OS)) - $(MAKE) -C $(dir $@) $(LIBTOOL_CCLD) check $(MPFR_CHECK_MFLAGS) + $(MAKE) -C $(dir $@) check endif echo 1 > $@ $(eval $(call staged-install, \ mpfr,mpfr-$(MPFR_VER), \ - MAKE_INSTALL,$$(LIBTOOL_CCLD),, \ - $$(INSTALL_NAME_CMD)libmpfr.$$(SHLIB_EXT) $$(build_shlibdir)/libmpfr.$$(SHLIB_EXT))) + MAKE_INSTALL,,, \ + $$(WIN_MAKE_HARD_LINK) $(build_bindir)/libmpfr-*.dll $(build_bindir)/libmpfr.dll && \ + $$(INSTALL_NAME_CMD)libmpfr.$$(SHLIB_EXT) $$(build_shlibdir)/libmpfr.$$(SHLIB_EXT))) clean-mpfr: -rm -f $(BUILDDIR)/mpfr-$(MPFR_VER)/build-configured $(BUILDDIR)/mpfr-$(MPFR_VER)/build-compiled diff --git a/deps/openblas.version b/deps/openblas.version index 843bb449c92c7..9e433d2629071 100644 --- a/deps/openblas.version +++ b/deps/openblas.version @@ -1,10 +1,11 @@ +# -*- makefile -*- ## jll artifact OPENBLAS_JLL_NAME := OpenBLAS ## source build -OPENBLAS_VER := 0.3.20 -OPENBLAS_BRANCH=v0.3.20 -OPENBLAS_SHA1=0b678b19dc03f2a999d6e038814c4c50b9640a4e +OPENBLAS_VER := 0.3.21 +OPENBLAS_BRANCH=v0.3.21 +OPENBLAS_SHA1=b89fb708caa5a5a32de8f4306c4ff132e0228e9a # LAPACK, source-only LAPACK_VER := 3.9.0 diff --git a/deps/patches/libssh2-fix-import-lib-name.patch b/deps/patches/libssh2-fix-import-lib-name.patch new file mode 100644 index 0000000000000..15aafb58d2736 --- /dev/null +++ b/deps/patches/libssh2-fix-import-lib-name.patch @@ -0,0 +1,26 @@ +From 3732420725efbf410df5863b91a09ca214ee18ba Mon Sep 17 00:00:00 2001 +From: "Y. Yang" +Date: Thu, 16 Jun 2022 19:16:37 +0800 +Subject: [PATCH] Fix DLL import library name + +https://aur.archlinux.org/packages/mingw-w64-libssh2 +https://cmake.org/cmake/help/latest/prop_tgt/IMPORT_PREFIX.html +--- + src/CMakeLists.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index cb8fee1..17ecefd 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -220,6 +220,7 @@ endif() + add_library(libssh2 ${SOURCES}) + # we want it to be called libssh2 on all platforms + set_target_properties(libssh2 PROPERTIES PREFIX "") ++set_target_properties(libssh2 PROPERTIES IMPORT_PREFIX "") + + target_compile_definitions(libssh2 PRIVATE ${PRIVATE_COMPILE_DEFINITIONS}) + target_include_directories(libssh2 +-- +2.36.1 + diff --git a/doc/make.jl b/doc/make.jl index 5f5986497c922..61adf2ec603fa 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -343,6 +343,7 @@ function Documenter.deploy_folder(::BuildBotConfig; devurl, repo, branch, kwargs @info "Unable to deploy the documentation: DOCUMENTER_KEY missing" return Documenter.DeployDecision(; all_ok=false) end + release = match(r"^release-([0-9]+\.[0-9]+)$", Base.GIT_VERSION_INFO.branch) if Base.GIT_VERSION_INFO.tagged_commit # Strip extra pre-release info (1.5.0-rc2.0 -> 1.5.0-rc2) ver = VersionNumber(VERSION.major, VERSION.minor, VERSION.patch, @@ -351,6 +352,10 @@ function Documenter.deploy_folder(::BuildBotConfig; devurl, repo, branch, kwargs return Documenter.DeployDecision(; all_ok=true, repo, branch, subfolder) elseif Base.GIT_VERSION_INFO.branch == "master" return Documenter.DeployDecision(; all_ok=true, repo, branch, subfolder=devurl) + elseif !isnothing(release) + # If this is a non-tag build from a release-* branch, we deploy them as dev docs into the + # appropriate vX.Y-dev subdirectory. + return Documenter.DeployDecision(; all_ok=true, repo, branch, subfolder="v$(release[1])-dev") end @info """ Unable to deploy the documentation: invalid GIT_VERSION_INFO diff --git a/doc/src/base/base.md b/doc/src/base/base.md index 51fa0150eab9d..54ef38f78616f 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -347,6 +347,8 @@ Base.Sys.iswindows Base.Sys.windows_version Base.Sys.free_memory Base.Sys.total_memory +Base.Sys.free_physical_memory +Base.Sys.total_physical_memory Base.Sys.uptime Base.Sys.isjsvm Base.Sys.loadavg diff --git a/doc/src/devdocs/build/build.md b/doc/src/devdocs/build/build.md index 541c402d7519c..4fd5e25731dff 100644 --- a/doc/src/devdocs/build/build.md +++ b/doc/src/devdocs/build/build.md @@ -167,7 +167,7 @@ Julia uses the following external libraries, which are automatically downloaded (or in a few cases, included in the Julia source repository) and then compiled from source the first time you run `make`. The specific version numbers of these libraries that Julia -uses are listed in [`deps/$(LibName).version`](https://github.com/JuliaLang/julia/blob/master/deps/): +uses are listed in [`deps/$(libname).version`](https://github.com/JuliaLang/julia/blob/master/deps/): - **[LLVM]** (14.0 + [patches](https://github.com/JuliaLang/llvm-project)) — compiler infrastructure (see [note below](#llvm)). - **[FemtoLisp]** — packaged with Julia source, and used to implement the compiler front-end. @@ -303,3 +303,50 @@ From this point, you should (Note that `sudo` isn't installed, but neither is it necessary since you are running as `root`, so you can omit `sudo` from all commands.) Then add all the [build dependencies](@ref build-tools), a console-based editor of your choice, `git`, and anything else you'll need (e.g., `gdb`, `rr`, etc). Pick a directory to work in and `git clone` Julia, check out the branch you wish to debug, and build Julia as usual. + + +## Update the version number of a dependency + +There are two types of builds +1. Build everything (`deps/` and `src/`) from source code. + (Add `USE_BINARYBUILDER=0` to `Make.user`, see [Building Julia](#building-julia)) +2. Build from source (`src/`) with pre-compiled dependencies (default) + +When you want to update the version number of a dependency in `deps/`, +you may want to use the following checklist: + +```md +### Check list + +Version numbers: +- [ ] `deps/$(libname).version`: `LIBNAME_VER`, `LIBNAME_BRANCH`, `LIBNAME_SHA1` and `LIBNAME_JLL_VER` +- [ ] `stdlib/$(LIBNAME_JLL_NAME)_jll/Project.toml`: `version` + +Checksum: +- [ ] `deps/checksums/$(libname)` +- [ ] `deps/checksums/$(LIBNAME_JLL_NAME)-*/`: `md5` and `sha512` + +Patches: +- [ ] `deps/$(libname).mk` +- [ ] `deps/patches/$(libname)-*.patch` +``` + +Note: +- For specific dependencies, some items in the checklist may not exist. +- For checksum file, it may be **a single file** without a suffix, or **a folder** containing two files. + + +### Example: `OpenLibm` + +1. Update Version numbers in `deps/openlibm.version` + - `OPENLIBM_VER := 0.X.Y` + - `OPENLIBM_BRANCH = v0.X.Y` + - `OPENLIBM_SHA1 = new-sha1-hash` +2. Update Version number in `stdlib/OpenLibm_jll/Project.toml` + - `version = "0.X.Y+0"` +3. Update checksums in `deps/checksums/openlibm` + - `make -f contrib/refresh_checksums.mk openlibm` +4. Check if the patch files `deps/patches/openlibm-*.patch` exist + - if patches don't exist, skip. + - if patches exist, check if they have been merged into the new version and need to be removed. + When deleting a patch, remember to modify the corresponding Makefile file (`deps/openlibm.mk`). diff --git a/doc/src/devdocs/build/windows.md b/doc/src/devdocs/build/windows.md index 4b1ed0054e18f..4f7f40a030488 100644 --- a/doc/src/devdocs/build/windows.md +++ b/doc/src/devdocs/build/windows.md @@ -115,11 +115,67 @@ MinGW-w64 compilers available through Cygwin's package manager. ### Compiling with MinGW/MSYS2 -Compiling Julia from source using [MSYS2](https://msys2.github.io) has worked in the past -but is not actively supported. Pull requests to restore support would be welcome. See a -[past version of this -file](https://github.com/JuliaLang/julia/blob/v0.6.0/README.windows.md) for the former -instructions for compiling using MSYS2. +> MSYS2 provides a robust MSYS experience. + +Note: MSYS2 requires **64 bit** Windows 7 or newer. + + 1. Install and configure [MSYS2](https://www.msys2.org/), Software Distribution + and Building Platform for Windows. + + 1. Download and run the latest installer for the + [64-bit](https://github.com/msys2/msys2-installer/releases/latest) distribution. + The installer will have a name like `msys2-x86_64-yyyymmdd.exe`. + + 2. Open MSYS2. Update package database and base packages: + ```sh + pacman -Syu + ``` + + 3. Exit and restart MSYS2, Update the rest of the base packages: + ```sh + pacman -Syu + ``` + + 3. Then install tools required to build julia: + ```sh + # tools + pacman -S cmake diffutils git m4 make patch tar p7zip curl python + + # For 64 bit Julia, install x86_64 + pacman -S mingw-w64-x86_64-gcc + # For 32 bit Julia, install i686 + pacman -S mingw-w64-i686-gcc + ``` + + 4. Configuration of MSYS2 is complete. Now `exit` the MSYS2 shell. + + + 2. Build Julia and its dependencies with pre-build dependencies. + + 1. Open a new [**MINGW64/MINGW32 shell**](https://www.msys2.org/docs/environments/#overview). + Currently we can't use both mingw32 and mingw64, + so if you want to build the x86_64 and i686 versions, + you'll need to build them in each environment separately. + + 2. and clone the Julia sources + ```sh + git clone https://github.com/JuliaLang/julia.git + cd julia + ``` + + 3. Start the build + ```sh + make -j$(nproc) + ``` + + > Protip: build in dir + > ```sh + > make O=julia-mingw-w64 configure + > echo 'ifeq ($(BUILDROOT),$(JULIAHOME)) + > $(error "in-tree build disabled") + > endif' >> Make.user + > make -C julia-mingw-w64 + > ``` ### Cross-compiling from Unix (Linux/Mac/WSL) diff --git a/doc/src/devdocs/llvm.md b/doc/src/devdocs/llvm.md index 9a833ca8af516..6c6b33c2281dc 100644 --- a/doc/src/devdocs/llvm.md +++ b/doc/src/devdocs/llvm.md @@ -9,18 +9,36 @@ Julia dynamically links against LLVM by default. Build with `USE_LLVM_SHLIB=0` t The code for lowering Julia AST to LLVM IR or interpreting it directly is in directory `src/`. -| File | Description | -|:------------------- |:---------------------------------------------------------- | -| `builtins.c` | Builtin functions | -| `ccall.cpp` | Lowering [`ccall`](@ref) | -| `cgutils.cpp` | Lowering utilities, notably for array and tuple accesses | -| `codegen.cpp` | Top-level of code generation, pass list, lowering builtins | -| `debuginfo.cpp` | Tracks debug information for JIT code | -| `disasm.cpp` | Handles native object file and JIT code diassembly | -| `gf.c` | Generic functions | -| `intrinsics.cpp` | Lowering intrinsics | -| `llvm-simdloop.cpp` | Custom LLVM pass for [`@simd`](@ref) | -| `sys.c` | I/O and operating system utility functions | +| File | Description | +|:-------------------------------- |:------------------------------------------------------------------ | +| `aotcompile.cpp` | Legacy pass manager pipeline, compiler C-interface entry | +| `builtins.c` | Builtin functions | +| `ccall.cpp` | Lowering [`ccall`](@ref) | +| `cgutils.cpp` | Lowering utilities, notably for array and tuple accesses | +| `codegen.cpp` | Top-level of code generation, pass list, lowering builtins | +| `debuginfo.cpp` | Tracks debug information for JIT code | +| `disasm.cpp` | Handles native object file and JIT code diassembly | +| `gf.c` | Generic functions | +| `intrinsics.cpp` | Lowering intrinsics | +| `jitlayers.cpp` | JIT-specific code, ORC compilation layers/utilities | +| `llvm-alloc-helpers.cpp` | Julia-specific escape analysis | +| `llvm-alloc-opt.cpp` | Custom LLVM pass to demote heap allocations to the stack | +| `llvm-cpufeatures.cpp` | Custom LLVM pass to lower CPU-based functions (e.g. haveFMA) | +| `llvm-demote-float16.cpp` | Custom LLVM pass to lower 16b float ops to 32b float ops | +| `llvm-final-gc-lowering.cpp` | Custom LLVM pass to lower GC calls to their final form | +| `llvm-gc-invariant-verifier.cpp` | Custom LLVM pass to verify Julia GC invariants | +| `llvm-julia-licm.cpp` | Custom LLVM pass to hoist/sink Julia-specific intrinsics | +| `llvm-late-gc-lowering.cpp` | Custom LLVM pass to root GC-tracked values | +| `llvm-lower-handlers.cpp` | Custom LLVM pass to lower try-catch blocks | +| `llvm-muladd.cpp` | Custom LLVM pass for fast-match FMA | +| `llvm-multiversioning.cpp` | Custom LLVM pass to generate sysimg code on multiple architectures | +| `llvm-propagate-addrspaces.cpp` | Custom LLVM pass to canonicalize addrspaces | +| `llvm-ptls.cpp` | Custom LLVM pass to lower TLS operations | +| `llvm-remove-addrspaces.cpp` | Custom LLVM pass to remove Julia addrspaces | +| `llvm-remove-ni.cpp` | Custom LLVM pass to remove Julia non-integral addrspaces | +| `llvm-simdloop.cpp` | Custom LLVM pass for [`@simd`](@ref) | +| `pipeline.cpp` | New pass manager pipeline, pass pipeline parsing | +| `sys.c` | I/O and operating system utility functions | Some of the `.cpp` files form a group that compile to a single object. @@ -77,12 +95,18 @@ LLVM tools as usual. `libjulia` can function as an LLVM pass plugin and can be loaded into LLVM tools, to make julia-specific passes available in this environment. In addition, it exposes the `-julia` meta-pass, which runs the entire Julia pass-pipeline over the IR. As an example, to generate a system -image, one could do: +image with the old pass manager, one could do: ``` opt -enable-new-pm=0 -load libjulia-codegen.so -julia -o opt.bc unopt.bc llc -o sys.o opt.bc cc -shared -o sys.so sys.o ``` +To generate a system image with the new pass manager, one could do: +``` +opt -load-pass-plugin=libjulia-codegen.so --passes='julia' -o opt.bc unopt.bc +llc -o sys.o opt.bc +cc -shared -o sys.so sys.o +``` This system image can then be loaded by `julia` as usual. It is also possible to dump an LLVM IR module for just one Julia function, diff --git a/doc/src/devdocs/locks.md b/doc/src/devdocs/locks.md index 6390277826f7a..6cc0c1270ca85 100644 --- a/doc/src/devdocs/locks.md +++ b/doc/src/devdocs/locks.md @@ -32,6 +32,7 @@ The following are definitely leaf locks (level 1), and must not try to acquire a > * RLST_mutex > * jl_locked_stream::mutex > * debuginfo_asyncsafe +> * inference_timing_mutex > > > flisp itself is already threadsafe, this lock only protects the `jl_ast_context_list_t` pool > > likewise, the ResourcePool::mutexes just protect the associated resource pool diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 1c71a4bd59e35..3126f1c2a3270 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -879,10 +879,15 @@ slower than multiplication. While some arrays — like [`Array`](@ref) itself are implemented using a linear chunk of memory and directly use a linear index in their implementations, other arrays — like [`Diagonal`](@ref) — need the full set of cartesian indices to do their lookup (see [`IndexStyle`](@ref) to -introspect which is which). As such, when iterating over an entire array, it's -much better to iterate over [`eachindex(A)`](@ref) instead of `1:length(A)`. -Not only will the former be much faster in cases where `A` is `IndexCartesian`, -but it will also support [OffsetArrays](https://github.com/JuliaArrays/OffsetArrays.jl), too. +introspect which is which). + +!!! warnings + + When iterating over all the indices for an array, it is + better to iterate over [`eachindex(A)`](@ref) instead of `1:length(A)`. + Not only will this be faster in cases where `A` is `IndexCartesian`, + but it will also support arrays with custom indexing, such as [OffsetArrays](https://github.com/JuliaArrays/OffsetArrays.jl). + If only the values are needed, then is better to just iterate the array directly, i.e. `for a in A`. #### Omitted and extra indices @@ -974,8 +979,11 @@ i = CartesianIndex(2, 2) i = CartesianIndex(3, 2) ``` -In contrast with `for i = 1:length(A)`, iterating with [`eachindex`](@ref) provides an efficient way to -iterate over any array type. +!!! note + + In contrast with `for i = 1:length(A)`, iterating with [`eachindex`](@ref) provides an efficient way to + iterate over any array type. Besides, this also supports generic arrays with custom indexing such as + [OffsetArrays](https://github.com/JuliaArrays/OffsetArrays.jl). ## Array traits diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index 63ae37660cff4..82073c1446bf8 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -181,7 +181,7 @@ For example, this definition states that it's valid to `convert` any `Number` ty any other by calling a 1-argument constructor: ```julia -convert(::Type{T}, x::Number) where {T<:Number} = T(x) +convert(::Type{T}, x::Number) where {T<:Number} = T(x)::T ``` This means that new `Number` types only need to define constructors, since this diff --git a/doc/src/manual/distributed-computing.md b/doc/src/manual/distributed-computing.md index 2c1af8ecb9c26..544dace1a99ec 100644 --- a/doc/src/manual/distributed-computing.md +++ b/doc/src/manual/distributed-computing.md @@ -251,7 +251,7 @@ The base Julia installation has in-built support for two types of clusters: should use to connect to this worker. !!! note - While Julia generally strives for backward compatability, distribution of code to worker processes relies on + While Julia generally strives for backward compatibility, distribution of code to worker processes relies on [`Serialization.serialize`](@ref). As pointed out in the corresponding documentation, this can not be guaranteed to work across different Julia versions, so it is advised that all workers on all machines use the same version. diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index af4185a0f1266..5f1671bc416cf 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -220,10 +220,10 @@ ourselves, we can officially define it as a subtype of an [`AbstractArray`](@ref | `size(A)` | | Returns a tuple containing the dimensions of `A` | | `getindex(A, i::Int)` | | (if `IndexLinear`) Linear scalar indexing | | `getindex(A, I::Vararg{Int, N})` | | (if `IndexCartesian`, where `N = ndims(A)`) N-dimensional scalar indexing | -| `setindex!(A, v, i::Int)` | | (if `IndexLinear`) Scalar indexed assignment | -| `setindex!(A, v, I::Vararg{Int, N})` | | (if `IndexCartesian`, where `N = ndims(A)`) N-dimensional scalar indexed assignment | | **Optional methods** | **Default definition** | **Brief description** | | `IndexStyle(::Type)` | `IndexCartesian()` | Returns either `IndexLinear()` or `IndexCartesian()`. See the description below. | +| `setindex!(A, v, i::Int)` | | (if `IndexLinear`) Scalar indexed assignment | +| `setindex!(A, v, I::Vararg{Int, N})` | | (if `IndexCartesian`, where `N = ndims(A)`) N-dimensional scalar indexed assignment | | `getindex(A, I...)` | defined in terms of scalar `getindex` | [Multidimensional and nonscalar indexing](@ref man-array-indexing) | | `setindex!(A, X, I...)` | defined in terms of scalar `setindex!` | [Multidimensional and nonscalar indexed assignment](@ref man-array-indexing) | | `iterate` | defined in terms of scalar `getindex` | Iteration | @@ -739,7 +739,7 @@ in one or two dimensional outputs, but produce an `Array` for any other dimensio | Methods to implement | Default definition | Brief description | |:--------------------------------- |:---------------------------- |:------------------------------------------------------------------------------------- | -| `propertynames(x::ObjType, private::Bool=false)` | `fieldnames(typeof((x))` | Return a tuple of the properties (`x.property`) of an object `x`. If `private=true`, also return fieldnames intended to be kept as private | +| `propertynames(x::ObjType, private::Bool=false)` | `fieldnames(typeof(x))` | Return a tuple of the properties (`x.property`) of an object `x`. If `private=true`, also return property names intended to be kept as private | | `getproperty(x::ObjType, s::Symbol)` | `getfield(x, s)` | Return property `s` of `x`. `x.s` calls `getproperty(x, :s)`. | | `setproperty!(x::ObjType, s::Symbol, v)` | `setfield!(x, s, v)` | Set property `s` of `x` to `v`. `x.s = v` calls `setproperty!(x, :s, v)`. Should return `v`.| diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index c6009594bea2d..9a250fdf716a8 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -325,7 +325,17 @@ include(p) = Base.include(Mod, p) end ``` -If even `Core` is not wanted, a module that imports nothing and defines no names at all can be defined with `Module(:YourNameHere, false, false)` and code can be evaluated into it with [`@eval`](@ref) or [`Core.eval`](@ref). +If even `Core` is not wanted, a module that imports nothing and defines no names at all can be defined with `Module(:YourNameHere, false, false)` and code can be evaluated into it with [`@eval`](@ref) or [`Core.eval`](@ref): +```jldoctest +julia> arithmetic = Module(:arithmetic, false, false) +Main.arithmetic + +julia> @eval arithmetic add(x, y) = $(+)(x, y) +add (generic function with 1 method) + +julia> arithmetic.add(12, 13) +25 +``` ### Standard modules diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 055569d873d50..8a2b5ab1d4a5b 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -108,9 +108,26 @@ local x::Int8 # in a local declaration x::Int8 = 10 # as the left-hand side of an assignment ``` -and applies to the whole current scope, even before the declaration. Currently, type declarations -cannot be used in global scope, e.g. in the REPL, since Julia does not yet have constant-type -globals. +and applies to the whole current scope, even before the declaration. + +As of Julia 1.8, type declarations can now be used in global scope i.e. +type annotations can be added to global variables to make accessing them type stable. +```julia +julia> x::Int = 10 +10 + +julia> x = 3.5 +ERROR: InexactError: Int64(3.5) + +julia> function foo(y) + global x = 15.8 # throws an error when foo is called + return x + y + end +foo (generic function with 1 method) + +julia> foo(10) +ERROR: InexactError: Int64(15.8) +``` Declarations can also be attached to function definitions: @@ -1524,7 +1541,7 @@ when the `:compact` property is set to `true`, falling back to the long representation if the property is `false` or absent: ```jldoctest polartype julia> function Base.show(io::IO, z::Polar) - if get(io, :compact, false) + if get(io, :compact, false)::Bool print(io, z.r, "ℯ", z.Θ, "im") else print(io, z.r, " * exp(", z.Θ, "im)") diff --git a/src/abi_aarch64.cpp b/src/abi_aarch64.cpp index 1a3f160329c6c..514c3c5a81a6d 100644 --- a/src/abi_aarch64.cpp +++ b/src/abi_aarch64.cpp @@ -43,9 +43,11 @@ Type *get_llvm_vectype(jl_datatype_t *dt, LLVMContext &ctx) const // the homogeneity check. jl_datatype_t *ft0 = (jl_datatype_t*)jl_field_type(dt, 0); // `ft0` should be a `VecElement` type and the true element type - // should be a primitive type - if (ft0->name != jl_vecelement_typename || - ((jl_datatype_t*)jl_field_type(ft0, 0))->layout->nfields) + // should be a primitive type (nfields == 0) + if (!jl_is_datatype(ft0) || ft0->name != jl_vecelement_typename) + return nullptr; + jl_datatype_t *ft00 = (jl_datatype_t*)jl_field_type(ft0, 0); + if (!jl_is_datatype(ft00) || ft00->layout->nfields) return nullptr; for (size_t i = 1; i < nfields; i++) { if (jl_field_type(dt, i) != (jl_value_t*)ft0) { @@ -120,15 +122,17 @@ bool isHFAorHVA(jl_datatype_t *dt, size_t dsz, size_t &nele, ElementType &ele, L // For composite types, find the first non zero sized member size_t i; size_t fieldsz; - for (i = 0;i < nfields;i++) { + for (i = 0; i < nfields; i++) { if ((fieldsz = jl_field_size(dt, i))) { break; } } assert(i < nfields); - // If there's only one non zero sized member, try again on this member + // If there's only one non-zero sized member, try again on this member if (fieldsz == dsz) { dt = (jl_datatype_t*)jl_field_type(dt, i); + if (!jl_is_datatype(dt)) + return false; continue; } if (Type *vectype = get_llvm_vectype(dt, ctx)) { @@ -140,11 +144,13 @@ bool isHFAorHVA(jl_datatype_t *dt, size_t dsz, size_t &nele, ElementType &ele, L return true; } // Otherwise, process each members - for (;i < nfields;i++) { + for (; i < nfields; i++) { size_t fieldsz = jl_field_size(dt, i); if (fieldsz == 0) continue; jl_datatype_t *fieldtype = (jl_datatype_t*)jl_field_type(dt, i); + if (!jl_is_datatype(dt)) + return false; // Check element count. // This needs to be done after the zero size member check if (nele > 3 || !isHFAorHVA(fieldtype, fieldsz, nele, ele, ctx)) { diff --git a/src/abi_arm.cpp b/src/abi_arm.cpp index 4987d07657ae6..441aa95b1fdf6 100644 --- a/src/abi_arm.cpp +++ b/src/abi_arm.cpp @@ -91,6 +91,8 @@ size_t isLegalHA(jl_datatype_t *dt, Type *&base, LLVMContext &ctx) const size_t parent_members = jl_datatype_nfields(dt); for (size_t i = 0; i < parent_members; ++i) { jl_datatype_t *fdt = (jl_datatype_t*)jl_field_type(dt,i); + if (!jl_is_datatype(fdt)) + return 0; Type *T = isLegalHAType(fdt, ctx); if (T) diff --git a/src/abi_ppc64le.cpp b/src/abi_ppc64le.cpp index 016eebd455525..2e18acdbd4f4b 100644 --- a/src/abi_ppc64le.cpp +++ b/src/abi_ppc64le.cpp @@ -44,6 +44,9 @@ struct ABI_PPC64leLayout : AbiLayout { // count the homogeneous floating aggregate size (saturating at max count of 8) unsigned isHFA(jl_datatype_t *ty, jl_datatype_t **ty0, bool *hva) const { + if (jl_datatype_size(ty) > 128 || ty->layout->npointers || ty->layout->haspadding) + return 9; + size_t i, l = ty->layout->nfields; // handle homogeneous float aggregates if (l == 0) { @@ -52,7 +55,7 @@ unsigned isHFA(jl_datatype_t *ty, jl_datatype_t **ty0, bool *hva) const *hva = false; if (*ty0 == NULL) *ty0 = ty; - else if (*hva || ty->size != (*ty0)->size) + else if (*hva || jl_datatype_size(ty) != jl_datatype_size(*ty0)) return 9; return 1; } @@ -69,7 +72,7 @@ unsigned isHFA(jl_datatype_t *ty, jl_datatype_t **ty0, bool *hva) const *hva = true; if (*ty0 == NULL) *ty0 = ty; - else if (!*hva || ty->size != (*ty0)->size) + else if (!*hva || jl_datatype_size(ty) != jl_datatype_size(*ty0)) return 9; for (i = 1; i < l; i++) { jl_datatype_t *fld = (jl_datatype_t*)jl_field_type(ty, i); diff --git a/src/abi_x86_64.cpp b/src/abi_x86_64.cpp index 43e539b8386ce..c3d12417e6de8 100644 --- a/src/abi_x86_64.cpp +++ b/src/abi_x86_64.cpp @@ -153,6 +153,10 @@ void classifyType(Classification& accum, jl_datatype_t *dt, uint64_t offset) con jl_value_t *ty = jl_field_type(dt, i); if (jl_field_isptr(dt, i)) ty = (jl_value_t*)jl_voidpointer_type; + else if (!jl_is_datatype(ty)) { // inline union + accum.addField(offset, Memory); + continue; + } classifyType(accum, (jl_datatype_t*)ty, offset + jl_field_offset(dt, i)); } } diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 78a259244c74e..98777ddd175a1 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -5,6 +5,7 @@ // target support #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -58,11 +60,17 @@ using namespace llvm; -#include "julia.h" -#include "julia_internal.h" #include "jitlayers.h" #include "julia_assert.h" +#define DEBUG_TYPE "julia_aotcompile" + +STATISTIC(CICacheLookups, "Number of codeinst cache lookups"); +STATISTIC(CreateNativeCalls, "Number of jl_create_native calls made"); +STATISTIC(CreateNativeMethods, "Number of methods compiled for jl_create_native"); +STATISTIC(CreateNativeMax, "Max number of methods compiled at once for jl_create_native"); +STATISTIC(CreateNativeGlobals, "Number of globals compiled for jl_create_native"); + template // for GlobalObject's static T *addComdat(T *G) { @@ -215,6 +223,7 @@ static void makeSafeName(GlobalObject &G) static void jl_ci_cache_lookup(const jl_cgparams_t &cgparams, jl_method_instance_t *mi, size_t world, jl_code_instance_t **ci_out, jl_code_info_t **src_out) { + ++CICacheLookups; jl_value_t *ci = cgparams.lookup(mi, world, world); JL_GC_PROMISE_ROOTED(ci); jl_code_instance_t *codeinst = NULL; @@ -253,6 +262,8 @@ static void jl_ci_cache_lookup(const jl_cgparams_t &cgparams, jl_method_instance extern "C" JL_DLLEXPORT void *jl_create_native_impl(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvmmod, const jl_cgparams_t *cgparams, int _policy) { + ++CreateNativeCalls; + CreateNativeMax.updateMax(jl_array_len(methods)); if (cgparams == NULL) cgparams = &jl_default_cgparams; jl_native_code_desc_t *data = new jl_native_code_desc_t; @@ -334,6 +345,7 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvm gvars.push_back(std::string(global.second->getName())); data->jl_value_to_llvm[global.first] = gvars.size(); } + CreateNativeMethods += emitted.size(); // clones the contents of the module `m` to the shadow_output collector // while examining and recording what kind of function pointer we have @@ -376,6 +388,7 @@ void *jl_create_native_impl(jl_array_t *methods, LLVMOrcThreadSafeModuleRef llvm G->setLinkage(GlobalVariable::InternalLinkage); data->jl_sysimg_gvars.push_back(G); } + CreateNativeGlobals += gvars.size(); //Safe b/c context is locked by params #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) @@ -537,17 +550,20 @@ void jl_dump_native_impl(void *native_code, if (TM->addPassesToEmitFile(emitter, asm_OS, nullptr, CGFT_AssemblyFile, false)) jl_safe_printf("ERROR: target does not support generation of object files\n"); - legacy::PassManager optimizer; - if (bc_fname || obj_fname || asm_fname) { - addTargetPasses(&optimizer, TM->getTargetTriple(), TM->getTargetIRAnalysis()); - addOptimizationPasses(&optimizer, jl_options.opt_level, true, true); - addMachinePasses(&optimizer, jl_options.opt_level); - } - // Reset the target triple to make sure it matches the new target machine auto dataM = data->M.getModuleUnlocked(); dataM->setTargetTriple(TM->getTargetTriple().str()); dataM->setDataLayout(jl_create_datalayout(*TM)); + +#ifndef JL_USE_NEW_PM + legacy::PassManager optimizer; + addTargetPasses(&optimizer, TM->getTargetTriple(), TM->getTargetIRAnalysis()); + addOptimizationPasses(&optimizer, jl_options.opt_level, true, true); + addMachinePasses(&optimizer, jl_options.opt_level); +#else + NewPM optimizer{std::move(TM), getOptLevel(jl_options.opt_level), OptimizationOptions::defaults(true, true)}; +#endif + Type *T_size; if (sizeof(size_t) == 8) T_size = Type::getInt64Ty(Context); @@ -574,7 +590,7 @@ void jl_dump_native_impl(void *native_code, // do the actual work auto add_output = [&] (Module &M, StringRef unopt_bc_Name, StringRef bc_Name, StringRef obj_Name, StringRef asm_Name) { preopt.run(M, empty.MAM); - optimizer.run(M); + if (bc_fname || obj_fname || asm_fname) optimizer.run(M); // We would like to emit an alias or an weakref alias to redirect these symbols // but LLVM doesn't let us emit a GlobalAlias to a declaration... @@ -797,7 +813,11 @@ void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level, PM->add(createLowerSimdLoopPass()); // Annotate loop marked with "loopinfo" as LLVM parallel loop PM->add(createLICMPass()); PM->add(createJuliaLICMPass()); +#if JL_LLVM_VERSION >= 150000 + PM->add(createSimpleLoopUnswitchLegacyPass()); +#else PM->add(createLoopUnswitchPass()); +#endif PM->add(createLICMPass()); PM->add(createJuliaLICMPass()); PM->add(createInductiveRangeCheckEliminationPass()); // Must come before indvars @@ -944,45 +964,6 @@ void jl_add_optimization_passes_impl(LLVMPassManagerRef PM, int opt_level, int l addOptimizationPasses(unwrap(PM), opt_level, lower_intrinsics); } -// new pass manager plugin - -// NOTE: Instead of exporting all the constructors in passes.h we could -// forward the callbacks to the respective passes. LLVM seems to prefer this, -// and when we add the full pass builder having them directly will be helpful. -static void registerCallbacks(PassBuilder &PB) { - PB.registerPipelineParsingCallback( - [](StringRef Name, FunctionPassManager &PM, - ArrayRef InnerPipeline) { -#define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) { PM.addPass(CREATE_PASS); return true; } -#include "llvm-julia-passes.inc" -#undef FUNCTION_PASS - return false; - }); - - PB.registerPipelineParsingCallback( - [](StringRef Name, ModulePassManager &PM, - ArrayRef InnerPipeline) { -#define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) { PM.addPass(CREATE_PASS); return true; } -#include "llvm-julia-passes.inc" -#undef MODULE_PASS - return false; - }); - - PB.registerPipelineParsingCallback( - [](StringRef Name, LoopPassManager &PM, - ArrayRef InnerPipeline) { -#define LOOP_PASS(NAME, CREATE_PASS) if (Name == NAME) { PM.addPass(CREATE_PASS); return true; } -#include "llvm-julia-passes.inc" -#undef LOOP_PASS - return false; - }); -} - -extern "C" JL_DLLEXPORT ::llvm::PassPluginLibraryInfo -llvmGetPassPluginInfo() { - return {LLVM_PLUGIN_API_VERSION, "Julia", "1", registerCallbacks}; -} - // --- native code info, and dump function to IR and ASM --- // Get pointer to llvm::Function instance, compiling if necessary // for use in reflection from Julia. @@ -1051,10 +1032,14 @@ void jl_get_llvmf_defn_impl(jl_llvmf_dump_t* dump, jl_method_instance_t *mi, siz for (auto &global : output.globals) global.second->setLinkage(GlobalValue::ExternalLinkage); if (optimize) { +#ifndef JL_USE_NEW_PM legacy::PassManager PM; addTargetPasses(&PM, jl_ExecutionEngine->getTargetTriple(), jl_ExecutionEngine->getTargetIRAnalysis()); addOptimizationPasses(&PM, jl_options.opt_level); addMachinePasses(&PM, jl_options.opt_level); +#else + NewPM PM{jl_ExecutionEngine->cloneTargetMachine(), getOptLevel(jl_options.opt_level)}; +#endif //Safe b/c context lock is held by output PM.run(*m.getModuleUnlocked()); } diff --git a/src/builtins.c b/src/builtins.c index 954bff7771e3e..595014e97ee50 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -569,7 +569,7 @@ STATIC_INLINE void _grow_to(jl_value_t **root, jl_value_t ***oldargs, jl_svec_t *n_alloc = newalloc; } -static jl_value_t *do_apply( jl_value_t **args, uint32_t nargs, jl_value_t *iterate) +static jl_value_t *do_apply(jl_value_t **args, uint32_t nargs, jl_value_t *iterate) { jl_function_t *f = args[0]; if (nargs == 2) { diff --git a/src/ccall.cpp b/src/ccall.cpp index 99cf6a1f67f96..fb5799b081537 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -28,7 +28,6 @@ TRANSFORMED_CCALL_STAT(jl_set_next_task); TRANSFORMED_CCALL_STAT(jl_sigatomic_begin); TRANSFORMED_CCALL_STAT(jl_sigatomic_end); TRANSFORMED_CCALL_STAT(jl_svec_len); -TRANSFORMED_CCALL_STAT(jl_svec_isassigned); TRANSFORMED_CCALL_STAT(jl_svec_ref); TRANSFORMED_CCALL_STAT(jl_array_isassigned); TRANSFORMED_CCALL_STAT(jl_string_ptr); @@ -1687,28 +1686,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) JL_GC_POP(); return mark_or_box_ccall_result(ctx, len, retboxed, rt, unionall, static_rt); } - else if (is_libjulia_func(jl_svec_isassigned) && - argv[1].typ == (jl_value_t*)jl_long_type) { - ++CCALL_STAT(jl_svec_isassigned); - assert(!isVa && !llvmcall && nccallargs == 2); - const jl_cgval_t &svecv = argv[0]; - const jl_cgval_t &idxv = argv[1]; - Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idxv, (jl_value_t*)jl_long_type); - idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1)); - auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), ctx.types().T_pprjlvalue); - Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, - decay_derived(ctx, ptr), idx); - LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr, - Align(sizeof(void*))); - 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); - Value *res = ctx.builder.CreateZExt(ctx.builder.CreateICmpNE(load, Constant::getNullValue(ctx.types().T_prjlvalue)), getInt8Ty(ctx.builder.getContext())); - JL_GC_POP(); - return mark_or_box_ccall_result(ctx, res, retboxed, rt, unionall, static_rt); - } else if (is_libjulia_func(jl_svec_ref) && argv[1].typ == (jl_value_t*)jl_long_type) { ++CCALL_STAT(jl_svec_ref); assert(lrt == ctx.types().T_prjlvalue); @@ -1727,7 +1704,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) // This could otherwise be in a dead branch if (svecv.typ == (jl_value_t*)jl_simplevector_type) tbaa_decorate(ctx.tbaa().tbaa_const, load); - null_pointer_check(ctx, load); JL_GC_POP(); return mark_or_box_ccall_result(ctx, load, retboxed, rt, unionall, static_rt); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index ea42a319ff5cf..c42e6f14473b3 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -431,7 +431,7 @@ static inline void maybe_mark_argument_dereferenceable(AttrBuilder &B, jl_value_ { B.addAttribute(Attribute::NonNull); B.addAttribute(Attribute::NoUndef); - // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers. + // The `dereferenceable` below does not imply `nonnull` for non addrspace(0) pointers. size_t size = dereferenceable_size(jt); if (size) { B.addDereferenceableAttr(size); @@ -444,7 +444,7 @@ static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool { if (isa(LI->getType())) { if (!can_be_null) - // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers. + // The `dereferenceable` below does not imply `nonnull` for non addrspace(0) pointers. LI->setMetadata(LLVMContext::MD_nonnull, MDNode::get(LI->getContext(), None)); if (size) { Metadata *OP = ConstantAsMetadata::get(ConstantInt::get(getInt64Ty(LI->getContext()), size)); @@ -3348,7 +3348,7 @@ static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo, bool is_promotab static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, const jl_cgval_t &src, Value *skip, bool isVolatile=false) { if (AllocaInst *ai = dyn_cast(dest)) - // TODO: make this a lifetime_end & dereferencable annotation? + // TODO: make this a lifetime_end & dereferenceable annotation? ctx.builder.CreateAlignedStore(UndefValue::get(ai->getAllocatedType()), ai, ai->getAlign()); if (jl_is_concrete_type(src.typ) || src.constant) { jl_value_t *typ = src.constant ? jl_typeof(src.constant) : src.typ; diff --git a/src/clangsa/GCChecker.cpp b/src/clangsa/GCChecker.cpp index 38bd012ff46fc..34821d6bac9cb 100644 --- a/src/clangsa/GCChecker.cpp +++ b/src/clangsa/GCChecker.cpp @@ -53,8 +53,8 @@ class GCChecker check::Location> { mutable std::unique_ptr BT; template - void report_error(callback f, CheckerContext &C, const char *message) const; - void report_error(CheckerContext &C, const char *message) const { + void report_error(callback f, CheckerContext &C, StringRef message) const; + void report_error(CheckerContext &C, StringRef message) const { return report_error([](PathSensitiveBugReport *) {}, C, message); } void @@ -509,7 +509,7 @@ PDP GCChecker::GCValueBugVisitor::VisitNode(const ExplodedNode *N, template void GCChecker::report_error(callback f, CheckerContext &C, - const char *message) const { + StringRef message) const { // Generate an error node. ExplodedNode *N = C.generateErrorNode(); if (!N) @@ -745,6 +745,7 @@ bool GCChecker::isGCTrackedType(QualType QT) { Name.endswith_lower("jl_method_match_t") || Name.endswith_lower("jl_vararg_t") || Name.endswith_lower("jl_opaque_closure_t") || + Name.endswith_lower("jl_globalref_t") || // Probably not technically true for these, but let's allow it Name.endswith_lower("typemap_intersection_env") || Name.endswith_lower("interpreter_state") || @@ -1229,8 +1230,15 @@ void GCChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { // We could separate out "not safepoint, except for noreturn functions", // but that seems like a lot of effort with little benefit. if (!FD || !FD->isNoReturn()) { - report_error(C, "Calling potential safepoint from function annotated " - "JL_NOTSAFEPOINT"); + report_error( + [&](PathSensitiveBugReport *Report) { + if (FD) + Report->addNote( + "Tried to call method defined here", + PathDiagnosticLocation::create(FD, C.getSourceManager())); + }, + C, ("Calling potential safepoint as " + + Call.getKindAsString() + " from function annotated JL_NOTSAFEPOINT").str()); return; } } diff --git a/src/codegen.cpp b/src/codegen.cpp index 53bac38f78686..9c09314c9aee1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -155,8 +155,6 @@ typedef Instruction TerminatorInst; #define NOMINMAX #endif -#include "julia.h" -#include "julia_internal.h" #include "jitlayers.h" #include "codegen_shared.h" #include "processor.h" @@ -2146,12 +2144,7 @@ static void jl_init_function(Function *F) static std::pair uses_specsig(jl_method_instance_t *lam, jl_value_t *rettype, bool prefer_specsig) { - size_t nreq = jl_is_method(lam->def.method) ? lam->def.method->nargs : 0; - int va = 0; - if (nreq > 0 && lam->def.method->isva) { - nreq--; - va = 1; - } + int va = lam->def.method->isva; jl_value_t *sig = lam->specTypes; bool needsparams = false; if (jl_is_method(lam->def.method)) { @@ -4260,26 +4253,6 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i) return mark_julia_type(ctx, sp, true, jl_any_type); } -static jl_cgval_t emit_global(jl_codectx_t &ctx, jl_sym_t *sym) -{ - jl_binding_t *jbp = NULL; - Value *bp = global_binding_pointer(ctx, ctx.module, sym, &jbp, false); - if (bp == NULL) - return jl_cgval_t(); - if (jbp && jbp->value != NULL) { - if (jbp->constp) - return mark_julia_const(ctx, jbp->value); - // double-check that a global variable is actually defined. this - // can be a problem in parallel when a definition is missing on - // one machine. - LoadInst *v = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, bp, Align(sizeof(void*))); - v->setOrdering(AtomicOrdering::Unordered); - tbaa_decorate(ctx.tbaa().tbaa_binding, v); - return mark_julia_type(ctx, v, true, jl_any_type); - } - return emit_checked_var(ctx, bp, sym, false, ctx.tbaa().tbaa_binding); -} - static jl_cgval_t emit_isdefined(jl_codectx_t &ctx, jl_value_t *sym) { Value *isnull = NULL; @@ -4930,7 +4903,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_ { if (jl_is_symbol(expr)) { jl_sym_t *sym = (jl_sym_t*)expr; - return emit_global(ctx, sym); + return emit_globalref(ctx, ctx.module, sym, AtomicOrdering::Unordered); } if (jl_is_slot(expr) || jl_is_argument(expr)) { return emit_local(ctx, expr); @@ -6616,6 +6589,7 @@ get_specsig_di(jl_codectx_t &ctx, jl_debugcache_t &debuginfo, jl_value_t *rt, jl return dbuilder.createSubroutineType(dbuilder.getOrCreateTypeArray(ditypes)); } +/* aka Core.Compiler.tuple_tfunc */ static jl_datatype_t *compute_va_type(jl_method_instance_t *lam, size_t nreq) { size_t nvargs = jl_nparams(lam->specTypes)-nreq; @@ -6623,6 +6597,12 @@ static jl_datatype_t *compute_va_type(jl_method_instance_t *lam, size_t nreq) JL_GC_PUSH1(&tupargs); for (size_t i = nreq; i < jl_nparams(lam->specTypes); ++i) { jl_value_t *argType = jl_nth_slot_type(lam->specTypes, i); + if (is_uniquerep_Type(argType)) + argType = jl_typeof(jl_tparam0(argType)); + else if (jl_has_intersect_type_not_kind(argType)) { + jl_value_t *ts[2] = {argType, (jl_value_t*)jl_type_type}; + argType = jl_type_union(ts, 2); + } jl_svecset(tupargs, i-nreq, argType); } jl_datatype_t *typ = jl_apply_tuple_type(tupargs); @@ -7202,7 +7182,7 @@ static jl_llvm_functions_t #endif if (returninfo.cc == jl_returninfo_t::Union) { param.addAttribute(Attribute::NonNull); - // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers. + // The `dereferenceable` below does not imply `nonnull` for non addrspace(0) pointers. param.addDereferenceableAttr(returninfo.union_bytes); param.addAlignmentAttr(returninfo.union_align); } @@ -7212,7 +7192,7 @@ static jl_llvm_functions_t TypeSize sz = DL.getTypeAllocSize(RT); Align al = DL.getPrefTypeAlign(RT); param.addAttribute(Attribute::NonNull); - // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers. + // The `dereferenceable` below does not imply `nonnull` for non addrspace(0) pointers. param.addDereferenceableAttr(sz); param.addAlignmentAttr(al); } @@ -7227,7 +7207,7 @@ static jl_llvm_functions_t AttrBuilder param(f->getAttributes().getParamAttributes(Arg->getArgNo())); #endif param.addAttribute(Attribute::NonNull); - // The `dereferencable` below does not imply `nonnull` for non addrspace(0) pointers. + // The `dereferenceable` below does not imply `nonnull` for non addrspace(0) pointers. size_t size = returninfo.return_roots * sizeof(jl_value_t*); param.addDereferenceableAttr(size); param.addAlignmentAttr(Align(sizeof(jl_value_t*))); @@ -8543,7 +8523,9 @@ extern "C" void jl_init_llvm(void) // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); +#if JL_LLVM_VERSION < 150000 initializeCoroutines(Registry); +#endif initializeScalarOpts(Registry); initializeVectorization(Registry); initializeAnalysis(Registry); @@ -8578,12 +8560,11 @@ extern "C" void jl_init_llvm(void) // Register GDB event listener #if defined(JL_DEBUG_BUILD) jl_using_gdb_jitevents = true; -# else +#endif const char *jit_gdb = getenv("ENABLE_GDBLISTENER"); - if (jit_gdb && atoi(jit_gdb)) { - jl_using_gdb_jitevents = true; + if (jit_gdb) { + jl_using_gdb_jitevents = !!atoi(jit_gdb); } -#endif if (jl_using_gdb_jitevents) jl_ExecutionEngine->enableJITDebuggingSupport(); diff --git a/src/debug-registry.h b/src/debug-registry.h index b98c42f8de1fc..3780bbee33718 100644 --- a/src/debug-registry.h +++ b/src/debug-registry.h @@ -2,6 +2,7 @@ #include #include +#include "julia.h" #include "julia_internal.h" #include "processor.h" diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index eba6ea793b71c..fe5614100f9e3 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -20,10 +20,13 @@ #include #include +#ifdef _OS_DARWIN_ +#include +#endif + using namespace llvm; -#include "julia.h" -#include "julia_internal.h" +#include "jitlayers.h" #include "debuginfo.h" #if defined(_OS_LINUX_) # include @@ -37,11 +40,6 @@ using namespace llvm; #include #include "julia_assert.h" -#ifdef _OS_DARWIN_ -#include -#endif - -#include "jitlayers.h" static JITDebugInfoRegistry &getJITDebugRegistry() JL_NOTSAFEPOINT { return jl_ExecutionEngine->getDebugInfoRegistry(); diff --git a/src/disasm.cpp b/src/disasm.cpp index 69692da4c4b16..cfc030f649fd6 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -111,8 +111,6 @@ #include -#include "julia.h" -#include "julia_internal.h" #include "jitlayers.h" #include "processor.h" @@ -796,7 +794,13 @@ static const char *SymbolLookup(void *DisInfo, uint64_t ReferenceValue, uint64_t return NULL; } -static int OpInfoLookup(void *DisInfo, uint64_t PC, uint64_t Offset, uint64_t Size, +static int OpInfoLookup(void *DisInfo, uint64_t PC, + uint64_t Offset, +#if JL_LLVM_VERSION < 150000 + uint64_t Size, +#else + uint64_t OpSize, uint64_t InstSize, +#endif int TagType, void *TagBuf) { SymbolTable *SymTab = (SymbolTable*)DisInfo; @@ -1050,10 +1054,14 @@ static void jl_dump_asm_internal( MCInst Inst; MCDisassembler::DecodeStatus S; FuncMCView view = memoryObject.slice(Index); +#if JL_LLVM_VERSION < 150000 +#define getCommentOS() GetCommentOS() +#endif S = DisAsm->getInstruction(Inst, insSize, view, 0, - /*CStream*/ pass != 0 ? Streamer->GetCommentOS() : nulls()); - if (pass != 0 && Streamer->GetCommentOS().tell() > 0) - Streamer->GetCommentOS() << '\n'; + /*CStream*/ pass != 0 ? Streamer->getCommentOS () : nulls()); + if (pass != 0 && Streamer->getCommentOS ().tell() > 0) + Streamer->getCommentOS () << '\n'; +#undef GetCommentOS switch (S) { case MCDisassembler::Fail: if (insSize == 0) // skip illegible bytes diff --git a/src/dump.c b/src/dump.c index 22369599806ec..f267fa135b599 100644 --- a/src/dump.c +++ b/src/dump.c @@ -188,11 +188,6 @@ static jl_typename_t *jl_idtable_typename = NULL; static jl_value_t *jl_bigint_type = NULL; static int gmp_limb_size = 0; -static void write_uint64(ios_t *s, uint64_t i) JL_NOTSAFEPOINT -{ - ios_write(s, (char*)&i, 8); -} - static void write_float64(ios_t *s, double x) JL_NOTSAFEPOINT { write_uint64(s, *((uint64_t*)&x)); @@ -314,77 +309,127 @@ static int type_recursively_external(jl_datatype_t *dt) JL_NOTSAFEPOINT return 1; } +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 && !module_in_worklist(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) +static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, int depth) { - void **bp = ptrhash_bp(visited, mi); - // HT_NOTFOUND: not yet analyzed - // HT_NOTFOUND + 1: doesn't link back - // HT_NOTFOUND + 2: does link back - if (*bp != HT_NOTFOUND) - return (char*)*bp - (char*)HT_NOTFOUND - 1; - *bp = (void*)((char*)HT_NOTFOUND + 1); // preliminarily mark as "not found" - // TODO: this algorithm deals with cycles incorrectly jl_module_t *mod = mi->def.module; if (jl_is_method(mod)) mod = ((jl_method_t*)mod)->module; assert(jl_is_module(mod)); if (mi->precompiled || module_in_worklist(mod)) { - *bp = (void*)((char*)HT_NOTFOUND + 2); // found return 1; } if (!mi->backedges) { return 0; } + void **bp = ptrhash_bp(visited, mi); + // HT_NOTFOUND: not yet analyzed + // HT_NOTFOUND + 1: no link back + // HT_NOTFOUND + 2: does link back + // HT_NOTFOUND + 3 + depth: in-progress + int found = (char*)*bp - (char*)HT_NOTFOUND; + if (found) + return found - 1; + *bp = (void*)((char*)HT_NOTFOUND + 3 + depth); // preliminarily mark as in-progress size_t i = 0, n = jl_array_len(mi->backedges); - jl_method_instance_t *be; + int cycle = 0; while (i < n) { + jl_method_instance_t *be; i = get_next_edge(mi->backedges, i, NULL, &be); - if (has_backedge_to_worklist(be, visited)) { - bp = ptrhash_bp(visited, mi); // re-acquire since rehashing might change the location - *bp = (void*)((char*)HT_NOTFOUND + 2); // found - return 1; + int child_found = has_backedge_to_worklist(be, visited, depth + 1); + if (child_found == 1) { + found = 1; + break; + } + else if (child_found >= 2 && child_found - 2 < cycle) { + // record the cycle will resolve at depth "cycle" + cycle = child_found - 2; + assert(cycle); } } - return 0; + 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); + } + } + return found; } // given the list of MethodInstances that were inferred during the // build, select those that are external and have at least one -// relocatable CodeInstance. +// relocatable CodeInstance and are inferred to be called from the worklist +// or explicitly added by a precompile statement. static size_t queue_external_mis(jl_array_t *list) { + if (list == NULL) + return 0; size_t i, n = 0; htable_t visited; - if (list) { - assert(jl_is_array(list)); - size_t n0 = jl_array_len(list); - htable_new(&visited, n0); - for (i = 0; i < n0; i++) { - jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i); - assert(jl_is_method_instance(mi)); - if (jl_is_method(mi->def.value)) { - jl_method_t *m = mi->def.method; - if (!module_in_worklist(m->module)) { - jl_code_instance_t *ci = mi->cache; - int relocatable = 0; - while (ci) { - if (ci->max_world == ~(size_t)0) - relocatable |= ci->relocatability; - ci = ci->next; - } - if (relocatable && ptrhash_get(&external_mis, mi) == HT_NOTFOUND) { - if (has_backedge_to_worklist(mi, &visited)) { - ptrhash_put(&external_mis, mi, mi); - n++; - } + assert(jl_is_array(list)); + size_t n0 = jl_array_len(list); + htable_new(&visited, n0); + for (i = 0; i < n0; i++) { + jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i); + assert(jl_is_method_instance(mi)); + if (jl_is_method(mi->def.value)) { + jl_method_t *m = mi->def.method; + if (!module_in_worklist(m->module)) { + jl_code_instance_t *ci = mi->cache; + int relocatable = 0; + while (ci) { + if (ci->max_world == ~(size_t)0) + relocatable |= ci->relocatability; + ci = ci->next; + } + if (relocatable && ptrhash_get(&external_mis, mi) == HT_NOTFOUND) { + int found = has_backedge_to_worklist(mi, &visited, 1); + assert(found == 0 || found == 1); + if (found == 1) { + ptrhash_put(&external_mis, mi, mi); + n++; } } } } - htable_free(&visited); } + htable_free(&visited); return n; } @@ -653,13 +698,15 @@ static int jl_serialize_generic(jl_serializer_state *s, jl_value_t *v) JL_GC_DIS return 0; } -static void jl_serialize_code_instance(jl_serializer_state *s, jl_code_instance_t *codeinst, int skip_partial_opaque, int internal) JL_GC_DISABLED +static void jl_serialize_code_instance(jl_serializer_state *s, jl_code_instance_t *codeinst, + int skip_partial_opaque, int internal, + int force) JL_GC_DISABLED { if (internal > 2) { while (codeinst && !codeinst->relocatability) codeinst = codeinst->next; } - if (jl_serialize_generic(s, (jl_value_t*)codeinst)) { + if (!force && jl_serialize_generic(s, (jl_value_t*)codeinst)) { return; } assert(codeinst != NULL); // handle by jl_serialize_generic, but this makes clang-sa happy @@ -680,7 +727,7 @@ static void jl_serialize_code_instance(jl_serializer_state *s, jl_code_instance_ if (write_ret_type && codeinst->rettype_const && jl_typeis(codeinst->rettype_const, jl_partial_opaque_type)) { if (skip_partial_opaque) { - jl_serialize_code_instance(s, codeinst->next, skip_partial_opaque, internal); + jl_serialize_code_instance(s, codeinst->next, skip_partial_opaque, internal, 0); return; } else { @@ -707,7 +754,7 @@ static void jl_serialize_code_instance(jl_serializer_state *s, jl_code_instance_ jl_serialize_value(s, jl_nothing); } write_uint8(s->s, codeinst->relocatability); - jl_serialize_code_instance(s, codeinst->next, skip_partial_opaque, internal); + jl_serialize_code_instance(s, codeinst->next, skip_partial_opaque, internal, 0); } enum METHOD_SERIALIZATION_MODE { @@ -968,10 +1015,10 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } jl_serialize_value(s, (jl_value_t*)backedges); jl_serialize_value(s, (jl_value_t*)NULL); //callbacks - jl_serialize_code_instance(s, mi->cache, 1, internal); + jl_serialize_code_instance(s, mi->cache, 1, internal, 0); } else if (jl_is_code_instance(v)) { - jl_serialize_code_instance(s, (jl_code_instance_t*)v, 0, 2); + jl_serialize_code_instance(s, (jl_code_instance_t*)v, 0, 2, 1); } else if (jl_typeis(v, jl_module_type)) { jl_serialize_module(s, (jl_module_t*)v); @@ -999,7 +1046,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } else { write_uint8(s->s, TAG_INT64); - write_int64(s->s, *(int64_t*)data); + write_uint64(s->s, *(int64_t*)data); } } else if (jl_typeis(v, jl_int32_type)) { @@ -1163,7 +1210,7 @@ static void serialize_htable_keys(jl_serializer_state *s, htable_t *ht, int nite // or method instances not in the queue // // from MethodTables -static void jl_collect_missing_backedges_to_mod(jl_methtable_t *mt) +static void jl_collect_missing_backedges(jl_methtable_t *mt) { jl_array_t *backedges = mt->backedges; if (backedges) { @@ -1252,7 +1299,7 @@ static void jl_collect_extext_methods_from_mod(jl_array_t *s, jl_module_t *m) JL (jl_value_t*)mt != jl_nothing && (mt != jl_type_type_mt && mt != jl_nonfunction_mt)) { jl_collect_methtable_from_mod(s, mt); - jl_collect_missing_backedges_to_mod(mt); + jl_collect_missing_backedges(mt); } } } @@ -1321,6 +1368,7 @@ static void jl_collect_backedges(jl_array_t *edges, jl_array_t *ext_targets) jl_value_t *invokeTypes; jl_method_instance_t *c; size_t i; + size_t world = jl_get_world_counter(); void **table = edges_map.table; // edges is caller => callees size_t table_size = edges_map.size; for (i = 0; i < table_size; i += 2) { @@ -1363,15 +1411,28 @@ static void jl_collect_backedges(jl_array_t *edges, jl_array_t *ext_targets) size_t min_valid = 0; size_t max_valid = ~(size_t)0; int ambig = 0; - jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_atomic_load_acquire(&jl_world_counter), &min_valid, &max_valid, &ambig); - if (matches == jl_false) { - valid = 0; - break; - } - size_t k; - for (k = 0; k < jl_array_len(matches); k++) { - jl_method_match_t *match = (jl_method_match_t *)jl_array_ptr_ref(matches, k); - jl_array_ptr_set(matches, k, match->method); + jl_value_t *matches; + if (mode == 2 && callee && jl_is_method_instance(callee) && jl_is_type(sig)) { + // invoke, use subtyping + jl_methtable_t *mt = jl_method_get_table(((jl_method_instance_t*)callee)->def.method); + size_t min_world, max_world; + matches = jl_gf_invoke_lookup_worlds(sig, (jl_value_t*)mt, world, &min_world, &max_world); + if (matches == jl_nothing) { + valid = 0; + break; + } + matches = (jl_value_t*)((jl_method_match_t*)matches)->method; + } else { + matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_atomic_load_acquire(&jl_world_counter), &min_valid, &max_valid, &ambig); + if (matches == jl_false) { + valid = 0; + break; + } + size_t k; + for (k = 0; k < jl_array_len(matches); k++) { + jl_method_match_t *match = (jl_method_match_t *)jl_array_ptr_ref(matches, k); + jl_array_ptr_set(matches, k, match->method); + } } jl_array_ptr_1d_push(ext_targets, mode == 1 ? NULL : sig); jl_array_ptr_1d_push(ext_targets, callee); @@ -1576,7 +1637,7 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t **udepsp) ios_seek(s, initial_pos); write_uint64(s, pos - initial_pos); ios_seek(s, pos); - write_int64(s, 0); + write_uint64(s, 0); } return pos; } @@ -2084,6 +2145,10 @@ static void jl_deserialize_struct(jl_serializer_state *s, jl_value_t *v) JL_GC_D entry->min_world = 1; entry->max_world = 0; } + } else if (dt == jl_globalref_type) { + jl_globalref_t *r = (jl_globalref_t*)v; + jl_binding_t *b = jl_get_binding_if_bound(r->mod, r->name); + r->bnd_cache = b && b->value ? b : NULL; } } @@ -2321,6 +2386,44 @@ void remove_code_instance_from_validation(jl_code_instance_t *codeinst) ptrhash_remove(&new_code_instance_validate, codeinst); } +static int do_selective_invoke_backedge_invalidation(jl_methtable_t *mt, jl_value_t *mworld, jl_method_instance_t *mi, size_t world) +{ + jl_value_t *invokeTypes; + jl_method_instance_t *caller; + size_t jins = 0, j0, j = 0, nbe = jl_array_len(mi->backedges); + while (j < nbe) { + j0 = j; + j = get_next_edge(mi->backedges, j, &invokeTypes, &caller); + if (invokeTypes) { + struct jl_typemap_assoc search = {invokeTypes, world, NULL, 0, ~(size_t)0}; + jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->defs, &search, /*offs*/0, /*subtype*/0); + if (entry) { + jl_value_t *imworld = entry->func.value; + if (jl_is_method(imworld) && mi->def.method == (jl_method_t*)imworld) { + // this one is OK + // in case we deleted some earlier ones, move this earlier + for (; j0 < j; jins++, j0++) { + jl_array_ptr_set(mi->backedges, jins, jl_array_ptr_ref(mi->backedges, j0)); + } + continue; + } + } + } + invalidate_backedges(&remove_code_instance_from_validation, caller, world, "jl_insert_method_instance caller"); + // The codeinst of this mi haven't yet been removed + jl_code_instance_t *codeinst = caller->cache; + while (codeinst) { + remove_code_instance_from_validation(codeinst); + codeinst = codeinst->next; + } + } + jl_array_del_end(mi->backedges, j - jins); + if (jins == 0) { + return 0; + } + return 1; +} + static void jl_insert_method_instances(jl_array_t *list) JL_GC_DISABLED { size_t i, l = jl_array_len(list); @@ -2345,41 +2448,15 @@ static void jl_insert_method_instances(jl_array_t *list) JL_GC_DISABLED if (entry) { jl_value_t *mworld = entry->func.value; if (jl_is_method(mworld) && mi->def.method != (jl_method_t*)mworld && jl_type_morespecific(((jl_method_t*)mworld)->sig, mi->def.method->sig)) { - // There's still a chance this is valid, if any caller made this via `invoke` and the invoke-signature is still valid - assert(mi->backedges); // should not be NULL if it's on `list` - jl_value_t *invokeTypes; - jl_method_instance_t *caller; - size_t jins = 0, j0, j = 0, nbe = jl_array_len(mi->backedges); - while (j < nbe) { - j0 = j; - j = get_next_edge(mi->backedges, j, &invokeTypes, &caller); - if (invokeTypes) { - struct jl_typemap_assoc search = {invokeTypes, world, NULL, 0, ~(size_t)0}; - entry = jl_typemap_assoc_by_type(mt->defs, &search, /*offs*/0, /*subtype*/0); - if (entry) { - jl_value_t *imworld = entry->func.value; - if (jl_is_method(imworld) && mi->def.method == (jl_method_t*)imworld) { - // this one is OK - // in case we deleted some earlier ones, move this earlier - for (; j0 < j; jins++, j0++) { - jl_array_ptr_set(mi->backedges, jins, jl_array_ptr_ref(mi->backedges, j0)); - } - continue; - } - } - } - invalidate_backedges(&remove_code_instance_from_validation, caller, world, "jl_insert_method_instance caller"); - // The codeinst of this mi haven't yet been removed - jl_code_instance_t *codeinst = caller->cache; - while (codeinst) { - remove_code_instance_from_validation(codeinst); - codeinst = codeinst->next; - } - } - jl_array_del_end(mi->backedges, j - jins); - if (jins == 0) { - m = (jl_method_t*)mworld; + if (!mi->backedges) { valid = 0; + } else { + // There's still a chance this is valid, if any caller made this via `invoke` and the invoke-signature is still valid. + // Selectively go through all the backedges, invalidating those not made via `invoke` and validating those that are. + if (!do_selective_invoke_backedge_invalidation(mt, mworld, mi, world)) { + m = (jl_method_t*)mworld; + valid = 0; + } } } } @@ -2480,9 +2557,11 @@ static void jl_verify_edges(jl_array_t *targets, jl_array_t **pvalids) size_t i, l = jl_array_len(targets) / 3; jl_array_t *valids = jl_alloc_array_1d(jl_array_uint8_type, l); memset(jl_array_data(valids), 1, l); - jl_value_t *loctag = NULL; - JL_GC_PUSH1(&loctag); + jl_value_t *loctag = NULL, *matches = NULL; + jl_methtable_t *mt = NULL; + JL_GC_PUSH3(&loctag, &matches, &mt); *pvalids = valids; + size_t world = jl_get_world_counter(); for (i = 0; i < l; i++) { jl_value_t *invokesig = jl_array_ptr_ref(targets, i * 3); jl_value_t *callee = jl_array_ptr_ref(targets, i * 3 + 1); @@ -2494,40 +2573,68 @@ static void jl_verify_edges(jl_array_t *targets, jl_array_t **pvalids) else { sig = callee == NULL ? invokesig : callee; } - jl_array_t *expected = (jl_array_t*)jl_array_ptr_ref(targets, i * 3 + 2); - assert(jl_is_array(expected)); + jl_value_t *expected = jl_array_ptr_ref(targets, i * 3 + 2); int valid = 1; size_t min_valid = 0; size_t max_valid = ~(size_t)0; int ambig = 0; - // TODO: possibly need to included ambiguities too (for the optimizer correctness)? - jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_atomic_load_acquire(&jl_world_counter), &min_valid, &max_valid, &ambig); - if (matches == jl_false || jl_array_len(matches) != jl_array_len(expected)) { - valid = 0; - } - else { - size_t j, k, l = jl_array_len(expected); - for (k = 0; k < jl_array_len(matches); k++) { - jl_method_match_t *match = (jl_method_match_t*)jl_array_ptr_ref(matches, k); - jl_method_t *m = match->method; - for (j = 0; j < l; j++) { - if (m == (jl_method_t*)jl_array_ptr_ref(expected, j)) + int use_invoke = invokesig == NULL || callee == NULL ? 0 : 1; + if (!use_invoke) { + // TODO: possibly need to included ambiguities too (for the optimizer correctness)? + matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_atomic_load_acquire(&jl_world_counter), &min_valid, &max_valid, &ambig); + if (matches == jl_false || jl_array_len(matches) != jl_array_len(expected)) { + valid = 0; + } + else { + assert(jl_is_array(expected)); + size_t j, k, l = jl_array_len(expected); + for (k = 0; k < jl_array_len(matches); k++) { + jl_method_match_t *match = (jl_method_match_t*)jl_array_ptr_ref(matches, k); + jl_method_t *m = match->method; + for (j = 0; j < l; j++) { + if (m == (jl_method_t*)jl_array_ptr_ref(expected, j)) + break; + } + if (j == l) { + // intersection has a new method or a method was + // deleted--this is now probably no good, just invalidate + // everything about it now + valid = 0; break; + } } - if (j == l) { - // intersection has a new method or a method was - // deleted--this is now probably no good, just invalidate - // everything about it now - valid = 0; - break; - } + } + } else { + mt = jl_method_get_table(((jl_method_instance_t*)callee)->def.method); + size_t min_world, max_world; + matches = jl_gf_invoke_lookup_worlds(invokesig, (jl_value_t*)mt, world, &min_world, &max_world); + if (matches == jl_nothing || expected != (jl_value_t*)((jl_method_match_t*)matches)->method) { + valid = 0; } } jl_array_uint8_set(valids, i, valid); if (!valid && _jl_debug_method_invalidation) { - jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)callee); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, callee ? (jl_value_t*)callee : sig); loctag = jl_cstr_to_string("insert_backedges_callee"); jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); + loctag = jl_box_int32((int32_t)i); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); + loctag = jl_box_uint64(jl_worklist_key(serializer_worklist)); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); + if (!use_invoke && matches != jl_false) { + // setdiff!(matches, expected) + size_t j, k, ins = 0; + for (j = 0; j < jl_array_len(matches); j++) { + int found = 0; + jl_method_t *match = ((jl_method_match_t*)jl_array_ptr_ref(matches, j))->method; + for (k = 0; !found && k < jl_array_len(expected); k++) + found |= jl_egal((jl_value_t*)match, jl_array_ptr_ref(expected, k)); + if (!found) + jl_array_ptr_set(matches, ins++, match); + } + jl_array_del_end((jl_array_t*)matches, jl_array_len(matches) - ins); + } + jl_array_ptr_1d_push(_jl_debug_method_invalidation, matches); } } JL_GC_POP(); @@ -2540,9 +2647,10 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets) { // foreach(enable, ((edges[2i-1] => ext_targets[edges[2i] .* 3]) for i in 1:length(edges)÷2 if all(valids[edges[2i]]))) size_t i, l = jl_array_len(edges); + size_t world = jl_atomic_load_acquire(&jl_world_counter); jl_array_t *valids = NULL; - jl_value_t *loctag = NULL; - JL_GC_PUSH2(&valids, &loctag); + jl_value_t *targetidx = NULL; + JL_GC_PUSH2(&valids, &targetidx); jl_verify_edges(ext_targets, &valids); for (i = 0; i < l; i += 2) { jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(edges, i); @@ -2551,10 +2659,12 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets) assert(jl_isa((jl_value_t*)idxs_array, jl_array_int32_type)); int32_t *idxs = (int32_t*)jl_array_data(idxs_array); int valid = 1; - size_t j; + size_t j, idxbad = -1; for (j = 0; valid && j < jl_array_len(idxs_array); j++) { int32_t idx = idxs[j]; valid = jl_array_uint8_ref(valids, idx); + if (!valid) + idxbad = idx; } if (valid) { // if this callee is still valid, add all the backedges @@ -2591,10 +2701,12 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets) ptrhash_remove(&new_code_instance_validate, codeinst); // should be left invalid codeinst = jl_atomic_load_relaxed(&codeinst->next); } + invalidate_backedges(&remove_code_instance_from_validation, caller, world, "insert_backedges"); if (_jl_debug_method_invalidation) { - jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)caller); - loctag = jl_cstr_to_string("insert_backedges"); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); + targetidx = jl_box_int32((int32_t)idxbad); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, targetidx); + targetidx = jl_box_uint64(jl_worklist_key(serializer_worklist)); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, targetidx); } } } @@ -2838,11 +2950,11 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) jl_collect_extext_methods_from_mod(extext_methods, m); } jl_collect_methtable_from_mod(extext_methods, jl_type_type_mt); - jl_collect_missing_backedges_to_mod(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_to_mod(jl_nonfunction_mt); + jl_collect_missing_backedges(jl_nonfunction_mt); - // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges_to_mod accumulate data in edges_map. + // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges accumulate data in edges_map. // Process this to extract `edges` and `ext_targets`. jl_collect_backedges(edges, ext_targets); @@ -2873,7 +2985,7 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) // Go back and update the source-text position to point to the current position int64_t posfile = ios_pos(&f); ios_seek(&f, srctextpos); - write_int64(&f, posfile); + write_uint64(&f, posfile); ios_seek_end(&f); // Each source-text file is written as // int32: length of abspath diff --git a/src/gc-alloc-profiler.h b/src/gc-alloc-profiler.h index 8be6fed21a899..3fd8bf4388a0a 100644 --- a/src/gc-alloc-profiler.h +++ b/src/gc-alloc-profiler.h @@ -14,7 +14,7 @@ extern "C" { // The public interface to call from Julia for allocations profiling // --------------------------------------------------------------------- -// Forward-declaration to avoid depenency in header file. +// Forward-declaration to avoid dependency in header file. struct jl_raw_alloc_t; // Defined in gc-alloc-profiler.cpp typedef struct { diff --git a/src/gc.c b/src/gc.c index 61dc4c937fe8e..238a10bcc35dc 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1738,8 +1738,9 @@ static void NOINLINE gc_mark_stack_resize(jl_gc_mark_cache_t *gc_cache, jl_gc_ma jl_gc_mark_data_t *old_data = gc_cache->data_stack; void **pc_stack = sp->pc_start; size_t stack_size = (char*)sp->pc_end - (char*)pc_stack; + ptrdiff_t datadiff = (char*)sp->data - (char*)old_data; gc_cache->data_stack = (jl_gc_mark_data_t *)realloc_s(old_data, stack_size * 2 * sizeof(jl_gc_mark_data_t)); - sp->data = (jl_gc_mark_data_t *)(((char*)sp->data) + (((char*)gc_cache->data_stack) - ((char*)old_data))); + sp->data = (jl_gc_mark_data_t *)((char*)gc_cache->data_stack + datadiff); sp->pc_start = gc_cache->pc_stack = (void**)realloc_s(pc_stack, stack_size * 2 * sizeof(void*)); gc_cache->pc_stack_end = sp->pc_end = sp->pc_start + stack_size * 2; @@ -3486,7 +3487,7 @@ void jl_gc_init(void) // on a big memory machine, set max_collect_interval to totalmem / nthreads / 2 uint64_t total_mem = uv_get_total_memory(); uint64_t constrained_mem = uv_get_constrained_memory(); - if (constrained_mem > 0 && constrained_mem < total_mem) + if (constrained_mem != 0) total_mem = constrained_mem; size_t maxmem = total_mem / jl_n_threads / 2; if (maxmem > max_collect_interval) @@ -3494,7 +3495,7 @@ void jl_gc_init(void) #endif // We allocate with abandon until we get close to the free memory on the machine. - uint64_t free_mem = uv_get_free_memory(); + uint64_t free_mem = uv_get_available_memory(); uint64_t high_water_mark = free_mem / 10 * 7; // 70% high water mark if (high_water_mark < max_total_memory) diff --git a/src/gf.c b/src/gf.c index abc04f2e779ee..138092ab9c93e 100644 --- a/src/gf.c +++ b/src/gf.c @@ -281,8 +281,6 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t *mi, size_t world, int force) JL_TIMING(INFERENCE); if (jl_typeinf_func == NULL) return NULL; - if (jl_is_method(mi->def.method) && jl_atomic_load_relaxed(&mi->def.method->unspecialized) == mi) - return NULL; // avoid inferring the unspecialized method static int in_inference; if (in_inference > 2) return NULL; @@ -1153,6 +1151,7 @@ static jl_method_instance_t *cache_method( // NULL, jl_emptysvec, /*guard*/NULL, jl_cachearg_offset(mt), other->min_world, other->max_world); } } + assert(guards == jl_svec_len(guardsigs)); } if (!cache_with_orig) { // determined above that there's no ambiguity in also using compilationsig as the cacheablesig @@ -2004,7 +2003,7 @@ JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t * if (ambig != NULL) *ambig = 0; jl_value_t *unw = jl_unwrap_unionall((jl_value_t*)types); - if (jl_is_tuple_type(unw) && jl_tparam0(unw) == jl_bottom_type) + if (jl_is_tuple_type(unw) && (unw == (jl_value_t*)jl_emptytuple_type || jl_tparam0(unw) == jl_bottom_type)) return (jl_value_t*)jl_an_empty_vec_any; if (mt == jl_nothing) mt = (jl_value_t*)jl_method_table_for(unw); @@ -2137,7 +2136,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t if (compile_option == JL_OPTIONS_COMPILE_OFF || compile_option == JL_OPTIONS_COMPILE_MIN) { jl_code_info_t *src = jl_code_for_interpreter(mi); - if (!jl_code_requires_compiler(src)) { + if (!jl_code_requires_compiler(src, 0)) { jl_code_instance_t *codeinst = jl_new_codeinst(mi, (jl_value_t*)jl_any_type, NULL, NULL, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); @@ -3314,13 +3313,9 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, if (!jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig) && !jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig)) { ambig1 = 1; + break; } } - else { - // otherwise some aspect of m is not ambiguous - ambig1 = 0; - break; - } } } if (ambig1) @@ -3382,24 +3377,37 @@ int jl_has_concrete_subtype(jl_value_t *typ) //static jl_mutex_t typeinf_lock; #define typeinf_lock jl_codegen_lock +static jl_mutex_t inference_timing_mutex; static uint64_t inference_start_time = 0; static uint8_t inference_is_measuring_compile_time = 0; -JL_DLLEXPORT void jl_typeinf_begin(void) +JL_DLLEXPORT void jl_typeinf_timing_begin(void) { - JL_LOCK(&typeinf_lock); if (jl_atomic_load_relaxed(&jl_measure_compile_time_enabled)) { - inference_start_time = jl_hrtime(); - inference_is_measuring_compile_time = 1; + JL_LOCK_NOGC(&inference_timing_mutex); + if (inference_is_measuring_compile_time++ == 0) { + inference_start_time = jl_hrtime(); + } + JL_UNLOCK_NOGC(&inference_timing_mutex); } } -JL_DLLEXPORT void jl_typeinf_end(void) +JL_DLLEXPORT void jl_typeinf_timing_end(void) { - if (typeinf_lock.count == 1 && inference_is_measuring_compile_time) { + JL_LOCK_NOGC(&inference_timing_mutex); + if (--inference_is_measuring_compile_time == 0) { jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, (jl_hrtime() - inference_start_time)); - inference_is_measuring_compile_time = 0; } + JL_UNLOCK_NOGC(&inference_timing_mutex); +} + +JL_DLLEXPORT void jl_typeinf_lock_begin(void) +{ + JL_LOCK(&typeinf_lock); +} + +JL_DLLEXPORT void jl_typeinf_lock_end(void) +{ JL_UNLOCK(&typeinf_lock); } diff --git a/src/init.c b/src/init.c index 565f3d55f0f78..b42aea8bd4883 100644 --- a/src/init.c +++ b/src/init.c @@ -197,6 +197,8 @@ static void jl_close_item_atexit(uv_handle_t *handle) } } +void jl_task_frame_noreturn(jl_task_t *ct); + JL_DLLEXPORT void jl_atexit_hook(int exitcode) { if (jl_all_tls_states == NULL) @@ -204,6 +206,10 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) jl_task_t *ct = jl_current_task; + // we are about to start tearing everything down, so lets try not to get + // upset by the local mess of things when we run the user's _atexit hooks + jl_task_frame_noreturn(ct); + if (exitcode == 0) jl_write_compiler_output(); jl_print_gc_stats(JL_STDERR); diff --git a/src/interpreter.c b/src/interpreter.c index 0b6666f2637f6..1f9c416d99b1b 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -151,6 +151,17 @@ jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e) return v; } +jl_value_t *jl_eval_globalref(jl_globalref_t *g) +{ + if (g->bnd_cache) { + jl_value_t *v = jl_atomic_load_relaxed(&g->bnd_cache->value); + if (v == NULL) + jl_undefined_var_error(g->name); + return v; + } + return jl_eval_global_var(g->mod, g->name); +} + static int jl_source_nslots(jl_code_info_t *src) JL_NOTSAFEPOINT { return jl_array_len(src->slotflags); @@ -190,7 +201,7 @@ static jl_value_t *eval_value(jl_value_t *e, interpreter_state *s) return jl_quotenode_value(e); } if (jl_is_globalref(e)) { - return jl_eval_global_var(jl_globalref_mod(e), jl_globalref_name(e)); + return jl_eval_globalref((jl_globalref_t*)e); } if (jl_is_symbol(e)) { // bare symbols appear in toplevel exprs not wrapped in `thunk` return jl_eval_global_var(s->module, (jl_sym_t*)e); diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 117971a083db8..31f47bd7166c4 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -1357,7 +1357,7 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **arg return ctx.builder.CreateCall(fmaintr, {x, y, z}); } case muladd_float: { - // LLVM 5.0 can create FMA in the backend for contractable fmul and fadd + // LLVM 5.0 can create FMA in the backend for contractible fmul and fadd // Emitting fmul and fadd here since they are easier for other LLVM passes to // optimize. auto mathb = math_builder(ctx, false, true); diff --git a/src/ircode.c b/src/ircode.c index f0e7cbd389d78..6da4045035c33 100644 --- a/src/ircode.c +++ b/src/ircode.c @@ -80,7 +80,7 @@ static void jl_encode_as_indexed_root(jl_ircode_state *s, jl_value_t *v) assert(id >= 0); if (rr.key) { write_uint8(s->s, TAG_RELOC_METHODROOT); - write_int64(s->s, rr.key); + write_uint64(s->s, rr.key); } if (id < 256) { write_uint8(s->s, TAG_METHODROOT); @@ -283,7 +283,7 @@ static void jl_encode_value_(jl_ircode_state *s, jl_value_t *v, int as_literal) } else { write_uint8(s->s, TAG_INT64); - write_int64(s->s, *(int64_t*)data); + write_uint64(s->s, *(int64_t*)data); } } else if (jl_typeis(v, jl_int32_type)) { diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 1709c62326238..a0dd11e7f009e 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -5,6 +5,7 @@ #include #include "llvm/IR/Mangler.h" +#include #include #include #include @@ -35,8 +36,6 @@ using namespace llvm; -#include "julia.h" -#include "julia_internal.h" #include "codegen_shared.h" #include "jitlayers.h" #include "julia_assert.h" @@ -48,10 +47,30 @@ using namespace llvm; # endif # include # include +# if JL_LLVM_VERSION >= 150000 +# include +# endif #else # include #endif +#define DEBUG_TYPE "julia_jitlayers" + +STATISTIC(LinkedGlobals, "Number of globals linked"); +STATISTIC(CompiledCodeinsts, "Number of codeinsts compiled directly"); +STATISTIC(MaxWorkqueueSize, "Maximum number of elements in the workqueue"); +STATISTIC(IndirectCodeinsts, "Number of dependent codeinsts compiled"); +STATISTIC(SpecFPtrCount, "Number of specialized function pointers compiled"); +STATISTIC(UnspecFPtrCount, "Number of specialized function pointers compiled"); +STATISTIC(ModulesAdded, "Number of modules added to the JIT"); +STATISTIC(ModulesOptimized, "Number of modules optimized by the JIT"); +STATISTIC(OptO0, "Number of modules optimized at level -O0"); +STATISTIC(OptO1, "Number of modules optimized at level -O1"); +STATISTIC(OptO2, "Number of modules optimized at level -O2"); +STATISTIC(OptO3, "Number of modules optimized at level -O3"); +STATISTIC(ModulesMerged, "Number of modules merged"); +STATISTIC(InternedGlobals, "Number of global constants interned in the string pool"); + #ifdef _COMPILER_MSAN_ENABLED_ // TODO: This should not be necessary on ELF x86_64, but LLVM's implementation // of the TLS relocations is currently broken, so enable this unconditionally. @@ -104,8 +123,6 @@ static void *getTLSAddress(void *control) } #endif -#define DEBUG_TYPE "jitlayers" - // Snooping on which functions are being compiled, and how long it takes extern "C" JL_DLLEXPORT void jl_dump_compiles_impl(void *s) @@ -124,6 +141,7 @@ static uint64_t getAddressForFunction(StringRef fname); void jl_link_global(GlobalVariable *GV, void *addr) { + ++LinkedGlobals; Constant *P = literal_static_pointer_val(addr, GV->getValueType()); GV->setInitializer(P); if (jl_options.image_codegen) { @@ -214,6 +232,9 @@ static jl_callptr_t _jl_compile_codeinst( orc::ThreadSafeModule &M = std::get<0>(def.second); jl_add_to_ee(M, NewExports); } + ++CompiledCodeinsts; + MaxWorkqueueSize.updateMax(emitted.size()); + IndirectCodeinsts += emitted.size() - 1; } JL_TIMING(LLVM_MODULE_FINISH); @@ -365,8 +386,6 @@ extern "C" JL_DLLEXPORT jl_code_instance_t *jl_generate_fptr_impl(jl_method_instance_t *mi JL_PROPAGATES_ROOT, size_t world) { JL_LOCK(&jl_codegen_lock); // also disables finalizers, to prevent any unexpected recursion - auto ctx = jl_ExecutionEngine->getContext(); - auto &context = *ctx; uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); bool is_recompile = false; @@ -409,7 +428,8 @@ jl_code_instance_t *jl_generate_fptr_impl(jl_method_instance_t *mi JL_PROPAGATES jl_atomic_cmpswap_relaxed(&codeinst->inferred, &null, jl_nothing); } } - _jl_compile_codeinst(codeinst, src, world, context); + ++SpecFPtrCount; + _jl_compile_codeinst(codeinst, src, world, *jl_ExecutionEngine->getContext()); if (jl_atomic_load_relaxed(&codeinst->invoke) == NULL) codeinst = NULL; } @@ -434,8 +454,6 @@ void jl_generate_fptr_for_unspecialized_impl(jl_code_instance_t *unspec) return; } JL_LOCK(&jl_codegen_lock); - auto ctx = jl_ExecutionEngine->getContext(); - auto &context = *ctx; uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); if (measure_compile_time_enabled) @@ -459,7 +477,8 @@ void jl_generate_fptr_for_unspecialized_impl(jl_code_instance_t *unspec) src = (jl_code_info_t*)unspec->def->uninferred; } assert(src && jl_is_code_info(src)); - _jl_compile_codeinst(unspec, src, unspec->min_world, context); + ++UnspecFPtrCount; + _jl_compile_codeinst(unspec, src, unspec->min_world, *jl_ExecutionEngine->getContext()); if (jl_atomic_load_relaxed(&unspec->invoke) == NULL) { // if we hit a codegen bug (or ran into a broken generated function or llvmcall), fall back to the interpreter as a last resort jl_atomic_store_release(&unspec->invoke, jl_fptr_interpret_call_addr); @@ -489,8 +508,6 @@ jl_value_t *jl_dump_method_asm_impl(jl_method_instance_t *mi, size_t world, // (using sentinel value `1` instead) // so create an exception here so we can print pretty our lies JL_LOCK(&jl_codegen_lock); // also disables finalizers, to prevent any unexpected recursion - auto ctx = jl_ExecutionEngine->getContext(); - auto &context = *ctx; uint64_t compiler_start_time = 0; uint8_t measure_compile_time_enabled = jl_atomic_load_relaxed(&jl_measure_compile_time_enabled); if (measure_compile_time_enabled) @@ -512,7 +529,7 @@ jl_value_t *jl_dump_method_asm_impl(jl_method_instance_t *mi, size_t world, specfptr = (uintptr_t)jl_atomic_load_relaxed(&codeinst->specptr.fptr); if (src && jl_is_code_info(src)) { if (fptr == (uintptr_t)jl_fptr_const_return_addr && specfptr == 0) { - fptr = (uintptr_t)_jl_compile_codeinst(codeinst, src, world, context); + fptr = (uintptr_t)_jl_compile_codeinst(codeinst, src, world, *jl_ExecutionEngine->getContext()); specfptr = (uintptr_t)jl_atomic_load_relaxed(&codeinst->specptr.fptr); } } @@ -551,6 +568,7 @@ static auto countBasicBlocks(const Function &F) } void JuliaOJIT::OptSelLayerT::emit(std::unique_ptr R, orc::ThreadSafeModule TSM) { + ++ModulesOptimized; size_t optlevel = SIZE_MAX; TSM.withModuleDo([&](Module &M) { if (jl_generating_output()) { @@ -721,6 +739,50 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin { }); } }; + +class JLMemoryUsagePlugin : public ObjectLinkingLayer::Plugin { +private: + std::atomic &total_size; + +public: + + JLMemoryUsagePlugin(std::atomic &total_size) + : total_size(total_size) {} + + Error notifyFailed(orc::MaterializationResponsibility &MR) override { + return Error::success(); + } + Error notifyRemovingResources(orc::ResourceKey K) override { + return Error::success(); + } + void notifyTransferringResources(orc::ResourceKey DstKey, + orc::ResourceKey SrcKey) override {} + + void modifyPassConfig(orc::MaterializationResponsibility &, + jitlink::LinkGraph &, + jitlink::PassConfiguration &Config) override { + Config.PostAllocationPasses.push_back([this](jitlink::LinkGraph &G) { + size_t graph_size = 0; + for (auto block : G.blocks()) { + graph_size += block->getSize(); + } + this->total_size.fetch_add(graph_size, std::memory_order_relaxed); + return Error::success(); + }); + } +}; + +// TODO: Port our memory management optimisations to JITLink instead of using the +// default InProcessMemoryManager. +std::unique_ptr createJITLinkMemoryManager() { +#if JL_LLVM_VERSION < 140000 + return std::make_unique(); +#elif JL_LLVM_VERSION < 150000 + return cantFail(jitlink::InProcessMemoryManager::Create()); +#else + return cantFail(orc::MapperJITLinkMemoryManager::CreateWithMapper()); +#endif +} } # ifdef LLVM_SHLIB @@ -950,7 +1012,11 @@ namespace { namespace { +#ifndef JL_USE_NEW_PM typedef legacy::PassManager PassManager; +#else + typedef NewPM PassManager; +#endif orc::JITTargetMachineBuilder createJTMBFromTM(TargetMachine &TM, int optlevel) { return orc::JITTargetMachineBuilder(TM.getTargetTriple()) @@ -972,6 +1038,7 @@ namespace { } }; +#ifndef JL_USE_NEW_PM struct PMCreator { std::unique_ptr TM; int optlevel; @@ -987,7 +1054,7 @@ namespace { swap(*this, other); return *this; } - std::unique_ptr operator()() { + auto operator()() { auto PM = std::make_unique(); addTargetPasses(PM.get(), TM->getTargetTriple(), TM->getTargetIRAnalysis()); addOptimizationPasses(PM.get(), optlevel); @@ -995,6 +1062,17 @@ namespace { return PM; } }; +#else + struct PMCreator { + orc::JITTargetMachineBuilder JTMB; + OptimizationLevel O; + PMCreator(TargetMachine &TM, int optlevel) : JTMB(createJTMBFromTM(TM, optlevel)), O(getOptLevel(optlevel)) {} + + auto operator()() { + return std::make_unique(cantFail(JTMB.createTargetMachine()), O); + } + }; +#endif struct OptimizerT { OptimizerT(TargetMachine &TM, int optlevel) : optlevel(optlevel), PMs(PMCreator(TM, optlevel)) {} @@ -1051,6 +1129,22 @@ namespace { } } }); + switch (optlevel) { + case 0: + ++OptO0; + break; + case 1: + ++OptO1; + break; + case 2: + ++OptO2; + break; + case 3: + ++OptO3; + break; + default: + llvm_unreachable("optlevel is between 0 and 3!"); + } return Expected{std::move(TSM)}; } private: @@ -1096,18 +1190,13 @@ JuliaOJIT::JuliaOJIT() ContextPool([](){ auto ctx = std::make_unique(); #ifdef JL_LLVM_OPAQUE_POINTERS - ctx->enableOpaquePointers(); + ctx->setOpaquePointers(true); #endif return orc::ThreadSafeContext(std::move(ctx)); }), #ifdef JL_USE_JITLINK - // TODO: Port our memory management optimisations to JITLink instead of using the - // default InProcessMemoryManager. -# if JL_LLVM_VERSION < 140000 - ObjectLayer(ES, std::make_unique()), -# else - ObjectLayer(ES, cantFail(jitlink::InProcessMemoryManager::Create())), -# endif + MemMgr(createJITLinkMemoryManager()), + ObjectLayer(ES, *MemMgr), #else MemMgr(createRTDyldMemoryManager()), ObjectLayer( @@ -1138,6 +1227,7 @@ JuliaOJIT::JuliaOJIT() ES, std::move(ehRegistrar))); ObjectLayer.addPlugin(std::make_unique()); + ObjectLayer.addPlugin(std::make_unique(total_size)); #else ObjectLayer.setNotifyLoaded( [this](orc::MaterializationResponsibility &MR, @@ -1230,6 +1320,7 @@ void JuliaOJIT::addGlobalMapping(StringRef Name, uint64_t Addr) void JuliaOJIT::addModule(orc::ThreadSafeModule TSM) { JL_TIMING(LLVM_MODULE_FINISH); + ++ModulesAdded; std::vector NewExports; TSM.withModuleDo([&](Module &M) { jl_decorate_module(M); @@ -1387,8 +1478,7 @@ std::string JuliaOJIT::getMangledName(const GlobalValue *GV) #ifdef JL_USE_JITLINK size_t JuliaOJIT::getTotalBytes() const { - // TODO: Implement in future custom JITLink memory manager. - return 0; + return total_size.load(std::memory_order_relaxed); } #else size_t getRTDyldMemoryManagerTotalBytes(RTDyldMemoryManager *mm); @@ -1408,6 +1498,7 @@ JuliaOJIT *jl_ExecutionEngine; // Comdat is also removed, since the JIT doesn't need it void jl_merge_module(orc::ThreadSafeModule &destTSM, orc::ThreadSafeModule srcTSM) { + ++ModulesMerged; destTSM.withModuleDo([&](Module &dest) { srcTSM.withModuleDo([&](Module &src) { assert(&dest != &src && "Cannot merge module with itself!"); @@ -1521,6 +1612,7 @@ void jl_merge_module(orc::ThreadSafeModule &destTSM, orc::ThreadSafeModule srcTS // making a copy per object file of output. void JuliaOJIT::shareStrings(Module &M) { + ++InternedGlobals; std::vector erase; for (auto &GV : M.globals()) { if (!GV.hasInitializer() || !GV.isConstant()) diff --git a/src/jitlayers.h b/src/jitlayers.h index 54a76630330f8..ba38abff0d6f4 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -41,7 +41,9 @@ // and feature support (e.g. Windows, JITEventListeners for various profilers, // etc.). Thus, we currently only use JITLink where absolutely required, that is, // for Mac/aarch64. -#if defined(_OS_DARWIN_) && defined(_CPU_AARCH64_) +// #define JL_FORCE_JITLINK + +#if defined(_OS_DARWIN_) && defined(_CPU_AARCH64_) || defined(JL_FORCE_JITLINK) # if JL_LLVM_VERSION < 130000 # pragma message("On aarch64-darwin, LLVM version >= 13 is required for JITLink; fallback suffers from occasional segfaults") # endif @@ -78,9 +80,14 @@ struct OptimizationOptions { bool lower_intrinsics; bool dump_native; bool external_use; - - static constexpr OptimizationOptions defaults() { - return {true, false, false}; + bool llvm_only; + + static constexpr OptimizationOptions defaults( + bool lower_intrinsics=true, + bool dump_native=false, + bool external_use=false, + bool llvm_only=false) { + return {lower_intrinsics, dump_native, external_use, llvm_only}; } }; @@ -481,6 +488,9 @@ class JuliaOJIT { #ifndef JL_USE_JITLINK const std::shared_ptr MemMgr; +#else + std::atomic total_size; + const std::unique_ptr MemMgr; #endif ObjLayerT ObjectLayer; const std::array, 4> Pipelines; diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index dfb6becea43e1..b17251d4a5af3 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -453,7 +453,6 @@ XX(jl_svec2) \ XX(jl_svec_copy) \ XX(jl_svec_fill) \ - XX(jl_svec_isassigned) \ XX(jl_svec_ref) \ XX(jl_switch) \ XX(jl_switchto) \ @@ -479,8 +478,10 @@ XX(jl_tty_set_mode) \ XX(jl_tupletype_fill) \ XX(jl_typeassert) \ - XX(jl_typeinf_begin) \ - XX(jl_typeinf_end) \ + XX(jl_typeinf_lock_begin) \ + XX(jl_typeinf_lock_end) \ + XX(jl_typeinf_timing_begin) \ + XX(jl_typeinf_timing_end) \ XX(jl_typename_str) \ XX(jl_typeof_str) \ XX(jl_types_equal) \ diff --git a/src/jltypes.c b/src/jltypes.c index 9da7209f17f2c..7c527450b4cd3 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -657,9 +657,9 @@ static jl_datatype_t *lookup_type_set(jl_svec_t *cache, jl_value_t **key, size_t size_t iter = 0; do { jl_datatype_t *val = jl_atomic_load_relaxed(&tab[index]); - if (val == NULL) + if ((jl_value_t*)val == jl_nothing) return NULL; - if ((jl_value_t*)val != jl_nothing && val->hash == hv && typekey_eq(val, key, n)) + if (val->hash == hv && typekey_eq(val, key, n)) return val; index = (index + 1) & (sz - 1); iter++; @@ -680,9 +680,9 @@ static jl_datatype_t *lookup_type_setvalue(jl_svec_t *cache, jl_value_t *key1, j size_t iter = 0; do { jl_datatype_t *val = jl_atomic_load_relaxed(&tab[index]); - if (val == NULL) + if ((jl_value_t*)val == jl_nothing) return NULL; - if ((jl_value_t*)val != jl_nothing && val->hash == hv && typekeyvalue_eq(val, key1, key, n, leaf)) + if (val->hash == hv && typekeyvalue_eq(val, key1, key, n, leaf)) return val; index = (index + 1) & (sz - 1); iter++; @@ -702,7 +702,7 @@ static ssize_t lookup_type_idx_linear(jl_svec_t *cache, jl_value_t **key, size_t ssize_t i; for (i = 0; i < cl; i++) { jl_datatype_t *tt = jl_atomic_load_relaxed(&data[i]); - if (tt == NULL) + if ((jl_value_t*)tt == jl_nothing) return ~i; if (typekey_eq(tt, key, n)) return i; @@ -719,7 +719,7 @@ static ssize_t lookup_type_idx_linearvalue(jl_svec_t *cache, jl_value_t *key1, j ssize_t i; for (i = 0; i < cl; i++) { jl_datatype_t *tt = jl_atomic_load_relaxed(&data[i]); - if (tt == NULL) + if ((jl_value_t*)tt == jl_nothing) return ~i; if (typekeyvalue_eq(tt, key1, key, n, 1)) return i; @@ -777,7 +777,7 @@ static int cache_insert_type_set_(jl_svec_t *a, jl_datatype_t *val, uint_t hv, i size_t maxprobe = max_probe(sz); do { jl_value_t *tab_i = jl_atomic_load_relaxed(&tab[index]); - if (tab_i == NULL || tab_i == jl_nothing) { + if (tab_i == jl_nothing) { if (atomic) jl_atomic_store_release(&tab[index], (jl_value_t*)val); else @@ -792,8 +792,6 @@ static int cache_insert_type_set_(jl_svec_t *a, jl_datatype_t *val, uint_t hv, i return 0; } -static jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz); - static void cache_insert_type_set(jl_datatype_t *val, uint_t hv) { jl_svec_t *a = jl_atomic_load_relaxed(&val->name->cache); @@ -820,17 +818,17 @@ static void cache_insert_type_set(jl_datatype_t *val, uint_t hv) } } -static jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz) +jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz) { jl_value_t **ol = jl_svec_data(a); size_t sz = jl_svec_len(a); while (1) { size_t i; - jl_svec_t *newa = jl_alloc_svec(newsz); + jl_svec_t *newa = jl_svec_fill(newsz, jl_nothing); JL_GC_PUSH1(&newa); for (i = 0; i < sz; i += 1) { jl_value_t *val = ol[i]; - if (val != NULL && val != jl_nothing) { + if (val != jl_nothing) { uint_t hv = ((jl_datatype_t*)val)->hash; if (!cache_insert_type_set_(newa, (jl_datatype_t*)val, hv, 0)) { break; @@ -849,15 +847,15 @@ static void cache_insert_type_linear(jl_datatype_t *type, ssize_t insert_at) jl_svec_t *cache = jl_atomic_load_relaxed(&type->name->linearcache); assert(jl_is_svec(cache)); size_t n = jl_svec_len(cache); - if (n == 0 || jl_svecref(cache, n - 1) != NULL) { - jl_svec_t *nc = jl_alloc_svec(n < 8 ? 8 : (n*3)>>1); + if (n == 0 || jl_svecref(cache, n - 1) != jl_nothing) { + jl_svec_t *nc = jl_svec_fill(n < 4 ? 4 : n * 2, jl_nothing); memcpy(jl_svec_data(nc), jl_svec_data(cache), sizeof(void*) * n); jl_atomic_store_release(&type->name->linearcache, nc); jl_gc_wb(type->name, nc); cache = nc; n = jl_svec_len(nc); } - assert(jl_svecref(cache, insert_at) == NULL); + assert(jl_svecref(cache, insert_at) == jl_nothing); jl_svecset(cache, insert_at, (jl_value_t*)type); // todo: make this an atomic-store } @@ -2392,12 +2390,6 @@ void jl_init_types(void) JL_GC_DISABLED jl_svec(1, jl_slotnumber_type), jl_emptysvec, 0, 0, 1); - jl_globalref_type = - jl_new_datatype(jl_symbol("GlobalRef"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(2, "mod", "name"), - jl_svec(2, jl_module_type, jl_symbol_type), - jl_emptysvec, 0, 0, 2); - jl_code_info_type = jl_new_datatype(jl_symbol("CodeInfo"), core, jl_any_type, jl_emptysvec, @@ -2694,6 +2686,12 @@ void jl_init_types(void) JL_GC_DISABLED jl_value_t *pointer_void = jl_apply_type1((jl_value_t*)jl_pointer_type, (jl_value_t*)jl_nothing_type); + jl_globalref_type = + jl_new_datatype(jl_symbol("GlobalRef"), core, jl_any_type, jl_emptysvec, + jl_perm_symsvec(3, "mod", "name", "binding"), + jl_svec(3, jl_module_type, jl_symbol_type, pointer_void), + jl_emptysvec, 0, 0, 3); + tv = jl_svec2(tvar("A"), tvar("R")); jl_opaque_closure_type = (jl_unionall_t*)jl_new_datatype(jl_symbol("OpaqueClosure"), core, jl_function_type, tv, jl_perm_symsvec(5, "captures", "world", "source", "invoke", "specptr"), diff --git a/src/julia.h b/src/julia.h index 674cb451b7f87..644ce0dbd78ae 100644 --- a/src/julia.h +++ b/src/julia.h @@ -603,6 +603,13 @@ typedef struct _jl_module_t { jl_mutex_t lock; } jl_module_t; +typedef struct { + jl_module_t *mod; + jl_sym_t *name; + // Not serialized. Caches the value of jl_get_binding(mod, name). + jl_binding_t *bnd_cache; +} jl_globalref_t; + // one Type-to-Value entry typedef struct _jl_typemap_entry_t { JL_DATA_TYPE @@ -1616,6 +1623,7 @@ JL_DLLEXPORT int jl_get_module_max_methods(jl_module_t *m); // get binding for reading JL_DLLEXPORT jl_binding_t *jl_get_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var); JL_DLLEXPORT jl_binding_t *jl_get_binding_or_error(jl_module_t *m, jl_sym_t *var); +JL_DLLEXPORT jl_binding_t *jl_get_binding_if_bound(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT jl_value_t *jl_module_globalref(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT jl_value_t *jl_binding_type(jl_module_t *m, jl_sym_t *var); // get binding for assignment @@ -1626,6 +1634,8 @@ JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var); +JL_DLLEXPORT int jl_binding_is_const(jl_binding_t *b); +JL_DLLEXPORT int jl_binding_boundp(jl_binding_t *b); JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var); JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT); JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT); diff --git a/src/julia_gcext.h b/src/julia_gcext.h index 6787dafb4b7ee..631d9c2910330 100644 --- a/src/julia_gcext.h +++ b/src/julia_gcext.h @@ -76,7 +76,7 @@ JL_DLLEXPORT void jl_gc_mark_queue_objarray(jl_ptls_t ptls, jl_value_t *parent, // Sweep functions will not automatically be called for objects of // foreign types, as that may not always be desired. Only calling // jl_gc_schedule_foreign_sweepfunc() on an object of a foreign type -// will result in the custome sweep function actually being called. +// will result in the custom sweep function actually being called. // This must be done at most once per object and should usually be // done right after allocating the object. JL_DLLEXPORT void jl_gc_schedule_foreign_sweepfunc(jl_ptls_t ptls, jl_value_t * bj); diff --git a/src/julia_internal.h b/src/julia_internal.h index ccc542ba89f09..b5fbf9416fcf0 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -599,7 +599,7 @@ jl_method_instance_t *jl_get_unspecialized(jl_method_t *def JL_PROPAGATES_ROOT); JL_DLLEXPORT void jl_compile_method_instance(jl_method_instance_t *mi, jl_tupletype_t *types, size_t world); JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types); jl_code_info_t *jl_code_for_interpreter(jl_method_instance_t *lam JL_PROPAGATES_ROOT); -int jl_code_requires_compiler(jl_code_info_t *src); +int jl_code_requires_compiler(jl_code_info_t *src, int include_force_compile); jl_code_info_t *jl_new_code_info_from_ir(jl_expr_t *ast); JL_DLLEXPORT jl_code_info_t *jl_new_code_info_uninit(void); void jl_resolve_globals_in_ir(jl_array_t *stmts, jl_module_t *m, jl_svec_t *sparam_vals, @@ -685,6 +685,7 @@ jl_vararg_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n); void jl_reinstantiate_inner_types(jl_datatype_t *t); jl_datatype_t *jl_lookup_cache_type_(jl_datatype_t *type); void jl_cache_type_(jl_datatype_t *type); +jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz); void set_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *rhs, int isatomic) JL_NOTSAFEPOINT; jl_value_t *swap_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *rhs, int isatomic); jl_value_t *modify_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *op, jl_value_t *rhs, int isatomic); @@ -716,13 +717,14 @@ jl_value_t *jl_gf_invoke_by_method(jl_method_t *method, jl_value_t *gf, jl_value jl_value_t *jl_gf_invoke(jl_value_t *types, jl_value_t *f, jl_value_t **args, size_t nargs); JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t *mt, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid, int *ambig); +JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup_worlds(jl_value_t *types, jl_value_t *mt, size_t world, size_t *min_world, size_t *max_world); JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_argument_datatype(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_methtable_t *jl_method_table_for( jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_methtable_t *jl_method_get_table( - jl_method_t *method) JL_NOTSAFEPOINT; + jl_method_t *method JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT; jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAGATES_ROOT); JL_DLLEXPORT int jl_pointer_egal(jl_value_t *t); @@ -989,7 +991,7 @@ jl_value_t *jl_parse(const char *text, size_t text_len, jl_value_t *filename, // 2. An "extended entry": a mixture of raw data and pointers to julia objects // which must be treated as GC roots. // -// A single extended entry is seralized using multiple elements from the raw +// A single extended entry is serialized using multiple elements from the raw // buffer; if `e` is the pointer to the first slot we have: // // e[0] JL_BT_NON_PTR_ENTRY - Special marker to distinguish extended entries @@ -1429,7 +1431,6 @@ int jl_typemap_intersection_visitor(jl_typemap_t *a, int offs, struct typemap_in // For codegen only. JL_DLLEXPORT size_t (jl_svec_len)(jl_svec_t *t) JL_NOTSAFEPOINT; -JL_DLLEXPORT int8_t jl_svec_isassigned(jl_svec_t *t JL_PROPAGATES_ROOT, ssize_t i) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_svec_ref(jl_svec_t *t JL_PROPAGATES_ROOT, ssize_t i); diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index 9caa45e193912..9cc125820d2f3 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -27,12 +27,12 @@ #include +#include "passes.h" #include "codegen_shared.h" #include "julia.h" #include "julia_internal.h" #include "llvm-pass-helpers.h" #include "llvm-alloc-helpers.h" -#include "passes.h" #include #include @@ -312,7 +312,10 @@ ssize_t Optimizer::getGCAllocSize(Instruction *I) if (call->getCalledOperand() != pass.alloc_obj_func) return -1; assert(call->arg_size() == 3); - size_t sz = (size_t)cast(call->getArgOperand(1))->getZExtValue(); + auto CI = dyn_cast(call->getArgOperand(1)); + if (!CI) + return -1; + size_t sz = (size_t)CI->getZExtValue(); if (sz < IntegerType::MAX_INT_BITS / 8 && sz < INT32_MAX) return sz; return -1; diff --git a/src/llvm-cpufeatures.cpp b/src/llvm-cpufeatures.cpp index 1c21ddba49be6..6211d284bdd24 100644 --- a/src/llvm-cpufeatures.cpp +++ b/src/llvm-cpufeatures.cpp @@ -26,7 +26,6 @@ #include #include -#include "julia.h" #include "jitlayers.h" #define DEBUG_TYPE "cpufeatures" diff --git a/src/llvm-final-gc-lowering.cpp b/src/llvm-final-gc-lowering.cpp index 0ef7289df827c..e7e9fe2f4f26a 100644 --- a/src/llvm-final-gc-lowering.cpp +++ b/src/llvm-final-gc-lowering.cpp @@ -3,6 +3,7 @@ #include "llvm-version.h" #include "passes.h" +#include #include #include #include @@ -18,6 +19,13 @@ #include "llvm-pass-helpers.h" #define DEBUG_TYPE "final_gc_lowering" +STATISTIC(NewGCFrameCount, "Number of lowered newGCFrameFunc intrinsics"); +STATISTIC(PushGCFrameCount, "Number of lowered pushGCFrameFunc intrinsics"); +STATISTIC(PopGCFrameCount, "Number of lowered popGCFrameFunc intrinsics"); +STATISTIC(GetGCFrameSlotCount, "Number of lowered getGCFrameSlotFunc intrinsics"); +STATISTIC(GCAllocBytesCount, "Number of lowered GCAllocBytesFunc intrinsics"); +STATISTIC(QueueGCRootCount, "Number of lowered queueGCRootFunc intrinsics"); +STATISTIC(QueueGCBindingCount, "Number of lowered queueGCBindingFunc intrinsics"); using namespace llvm; @@ -66,6 +74,7 @@ struct FinalLowerGC: private JuliaPassContext { Value *FinalLowerGC::lowerNewGCFrame(CallInst *target, Function &F) { + ++NewGCFrameCount; assert(target->arg_size() == 1); unsigned nRoots = cast(target->getArgOperand(0))->getLimitedValue(INT_MAX); @@ -98,7 +107,7 @@ Value *FinalLowerGC::lowerNewGCFrame(CallInst *target, Function &F) ConstantInt::get(Type::getInt32Ty(F.getContext()), sizeof(jl_value_t*) * (nRoots + 2)), // len ConstantInt::get(Type::getInt1Ty(F.getContext()), 0)}; // volatile CallInst *zeroing = CallInst::Create(memset, makeArrayRef(args)); - cast(zeroing)->setDestAlignment(16); + cast(zeroing)->setDestAlignment(Align(16)); zeroing->setMetadata(LLVMContext::MD_tbaa, tbaa_gcframe); zeroing->insertAfter(tempSlot_i8); @@ -107,6 +116,7 @@ Value *FinalLowerGC::lowerNewGCFrame(CallInst *target, Function &F) void FinalLowerGC::lowerPushGCFrame(CallInst *target, Function &F) { + ++PushGCFrameCount; assert(target->arg_size() == 2); auto gcframe = target->getArgOperand(0); unsigned nRoots = cast(target->getArgOperand(1))->getLimitedValue(INT_MAX); @@ -136,6 +146,7 @@ void FinalLowerGC::lowerPushGCFrame(CallInst *target, Function &F) void FinalLowerGC::lowerPopGCFrame(CallInst *target, Function &F) { + ++PopGCFrameCount; assert(target->arg_size() == 1); auto gcframe = target->getArgOperand(0); @@ -155,6 +166,7 @@ void FinalLowerGC::lowerPopGCFrame(CallInst *target, Function &F) Value *FinalLowerGC::lowerGetGCFrameSlot(CallInst *target, Function &F) { + ++GetGCFrameSlotCount; assert(target->arg_size() == 2); auto gcframe = target->getArgOperand(0); auto index = target->getArgOperand(1); @@ -174,6 +186,7 @@ Value *FinalLowerGC::lowerGetGCFrameSlot(CallInst *target, Function &F) Value *FinalLowerGC::lowerQueueGCRoot(CallInst *target, Function &F) { + ++QueueGCRootCount; assert(target->arg_size() == 1); target->setCalledFunction(queueRootFunc); return target; @@ -181,6 +194,7 @@ Value *FinalLowerGC::lowerQueueGCRoot(CallInst *target, Function &F) Value *FinalLowerGC::lowerQueueGCBinding(CallInst *target, Function &F) { + ++QueueGCBindingCount; assert(target->arg_size() == 1); target->setCalledFunction(queueBindingFunc); return target; @@ -188,6 +202,7 @@ Value *FinalLowerGC::lowerQueueGCBinding(CallInst *target, Function &F) Value *FinalLowerGC::lowerGCAllocBytes(CallInst *target, Function &F) { + ++GCAllocBytesCount; assert(target->arg_size() == 2); auto sz = (size_t)cast(target->getArgOperand(1))->getZExtValue(); // This is strongly architecture and OS dependent diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 1fab161a4766e..8847a3e34be51 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "llvm/Analysis/CFG.h" #include #include @@ -749,6 +750,7 @@ void LateLowerGCFrame::LiftPhi(State &S, PHINode *Phi) { } if (!isa(Phi->getType())) S.AllCompositeNumbering[Phi] = Numbers; + SmallVector, 4> CastedRoots(NumRoots); for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { Value *Incoming = Phi->getIncomingValue(i); BasicBlock *IncomingBB = Phi->getIncomingBlock(i); @@ -766,8 +768,27 @@ void LateLowerGCFrame::LiftPhi(State &S, PHINode *Phi) { BaseElem = Base; else BaseElem = IncomingBases[i]; - if (BaseElem->getType() != T_prjlvalue) - BaseElem = new BitCastInst(BaseElem, T_prjlvalue, "", Terminator); + if (BaseElem->getType() != T_prjlvalue) { + auto &remap = CastedRoots[i][BaseElem]; + if (!remap) { + if (auto constant = dyn_cast(BaseElem)) { + remap = ConstantExpr::getBitCast(constant, T_prjlvalue, ""); + } else { + Instruction *InsertBefore; + if (auto arg = dyn_cast(BaseElem)) { + InsertBefore = &*arg->getParent()->getEntryBlock().getFirstInsertionPt(); + } else { + assert(isa(BaseElem) && "Unknown value type detected!"); + InsertBefore = cast(BaseElem)->getNextNonDebugInstruction(); + } + while (isa(InsertBefore)) { + InsertBefore = InsertBefore->getNextNonDebugInstruction(); + } + remap = new BitCastInst(BaseElem, T_prjlvalue, "", InsertBefore); + } + } + BaseElem = remap; + } lift->addIncoming(BaseElem, IncomingBB); } } @@ -1288,7 +1309,7 @@ void LateLowerGCFrame::FixUpRefinements(ArrayRef PHINumbers, State &S) // value of -1 or -2 in the refinement map), or may be externally rooted by refinement to other // values. Thus a value is not externally rooted if it either: // either: - // - Has no refinements (all obiviously externally rooted values are annotated by -1/-2 in the + // - Has no refinements (all obviously externally rooted values are annotated by -1/-2 in the // refinement map). // - Recursively reaches a not-externally rooted value through its refinements // @@ -2614,7 +2635,8 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(std::vector &Colors, State unsigned AllocaSlot = 2; // first two words are metadata auto replace_alloca = [this, gcframe, &AllocaSlot, T_int32](AllocaInst *&AI) { // Pick a slot for the alloca. - unsigned align = AI->getAlignment() / sizeof(void*); // TODO: use DataLayout pointer size + AI->getAlign(); + unsigned align = AI->getAlign().value() / sizeof(void*); // TODO: use DataLayout pointer size assert(align <= 16 / sizeof(void*) && "Alignment exceeds llvm-final-gc-lowering abilities"); if (align > 1) AllocaSlot = LLT_ALIGN(AllocaSlot, align); diff --git a/src/llvm-lower-handlers.cpp b/src/llvm-lower-handlers.cpp index d4d4aa965b175..881d2252eacbf 100644 --- a/src/llvm-lower-handlers.cpp +++ b/src/llvm-lower-handlers.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,8 @@ #define DEBUG_TYPE "lower_handlers" #undef DEBUG +STATISTIC(MaxExceptionHandlerDepth, "Maximum nesting of exception handlers"); +STATISTIC(ExceptionHandlerBuffers, "Number of exception handler buffers inserted"); using namespace llvm; @@ -156,6 +159,8 @@ static bool lowerExcHandlers(Function &F) { /* Remember the depth at the BB boundary */ ExitDepth[BB] = Depth; } + MaxExceptionHandlerDepth.updateMax(MaxDepth); + ExceptionHandlerBuffers += MaxDepth; /* Step 2: EH Frame lowering */ // Allocate stack space for each handler. We allocate these as separate diff --git a/src/llvm-propagate-addrspaces.cpp b/src/llvm-propagate-addrspaces.cpp index 97ae9d0555a8f..e2d390a5e4395 100644 --- a/src/llvm-propagate-addrspaces.cpp +++ b/src/llvm-propagate-addrspaces.cpp @@ -22,9 +22,8 @@ #include #include -#include "codegen_shared.h" -#include "julia.h" #include "passes.h" +#include "codegen_shared.h" #define DEBUG_TYPE "propagate_julia_addrspaces" diff --git a/src/llvm-remove-addrspaces.cpp b/src/llvm-remove-addrspaces.cpp index a3f3cbb1fee72..814e31ec2252f 100644 --- a/src/llvm-remove-addrspaces.cpp +++ b/src/llvm-remove-addrspaces.cpp @@ -12,9 +12,8 @@ #include #include -#include "codegen_shared.h" -#include "julia.h" #include "passes.h" +#include "codegen_shared.h" #define DEBUG_TYPE "remove_addrspaces" diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp index c9a38a6a879b8..1848b429869dd 100644 --- a/src/llvm-simdloop.cpp +++ b/src/llvm-simdloop.cpp @@ -38,6 +38,7 @@ STATISTIC(SimdLoops, "Number of loops with SIMD instructions"); STATISTIC(IVDepInstructions, "Number of instructions marked ivdep"); STATISTIC(ReductionChains, "Number of reduction chains folded"); STATISTIC(ReductionChainLength, "Total sum of instructions folded from reduction chain"); +STATISTIC(MaxChainLength, "Max length of reduction chain"); STATISTIC(AddChains, "Addition reduction chains"); STATISTIC(MulChains, "Multiply reduction chains"); @@ -119,11 +120,14 @@ static void enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) break; } ++ReductionChains; + int length = 0; for (chainVector::const_iterator K=chain.begin(); K!=chain.end(); ++K) { LLVM_DEBUG(dbgs() << "LSL: marking " << **K << "\n"); (*K)->setFast(true); - ++ReductionChainLength; + ++length; } + ReductionChainLength += length; + MaxChainLength.updateMax(length); } static bool markLoopInfo(Module &M, Function *marker, function_ref GetLI) diff --git a/src/method.c b/src/method.c index 52748ede0d35a..f0e2598750801 100644 --- a/src/method.c +++ b/src/method.c @@ -957,12 +957,6 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, size_t i, na = jl_svec_len(atypes); argtype = (jl_value_t*)jl_apply_tuple_type(atypes); - for (i = jl_svec_len(tvars); i > 0; i--) { - jl_value_t *tv = jl_svecref(tvars, i - 1); - if (!jl_is_typevar(tv)) - jl_type_error("method signature", (jl_value_t*)jl_tvar_type, tv); - argtype = jl_new_struct(jl_unionall_type, tv, argtype); - } jl_methtable_t *external_mt = mt; if (!mt) @@ -972,6 +966,12 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, if (mt->frozen) jl_error("cannot add methods to a builtin function"); + assert(jl_is_linenode(functionloc)); + jl_sym_t *file = (jl_sym_t*)jl_linenode_file(functionloc); + if (!jl_is_symbol(file)) + file = jl_empty_sym; + int32_t line = jl_linenode_line(functionloc); + // TODO: derive our debug name from the syntax instead of the type name = mt->name; if (mt == jl_type_type_mt || mt == jl_nonfunction_mt || external_mt) { @@ -988,6 +988,29 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, } } } + + for (i = jl_svec_len(tvars); i > 0; i--) { + jl_value_t *tv = jl_svecref(tvars, i - 1); + if (!jl_is_typevar(tv)) + jl_type_error("method signature", (jl_value_t*)jl_tvar_type, tv); + if (!jl_has_typevar(argtype, (jl_tvar_t*)tv)) // deprecate this to an error in v2 + jl_printf(JL_STDERR, + "WARNING: method definition for %s at %s:%d declares type variable %s but does not use it.\n", + jl_symbol_name(name), + jl_symbol_name(file), + line, + jl_symbol_name(((jl_tvar_t*)tv)->name)); + argtype = jl_new_struct(jl_unionall_type, tv, argtype); + } + if (jl_has_free_typevars(argtype)) { + jl_exceptionf(jl_argumenterror_type, + "method definition for %s at %s:%d has free type variables", + jl_symbol_name(name), + jl_symbol_name(file), + line); + } + + if (!jl_is_code_info(f)) { // this occurs when there is a closure being added to an out-of-scope function // the user should only do this at the toplevel @@ -1002,20 +1025,10 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, m->name = name; m->isva = isva; m->nargs = nargs; - assert(jl_is_linenode(functionloc)); - jl_value_t *file = jl_linenode_file(functionloc); - m->file = jl_is_symbol(file) ? (jl_sym_t*)file : jl_empty_sym; - m->line = jl_linenode_line(functionloc); + m->file = file; + m->line = line; jl_method_set_source(m, f); - if (jl_has_free_typevars(argtype)) { - jl_exceptionf(jl_argumenterror_type, - "method definition for %s at %s:%d has free type variables", - jl_symbol_name(name), - jl_symbol_name(m->file), - m->line); - } - for (i = 0; i < na; i++) { jl_value_t *elt = jl_svecref(atypes, i); if (!jl_is_type(elt) && !jl_is_typevar(elt) && !jl_is_vararg(elt)) { @@ -1025,22 +1038,22 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata, "invalid type for argument number %d in method definition for %s at %s:%d", i, jl_symbol_name(name), - jl_symbol_name(m->file), - m->line); + jl_symbol_name(file), + line); else jl_exceptionf(jl_argumenterror_type, "invalid type for argument %s in method definition for %s at %s:%d", jl_symbol_name(argname), jl_symbol_name(name), - jl_symbol_name(m->file), - m->line); + jl_symbol_name(file), + line); } if (jl_is_vararg(elt) && i < na-1) jl_exceptionf(jl_argumenterror_type, "Vararg on non-final argument in method definition for %s at %s:%d", jl_symbol_name(name), - jl_symbol_name(m->file), - m->line); + jl_symbol_name(file), + line); } #ifdef RECORD_METHOD_ORDER diff --git a/src/module.c b/src/module.c index 92393563dd8cb..805f4ca1affac 100644 --- a/src/module.c +++ b/src/module.c @@ -363,6 +363,20 @@ static jl_binding_t *jl_get_binding_(jl_module_t *m, jl_sym_t *var, modstack_t * return b; } +JL_DLLEXPORT jl_binding_t *jl_get_binding_if_bound(jl_module_t *m, jl_sym_t *var) +{ + JL_LOCK(&m->lock); + jl_binding_t *b = _jl_get_module_binding(m, var); + JL_UNLOCK(&m->lock); + if (b == HT_NOTFOUND || b->owner == NULL) { + return NULL; + } + if (b->owner != m || b->name != var) + return jl_get_binding_if_bound(b->owner, b->name); + return b; +} + + // get owner of binding when accessing m.var, without resolving the binding JL_DLLEXPORT jl_value_t *jl_binding_owner(jl_module_t *m, jl_sym_t *var) { @@ -410,17 +424,29 @@ JL_DLLEXPORT jl_binding_t *jl_get_binding_or_error(jl_module_t *m, jl_sym_t *var return b; } +JL_DLLEXPORT jl_globalref_t *jl_new_globalref(jl_module_t *mod, jl_sym_t *name, jl_binding_t *b) +{ + jl_task_t *ct = jl_current_task; + jl_globalref_t *g = (jl_globalref_t *)jl_gc_alloc(ct->ptls, sizeof(jl_globalref_t), jl_globalref_type); + g->mod = mod; + jl_gc_wb(g, g->mod); + g->name = name; + g->bnd_cache = b; + return g; +} + JL_DLLEXPORT jl_value_t *jl_module_globalref(jl_module_t *m, jl_sym_t *var) { JL_LOCK(&m->lock); - jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); + jl_binding_t *b = _jl_get_module_binding(m, var); if (b == HT_NOTFOUND) { JL_UNLOCK(&m->lock); - return jl_new_struct(jl_globalref_type, m, var); + return (jl_value_t *)jl_new_globalref(m, var, NULL); } jl_value_t *globalref = jl_atomic_load_relaxed(&b->globalref); if (globalref == NULL) { - jl_value_t *newref = jl_new_struct(jl_globalref_type, m, var); + jl_value_t *newref = (jl_value_t *)jl_new_globalref(m, var, + !b->owner ? NULL : b->owner == m ? b : _jl_get_module_binding(b->owner, b->name)); if (jl_atomic_cmpswap_relaxed(&b->globalref, &globalref, newref)) { JL_GC_PROMISE_ROOTED(newref); globalref = newref; @@ -662,12 +688,18 @@ JL_DLLEXPORT jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_RO return b == HT_NOTFOUND ? NULL : b; } + +JL_DLLEXPORT jl_value_t *jl_binding_value(jl_binding_t *b JL_PROPAGATES_ROOT) +{ + return jl_atomic_load_relaxed(&b->value); +} + JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var) { jl_binding_t *b = jl_get_binding(m, var); if (b == NULL) return NULL; if (b->deprecated) jl_binding_deprecation_warning(m, b); - return b->value; + return jl_binding_value(b); } JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT) @@ -696,10 +728,22 @@ JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var jl_symbol_name(bp->name)); } +JL_DLLEXPORT int jl_binding_is_const(jl_binding_t *b) +{ + assert(b); + return b->constp; +} + +JL_DLLEXPORT int jl_binding_boundp(jl_binding_t *b) +{ + assert(b); + return b->value != 0; +} + JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var) { jl_binding_t *b = jl_get_binding(m, var); - return b && b->constp; + return b && jl_binding_is_const(b); } // set the deprecated flag for a binding: diff --git a/src/options.h b/src/options.h index 75a3e6e02c1bc..6d2764fa91dfd 100644 --- a/src/options.h +++ b/src/options.h @@ -128,7 +128,7 @@ // controls for when threads sleep #define THREAD_SLEEP_THRESHOLD_NAME "JULIA_THREAD_SLEEP_THRESHOLD" -#define DEFAULT_THREAD_SLEEP_THRESHOLD 16*1000 // nanoseconds (16us) +#define DEFAULT_THREAD_SLEEP_THRESHOLD 100*1000 // nanoseconds (100us) // defaults for # threads #define NUM_THREADS_NAME "JULIA_NUM_THREADS" diff --git a/src/pipeline.cpp b/src/pipeline.cpp index d9602ad7010d4..10709989f55b0 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -12,6 +12,7 @@ // analysis passes #include #include +#include #include #include #include @@ -115,7 +116,7 @@ namespace { // TODO: Consider add more passes like in // addGeneralOptsForMemorySanitizer. EarlyCSEPass makes visible // difference on size. It's not clear if the rest is still - // usefull. InstCombinePass breakes + // useful. InstCombinePass breaks // compiler-rt/test/msan/select_origin.cpp. } MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); @@ -172,11 +173,10 @@ namespace { // } } - void addVerificationPasses(ModulePassManager &MPM) { - FunctionPassManager FPM; - FPM.addPass(GCInvariantVerifierPass()); - FPM.addPass(VerifierPass()); - MPM.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(FPM))); + void addVerificationPasses(ModulePassManager &MPM, bool llvm_only) { + if (!llvm_only) + MPM.addPass(llvm::createModuleToFunctionPassAdaptor(GCInvariantVerifierPass())); + MPM.addPass(VerifierPass()); } auto basicSimplifyCFGOptions() { @@ -207,16 +207,17 @@ namespace { //the PassBuilder extension point callbacks //For now we'll maintain the insertion points even though they don't do anything //for the sake of documentation - void invokePipelineStartCallbacks(ModulePassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokePeepholeEPCallbacks(FunctionPassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokeEarlySimplificationCallbacks(ModulePassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokeCGSCCCallbacks(CGSCCPassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokeOptimizerEarlyCallbacks(ModulePassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokeLateLoopOptimizationCallbacks(LoopPassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokeLoopOptimizerEndCallbacks(LoopPassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokeScalarOptimizerCallbacks(FunctionPassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokeVectorizerCallbacks(FunctionPassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} - void invokeOptimizerLastCallbacks(ModulePassManager &MPM, PassBuilder &PB, OptimizationLevel O) {} + //If PB is a nullptr, don't invoke anything (this happens when running julia from opt) + void invokePipelineStartCallbacks(ModulePassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokePeepholeEPCallbacks(FunctionPassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokeEarlySimplificationCallbacks(ModulePassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokeCGSCCCallbacks(CGSCCPassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokeOptimizerEarlyCallbacks(ModulePassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokeLateLoopOptimizationCallbacks(LoopPassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokeLoopOptimizerEndCallbacks(LoopPassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokeScalarOptimizerCallbacks(FunctionPassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokeVectorizerCallbacks(FunctionPassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} + void invokeOptimizerLastCallbacks(ModulePassManager &MPM, PassBuilder *PB, OptimizationLevel O) {} } //The actual pipelines @@ -239,15 +240,17 @@ namespace { //? loop sink pass //? hot-cold splitting pass +#define JULIA_PASS(ADD_PASS) if (!options.llvm_only) { ADD_PASS; } else do;while (0) + //Use for O1 and below -void buildBasicPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLevel O, OptimizationOptions options) { +void buildBasicPipeline(ModulePassManager &MPM, PassBuilder *PB, OptimizationLevel O, OptimizationOptions options) { // #ifdef JL_DEBUG_BUILD - addVerificationPasses(MPM); + addVerificationPasses(MPM, options.llvm_only); // #endif invokePipelineStartCallbacks(MPM, PB, O); MPM.addPass(ConstantMergePass()); if (!options.dump_native) { - MPM.addPass(CPUFeatures()); + JULIA_PASS(MPM.addPass(CPUFeatures())); if (O.getSpeedupLevel() > 0) { MPM.addPass(createModuleToFunctionPassAdaptor(InstSimplifyPass())); } @@ -271,7 +274,7 @@ void buildBasicPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLev MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); } invokeOptimizerEarlyCallbacks(MPM, PB, O); - MPM.addPass(LowerSIMDLoop()); + JULIA_PASS(MPM.addPass(LowerSIMDLoop())); { FunctionPassManager FPM; { @@ -288,21 +291,21 @@ void buildBasicPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLev //TODO no barrier pass? { FunctionPassManager FPM; - FPM.addPass(LowerExcHandlers()); - FPM.addPass(GCInvariantVerifierPass(false)); + JULIA_PASS(FPM.addPass(LowerExcHandlers())); + JULIA_PASS(FPM.addPass(GCInvariantVerifierPass(false))); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } - MPM.addPass(RemoveNI()); - MPM.addPass(createModuleToFunctionPassAdaptor(LateLowerGC())); - MPM.addPass(FinalLowerGCPass()); - MPM.addPass(LowerPTLSPass(options.dump_native)); + JULIA_PASS(MPM.addPass(RemoveNI())); + JULIA_PASS(MPM.addPass(createModuleToFunctionPassAdaptor(LateLowerGC()))); + JULIA_PASS(MPM.addPass(FinalLowerGCPass())); + JULIA_PASS(MPM.addPass(LowerPTLSPass(options.dump_native))); } else { - MPM.addPass(RemoveNI()); + JULIA_PASS(MPM.addPass(RemoveNI())); } - MPM.addPass(LowerSIMDLoop()); // TODO why do we do this twice + JULIA_PASS(MPM.addPass(LowerSIMDLoop())); // TODO why do we do this twice if (options.dump_native) { - MPM.addPass(MultiVersioning(options.external_use)); - MPM.addPass(CPUFeatures()); + JULIA_PASS(MPM.addPass(MultiVersioning(options.external_use))); + JULIA_PASS(MPM.addPass(CPUFeatures())); if (O.getSpeedupLevel() > 0) { FunctionPassManager FPM; FPM.addPass(InstSimplifyPass()); @@ -312,19 +315,19 @@ void buildBasicPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLev } invokeOptimizerLastCallbacks(MPM, PB, O); addSanitizerPasses(MPM, O); - MPM.addPass(createModuleToFunctionPassAdaptor(DemoteFloat16())); + JULIA_PASS(MPM.addPass(createModuleToFunctionPassAdaptor(DemoteFloat16()))); } //Use for O2 and above -void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLevel O, OptimizationOptions options) { +void buildFullPipeline(ModulePassManager &MPM, PassBuilder *PB, OptimizationLevel O, OptimizationOptions options) { // #ifdef JL_DEBUG_BUILD - addVerificationPasses(MPM); + addVerificationPasses(MPM, options.llvm_only); // #endif invokePipelineStartCallbacks(MPM, PB, O); MPM.addPass(ConstantMergePass()); { FunctionPassManager FPM; - FPM.addPass(PropagateJuliaAddrspacesPass()); + JULIA_PASS(FPM.addPass(PropagateJuliaAddrspacesPass())); //TODO consider not using even basic simplification //options here, and adding a run of CVP to take advantage //of the unsimplified codegen information (e.g. known @@ -342,7 +345,7 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve invokeCGSCCCallbacks(CGPM, PB, O); { FunctionPassManager FPM; - FPM.addPass(AllocOptPass()); + JULIA_PASS(FPM.addPass(AllocOptPass())); FPM.addPass(InstCombinePass()); FPM.addPass(SimplifyCFGPass(basicSimplifyCFGOptions())); CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM))); @@ -350,9 +353,9 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); } if (options.dump_native) { - MPM.addPass(MultiVersioning(options.external_use)); + JULIA_PASS(MPM.addPass(MultiVersioning(options.external_use))); } - MPM.addPass(CPUFeatures()); + JULIA_PASS(MPM.addPass(CPUFeatures())); { FunctionPassManager FPM; FPM.addPass(SROAPass()); @@ -361,7 +364,7 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve FPM.addPass(CorrelatedValuePropagationPass()); FPM.addPass(ReassociatePass()); FPM.addPass(EarlyCSEPass()); - FPM.addPass(AllocOptPass()); + JULIA_PASS(FPM.addPass(AllocOptPass())); invokePeepholeEPCallbacks(FPM, PB, O); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } @@ -374,11 +377,14 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve invokeLateLoopOptimizationCallbacks(LPM1, PB, O); //We don't know if the loop callbacks support MSSA FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM1), /*UseMemorySSA = */false)); - LPM2.addPass(LICMPass()); - LPM2.addPass(JuliaLICMPass()); +#if JL_LLVM_VERSION < 150000 +#define LICMOptions() +#endif + LPM2.addPass(LICMPass(LICMOptions())); + JULIA_PASS(LPM2.addPass(JuliaLICMPass())); LPM2.addPass(SimpleLoopUnswitchPass()); - LPM2.addPass(LICMPass()); - LPM2.addPass(JuliaLICMPass()); + LPM2.addPass(LICMPass(LICMOptions())); + JULIA_PASS(LPM2.addPass(JuliaLICMPass())); //LICM needs MemorySSA now, so we must use it FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM2), /*UseMemorySSA = */true)); } @@ -394,7 +400,7 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM), /*UseMemorySSA = */false)); } FPM.addPass(LoopUnrollPass()); - FPM.addPass(AllocOptPass()); + JULIA_PASS(FPM.addPass(AllocOptPass())); FPM.addPass(SROAPass()); FPM.addPass(InstSimplifyPass()); FPM.addPass(GVNPass()); @@ -411,7 +417,7 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve FPM.addPass(DSEPass()); invokePeepholeEPCallbacks(FPM, PB, O); FPM.addPass(SimplifyCFGPass(aggressiveSimplifyCFGOptions())); - FPM.addPass(AllocOptPass()); + JULIA_PASS(FPM.addPass(AllocOptPass())); { LoopPassManager LPM; LPM.addPass(LoopDeletionPass()); @@ -434,15 +440,15 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve //TODO barrier pass? { FunctionPassManager FPM; - FPM.addPass(LowerExcHandlers()); - FPM.addPass(GCInvariantVerifierPass(false)); + JULIA_PASS(FPM.addPass(LowerExcHandlers())); + JULIA_PASS(FPM.addPass(GCInvariantVerifierPass(false))); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } // Needed **before** LateLowerGCFrame on LLVM < 12 // due to bug in `CreateAlignmentAssumption`. - MPM.addPass(RemoveNI()); - MPM.addPass(createModuleToFunctionPassAdaptor(LateLowerGC())); - MPM.addPass(FinalLowerGCPass()); + JULIA_PASS(MPM.addPass(RemoveNI())); + JULIA_PASS(MPM.addPass(createModuleToFunctionPassAdaptor(LateLowerGC()))); + JULIA_PASS(MPM.addPass(FinalLowerGCPass())); { FunctionPassManager FPM; FPM.addPass(GVNPass()); @@ -450,7 +456,7 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve FPM.addPass(DCEPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } - MPM.addPass(LowerPTLSPass(options.dump_native)); + JULIA_PASS(MPM.addPass(LowerPTLSPass(options.dump_native))); { FunctionPassManager FPM; FPM.addPass(InstCombinePass()); @@ -458,11 +464,11 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } } else { - MPM.addPass(RemoveNI()); + JULIA_PASS(MPM.addPass(RemoveNI())); } { FunctionPassManager FPM; - FPM.addPass(CombineMulAdd()); + JULIA_PASS(FPM.addPass(CombineMulAdd())); FPM.addPass(DivRemPairsPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } @@ -470,12 +476,14 @@ void buildFullPipeline(ModulePassManager &MPM, PassBuilder &PB, OptimizationLeve addSanitizerPasses(MPM, O); { FunctionPassManager FPM; - FPM.addPass(DemoteFloat16()); + JULIA_PASS(FPM.addPass(DemoteFloat16())); FPM.addPass(GVNPass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } } +#undef JULIA_PASS + namespace { auto createPIC(StandardInstrumentations &SI) { auto PIC = std::make_unique(); @@ -553,9 +561,9 @@ PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); ModulePassManager createMPM(PassBuilder &PB, OptimizationLevel O, OptimizationOptions options) { ModulePassManager MPM; if (O.getSpeedupLevel() < 2) - buildBasicPipeline(MPM, PB, O, options); + buildBasicPipeline(MPM, &PB, O, options); else - buildFullPipeline(MPM, PB, O, options); + buildFullPipeline(MPM, &PB, O, options); return MPM; } } @@ -602,3 +610,108 @@ OptimizationLevel getOptLevel(int optlevel) { } llvm_unreachable("cannot get here!"); } + +//This part is also basically stolen from LLVM's PassBuilder.cpp file +static llvm::Optional> parseJuliaPipelineOptions(StringRef name) { + if (name.consume_front("julia")) { + auto O = OptimizationLevel::O2; + auto options = OptimizationOptions::defaults(); + if (!name.empty() && (!name.consume_front("<") || !name.consume_back(">"))) { + assert(false && "Expected pass options to be enclosed in <>!"); + } + std::map option_pointers = { +#define OPTION(name) {#name, &options.name} + OPTION(lower_intrinsics), + OPTION(dump_native), + OPTION(external_use), + OPTION(llvm_only) +#undef OPTION + }; + while (!name.empty()) { + StringRef option; + std::tie(option, name) = name.split(';'); + bool enable = !option.consume_front("no_"); + auto it = option_pointers.find(option); + if (it == option_pointers.end()) { + if (option.consume_front("level=")) { + int level = 2; + if (option.getAsInteger(0, level)) { + assert(false && "Non-integer passed to julia level!"); + } + switch (std::min(std::max(level, 0), 3)) { + case 0: + O = OptimizationLevel::O0; + break; + case 1: + O = OptimizationLevel::O1; + break; + case 2: + O = OptimizationLevel::O2; + break; + case 3: + O = OptimizationLevel::O3; + break; + } + } else { + errs() << "Unable to find julia option '" << option << "'!"; + assert(false && "Invalid option passed to julia pass!"); + } + } else { + *it->second = enable; + } + } + return {{O, options}}; + } + return {}; +} + +// new pass manager plugin + +// NOTE: Instead of exporting all the constructors in passes.h we could +// forward the callbacks to the respective passes. LLVM seems to prefer this, +// and when we add the full pass builder having them directly will be helpful. +void registerCallbacks(PassBuilder &PB) { + PB.registerPipelineParsingCallback( + [](StringRef Name, FunctionPassManager &PM, + ArrayRef InnerPipeline) { +#define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) { PM.addPass(CREATE_PASS); return true; } +#include "llvm-julia-passes.inc" +#undef FUNCTION_PASS + return false; + }); + + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &PM, + ArrayRef InnerPipeline) { +#define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) { PM.addPass(CREATE_PASS); return true; } +#include "llvm-julia-passes.inc" +#undef MODULE_PASS + //Add full pipelines here + auto julia_options = parseJuliaPipelineOptions(Name); + if (julia_options) { + ModulePassManager pipeline; + if (julia_options->first.getSpeedupLevel() < 2) { + buildBasicPipeline(pipeline, nullptr, julia_options->first, julia_options->second); + } else { + buildFullPipeline(pipeline, nullptr, julia_options->first, julia_options->second); + } + PM.addPass(std::move(pipeline)); + return true; + } + return false; + }); + + PB.registerPipelineParsingCallback( + [](StringRef Name, LoopPassManager &PM, + ArrayRef InnerPipeline) { +#define LOOP_PASS(NAME, CREATE_PASS) if (Name == NAME) { PM.addPass(CREATE_PASS); return true; } +#include "llvm-julia-passes.inc" +#undef LOOP_PASS + return false; + }); +} + +extern "C" JL_DLLEXPORT ::llvm::PassPluginLibraryInfo +llvmGetPassPluginInfo() { + return {LLVM_PLUGIN_API_VERSION, "Julia", "1", registerCallbacks}; +} diff --git a/src/precompile.c b/src/precompile.c index 8e1fed06837ed..73af6daa7c6aa 100644 --- a/src/precompile.c +++ b/src/precompile.c @@ -114,13 +114,6 @@ void jl_write_compiler_output(void) // and expanding the Union may give a leaf function static void _compile_all_tvar_union(jl_value_t *methsig) { - if (!jl_is_unionall(methsig) && jl_is_dispatch_tupletype(methsig)) { - // usually can create a specialized version of the function, - // if the signature is already a dispatch type - if (jl_compile_hint((jl_tupletype_t*)methsig)) - return; - } - int tvarslen = jl_subtype_env_size(methsig); jl_value_t *sigbody = methsig; jl_value_t **roots; @@ -247,85 +240,49 @@ static void _compile_all_union(jl_value_t *sig) JL_GC_POP(); } -static void _compile_all_deq(jl_array_t *found) -{ - int found_i, found_l = jl_array_len(found); - jl_printf(JL_STDERR, "found %d uncompiled methods for compile-all\n", (int)found_l); - jl_method_instance_t *mi = NULL; - jl_value_t *src = NULL; - JL_GC_PUSH2(&mi, &src); - for (found_i = 0; found_i < found_l; found_i++) { - if (found_i % (1 + found_l / 300) == 0 || found_i == found_l - 1) // show 300 progress steps, to show progress without overwhelming log files - jl_printf(JL_STDERR, " %d / %d\r", found_i + 1, found_l); - jl_typemap_entry_t *ml = (jl_typemap_entry_t*)jl_array_ptr_ref(found, found_i); - jl_method_t *m = ml->func.method; - if (m->source == NULL) // TODO: generic implementations of generated functions - continue; - mi = jl_get_unspecialized(m); - assert(mi == jl_atomic_load_relaxed(&m->unspecialized)); // make sure we didn't get tricked by a generated function, since we can't handle those - jl_code_instance_t *ucache = jl_get_method_inferred(mi, (jl_value_t*)jl_any_type, 1, ~(size_t)0); - if (jl_atomic_load_relaxed(&ucache->invoke) != NULL) - continue; - src = m->source; - assert(src); - // TODO: we could now enable storing inferred function pointers in the `unspecialized` cache - //src = jl_type_infer(mi, jl_atomic_load_acquire(&jl_world_counter), 1); - //if (jl_atomic_load_relaxed(&ucache->invoke) != NULL) - // continue; - - // first try to create leaf signatures from the signature declaration and compile those - _compile_all_union((jl_value_t*)ml->sig); - // then also compile the generic fallback - jl_generate_fptr_for_unspecialized(ucache); - } - JL_GC_POP(); - jl_printf(JL_STDERR, "\n"); -} - -static int compile_all_enq__(jl_typemap_entry_t *ml, void *env) +static int compile_all_collect__(jl_typemap_entry_t *ml, void *env) { - jl_array_t *found = (jl_array_t*)env; - // method definition -- compile template field + jl_array_t *allmeths = (jl_array_t*)env; jl_method_t *m = ml->func.method; if (m->source) { - // found a method to compile - jl_array_ptr_1d_push(found, (jl_value_t*)ml); + // method has a non-generated definition; can be compiled generically + jl_array_ptr_1d_push(allmeths, (jl_value_t*)m); } return 1; } - -static int compile_all_enq_(jl_methtable_t *mt, void *env) +static int compile_all_collect_(jl_methtable_t *mt, void *env) { - jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), compile_all_enq__, env); + jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), compile_all_collect__, env); return 1; } -static void jl_compile_all_defs(void) +static void jl_compile_all_defs(jl_array_t *mis) { - // this "found" array will contain - // TypeMapEntries for Methods and MethodInstances that need to be compiled - jl_array_t *m = jl_alloc_vec_any(0); - JL_GC_PUSH1(&m); - int _changes = -1; - int attempts = 0; - while (1) { - jl_foreach_reachable_mtable(compile_all_enq_, m); - size_t changes = jl_array_len(m); - if (!changes) - break; - if (changes == _changes) { - if (++attempts > 5) { - jl_printf(JL_STDERR, "unable to compile %d methods for compile-all\n", (int)changes); - break; - } - } else { - attempts = 0; + jl_array_t *allmeths = jl_alloc_vec_any(0); + JL_GC_PUSH1(&allmeths); + + jl_foreach_reachable_mtable(compile_all_collect_, allmeths); + + size_t i, l = jl_array_len(allmeths); + for (i = 0; i < l; i++) { + jl_method_t *m = (jl_method_t*)jl_array_ptr_ref(allmeths, i); + if (jl_isa_compileable_sig((jl_tupletype_t*)m->sig, m)) { + // method has a single compileable specialization, e.g. its definition + // signature is concrete. in this case we can just hint it. + jl_compile_hint((jl_tupletype_t*)m->sig); + } + else { + // first try to create leaf signatures from the signature declaration and compile those + _compile_all_union(m->sig); + + // finally, compile a fully generic fallback that can work for all arguments + jl_method_instance_t *unspec = jl_get_unspecialized(m); + if (unspec) + jl_array_ptr_1d_push(mis, (jl_value_t*)unspec); } - _compile_all_deq(m); - jl_array_del_end(m, changes); - _changes = changes; } + JL_GC_POP(); } @@ -385,14 +342,13 @@ static int precompile_enq_all_specializations_(jl_methtable_t *mt, void *env) static void *jl_precompile(int all) { - if (all) - jl_compile_all_defs(); - // this "found" array will contain function - // type signatures that were inferred but haven't been compiled + // array of MethodInstances and ccallable aliases to include in the output jl_array_t *m = jl_alloc_vec_any(0); jl_array_t *m2 = NULL; jl_method_instance_t *mi = NULL; JL_GC_PUSH3(&m, &m2, &mi); + if (all) + jl_compile_all_defs(m); jl_foreach_reachable_mtable(precompile_enq_all_specializations_, m); m2 = jl_alloc_vec_any(0); for (size_t i = 0; i < jl_array_len(m); i++) { @@ -401,7 +357,7 @@ static void *jl_precompile(int all) mi = (jl_method_instance_t*)item; size_t min_world = 0; size_t max_world = ~(size_t)0; - if (!jl_isa_compileable_sig((jl_tupletype_t*)mi->specTypes, mi->def.method)) + if (mi != jl_atomic_load_relaxed(&mi->def.method->unspecialized) && !jl_isa_compileable_sig((jl_tupletype_t*)mi->specTypes, mi->def.method)) mi = jl_get_specialization1((jl_tupletype_t*)mi->specTypes, jl_atomic_load_acquire(&jl_world_counter), &min_world, &max_world, 0); if (mi) jl_array_ptr_1d_push(m2, (jl_value_t*)mi); diff --git a/src/serialize.h b/src/serialize.h index 69aaeb4c39787..020cafc74c962 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -92,7 +92,7 @@ static inline uint64_t read_uint64(ios_t *s) JL_NOTSAFEPOINT return x; } -static inline void write_int64(ios_t *s, int64_t i) JL_NOTSAFEPOINT +static inline void write_uint64(ios_t *s, uint64_t i) JL_NOTSAFEPOINT { ios_write(s, (char*)&i, 8); } @@ -121,6 +121,19 @@ static inline uint32_t read_uint32(ios_t *s) JL_NOTSAFEPOINT return x; } +#ifdef _P64 +#define write_uint(s, i) write_uint64(s, i) +#else +#define write_uint(s, i) write_uint32(s, i) +#endif + +#ifdef _P64 +#define read_uint(s) read_uint64(s) +#else +#define read_uint(s) read_uint32(s) +#endif + + void *jl_lookup_ser_tag(jl_value_t *v); void *jl_lookup_common_symbol(jl_value_t *v); jl_value_t *jl_deser_tag(uint8_t tag); diff --git a/src/signal-handling.c b/src/signal-handling.c index 43782bf4070f2..3b1e4934e764b 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -6,8 +6,8 @@ #include #include "julia.h" #include "julia_internal.h" -#ifndef _OS_WINDOWS_ #include +#ifndef _OS_WINDOWS_ #include #endif @@ -419,6 +419,24 @@ void jl_show_sigill(void *_ctx) #endif } +// make it invalid for a task to return from this point to its stack +// this is generally quite an foolish operation, but does free you up to do +// arbitrary things on this stack now without worrying about corrupt state that +// existed already on it +void jl_task_frame_noreturn(jl_task_t *ct) +{ + jl_set_safe_restore(NULL); + if (ct) { + ct->gcstack = NULL; + ct->eh = NULL; + ct->excstack = NULL; + ct->ptls->locks.len = 0; + ct->ptls->in_pure_callback = 0; + ct->ptls->in_finalizer = 0; + ct->world_age = 1; + } +} + // what to do on a critical error on a thread void jl_critical_error(int sig, bt_context_t *context, jl_task_t *ct) { @@ -427,16 +445,7 @@ void jl_critical_error(int sig, bt_context_t *context, jl_task_t *ct) size_t i, n = ct ? *bt_size : 0; if (sig) { // kill this task, so that we cannot get back to it accidentally (via an untimely ^C or jlbacktrace in jl_exit) - jl_set_safe_restore(NULL); - if (ct) { - ct->gcstack = NULL; - ct->eh = NULL; - ct->excstack = NULL; - ct->ptls->locks.len = 0; - ct->ptls->in_pure_callback = 0; - ct->ptls->in_finalizer = 1; - ct->world_age = 1; - } + jl_task_frame_noreturn(ct); #ifndef _OS_WINDOWS_ sigset_t sset; sigemptyset(&sset); diff --git a/src/simplevector.c b/src/simplevector.c index 988cf18ccc9b6..cb65646e00936 100644 --- a/src/simplevector.c +++ b/src/simplevector.c @@ -93,15 +93,9 @@ JL_DLLEXPORT size_t (jl_svec_len)(jl_svec_t *t) JL_NOTSAFEPOINT return jl_svec_len(t); } -JL_DLLEXPORT int8_t jl_svec_isassigned(jl_svec_t *t JL_PROPAGATES_ROOT, ssize_t i) JL_NOTSAFEPOINT -{ - return jl_svecref(t, (size_t)i) != NULL; -} - JL_DLLEXPORT jl_value_t *jl_svec_ref(jl_svec_t *t JL_PROPAGATES_ROOT, ssize_t i) { jl_value_t *v = jl_svecref(t, (size_t)i); - if (__unlikely(v == NULL)) - jl_throw(jl_undefref_exception); + assert(v != NULL); return v; } diff --git a/src/staticdata.c b/src/staticdata.c index 1b5fc9bbe3edc..10c1c3cae9e3f 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -59,6 +59,7 @@ done by `get_item_for_reloc`. #include #include #include // printf +#include // PRIxPTR #include "julia.h" #include "julia_internal.h" @@ -362,9 +363,28 @@ typedef enum { } jl_callingconv_t; +//#ifdef _P64 +//#define RELOC_TAG_OFFSET 61 +//#else // this supports up to 8 RefTags, 512MB of pointer data, and 4/2 (64/32-bit) GB of constant data. -// if a larger size is required, will need to add support for writing larger relocations in many cases below #define RELOC_TAG_OFFSET 29 +//#endif + +#if RELOC_TAG_OFFSET <= 32 +typedef uint32_t reloc_t; +#else +typedef uint64_t reloc_t; +#endif +static void write_reloc_t(ios_t *s, uintptr_t reloc_id) JL_NOTSAFEPOINT +{ + if (sizeof(reloc_t) <= sizeof(uint32_t)) { + assert(reloc_id < UINT32_MAX); + write_uint32(s, reloc_id); + } + else { + write_uint64(s, reloc_id); + } +} // --- Static Compile --- @@ -576,6 +596,10 @@ static void jl_serialize_value__(jl_serializer_state *s, jl_value_t *v, int recu jl_serialize_value(s, tn->partial); } else if (t->layout->nfields > 0) { + if (jl_typeis(v, jl_globalref_type)) { + // Don't save the cached binding reference in staticdata + ((jl_globalref_t*)v)->bnd_cache = NULL; + } char *data = (char*)jl_data_ptr(v); size_t i, np = t->layout->npointers; for (i = 0; i < np; i++) { @@ -626,10 +650,9 @@ static void record_gvar(jl_serializer_state *s, int gid, uintptr_t reloc_id) JL_ { if (gid == 0) return; - ios_ensureroom(s->gvar_record, gid * sizeof(uint32_t)); - ios_seek(s->gvar_record, (gid - 1) * sizeof(uint32_t)); - assert(reloc_id < UINT32_MAX); - write_uint32(s->gvar_record, reloc_id); + ios_ensureroom(s->gvar_record, gid * sizeof(reloc_t)); + ios_seek(s->gvar_record, (gid - 1) * sizeof(reloc_t)); + write_reloc_t(s->gvar_record, reloc_id); } @@ -648,7 +671,7 @@ static void write_padding(ios_t *s, size_t nb) JL_NOTSAFEPOINT static void write_pointer(ios_t *s) JL_NOTSAFEPOINT { assert((ios_pos(s) & (sizeof(void*) - 1)) == 0 && "stream misaligned for writing a word-sized value"); - write_padding(s, sizeof(void*)); + write_uint(s, 0); } // Return the integer `id` for `v`. Generically this is looked up in `backref_table`, @@ -1068,6 +1091,10 @@ static void jl_write_values(jl_serializer_state *s) arraylist_push(&ccallable_list, (void*)3); } } + else if (jl_is_method_instance(v)) { + jl_method_instance_t *newmi = (jl_method_instance_t*)&s->s->buf[reloc_offset]; + newmi->precompiled = 0; + } else if (jl_is_code_instance(v)) { // Handle the native-code pointers jl_code_instance_t *m = (jl_code_instance_t*)v; @@ -1103,18 +1130,20 @@ static void jl_write_values(jl_serializer_state *s) assert(invokeptr_id > 0); ios_ensureroom(s->fptr_record, invokeptr_id * sizeof(void*)); ios_seek(s->fptr_record, (invokeptr_id - 1) * sizeof(void*)); - write_uint32(s->fptr_record, ~reloc_offset); + write_reloc_t(s->fptr_record, (uint32_t)~reloc_offset); #ifdef _P64 - write_padding(s->fptr_record, 4); + if (sizeof(reloc_t) < 8) + write_padding(s->fptr_record, 8 - sizeof(reloc_t)); #endif } if (specfptr_id) { assert(specfptr_id > invokeptr_id && specfptr_id > 0); ios_ensureroom(s->fptr_record, specfptr_id * sizeof(void*)); ios_seek(s->fptr_record, (specfptr_id - 1) * sizeof(void*)); - write_uint32(s->fptr_record, reloc_offset); + write_reloc_t(s->fptr_record, reloc_offset); #ifdef _P64 - write_padding(s->fptr_record, 4); + if (sizeof(reloc_t) < 8) + write_padding(s->fptr_record, 8 - sizeof(reloc_t)); #endif } } @@ -1237,14 +1266,6 @@ static void jl_write_gv_tagrefs(jl_serializer_state *s) } } -static inline uint32_t load_uint32(uintptr_t *base) -{ - uint32_t v = jl_load_unaligned_i32((void*)*base); - *base += 4; - return v; -} - - // In deserialization, create Symbols and set up the // index for backreferencing static void jl_read_symbols(jl_serializer_state *s) @@ -1253,7 +1274,8 @@ static void jl_read_symbols(jl_serializer_state *s) uintptr_t base = (uintptr_t)&s->symbols->buf[0]; uintptr_t end = base + s->symbols->size; while (base < end) { - uint32_t len = load_uint32(&base); + uint32_t len = jl_load_unaligned_i32((void*)base); + base += 4; const char *str = (const char*)base; base += len + 1; //printf("symbol %3d: %s\n", len, str); @@ -1311,7 +1333,7 @@ static uintptr_t get_reloc_for_item(uintptr_t reloc_item, size_t reloc_offset) } // Compute target location at deserialization -static inline uintptr_t get_item_for_reloc(jl_serializer_state *s, uintptr_t base, size_t size, uint32_t reloc_id) +static inline uintptr_t get_item_for_reloc(jl_serializer_state *s, uintptr_t base, size_t size, uintptr_t reloc_id) { enum RefTags tag = (enum RefTags)(reloc_id >> RELOC_TAG_OFFSET); size_t offset = (reloc_id & (((uintptr_t)1 << RELOC_TAG_OFFSET) - 1)); @@ -1383,10 +1405,9 @@ static void jl_write_skiplist(ios_t *s, char *base, size_t size, arraylist_t *li *pv = get_reloc_for_item(item, *pv); // record pos in relocations list // TODO: save space by using delta-compression - assert(pos < UINT32_MAX); - write_uint32(s, pos); + write_reloc_t(s, pos); } - write_uint32(s, 0); + write_reloc_t(s, 0); } @@ -1403,9 +1424,8 @@ static void jl_read_relocations(jl_serializer_state *s, uint8_t bits) uintptr_t base = (uintptr_t)&s->s->buf[0]; size_t size = s->s->size; while (1) { - uintptr_t val = (uintptr_t)&s->relocs->buf[s->relocs->bpos]; - uint32_t offset = load_uint32(&val); - s->relocs->bpos += sizeof(uint32_t); + uintptr_t offset = *(reloc_t*)&s->relocs->buf[(uintptr_t)s->relocs->bpos]; + s->relocs->bpos += sizeof(reloc_t); if (offset == 0) break; uintptr_t *pv = (uintptr_t*)(base + offset); @@ -1415,16 +1435,17 @@ static void jl_read_relocations(jl_serializer_state *s, uint8_t bits) } } -static char* sysimg_base; -static char* sysimg_relocs; +static char *sysimg_base; +static char *sysimg_relocs; void gc_sweep_sysimg(void) { - uintptr_t base = (uintptr_t)sysimg_base; - uintptr_t relocs = (uintptr_t)sysimg_relocs; - if (relocs == 0) + char *base = sysimg_base; + reloc_t *relocs = (reloc_t*)sysimg_relocs; + if (relocs == NULL) return; while (1) { - uint32_t offset = load_uint32(&relocs); + uintptr_t offset = *relocs; + relocs++; if (offset == 0) break; jl_taggedvalue_t *o = (jl_taggedvalue_t*)(base + offset); @@ -1436,13 +1457,12 @@ void gc_sweep_sysimg(void) static void _jl_write_value(jl_serializer_state *s, jl_value_t *v) { if (v == NULL) { - write_uint32(s->s, 0); + write_reloc_t(s->s, 0); return; } uintptr_t item = backref_id(s, v); uintptr_t reloc = get_reloc_for_item(item, 0); - assert(reloc < UINT32_MAX); - write_uint32(s->s, reloc); + write_reloc_t(s->s, reloc); } @@ -1450,9 +1470,8 @@ static jl_value_t *jl_read_value(jl_serializer_state *s) { uintptr_t base = (uintptr_t)&s->s->buf[0]; size_t size = s->s->size; - uintptr_t val = base + s->s->bpos; - uint32_t offset = load_uint32(&val); - s->s->bpos += sizeof(uint32_t); + uintptr_t offset = *(reloc_t*)(base + (uintptr_t)s->s->bpos); + s->s->bpos += sizeof(reloc_t); if (offset == 0) return NULL; return (jl_value_t*)get_item_for_reloc(s, base, size, offset); @@ -1475,12 +1494,11 @@ static void jl_update_all_fptrs(jl_serializer_state *s) jl_method_instance_t **linfos = (jl_method_instance_t**)&s->fptr_record->buf[0]; uint32_t clone_idx = 0; for (i = 0; i < sysimg_fvars_max; i++) { - uintptr_t val = (uintptr_t)&linfos[i]; - uint32_t offset = load_uint32(&val); + reloc_t offset = *(reloc_t*)&linfos[i]; linfos[i] = NULL; if (offset != 0) { int specfunc = 1; - if (offset & ((uintptr_t)1 << (8 * sizeof(uint32_t) - 1))) { + if (offset & ((uintptr_t)1 << (8 * sizeof(reloc_t) - 1))) { // if high bit is set, this is the func wrapper, not the specfunc specfunc = 0; offset = ~offset; @@ -1522,15 +1540,16 @@ static void jl_update_all_gvars(jl_serializer_state *s) size_t gvname_index = 0; uintptr_t base = (uintptr_t)&s->s->buf[0]; size_t size = s->s->size; - uintptr_t gvars = (uintptr_t)&s->gvar_record->buf[0]; - uintptr_t end = gvars + s->gvar_record->size; + reloc_t *gvars = (reloc_t*)&s->gvar_record->buf[0]; + reloc_t *end = gvars + s->gvar_record->size / sizeof(reloc_t); while (gvars < end) { - uint32_t offset = load_uint32(&gvars); + uintptr_t offset = *gvars; if (offset) { uintptr_t v = get_item_for_reloc(s, base, size, offset); *sysimg_gvars(sysimg_gvars_base, gvname_index) = v; } gvname_index += 1; + gvars++; } } @@ -1546,14 +1565,14 @@ static void jl_finalize_serializer(jl_serializer_state *s, arraylist_t *list) size_t item = (size_t)list->items[i]; size_t reloc_offset = (size_t)layout_table.items[item]; assert(reloc_offset != 0); - write_uint32(s->s, (uint32_t)reloc_offset); - write_uint32(s->s, (uint32_t)((uintptr_t)list->items[i + 1])); + write_reloc_t(s->s, reloc_offset); + write_uint8(s->s, (uintptr_t)list->items[i + 1]); } - write_uint32(s->s, 0); + write_reloc_t(s->s, 0); } -static void jl_reinit_item(jl_value_t *v, int how) JL_GC_DISABLED +static void jl_reinit_item(jl_value_t *v, uint8_t how) JL_GC_DISABLED { switch (how) { case 1: { // rehash IdDict @@ -1605,11 +1624,17 @@ static void jl_finalize_deserializer(jl_serializer_state *s) JL_GC_DISABLED // run reinitialization functions uintptr_t base = (uintptr_t)&s->s->buf[0]; while (1) { - size_t offset = read_uint32(s->s); + size_t offset; + if (sizeof(reloc_t) <= 4) { + offset = read_uint32(s->s); + } + else { + offset = read_uint64(s->s); + } if (offset == 0) break; jl_value_t *v = (jl_value_t*)(base + offset); - jl_reinit_item(v, read_uint32(s->s)); + jl_reinit_item(v, read_uint8(s->s)); } } @@ -1621,7 +1646,7 @@ static void jl_scan_type_cache_gv(jl_serializer_state *s, jl_svec_t *cache) size_t l = jl_svec_len(cache), i; for (i = 0; i < l; i++) { jl_value_t *ti = jl_svecref(cache, i); - if (ti == NULL || ti == jl_nothing) + if (ti == jl_nothing) continue; if (jl_get_llvm_gv(native_functions, ti)) { jl_serialize_value(s, ti); @@ -1635,16 +1660,21 @@ static void jl_scan_type_cache_gv(jl_serializer_state *s, jl_svec_t *cache) } // remove cached types not referenced in the stream -static void jl_prune_type_cache_hash(jl_svec_t *cache) +static jl_svec_t *jl_prune_type_cache_hash(jl_svec_t *cache) JL_GC_DISABLED { size_t l = jl_svec_len(cache), i; for (i = 0; i < l; i++) { jl_value_t *ti = jl_svecref(cache, i); - if (ti == NULL || ti == jl_nothing) + if (ti == jl_nothing) continue; if (ptrhash_get(&backref_table, ti) == HT_NOTFOUND) jl_svecset(cache, i, jl_nothing); } + void *idx = ptrhash_get(&backref_table, cache); + ptrhash_remove(&backref_table, cache); + cache = cache_rehash_set(cache, l); + ptrhash_put(&backref_table, cache, idx); + return cache; } static void jl_prune_type_cache_linear(jl_svec_t *cache) @@ -1652,14 +1682,13 @@ static void jl_prune_type_cache_linear(jl_svec_t *cache) size_t l = jl_svec_len(cache), ins = 0, i; for (i = 0; i < l; i++) { jl_value_t *ti = jl_svecref(cache, i); - if (ti == NULL) + if (ti == jl_nothing) break; if (ptrhash_get(&backref_table, ti) != HT_NOTFOUND) jl_svecset(cache, ins++, ti); } - if (i > ins) { - memset(&jl_svec_data(cache)[ins], 0, (i - ins) * sizeof(jl_value_t*)); - } + while (ins < l) + jl_svecset(cache, ins++, jl_nothing); } static jl_value_t *strip_codeinfo_meta(jl_method_t *m, jl_value_t *ci_, int orig) @@ -1933,61 +1962,80 @@ static void jl_save_system_image_to_stream(ios_t *f) JL_GC_DISABLED // built-in type caches for (i = 0; i < typenames.len; i++) { jl_typename_t *tn = (jl_typename_t*)typenames.items[i]; - jl_prune_type_cache_hash(tn->cache); + tn->cache = jl_prune_type_cache_hash(tn->cache); + jl_gc_wb(tn, tn->cache); jl_prune_type_cache_linear(tn->linearcache); } arraylist_free(&typenames); } { // step 2: build all the sysimg sections - write_padding(&sysimg, sizeof(uint32_t)); + write_padding(&sysimg, sizeof(uintptr_t)); jl_write_values(&s); jl_write_relocations(&s); jl_write_gv_syms(&s, jl_get_root_symbol()); jl_write_gv_tagrefs(&s); } - if (sysimg.size > ((uintptr_t)1 << RELOC_TAG_OFFSET) || - const_data.size > ((uintptr_t)1 << RELOC_TAG_OFFSET)*sizeof(void*)) { - jl_printf(JL_STDERR, "ERROR: system image too large\n"); + if (sysimg.size > ((uintptr_t)1 << RELOC_TAG_OFFSET)) { + jl_printf( + JL_STDERR, + "ERROR: system image too large: sysimg.size is %jd but the limit is %" PRIxPTR "\n", + (intmax_t)sysimg.size, + ((uintptr_t)1 << RELOC_TAG_OFFSET) + ); + jl_exit(1); + } + if (const_data.size / sizeof(void*) > ((uintptr_t)1 << RELOC_TAG_OFFSET)) { + jl_printf( + JL_STDERR, + "ERROR: system image too large: const_data.size is %jd but the limit is %" PRIxPTR "\n", + (intmax_t)const_data.size, + ((uintptr_t)1 << RELOC_TAG_OFFSET)*sizeof(void*) + ); jl_exit(1); } // step 3: combine all of the sections into one file - write_uint32(f, sysimg.size - sizeof(uint32_t)); - ios_seek(&sysimg, sizeof(uint32_t)); + write_uint(f, sysimg.size - sizeof(uintptr_t)); + ios_seek(&sysimg, sizeof(uintptr_t)); ios_copyall(f, &sysimg); ios_close(&sysimg); - write_uint32(f, const_data.size); + write_uint(f, const_data.size); // realign stream to max-alignment for data - write_padding(f, LLT_ALIGN(ios_pos(f), 16) - ios_pos(f)); + write_padding(f, LLT_ALIGN(ios_pos(f), JL_CACHE_BYTE_ALIGNMENT) - ios_pos(f)); ios_seek(&const_data, 0); ios_copyall(f, &const_data); ios_close(&const_data); - write_uint32(f, symbols.size); + write_uint(f, symbols.size); + write_padding(f, LLT_ALIGN(ios_pos(f), 8) - ios_pos(f)); ios_seek(&symbols, 0); ios_copyall(f, &symbols); ios_close(&symbols); - write_uint32(f, relocs.size); + write_uint(f, relocs.size); + write_padding(f, LLT_ALIGN(ios_pos(f), 8) - ios_pos(f)); ios_seek(&relocs, 0); ios_copyall(f, &relocs); ios_close(&relocs); - write_uint32(f, gvar_record.size); + write_uint(f, gvar_record.size); + write_padding(f, LLT_ALIGN(ios_pos(f), 8) - ios_pos(f)); ios_seek(&gvar_record, 0); ios_copyall(f, &gvar_record); ios_close(&gvar_record); - write_uint32(f, fptr_record.size); + write_uint(f, fptr_record.size); + write_padding(f, LLT_ALIGN(ios_pos(f), 8) - ios_pos(f)); ios_seek(&fptr_record, 0); ios_copyall(f, &fptr_record); ios_close(&fptr_record); { // step 4: record locations of special roots s.s = f; + write_padding(f, LLT_ALIGN(ios_pos(f), 8) - ios_pos(f)); size_t i; for (i = 0; tags[i] != NULL; i++) { jl_value_t *tag = *tags[i]; @@ -1996,8 +2044,8 @@ static void jl_save_system_image_to_stream(ios_t *f) JL_GC_DISABLED jl_write_value(&s, jl_global_roots_table); jl_write_value(&s, s.ptls->root_task->tls); write_uint32(f, jl_get_gs_ctr()); - write_uint32(f, jl_atomic_load_acquire(&jl_world_counter)); - write_uint32(f, jl_typeinf_world); + write_uint(f, jl_atomic_load_acquire(&jl_world_counter)); + write_uint(f, jl_typeinf_world); jl_finalize_serializer(&s, &reinit_list); jl_finalize_serializer(&s, &ccallable_list); } @@ -2084,37 +2132,43 @@ static void jl_restore_system_image_from_stream(ios_t *f) JL_GC_DISABLED // step 1: read section map assert(ios_pos(f) == 0 && f->bm == bm_mem); - size_t sizeof_sysimg = read_uint32(f); - ios_static_buffer(&sysimg, f->buf, sizeof_sysimg + sizeof(uint32_t)); + size_t sizeof_sysimg = read_uint(f); + ios_static_buffer(&sysimg, f->buf, sizeof_sysimg + sizeof(uintptr_t)); ios_skip(f, sizeof_sysimg); - size_t sizeof_constdata = read_uint32(f); + size_t sizeof_constdata = read_uint(f); // realign stream to max-alignment for data - ios_seek(f, LLT_ALIGN(ios_pos(f), 16)); + ios_seek(f, LLT_ALIGN(ios_pos(f), JL_CACHE_BYTE_ALIGNMENT)); ios_static_buffer(&const_data, f->buf + f->bpos, sizeof_constdata); ios_skip(f, sizeof_constdata); - size_t sizeof_symbols = read_uint32(f); + size_t sizeof_symbols = read_uint(f); + ios_seek(f, LLT_ALIGN(ios_pos(f), 8)); ios_static_buffer(&symbols, f->buf + f->bpos, sizeof_symbols); ios_skip(f, sizeof_symbols); - size_t sizeof_relocations = read_uint32(f); + size_t sizeof_relocations = read_uint(f); + ios_seek(f, LLT_ALIGN(ios_pos(f), 8)); assert(!ios_eof(f)); ios_static_buffer(&relocs, f->buf + f->bpos, sizeof_relocations); ios_skip(f, sizeof_relocations); - size_t sizeof_gvar_record = read_uint32(f); + size_t sizeof_gvar_record = read_uint(f); + ios_seek(f, LLT_ALIGN(ios_pos(f), 8)); assert(!ios_eof(f)); ios_static_buffer(&gvar_record, f->buf + f->bpos, sizeof_gvar_record); ios_skip(f, sizeof_gvar_record); - size_t sizeof_fptr_record = read_uint32(f); + size_t sizeof_fptr_record = read_uint(f); + ios_seek(f, LLT_ALIGN(ios_pos(f), 8)); assert(!ios_eof(f)); ios_static_buffer(&fptr_record, f->buf + f->bpos, sizeof_fptr_record); ios_skip(f, sizeof_fptr_record); // step 2: get references to special values s.s = f; + ios_seek(f, LLT_ALIGN(ios_pos(f), 8)); + assert(!ios_eof(f)); size_t i; for (i = 0; tags[i] != NULL; i++) { jl_value_t **tag = tags[i]; @@ -2130,8 +2184,8 @@ static void jl_restore_system_image_from_stream(ios_t *f) JL_GC_DISABLED jl_init_box_caches(); uint32_t gs_ctr = read_uint32(f); - jl_atomic_store_release(&jl_world_counter, read_uint32(f)); - jl_typeinf_world = read_uint32(f); + jl_atomic_store_release(&jl_world_counter, read_uint(f)); + jl_typeinf_world = read_uint(f); jl_set_gs_ctr(gs_ctr); s.s = NULL; diff --git a/src/subtype.c b/src/subtype.c index 23c752a4eec88..55579f2b47305 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -562,7 +562,7 @@ static int subtype_ccheck(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) static int subtype_left_var(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) { - if (x == y) + if (x == y && !(jl_is_unionall(y))) return 1; if (x == jl_bottom_type && jl_is_type(y)) return 1; @@ -2897,7 +2897,7 @@ static jl_value_t *intersect_sub_datatype(jl_datatype_t *xd, jl_datatype_t *yd, JL_GC_PUSHARGS(env, envsz); jl_stenv_t tempe; init_stenv(&tempe, env, envsz); - tempe.ignore_free = 1; + tempe.intersection = tempe.ignore_free = 1; if (subtype_in_env(isuper, super_pattern, &tempe)) { jl_value_t *wr = wrapper; int i; @@ -3248,18 +3248,15 @@ static int merge_env(jl_stenv_t *e, jl_value_t **root, jl_savedenv_t *se, int co } int n = 0; jl_varbinding_t *v = e->vars; - jl_value_t *ub = NULL, *vub = NULL; - JL_GC_PUSH2(&ub, &vub); + jl_value_t *b1 = NULL, *b2 = NULL; + JL_GC_PUSH2(&b1, &b2); while (v != NULL) { - if (v->ub != v->var->ub || v->lb != v->var->lb) { - jl_value_t *lb = jl_svecref(*root, n); - if (v->lb != lb) - jl_svecset(*root, n, lb ? jl_bottom_type : v->lb); - ub = jl_svecref(*root, n+1); - vub = v->ub; - if (vub != ub) - jl_svecset(*root, n+1, ub ? simple_join(ub, vub) : vub); - } + b1 = jl_svecref(*root, n); + b2 = v->lb; + jl_svecset(*root, n, simple_meet(b1, b2)); + b1 = jl_svecref(*root, n+1); + b2 = v->ub; + jl_svecset(*root, n+1, simple_join(b1, b2)); n = n + 3; v = v->prev; } @@ -3550,17 +3547,26 @@ jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t * } } if (sz == 0 && szb > 0) { - while (jl_is_unionall(b)) { - env[i++] = (jl_value_t*)((jl_unionall_t*)b)->var; - b = ((jl_unionall_t*)b)->body; + jl_unionall_t *ub = (jl_unionall_t*)b; + while (jl_is_unionall(ub)) { + env[i++] = (jl_value_t*)ub->var; + ub = (jl_unionall_t*)ub->body; } sz = szb; } if (penv) { jl_svec_t *e = jl_alloc_svec(sz); *penv = e; - for(i=0; i < sz; i++) + for (i = 0; i < sz; i++) jl_svecset(e, i, env[i]); + jl_unionall_t *ub = (jl_unionall_t*)b; + for (i = 0; i < sz; i++) { + assert(jl_is_unionall(ub)); + // TODO: assert(env[i] != NULL); + if (env[i] == NULL) + env[i] = (jl_value_t*)ub->var; + ub = (jl_unionall_t*)ub->body; + } } bot: JL_GC_POP(); @@ -3604,6 +3610,14 @@ int jl_subtype_matching(jl_value_t *a, jl_value_t *b, jl_svec_t **penv) *penv = e; for (i = 0; i < szb; i++) jl_svecset(e, i, env[i]); + jl_unionall_t *ub = (jl_unionall_t*)b; + for (i = 0; i < szb; i++) { + assert(jl_is_unionall(ub)); + // TODO: assert(env[i] != NULL); + if (env[i] == NULL) + env[i] = (jl_value_t*)ub->var; + ub = (jl_unionall_t*)ub->body; + } } JL_GC_POP(); return sub; diff --git a/src/toplevel.c b/src/toplevel.c index ff089c1aebfa6..84c3b77ade7f5 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -340,7 +340,7 @@ JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m) return jl_top_module; } -static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, int *has_opaque) +static void expr_attributes(jl_value_t *v, int *has_ccall, int *has_defs, int *has_opaque) { if (!jl_is_expr(v)) return; @@ -364,11 +364,11 @@ static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, i *has_defs = 1; } else if (head == jl_cfunction_sym) { - *has_intrinsics = 1; + *has_ccall = 1; return; } else if (head == jl_foreigncall_sym) { - *has_intrinsics = 1; + *has_ccall = 1; return; } else if (head == jl_new_opaque_closure_sym) { @@ -393,7 +393,7 @@ static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, i } if (called != NULL) { if (jl_is_intrinsic(called) && jl_unbox_int32(called) == (int)llvmcall) { - *has_intrinsics = 1; + *has_ccall = 1; } if (called == jl_builtin__typebody) { *has_defs = 1; @@ -405,28 +405,28 @@ static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, i for (i = 0; i < jl_array_len(e->args); i++) { jl_value_t *a = jl_exprarg(e, i); if (jl_is_expr(a)) - expr_attributes(a, has_intrinsics, has_defs, has_opaque); + expr_attributes(a, has_ccall, has_defs, has_opaque); } } -int jl_code_requires_compiler(jl_code_info_t *src) +int jl_code_requires_compiler(jl_code_info_t *src, int include_force_compile) { jl_array_t *body = src->code; assert(jl_typeis(body, jl_array_any_type)); size_t i; - int has_intrinsics = 0, has_defs = 0, has_opaque = 0; - if (jl_has_meta(body, jl_force_compile_sym)) + int has_ccall = 0, has_defs = 0, has_opaque = 0; + if (include_force_compile && jl_has_meta(body, jl_force_compile_sym)) return 1; for(i=0; i < jl_array_len(body); i++) { jl_value_t *stmt = jl_array_ptr_ref(body,i); - expr_attributes(stmt, &has_intrinsics, &has_defs, &has_opaque); - if (has_intrinsics) + expr_attributes(stmt, &has_ccall, &has_defs, &has_opaque); + if (has_ccall) return 1; } return 0; } -static void body_attributes(jl_array_t *body, int *has_intrinsics, int *has_defs, int *has_loops, int *has_opaque, int *forced_compile) +static void body_attributes(jl_array_t *body, int *has_ccall, int *has_defs, int *has_loops, int *has_opaque, int *forced_compile) { size_t i; *has_loops = 0; @@ -442,7 +442,7 @@ static void body_attributes(jl_array_t *body, int *has_intrinsics, int *has_defs *has_loops = 1; } } - expr_attributes(stmt, has_intrinsics, has_defs, has_opaque); + expr_attributes(stmt, has_ccall, has_defs, has_opaque); } *forced_compile = jl_has_meta(body, jl_force_compile_sym); } @@ -874,16 +874,16 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int return (jl_value_t*)ex; } - int has_intrinsics = 0, has_defs = 0, has_loops = 0, has_opaque = 0, forced_compile = 0; + int has_ccall = 0, has_defs = 0, has_loops = 0, has_opaque = 0, forced_compile = 0; assert(head == jl_thunk_sym); thk = (jl_code_info_t*)jl_exprarg(ex, 0); assert(jl_is_code_info(thk)); assert(jl_typeis(thk->code, jl_array_any_type)); - body_attributes((jl_array_t*)thk->code, &has_intrinsics, &has_defs, &has_loops, &has_opaque, &forced_compile); + body_attributes((jl_array_t*)thk->code, &has_ccall, &has_defs, &has_loops, &has_opaque, &forced_compile); jl_value_t *result; - if (forced_compile || has_intrinsics || - (!has_defs && fast && has_loops && + if (has_ccall || + ((forced_compile || (!has_defs && fast && has_loops)) && jl_options.compile_enabled != JL_OPTIONS_COMPILE_OFF && jl_options.compile_enabled != JL_OPTIONS_COMPILE_MIN && jl_get_module_compile(m) != JL_OPTIONS_COMPILE_OFF && diff --git a/stdlib/Artifacts/src/Artifacts.jl b/stdlib/Artifacts/src/Artifacts.jl index b446fdb12dd68..3f1574db4c4a6 100644 --- a/stdlib/Artifacts/src/Artifacts.jl +++ b/stdlib/Artifacts/src/Artifacts.jl @@ -88,7 +88,7 @@ function load_overrides(;force::Bool = false)::Dict{Symbol, Any} # # Overrides per UUID/bound name are intercepted upon Artifacts.toml load, and new # entries within the "hash" overrides are generated on-the-fly. Thus, all redirects - # mechanisticly happen through the "hash" overrides. + # mechanistically happen through the "hash" overrides. overrides = Dict{Symbol,Any}( # Overrides by UUID :UUID => Dict{Base.UUID,Dict{String,Union{String,SHA1}}}(), @@ -267,7 +267,7 @@ function unpack_platform(entry::Dict{String,Any}, name::String, end if !haskey(entry, "arch") - @error("Invalid artifacts file at '$(artifacts_toml)': platform-specific artifact entrty '$name' missing 'arch' key") + @error("Invalid artifacts file at '$(artifacts_toml)': platform-specific artifact entry '$name' missing 'arch' key") return nothing end @@ -325,7 +325,7 @@ function process_overrides(artifact_dict::Dict, pkg_uuid::Base.UUID) # override for this UUID, and inserting new overrides for those hashes. overrides = load_overrides() if haskey(overrides[:UUID], pkg_uuid) - pkg_overrides = overrides[:UUID][pkg_uuid] + pkg_overrides = overrides[:UUID][pkg_uuid]::Dict{String, <:Any} for name in keys(artifact_dict) # Skip names that we're not overriding @@ -570,7 +570,7 @@ end raw""" split_artifact_slash(name::String) -Splits an artifact indexing string by path deliminters, isolates the first path element, +Splits an artifact indexing string by path delimiters, isolates the first path element, returning that and the `joinpath()` of the remaining arguments. This normalizes all path separators to the native path separator for the current platform. Examples: @@ -652,13 +652,18 @@ access a single file/directory within an artifact. Example: !!! compat "Julia 1.6" Slash-indexing requires at least Julia 1.6. """ -macro artifact_str(name, platform=nothing) +macro artifact_str(name, platform=nothing, artifacts_toml_path=nothing) # Find Artifacts.toml file we're going to load from srcfile = string(__source__.file) if ((isinteractive() && startswith(srcfile, "REPL[")) || (!isinteractive() && srcfile == "none")) && !isfile(srcfile) srcfile = pwd() end - local artifacts_toml = find_artifacts_toml(srcfile) + # Sometimes we know the exact path to the Artifacts.toml file, so we can save some lookups + local artifacts_toml = if artifacts_toml_path === nothing || artifacts_toml_path == :(nothing) + find_artifacts_toml(srcfile) + else + eval(artifacts_toml_path) + end if artifacts_toml === nothing error(string( "Cannot locate '(Julia)Artifacts.toml' file when attempting to use artifact '", @@ -688,7 +693,7 @@ macro artifact_str(name, platform=nothing) # If `name` is a constant, (and we're using the default `Platform`) we can actually load # and parse the `Artifacts.toml` file now, saving the work from runtime. - if isa(name, AbstractString) && platform === nothing + if isa(name, AbstractString) && (platform === nothing || platform == :(nothing)) # To support slash-indexing, we need to split the artifact name from the path tail: platform = HostPlatform() artifact_name, artifact_path_tail, hash = artifact_slash_lookup(name, artifact_dict, artifacts_toml, platform) diff --git a/stdlib/Artifacts/test/runtests.jl b/stdlib/Artifacts/test/runtests.jl index 67117217be549..248d851ccad79 100644 --- a/stdlib/Artifacts/test/runtests.jl +++ b/stdlib/Artifacts/test/runtests.jl @@ -91,6 +91,9 @@ end HelloWorldC_exe_path = joinpath(HelloWorldC_dir, "bin", "hello_world$(exeext)") @test isfile(HelloWorldC_exe_path) + HelloWorldC_dir_explicit_artifact = eval(:(@artifact_str "HelloWorldC" nothing joinpath(@__DIR__, "Artifacts.toml"))) + @test isdir(HelloWorldC_dir_explicit_artifact) + # Simple slash-indexed lookup HelloWorldC_bin_path = artifact"HelloWorldC/bin" @test isdir(HelloWorldC_bin_path) diff --git a/stdlib/Dates/src/io.jl b/stdlib/Dates/src/io.jl index 0443c79f16ab9..c6682a0246ce7 100644 --- a/stdlib/Dates/src/io.jl +++ b/stdlib/Dates/src/io.jl @@ -55,7 +55,7 @@ Base.show(io::IO, ::MIME"text/plain", t::Time) = print(io, t) Base.print(io::IO, t::Time) = print(io, string(t)) function Base.show(io::IO, t::Time) - if get(io, :compact, false) + if get(io, :compact, false)::Bool print(io, t) else values = [ diff --git a/stdlib/Dates/src/types.jl b/stdlib/Dates/src/types.jl index d3a9203ed0cde..1d9769a05bd3d 100644 --- a/stdlib/Dates/src/types.jl +++ b/stdlib/Dates/src/types.jl @@ -103,7 +103,7 @@ end UTM(x) = UTInstant(Millisecond(x)) UTD(x) = UTInstant(Day(x)) -# Calendar types provide rules for interpretating instant +# Calendar types provide rules for interpreting instant # timelines in human-readable form. abstract type Calendar <: AbstractTime end @@ -199,7 +199,7 @@ daysinmonth(y,m) = DAYSINMONTH[m] + (m == 2 && isleapyear(y)) """ validargs(::Type{<:TimeType}, args...) -> Union{ArgumentError, Nothing} -Determine whether the given arguments consitute valid inputs for the given type. +Determine whether the given arguments constitute valid inputs for the given type. Returns either an `ArgumentError`, or [`nothing`](@ref) in case of success. """ function validargs end diff --git a/stdlib/Dates/test/accessors.jl b/stdlib/Dates/test/accessors.jl index 819fa8c40ddbc..b690a81d70e49 100644 --- a/stdlib/Dates/test/accessors.jl +++ b/stdlib/Dates/test/accessors.jl @@ -29,7 +29,7 @@ using Test @test Dates.yearmonthday(730120) == (2000, 1, 1) end @testset "year/month/day" begin - # year, month, and day return the indivial components + # year, month, and day return the individual components # of yearmonthday, avoiding additional calculations when possible @test Dates.year(-1) == 0 @test Dates.month(-1) == 12 diff --git a/stdlib/Dates/test/periods.jl b/stdlib/Dates/test/periods.jl index c37a1666375a9..7b23ffcb5d4e1 100644 --- a/stdlib/Dates/test/periods.jl +++ b/stdlib/Dates/test/periods.jl @@ -283,7 +283,7 @@ Beat(p::Period) = Beat(Dates.toms(p) ÷ 86400) Dates.toms(b::Beat) = Dates.value(b) * 86400 Dates._units(b::Beat) = " beat" * (abs(Dates.value(b)) == 1 ? "" : "s") Base.promote_rule(::Type{Dates.Day}, ::Type{Beat}) = Dates.Millisecond - Base.convert(::Type{T}, b::Beat) where {T<:Dates.Millisecond} = T(Dates.toms(b)) + Base.convert(::Type{T}, b::Beat) where {T<:Dates.Millisecond} = T(Dates.toms(b))::T @test Beat(1000) == Dates.Day(1) @test Beat(1) < Dates.Day(1) diff --git a/stdlib/Distributed/src/cluster.jl b/stdlib/Distributed/src/cluster.jl index 37f1660e19478..4845640a1a913 100644 --- a/stdlib/Distributed/src/cluster.jl +++ b/stdlib/Distributed/src/cluster.jl @@ -22,7 +22,7 @@ Some are used by the cluster manager to add workers to an already-initialized ho * `count` -- the number of workers to be launched on the host * `exename` -- the path to the Julia executable on the host, defaults to `"\$(Sys.BINDIR)/julia"` or `"\$(Sys.BINDIR)/julia-debug"` - * `exeflags` -- flags to use when lauching Julia remotely + * `exeflags` -- flags to use when launching Julia remotely The `userdata` field is used to store information for each worker by external managers. diff --git a/stdlib/Distributed/src/remotecall.jl b/stdlib/Distributed/src/remotecall.jl index d4bf767537c1d..0554f47670eb3 100644 --- a/stdlib/Distributed/src/remotecall.jl +++ b/stdlib/Distributed/src/remotecall.jl @@ -321,7 +321,7 @@ function process_worker(rr) w = worker_from_id(rr.where)::Worker msg = (remoteref_id(rr), myid()) - # Needs to aquire a lock on the del_msg queue + # Needs to acquire a lock on the del_msg queue T = Threads.@spawn begin publish_del_msg!($w, $msg) end diff --git a/stdlib/Distributed/src/workerpool.jl b/stdlib/Distributed/src/workerpool.jl index 0cada2db103de..89e52667c82c9 100644 --- a/stdlib/Distributed/src/workerpool.jl +++ b/stdlib/Distributed/src/workerpool.jl @@ -73,7 +73,7 @@ wp_local_length(pool::AbstractWorkerPool) = length(pool.workers) wp_local_isready(pool::AbstractWorkerPool) = isready(pool.channel) function wp_local_put!(pool::AbstractWorkerPool, w::Int) - # In case of default_worker_pool, the master is implictly considered a worker, i.e., + # In case of default_worker_pool, the master is implicitly considered a worker, i.e., # it is not present in pool.workers. # Confirm the that the worker is part of a pool before making it available. w in pool.workers && put!(pool.channel, w) diff --git a/stdlib/Distributed/test/distributed_exec.jl b/stdlib/Distributed/test/distributed_exec.jl index 8ed55550e61b9..9dffbe0e41994 100644 --- a/stdlib/Distributed/test/distributed_exec.jl +++ b/stdlib/Distributed/test/distributed_exec.jl @@ -993,7 +993,7 @@ end let @test_throws RemoteException remotecall_fetch(()->LocalFoo.foo, 2) - bad_thunk = ()->NonexistantModule.f() + bad_thunk = ()->NonexistentModule.f() @test_throws RemoteException remotecall_fetch(bad_thunk, 2) # Test that the stream is still usable diff --git a/stdlib/FileWatching/src/FileWatching.jl b/stdlib/FileWatching/src/FileWatching.jl index cfb7ede3b09ee..1b4886c0d8e32 100644 --- a/stdlib/FileWatching/src/FileWatching.jl +++ b/stdlib/FileWatching/src/FileWatching.jl @@ -748,7 +748,7 @@ elapsed. This function does not poll the file system and instead uses platform-s functionality to receive notifications from the operating system (e.g. via inotify on Linux). See the NodeJS documentation linked below for details. -The returned value is an object with boolean fields `changed`, `renamed`, and `timedout`, +The returned value is an object with boolean fields `renamed`, `changed`, and `timedout`, giving the result of watching the file. This behavior of this function varies slightly across platforms. See @@ -783,7 +783,7 @@ This will continuing tracking changes for `path` in the background until `unwatch_folder` is called on the same `path`. The returned value is an pair where the first field is the name of the changed file (if available) -and the second field is an object with boolean fields `changed`, `renamed`, and `timedout`, +and the second field is an object with boolean fields `renamed`, `changed`, and `timedout`, giving the event. This behavior of this function varies slightly across platforms. See diff --git a/stdlib/FileWatching/test/pidfile.jl b/stdlib/FileWatching/test/pidfile.jl index 77cf10470eb06..94621f6af78e3 100644 --- a/stdlib/FileWatching/test/pidfile.jl +++ b/stdlib/FileWatching/test/pidfile.jl @@ -109,7 +109,7 @@ end rm("pidfile") deleted = true end - isdefined(Base, :errormonitor) && Base.errormonitor(rmtask) + Base.errormonitor(rmtask) @test isfile("pidfile") @test !deleted @@ -146,7 +146,7 @@ end rm("pidfile") deleted = true end - isdefined(Base, :errormonitor) && Base.errormonitor(rmtask) + Base.errormonitor(rmtask) @test isfile("pidfile") @test !deleted # open the pidfile again (should wait for it to disappear first) @@ -177,7 +177,7 @@ end @test Pidfile.tryrmopenfile("pidfile") deleted = true end - isdefined(Base, :errormonitor) && Base.errormonitor(rmtask) + Base.errormonitor(rmtask) t1 = time() @test_throws ErrorException open_exclusive("pidfile", wait=false) @@ -243,7 +243,7 @@ end return close(lockf) end end - isdefined(Base, :errormonitor) && Base.errormonitor(waittask) + Base.errormonitor(waittask) # mkpidlock with no waiting t = @elapsed @test_throws ErrorException mkpidlock("pidfile", wait=false) @@ -276,27 +276,25 @@ end synchronizer2 = Base.Event() t_loop = @async begin for idx in 1:100 - t = @elapsed begin - if idx == 1 - wait(synchronizer) - notify(synchronizer2) - end - mkpidlock("do_block_pidfile") do - # nothing - end + if idx == 1 + wait(synchronizer) + notify(synchronizer2) + end + t = @elapsed mkpidlock("do_block_pidfile") do + # nothing end sleep(0.01) push!(lock_times, t) end end - isdefined(Base, :errormonitor) && Base.errormonitor(t_loop) + Base.errormonitor(t_loop) mkpidlock("do_block_pidfile") do notify(synchronizer) wait(synchronizer2) sleep(3) end wait(t_loop) - @test maximum(lock_times) > 2 + @test lock_times[1] >= 3 @test minimum(lock_times) < 1 end diff --git a/stdlib/InteractiveUtils/src/codeview.jl b/stdlib/InteractiveUtils/src/codeview.jl index 3937eeb4ba2e8..ce7e76ae4cfd7 100644 --- a/stdlib/InteractiveUtils/src/codeview.jl +++ b/stdlib/InteractiveUtils/src/codeview.jl @@ -27,19 +27,19 @@ end # displaying type warnings -function warntype_type_printer(io::IO, @nospecialize(ty), used::Bool) - used || return - str = "::$ty" +function warntype_type_printer(io::IO; @nospecialize(type), used::Bool, show_type::Bool=true, _...) + (show_type && used) || return nothing + str = "::$type" if !highlighting[:warntype] print(io, str) - elseif ty isa Union && is_expected_union(ty) + elseif type isa Union && is_expected_union(type) Base.emphasize(io, str, Base.warn_color()) # more mild user notification - elseif ty isa Type && (!Base.isdispatchelem(ty) || ty == Core.Box) + elseif type isa Type && (!Base.isdispatchelem(type) || type == Core.Box) Base.emphasize(io, str) else Base.printstyled(io, str, color=:cyan) # show the "good" type end - nothing + return nothing end # True if one can be pretty certain that the compiler handles this union well, @@ -66,7 +66,7 @@ Not all non-leaf types are particularly problematic for performance, and the per characteristics of a particular type is an implementation detail of the compiler. `code_warntype` will err on the side of coloring types red if they might be a performance concern, so some types may be colored red even if they do not impact performance. -Small unions of concrete types are usually not a concern, so these are highlighed in yellow. +Small unions of concrete types are usually not a concern, so these are highlighted in yellow. Keyword argument `debuginfo` may be one of `:source` or `:none` (default), to specify the verbosity of code comments. @@ -140,13 +140,13 @@ function code_warntype(io::IO, @nospecialize(f), @nospecialize(t=Base.default_tt end print(io, " ", slotnames[i]) if isa(slottypes, Vector{Any}) - warntype_type_printer(io, slottypes[i], true) + warntype_type_printer(io; type=slottypes[i], used=true) end println(io) end end print(io, "Body") - warntype_type_printer(io, rettype, true) + warntype_type_printer(io; type=rettype, used=true) println(io) irshow_config = Base.IRShow.IRShowConfig(lineprinter(src), warntype_type_printer) Base.IRShow.show_ir(lambda_io, src, irshow_config) @@ -269,7 +269,7 @@ Keyword argument `debuginfo` may be one of source (default) or none, to specify function code_llvm(io::IO, @nospecialize(f), @nospecialize(types), raw::Bool, dump_module::Bool=false, optimize::Bool=true, debuginfo::Symbol=:default) d = _dump_function(f, types, false, false, !raw, dump_module, :att, optimize, debuginfo, false) - if highlighting[:llvm] && get(io, :color, false) + if highlighting[:llvm] && get(io, :color, false)::Bool print_llvm(io, d) else print(io, d) @@ -296,7 +296,7 @@ See also: [`@code_native`](@ref), [`code_llvm`](@ref), [`code_typed`](@ref) and function code_native(io::IO, @nospecialize(f), @nospecialize(types=Base.default_tt(f)); dump_module::Bool=true, syntax::Symbol=:att, debuginfo::Symbol=:default, binary::Bool=false) d = _dump_function(f, types, true, false, false, dump_module, syntax, true, debuginfo, binary) - if highlighting[:native] && get(io, :color, false) + if highlighting[:native] && get(io, :color, false)::Bool print_native(io, d) else print(io, d) diff --git a/stdlib/InteractiveUtils/src/macros.jl b/stdlib/InteractiveUtils/src/macros.jl index 816438af86684..98189f62edf6f 100644 --- a/stdlib/InteractiveUtils/src/macros.jl +++ b/stdlib/InteractiveUtils/src/macros.jl @@ -24,7 +24,8 @@ function recursive_dotcalls!(ex, args, i=1) end end (start, branches) = ex.head === :. ? (1, ex.args[2].args) : (2, ex.args) - for j in start:length(branches) + length_branches = length(branches)::Integer + for j in start:length_branches branch, i = recursive_dotcalls!(branches[j], args, i) branches[j] = branch end diff --git a/stdlib/LLD_jll/Project.toml b/stdlib/LLD_jll/Project.toml new file mode 100644 index 0000000000000..7fbb85963f798 --- /dev/null +++ b/stdlib/LLD_jll/Project.toml @@ -0,0 +1,21 @@ +name = "LLD_jll" +uuid = "d55e3150-da41-5e91-b323-ecfd1eec6109" +version = "14.0.5+3" + +[deps] +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +Zlib_jll = "83775a58-1f1d-513f-b197-d71354ab007a" +Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" +TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +libLLVM_jll = "8f36deef-c2a5-5394-99ed-8e07531fb29a" +Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[compat] +julia = "1.9" +libLLVM_jll = "14.0.5" + +[extras] +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["Test"] diff --git a/stdlib/LLD_jll/src/LLD_jll.jl b/stdlib/LLD_jll/src/LLD_jll.jl new file mode 100644 index 0000000000000..d14d740fc5e5b --- /dev/null +++ b/stdlib/LLD_jll/src/LLD_jll.jl @@ -0,0 +1,108 @@ + +# This file is a part of Julia. License is MIT: https://julialang.org/license + +## dummy stub for https://github.com/JuliaBinaryWrappers/LLD_jll.jl + +baremodule LLD_jll +using Base, Libdl +Base.Experimental.@compiler_options compile=min optimize=0 infer=false + +const PATH_list = String[] +const LIBPATH_list = String[] + +export lld + +# These get calculated in __init__() +const PATH = Ref("") +const LIBPATH = Ref("") +artifact_dir = "" +lld_path = "" +if Sys.iswindows() + const lld_exe = "lld.exe" +else + const lld_exe = "lld" +end + +if Sys.iswindows() + const LIBPATH_env = "PATH" + const LIBPATH_default = "" + const pathsep = ';' +elseif Sys.isapple() + const LIBPATH_env = "DYLD_FALLBACK_LIBRARY_PATH" + const LIBPATH_default = "~/lib:/usr/local/lib:/lib:/usr/lib" + const pathsep = ':' +else + const LIBPATH_env = "LD_LIBRARY_PATH" + const LIBPATH_default = "" + const pathsep = ':' +end + +function adjust_ENV!(env::Dict, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool) + if adjust_LIBPATH + LIBPATH_base = get(env, LIBPATH_env, expanduser(LIBPATH_default)) + if !isempty(LIBPATH_base) + env[LIBPATH_env] = string(LIBPATH, pathsep, LIBPATH_base) + else + env[LIBPATH_env] = LIBPATH + end + end + if adjust_PATH && (LIBPATH_env != "PATH" || !adjust_LIBPATH) + if adjust_PATH + if !isempty(get(env, "PATH", "")) + env["PATH"] = string(PATH, pathsep, env["PATH"]) + else + env["PATH"] = PATH + end + end + end + return env +end + +function lld(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true) + env = adjust_ENV!(copy(ENV), PATH[], LIBPATH[], adjust_PATH, adjust_LIBPATH) + withenv(env...) do + return f(lld_path) + end +end +function lld(; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true) + env = adjust_ENV!(copy(ENV), PATH[], LIBPATH[], adjust_PATH, adjust_LIBPATH) + return Cmd(Cmd([lld_path]); env) +end + +function init_lld_path() + # Prefer our own bundled lld, but if we don't have one, pick it up off of the PATH + # If this is an in-tree build, `lld` will live in `tools`. Otherwise, it'll be in `libexec` + for bundled_lld_path in (joinpath(Sys.BINDIR, Base.LIBEXECDIR, lld_exe), + joinpath(Sys.BINDIR, "..", "tools", lld_exe), + joinpath(Sys.BINDIR, lld_exe)) + if isfile(bundled_lld_path) + global lld_path = abspath(bundled_lld_path) + return + end + end + global lld_path = something(Sys.which(lld_exe), lld_exe) +end + +function __init__() + global artifact_dir = dirname(Sys.BINDIR) + init_lld_path() + PATH[] = dirname(lld_path) + push!(PATH_list, PATH[]) + if Sys.iswindows() + # On windows, the dynamic libraries (.dll) are in Sys.BINDIR ("usr\\bin") + append!(LIBPATH_list, [joinpath(Sys.BINDIR, Base.LIBDIR, "julia"), Sys.BINDIR]) + else + append!(LIBPATH_list, [joinpath(Sys.BINDIR, Base.LIBDIR, "julia"), joinpath(Sys.BINDIR, Base.LIBDIR)]) + end + LIBPATH[] = join(LIBPATH_list, pathsep) +end + +# JLLWrappers API compatibility shims. Note that not all of these will really make sense. +# For instance, `find_artifact_dir()` won't actually be the artifact directory, because +# there isn't one. It instead returns the overall Julia prefix. +is_available() = true +find_artifact_dir() = artifact_dir +dev_jll() = error("stdlib JLLs cannot be dev'ed") +best_wrapper = nothing + +end # module libLLD_jll diff --git a/stdlib/LLD_jll/test/runtests.jl b/stdlib/LLD_jll/test/runtests.jl new file mode 100644 index 0000000000000..f8eccfe939dce --- /dev/null +++ b/stdlib/LLD_jll/test/runtests.jl @@ -0,0 +1,9 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +using Test, Libdl, LLD_jll + +@testset "LLD_jll" begin + @test isfile(LLD_jll.lld_path) + flavor = Sys.isapple() ? "darwin" : (Sys.iswindows() ? "link" : "gnu") + @test success(`$(LLD_jll.lld()) -flavor $flavor --version`) +end diff --git a/stdlib/LibGit2/src/gitcredential.jl b/stdlib/LibGit2/src/gitcredential.jl index 1b97c29cd933e..acfde02578523 100644 --- a/stdlib/LibGit2/src/gitcredential.jl +++ b/stdlib/LibGit2/src/gitcredential.jl @@ -219,7 +219,7 @@ function credential_helpers(cfg::GitConfig, cred::GitCredential) helpers = GitCredentialHelper[] # https://git-scm.com/docs/gitcredentials#gitcredentials-helper - for entry in GitConfigIter(cfg, r"credential.*\.helper") + for entry in GitConfigIter(cfg, r"credential.*\.helper$") section, url, name, value = split_cfg_entry(entry) @assert name == "helper" diff --git a/stdlib/LibGit2/src/oid.jl b/stdlib/LibGit2/src/oid.jl index 1074f003ebd2f..937684439419f 100644 --- a/stdlib/LibGit2/src/oid.jl +++ b/stdlib/LibGit2/src/oid.jl @@ -154,7 +154,7 @@ end Get a shortened identifier (`GitShortHash`) of `obj`. The minimum length (in characters) is determined by the `core.abbrev` config option, and will be of sufficient length to -unambiuously identify the object in the repository. +unambiguously identify the object in the repository. """ function GitShortHash(obj::GitObject) ensure_initialized() diff --git a/stdlib/LibGit2/test/libgit2-tests.jl b/stdlib/LibGit2/test/libgit2-tests.jl index 4dbd1837045e9..4ace98a0b1ac8 100644 --- a/stdlib/LibGit2/test/libgit2-tests.jl +++ b/stdlib/LibGit2/test/libgit2-tests.jl @@ -1011,7 +1011,7 @@ mktempdir() do dir LibGit2.Signature(repo) catch ex # these test configure repo with new signature - # in case when global one does not exsist + # in case when global one does not exist @test isa(ex, LibGit2.Error.GitError) == true cfg = LibGit2.GitConfig(repo) @@ -1994,7 +1994,7 @@ mktempdir() do dir @test parse(GitCredentialHelper, "store") == GitCredentialHelper(`git credential-store`) end - @testset "empty helper" begin + @testset "credential_helpers" begin config_path = joinpath(dir, config_file) # Note: LibGit2.set! doesn't allow us to set duplicates or ordering @@ -2007,16 +2007,14 @@ mktempdir() do dir [credential] helper = !echo second """) + # Git for Windows uses this config (see issue #45693) + write(fp,""" + [credential "helperselector"] + selected = manager-core + """) end LibGit2.with(LibGit2.GitConfig(config_path, LibGit2.Consts.CONFIG_LEVEL_APP)) do cfg - iter = LibGit2.GitConfigIter(cfg, r"credential.*\.helper") - @test LibGit2.split_cfg_entry.(iter) == [ - ("credential", "", "helper", "!echo first"), - ("credential", "https://mygithost", "helper", ""), - ("credential", "", "helper", "!echo second"), - ] - expected = [ GitCredentialHelper(`echo first`), GitCredentialHelper(`echo second`), diff --git a/stdlib/LibUV_jll/Project.toml b/stdlib/LibUV_jll/Project.toml index 9a46adb07cc95..6f68176fc97e7 100644 --- a/stdlib/LibUV_jll/Project.toml +++ b/stdlib/LibUV_jll/Project.toml @@ -1,6 +1,6 @@ name = "LibUV_jll" uuid = "183b4373-6708-53ba-ad28-60e28bb38547" -version = "2.0.1+8" +version = "2.0.1+11" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/LinearAlgebra/docs/src/index.md b/stdlib/LinearAlgebra/docs/src/index.md index 9e6d05aedcdd9..3c0004757788b 100644 --- a/stdlib/LinearAlgebra/docs/src/index.md +++ b/stdlib/LinearAlgebra/docs/src/index.md @@ -324,6 +324,8 @@ LinearAlgebra.dot(::Any, ::Any, ::Any) LinearAlgebra.cross LinearAlgebra.axpy! LinearAlgebra.axpby! +LinearAlgebra.rotate! +LinearAlgebra.reflect! LinearAlgebra.factorize LinearAlgebra.Diagonal LinearAlgebra.Bidiagonal diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index c9609449580ab..d9376cbda80cc 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -20,6 +20,7 @@ using Base: IndexLinear, promote_eltype, promote_op, promote_typeof, @propagate_inbounds, reduce, typed_hvcat, typed_vcat, require_one_based_indexing, Splat using Base.Broadcast: Broadcasted, broadcasted +using Base.PermutedDimsArrays: CommutativeOps using OpenBLAS_jll using libblastrampoline_jll import Libdl @@ -460,7 +461,7 @@ _cut_B(x::AbstractVector, r::UnitRange) = length(x) > length(r) ? x[r] : x _cut_B(X::AbstractMatrix, r::UnitRange) = size(X, 1) > length(r) ? X[r,:] : X # SymTridiagonal ev can be the same length as dv, but the last element is -# ignored. However, some methods can fail if they read the entired ev +# ignored. However, some methods can fail if they read the entire ev # rather than just the meaningful elements. This is a helper function # for getting only the meaningful elements of ev. See #41089 _evview(S::SymTridiagonal) = @view S.ev[begin:begin + length(S.dv) - 2] @@ -469,13 +470,17 @@ _evview(S::SymTridiagonal) = @view S.ev[begin:begin + length(S.dv) - 2] _zeros(::Type{T}, b::AbstractVector, n::Integer) where {T} = zeros(T, max(length(b), n)) _zeros(::Type{T}, B::AbstractMatrix, n::Integer) where {T} = zeros(T, max(size(B, 1), n), size(B, 2)) +# convert to Vector, if necessary +_makevector(x::Vector) = x +_makevector(x::AbstractVector) = Vector(x) + # append a zero element / drop the last element _pushzero(A) = (B = similar(A, length(A)+1); @inbounds B[begin:end-1] .= A; @inbounds B[end] = zero(eltype(B)); B) _droplast!(A) = deleteat!(A, lastindex(A)) # General fallback definition for handling under- and overdetermined system as well as square problems # While this definition is pretty general, it does e.g. promote to common element type of lhs and rhs -# which is required by LAPACK but not SuiteSpase which allows real-complex solves in some cases. Hence, +# which is required by LAPACK but not SuiteSparse which allows real-complex solves in some cases. Hence, # we restrict this method to only the LAPACK factorizations in LinearAlgebra. # The definition is put here since it explicitly references all the Factorizion structs so it has # to be located after all the files that define the structs. diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index cd0e433bf4fb2..1a67b7f69e24a 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -308,8 +308,8 @@ IndexStyle(::Type{<:AdjOrTransAbsMat}) = IndexCartesian() @propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, ::Colon) = wrapperop(v)(v.parent[:]) # conversion of underlying storage -convert(::Type{Adjoint{T,S}}, A::Adjoint) where {T,S} = Adjoint{T,S}(convert(S, A.parent)) -convert(::Type{Transpose{T,S}}, A::Transpose) where {T,S} = Transpose{T,S}(convert(S, A.parent)) +convert(::Type{Adjoint{T,S}}, A::Adjoint) where {T,S} = Adjoint{T,S}(convert(S, A.parent))::Adjoint{T,S} +convert(::Type{Transpose{T,S}}, A::Transpose) where {T,S} = Transpose{T,S}(convert(S, A.parent))::Transpose{T,S} # Strides and pointer for transposed strided arrays — but only if the elements are actually stored in memory Base.strides(A::Adjoint{<:Real, <:AbstractVector}) = (stride(A.parent, 2), stride(A.parent, 1)) @@ -378,22 +378,36 @@ Broadcast.broadcast_preserving_zero_d(f, tvs::Union{Number,TransposeAbsVec}...) ### reductions -# faster to sum the Array than to work through the wrapper -Base._mapreduce_dim(f, op, init::Base._InitialValue, A::Transpose, dims::Colon) = - transpose(Base._mapreduce_dim(_sandwich(transpose, f), _sandwich(transpose, op), init, parent(A), dims)) -Base._mapreduce_dim(f, op, init::Base._InitialValue, A::Adjoint, dims::Colon) = - adjoint(Base._mapreduce_dim(_sandwich(adjoint, f), _sandwich(adjoint, op), init, parent(A), dims)) +# faster to sum the Array than to work through the wrapper (but only in commutative reduction ops as in Base/permuteddimsarray.jl) +Base._mapreduce_dim(f, op::CommutativeOps, init::Base._InitialValue, A::Transpose, dims::Colon) = + Base._mapreduce_dim(f∘transpose, op, init, parent(A), dims) +Base._mapreduce_dim(f, op::CommutativeOps, init::Base._InitialValue, A::Adjoint, dims::Colon) = + Base._mapreduce_dim(f∘adjoint, op, init, parent(A), dims) +# in prod, use fast path only in the commutative case to avoid surprises +Base._mapreduce_dim(f::typeof(identity), op::Union{typeof(*),typeof(Base.mul_prod)}, init::Base._InitialValue, A::Transpose{<:Union{Real,Complex}}, dims::Colon) = + Base._mapreduce_dim(f∘transpose, op, init, parent(A), dims) +Base._mapreduce_dim(f::typeof(identity), op::Union{typeof(*),typeof(Base.mul_prod)}, init::Base._InitialValue, A::Adjoint{<:Union{Real,Complex}}, dims::Colon) = + Base._mapreduce_dim(f∘adjoint, op, init, parent(A), dims) +# count allows for optimization only if the parent array has Bool eltype +Base._count(::typeof(identity), A::Transpose{Bool}, ::Colon, init) = Base._count(identity, parent(A), :, init) +Base._count(::typeof(identity), A::Adjoint{Bool}, ::Colon, init) = Base._count(identity, parent(A), :, init) +Base._any(f, A::Transpose, ::Colon) = Base._any(f∘transpose, parent(A), :) +Base._any(f, A::Adjoint, ::Colon) = Base._any(f∘adjoint, parent(A), :) +Base._all(f, A::Transpose, ::Colon) = Base._all(f∘transpose, parent(A), :) +Base._all(f, A::Adjoint, ::Colon) = Base._all(f∘adjoint, parent(A), :) # sum(A'; dims) -Base.mapreducedim!(f, op, B::AbstractArray, A::TransposeAbsMat) = - transpose(Base.mapreducedim!(_sandwich(transpose, f), _sandwich(transpose, op), transpose(B), parent(A))) -Base.mapreducedim!(f, op, B::AbstractArray, A::AdjointAbsMat) = - adjoint(Base.mapreducedim!(_sandwich(adjoint, f), _sandwich(adjoint, op), adjoint(B), parent(A))) - -_sandwich(adj::Function, fun) = (xs...,) -> adj(fun(map(adj, xs)...)) -for fun in [:identity, :add_sum, :mul_prod] #, :max, :min] - @eval _sandwich(::Function, ::typeof(Base.$fun)) = Base.$fun -end - +Base.mapreducedim!(f, op::CommutativeOps, B::AbstractArray, A::TransposeAbsMat) = + (Base.mapreducedim!(f∘transpose, op, switch_dim12(B), parent(A)); B) +Base.mapreducedim!(f, op::CommutativeOps, B::AbstractArray, A::AdjointAbsMat) = + (Base.mapreducedim!(f∘adjoint, op, switch_dim12(B), parent(A)); B) +Base.mapreducedim!(f::typeof(identity), op::Union{typeof(*),typeof(Base.mul_prod)}, B::AbstractArray, A::TransposeAbsMat{<:Union{Real,Complex}}) = + (Base.mapreducedim!(f∘transpose, op, switch_dim12(B), parent(A)); B) +Base.mapreducedim!(f::typeof(identity), op::Union{typeof(*),typeof(Base.mul_prod)}, B::AbstractArray, A::AdjointAbsMat{<:Union{Real,Complex}}) = + (Base.mapreducedim!(f∘adjoint, op, switch_dim12(B), parent(A)); B) + +switch_dim12(B::AbstractVector) = permutedims(B) +switch_dim12(B::AbstractArray{<:Any,0}) = B +switch_dim12(B::AbstractArray) = PermutedDimsArray(B, (2, 1, ntuple(Base.Fix1(+,2), ndims(B) - 2)...)) ### linear algebra diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 1f18ad627f636..958466f25e1b5 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -200,14 +200,15 @@ promote_rule(::Type{<:Tridiagonal}, ::Type{<:Bidiagonal}) = Tridiagonal # When asked to convert Bidiagonal to AbstractMatrix{T}, preserve structure by converting to Bidiagonal{T} <: AbstractMatrix{T} AbstractMatrix{T}(A::Bidiagonal) where {T} = convert(Bidiagonal{T}, A) -convert(T::Type{<:Bidiagonal}, m::AbstractMatrix) = m isa T ? m : T(m) +convert(::Type{T}, m::AbstractMatrix) where {T<:Bidiagonal} = m isa T ? m : T(m)::T similar(B::Bidiagonal, ::Type{T}) where {T} = Bidiagonal(similar(B.dv, T), similar(B.ev, T), B.uplo) similar(B::Bidiagonal, ::Type{T}, dims::Union{Dims{1},Dims{2}}) where {T} = zeros(T, dims...) function kron(A::Diagonal, B::Bidiagonal) - kdv = kron(diag(A), B.dv) - kev = _droplast!(kron(diag(A), _pushzero(B.ev))) + # `_droplast!` is only guaranteed to work with `Vector` + kdv = _makevector(kron(diag(A), B.dv)) + kev = _droplast!(_makevector(kron(diag(A), _pushzero(B.ev)))) Bidiagonal(kdv, kev, B.uplo) end diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 4a83fcecbc8d9..7547a60f390d4 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -167,7 +167,7 @@ end # Level 1 # A help function to pick the pointer and inc for 1d like inputs. @inline function vec_pointer_stride(x::AbstractArray, stride0check = nothing) - Base._checkcontiguous(Bool, x) && return pointer(x), 1 # simpify runtime check when possibe + Base._checkcontiguous(Bool, x) && return pointer(x), 1 # simplify runtime check when possibe st, ptr = checkedstride(x), pointer(x) isnothing(stride0check) || (st == 0 && throw(stride0check)) ptr += min(st, 0) * sizeof(eltype(x)) * (length(x) - 1) diff --git a/stdlib/LinearAlgebra/src/bunchkaufman.jl b/stdlib/LinearAlgebra/src/bunchkaufman.jl index e0502b6f6dcfd..2cd8394b1076b 100644 --- a/stdlib/LinearAlgebra/src/bunchkaufman.jl +++ b/stdlib/LinearAlgebra/src/bunchkaufman.jl @@ -80,7 +80,7 @@ BunchKaufman(A::AbstractMatrix{T}, ipiv::AbstractVector{<:Integer}, uplo::Abstra symmetric::Bool, rook::Bool, info::BlasInt) where {T} = BunchKaufman{T,typeof(A),typeof(ipiv)}(A, ipiv, uplo, symmetric, rook, info) # backwards-compatible constructors (remove with Julia 2.0) -@deprecate(BunchKaufman(LD, ipiv, uplo, symmetric, rook, info) where {T,S}, +@deprecate(BunchKaufman{T,S}(LD, ipiv, uplo, symmetric, rook, info) where {T,S}, BunchKaufman{T,S,typeof(ipiv)}(LD, ipiv, uplo, symmetric, rook, info), false) # iteration for destructuring into components @@ -197,7 +197,7 @@ julia> S.L*S.D*S.L' - A[S.p, S.p] ``` """ bunchkaufman(A::AbstractMatrix{T}, rook::Bool=false; check::Bool = true) where {T} = - bunchkaufman!(copymutable_oftype(A, typeof(sqrt(oneunit(T)))), rook; check = check) + bunchkaufman!(eigencopy_oftype(A, typeof(sqrt(oneunit(T)))), rook; check = check) BunchKaufman{T}(B::BunchKaufman) where {T} = BunchKaufman(convert(Matrix{T}, B.LD), B.ipiv, B.uplo, B.symmetric, B.rook, B.info) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index 23f63f71f3e52..bcf9443f7632c 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -722,7 +722,7 @@ function exp!(A::StridedMatrix{T}) where T<:BlasFloat V = mul!(tmp2, A6, tmp1, true, true) tmp1 .= V .+ U - tmp2 .= V .- U # tmp2 aleady contained V but this seems more readable + tmp2 .= V .- U # tmp2 already contained V but this seems more readable X = LAPACK.gesv!(tmp2, tmp1)[1] # X now contains r_13 in Higham 2008 if s > 0 diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index bafe722ca0e07..32687404752ff 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -605,9 +605,10 @@ function kron(A::Diagonal, B::SymTridiagonal) SymTridiagonal(kdv, kev) end function kron(A::Diagonal, B::Tridiagonal) - kd = kron(diag(A), B.d) - kdl = _droplast!(kron(diag(A), _pushzero(B.dl))) - kdu = _droplast!(kron(diag(A), _pushzero(B.du))) + # `_droplast!` is only guaranteed to work with `Vector` + kd = _makevector(kron(diag(A), B.d)) + kdl = _droplast!(_makevector(kron(diag(A), _pushzero(B.dl)))) + kdu = _droplast!(_makevector(kron(diag(A), _pushzero(B.du)))) Tridiagonal(kdl, kd, kdu) end @@ -751,7 +752,7 @@ function eigen(D::Diagonal; permute::Bool=true, scale::Bool=true, sortby::Union{ λ = eigvals(D) if !isnothing(sortby) p = sortperm(λ; alg=QuickSort, by=sortby) - λ = λ[p] # make a copy, otherwise this permutes D.diag + λ = λ[p] evecs = zeros(Td, size(D)) @inbounds for i in eachindex(p) evecs[p[i],i] = one(Td) @@ -761,6 +762,29 @@ function eigen(D::Diagonal; permute::Bool=true, scale::Bool=true, sortby::Union{ end Eigen(λ, evecs) end +function eigen(Da::Diagonal, Db::Diagonal; sortby::Union{Function,Nothing}=nothing) + if any(!isfinite, Da.diag) || any(!isfinite, Db.diag) + throw(ArgumentError("matrices contain Infs or NaNs")) + end + if any(iszero, Db.diag) + throw(ArgumentError("right-hand side diagonal matrix is singular")) + end + return GeneralizedEigen(eigen(Db \ Da; sortby)...) +end +function eigen(A::AbstractMatrix, D::Diagonal; sortby::Union{Function,Nothing}=nothing) + if any(iszero, D.diag) + throw(ArgumentError("right-hand side diagonal matrix is singular")) + end + if size(A, 1) == size(A, 2) && isdiag(A) + return eigen(Diagonal(A), D; sortby) + elseif ishermitian(A) + S = promote_type(eigtype(eltype(A)), eltype(D)) + return eigen!(eigencopy_oftype(Hermitian(A), S), Diagonal{S}(D); sortby) + else + S = promote_type(eigtype(eltype(A)), eltype(D)) + return eigen!(eigencopy_oftype(A, S), Diagonal{S}(D); sortby) + end +end #Singular system svdvals(D::Diagonal{<:Number}) = sort!(abs.(D.diag), rev = true) @@ -827,6 +851,8 @@ end @deprecate cholesky!(A::Diagonal, ::Val{false}; check::Bool = true) cholesky!(A::Diagonal, NoPivot(); check) false @deprecate cholesky(A::Diagonal, ::Val{false}; check::Bool = true) cholesky(A::Diagonal, NoPivot(); check) false +inv(C::Cholesky{<:Any,<:Diagonal}) = Diagonal(map(inv∘abs2, C.factors.diag)) + @inline cholcopy(A::Diagonal) = copymutable_oftype(A, choltype(A)) @inline cholcopy(A::RealHermSymComplexHerm{<:Real,<:Diagonal}) = copymutable_oftype(A, choltype(A)) diff --git a/stdlib/LinearAlgebra/src/eigen.jl b/stdlib/LinearAlgebra/src/eigen.jl index 14de91a9180af..14676ad6df6eb 100644 --- a/stdlib/LinearAlgebra/src/eigen.jl +++ b/stdlib/LinearAlgebra/src/eigen.jl @@ -233,16 +233,20 @@ true ``` """ function eigen(A::AbstractMatrix{T}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=eigsortby) where T - AA = copymutable_oftype(A, eigtype(T)) - isdiag(AA) && return eigen(Diagonal(AA); permute=permute, scale=scale, sortby=sortby) - return eigen!(AA; permute=permute, scale=scale, sortby=sortby) + isdiag(A) && return eigen(Diagonal{eigtype(T)}(diag(A)); sortby) + ishermitian(A) && return eigen!(eigencopy_oftype(Hermitian(A), eigtype(T)); sortby) + AA = eigencopy_oftype(A, eigtype(T)) + return eigen!(AA; permute, scale, sortby) end function eigen(A::AbstractMatrix{T}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=eigsortby) where {T <: Union{Float16,Complex{Float16}}} - AA = copymutable_oftype(A, eigtype(T)) - isdiag(AA) && return eigen(Diagonal(AA); permute=permute, scale=scale, sortby=sortby) - A = eigen!(AA; permute, scale, sortby) - values = convert(AbstractVector{isreal(A.values) ? Float16 : Complex{Float16}}, A.values) - vectors = convert(AbstractMatrix{isreal(A.vectors) ? Float16 : Complex{Float16}}, A.vectors) + isdiag(A) && return eigen(Diagonal{eigtype(T)}(diag(A)); sortby) + E = if ishermitian(A) + eigen!(eigencopy_oftype(Hermitian(A), eigtype(T)); sortby) + else + eigen!(eigencopy_oftype(A, eigtype(T)); permute, scale, sortby) + end + values = convert(AbstractVector{isreal(E.values) ? Float16 : Complex{Float16}}, E.values) + vectors = convert(AbstractMatrix{isreal(E.vectors) ? Float16 : Complex{Float16}}, E.vectors) return Eigen(values, vectors) end eigen(x::Number) = Eigen([x], fill(one(x), 1, 1)) @@ -333,7 +337,7 @@ julia> eigvals(diag_matrix) ``` """ eigvals(A::AbstractMatrix{T}; kws...) where T = - eigvals!(copymutable_oftype(A, eigtype(T)); kws...) + eigvals!(eigencopy_oftype(A, eigtype(T)); kws...) """ For a scalar input, `eigvals` will return a scalar. @@ -507,12 +511,20 @@ true ``` """ function eigen(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}; kws...) where {TA,TB} - S = promote_type(eigtype(TA),TB) - eigen!(copymutable_oftype(A, S), copymutable_oftype(B, S); kws...) + S = promote_type(eigtype(TA), TB) + eigen!(eigencopy_oftype(A, S), eigencopy_oftype(B, S); kws...) end - eigen(A::Number, B::Number) = eigen(fill(A,1,1), fill(B,1,1)) +""" + LinearAlgebra.eigencopy_oftype(A::AbstractMatrix, ::Type{S}) + +Creates a dense copy of `A` with eltype `S` by calling `copy_similar(A, S)`. +In the case of `Hermitian` or `Symmetric` matrices additionally retains the wrapper, +together with the `uplo` field. +""" +eigencopy_oftype(A, S) = copy_similar(A, S) + """ eigvals!(A, B; sortby) -> values @@ -586,8 +598,8 @@ julia> eigvals(A,B) ``` """ function eigvals(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}; kws...) where {TA,TB} - S = promote_type(eigtype(TA),TB) - return eigvals!(copymutable_oftype(A, S), copymutable_oftype(B, S); kws...) + S = promote_type(eigtype(TA), TB) + return eigvals!(eigencopy_oftype(A, S), eigencopy_oftype(B, S); kws...) end """ diff --git a/stdlib/LinearAlgebra/src/exceptions.jl b/stdlib/LinearAlgebra/src/exceptions.jl index ae29b8bc2f7b9..a8d81aad3e067 100644 --- a/stdlib/LinearAlgebra/src/exceptions.jl +++ b/stdlib/LinearAlgebra/src/exceptions.jl @@ -50,7 +50,7 @@ end Exception thrown when a matrix factorization/solve encounters a zero in a pivot (diagonal) position and cannot proceed. This may *not* mean that the matrix is singular: -it may be fruitful to switch to a diffent factorization such as pivoted LU +it may be fruitful to switch to a different factorization such as pivoted LU that can re-order variables to eliminate spurious zero pivots. The `info` field indicates the location of (one of) the zero pivot(s). """ diff --git a/stdlib/LinearAlgebra/src/factorization.jl b/stdlib/LinearAlgebra/src/factorization.jl index 82c593f9bd7c4..a5bcdf66ecc7c 100644 --- a/stdlib/LinearAlgebra/src/factorization.jl +++ b/stdlib/LinearAlgebra/src/factorization.jl @@ -54,9 +54,9 @@ function det(F::Factorization) end convert(::Type{T}, f::T) where {T<:Factorization} = f -convert(::Type{T}, f::Factorization) where {T<:Factorization} = T(f) +convert(::Type{T}, f::Factorization) where {T<:Factorization} = T(f)::T -convert(::Type{T}, f::Factorization) where {T<:AbstractArray} = T(f) +convert(::Type{T}, f::Factorization) where {T<:AbstractArray} = T(f)::T ### General promotion rules Factorization{T}(F::Factorization{T}) where {T} = F diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index ac56cb191488a..d4d33f1320ea6 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1774,7 +1774,8 @@ function isapprox(x::AbstractArray, y::AbstractArray; return d <= max(atol, rtol*max(norm(x), norm(y))) else # Fall back to a component-wise approximate comparison - return all(ab -> isapprox(ab[1], ab[2]; rtol=rtol, atol=atol, nans=nans), zip(x, y)) + # (mapreduce instead of all for greater generality [#44893]) + return mapreduce((a, b) -> isapprox(a, b; rtol=rtol, atol=atol, nans=nans), &, x, y) end end diff --git a/stdlib/LinearAlgebra/src/givens.jl b/stdlib/LinearAlgebra/src/givens.jl index 155d8d6f23ce6..6074bb1ed3b94 100644 --- a/stdlib/LinearAlgebra/src/givens.jl +++ b/stdlib/LinearAlgebra/src/givens.jl @@ -3,6 +3,9 @@ # givensAlgorithm functions are derived from LAPACK, see below abstract type AbstractRotation{T} end +struct AdjointRotation{T,S<:AbstractRotation{T}} <: AbstractRotation{T} + R::S +end transpose(R::AbstractRotation) = error("transpose not implemented for $(typeof(R)). Consider using adjoint instead of transpose.") @@ -10,16 +13,19 @@ function (*)(R::AbstractRotation{T}, A::AbstractVecOrMat{S}) where {T,S} TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) lmul!(convert(AbstractRotation{TS}, R), copy_similar(A, TS)) end -(*)(A::AbstractVector, adjR::Adjoint{<:Any,<:AbstractRotation}) = _absvecormat_mul_adjrot(A, adjR) -(*)(A::AbstractMatrix, adjR::Adjoint{<:Any,<:AbstractRotation}) = _absvecormat_mul_adjrot(A, adjR) -function _absvecormat_mul_adjrot(A::AbstractVecOrMat{T}, adjR::Adjoint{<:Any,<:AbstractRotation{S}}) where {T,S} - R = adjR.parent +function (*)(adjR::AdjointRotation{T}, A::AbstractVecOrMat{S}) where {T,S} + TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) + lmul!(convert(AbstractRotation{TS}, adjR.R)', copy_similar(A, TS)) +end +(*)(A::AbstractVector, adjR::AdjointRotation) = _absvecormat_mul_adjrot(A, adjR) +(*)(A::AbstractMatrix, adjR::AdjointRotation) = _absvecormat_mul_adjrot(A, adjR) +function _absvecormat_mul_adjrot(A::AbstractVecOrMat{T}, adjR::AdjointRotation{S}) where {T,S} TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) - rmul!(TS.(A), convert(AbstractRotation{TS}, R)') + rmul!(copy_similar(A, TS), convert(AbstractRotation{TS}, adjR.R)') end function(*)(A::AbstractMatrix{T}, R::AbstractRotation{S}) where {T,S} TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) - rmul!(TS.(A), convert(AbstractRotation{TS}, R)) + rmul!(copy_similar(A, TS), convert(AbstractRotation{TS}, R)) end """ @@ -44,7 +50,7 @@ struct Rotation{T} <: AbstractRotation{T} end convert(::Type{T}, r::T) where {T<:AbstractRotation} = r -convert(::Type{T}, r::AbstractRotation) where {T<:AbstractRotation} = T(r) +convert(::Type{T}, r::AbstractRotation) where {T<:AbstractRotation} = T(r)::T Givens(i1, i2, c, s) = Givens(i1, i2, promote(c, s)...) Givens{T}(G::Givens{T}) where {T} = G @@ -55,12 +61,11 @@ AbstractRotation{T}(G::Givens) where {T} = Givens{T}(G) AbstractRotation{T}(R::Rotation) where {T} = Rotation{T}(R) adjoint(G::Givens) = Givens(G.i1, G.i2, G.c', -G.s) -adjoint(R::Rotation) = Adjoint(R) -function Base.copy(aG::Adjoint{<:Any,<:Givens}) - G = aG.parent - return Givens(G.i1, G.i2, conj(G.c), -G.s) -end -Base.copy(aR::Adjoint{<:Any,Rotation{T}}) where {T} = Rotation{T}(reverse!([r' for r in aR.parent.rotations])) +adjoint(R::AbstractRotation) = AdjointRotation(R) +adjoint(adjR::AdjointRotation) = adjR.R + +Base.copy(aR::AdjointRotation{T,Rotation{T}}) where {T} = + Rotation{T}([r' for r in Iterators.reverse(aR.R.rotations)]) floatmin2(::Type{Float32}) = reinterpret(Float32, 0x26000000) floatmin2(::Type{Float64}) = reinterpret(Float64, 0x21a0000000000000) @@ -291,7 +296,7 @@ function givens(f::T, g::T, i1::Integer, i2::Integer) where T c, s, r = givensAlgorithm(f, g) if i1 > i2 s = -conj(s) - i1,i2 = i2,i1 + i1, i2 = i2, i1 end Givens(i1, i2, c, s), r end @@ -329,9 +334,7 @@ B[i2] = 0 See also [`LinearAlgebra.Givens`](@ref). """ -givens(x::AbstractVector, i1::Integer, i2::Integer) = - givens(x[i1], x[i2], i1, i2) - +givens(x::AbstractVector, i1::Integer, i2::Integer) = givens(x[i1], x[i2], i1, i2) function getindex(G::Givens, i::Integer, j::Integer) if i == j @@ -386,23 +389,24 @@ function lmul!(R::Rotation, A::AbstractMatrix) end return A end -function rmul!(A::AbstractMatrix, adjR::Adjoint{<:Any,<:Rotation}) - R = adjR.parent +function rmul!(A::AbstractMatrix, R::Rotation) + @inbounds for i = 1:length(R.rotations) + rmul!(A, R.rotations[i]) + end + return A +end +function lmul!(adjR::AdjointRotation{<:Any,<:Rotation}, A::AbstractMatrix) + R = adjR.R + @inbounds for i = 1:length(R.rotations) + lmul!(adjoint(R.rotations[i]), A) + end + return A +end +function rmul!(A::AbstractMatrix, adjR::AdjointRotation{<:Any,<:Rotation}) + R = adjR.R @inbounds for i = 1:length(R.rotations) rmul!(A, adjoint(R.rotations[i])) end return A end -*(G1::Givens{T}, G2::Givens{T}) where {T} = Rotation(push!(push!(Givens{T}[], G2), G1)) - -# TODO: None of the following disambiguation methods are great. They should perhaps -# instead be MethodErrors, or revised. -# -# disambiguation methods: *(Adj/Trans of AbsVec or AbsMat, Adj of AbstractRotation) -*(A::Adjoint{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractRotation}) = copy(A) * B -*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractRotation}) = copy(A) * B -*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractRotation}) = copy(A) * B -*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractRotation}) = copy(A) * B -# disambiguation methods: *(Diag/AbsTri, Adj of AbstractRotation) -*(A::Diagonal, B::Adjoint{<:Any,<:AbstractRotation}) = A * copy(B) -*(A::AbstractTriangular, B::Adjoint{<:Any,<:AbstractRotation}) = A * copy(B) +*(G1::Givens{T}, G2::Givens{T}) where {T} = Rotation([G2, G1]) diff --git a/stdlib/LinearAlgebra/src/matmul.jl b/stdlib/LinearAlgebra/src/matmul.jl index 81eb9e3d3012a..2216d1858d46f 100644 --- a/stdlib/LinearAlgebra/src/matmul.jl +++ b/stdlib/LinearAlgebra/src/matmul.jl @@ -66,7 +66,7 @@ end gemv!(y, 'N', A, x, alpha, beta) # Complex matrix times real vector. -# Reinterpret the matrix as a real matrix and do real matvec compuation. +# Reinterpret the matrix as a real matrix and do real matvec computation. @inline mul!(y::StridedVector{Complex{T}}, A::StridedVecOrMat{Complex{T}}, x::StridedVector{T}, alpha::Number, beta::Number) where {T<:BlasReal} = gemv!(y, 'N', A, x, alpha, beta) @@ -469,7 +469,7 @@ end # Supporting functions for matrix multiplication -# copy transposed(adjoint) of upper(lower) side-digonals. Optionally include diagonal. +# copy transposed(adjoint) of upper(lower) side-diagonals. Optionally include diagonal. @inline function copytri!(A::AbstractMatrix, uplo::AbstractChar, conjugate::Bool=false, diag::Bool=false) n = checksquare(A) off = diag ? 0 : 1 diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index d4cff63dcc045..7fcace8e4ef71 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -2,13 +2,6 @@ # Methods operating on different special matrix types - -# Usually, reducedim_initarray calls similar, which yields a sparse matrix for a -# Diagonal/Bidiagonal/Tridiagonal/SymTridiagonal matrix. However, reducedim should -# yield a dense vector to increase performance. -Base.reducedim_initarray(A::Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal}, region, init, ::Type{R}) where {R} = fill(convert(R, init), Base.reduced_indices(A,region)) - - # Interconversion between special matrix types # conversions from Diagonal to other special matrix types @@ -62,20 +55,20 @@ end const ConvertibleSpecialMatrix = Union{Diagonal,Bidiagonal,SymTridiagonal,Tridiagonal,AbstractTriangular} const PossibleTriangularMatrix = Union{Diagonal, Bidiagonal, AbstractTriangular} -convert(T::Type{<:Diagonal}, m::ConvertibleSpecialMatrix) = m isa T ? m : - isdiag(m) ? T(m) : throw(ArgumentError("matrix cannot be represented as Diagonal")) -convert(T::Type{<:SymTridiagonal}, m::ConvertibleSpecialMatrix) = m isa T ? m : - issymmetric(m) && isbanded(m, -1, 1) ? T(m) : throw(ArgumentError("matrix cannot be represented as SymTridiagonal")) -convert(T::Type{<:Tridiagonal}, m::ConvertibleSpecialMatrix) = m isa T ? m : - isbanded(m, -1, 1) ? T(m) : throw(ArgumentError("matrix cannot be represented as Tridiagonal")) +convert(::Type{T}, m::ConvertibleSpecialMatrix) where {T<:Diagonal} = m isa T ? m : + isdiag(m) ? T(m)::T : throw(ArgumentError("matrix cannot be represented as Diagonal")) +convert(::Type{T}, m::ConvertibleSpecialMatrix) where {T<:SymTridiagonal} = m isa T ? m : + issymmetric(m) && isbanded(m, -1, 1) ? T(m)::T : throw(ArgumentError("matrix cannot be represented as SymTridiagonal")) +convert(::Type{T}, m::ConvertibleSpecialMatrix) where {T<:Tridiagonal} = m isa T ? m : + isbanded(m, -1, 1) ? T(m)::T : throw(ArgumentError("matrix cannot be represented as Tridiagonal")) -convert(T::Type{<:LowerTriangular}, m::Union{LowerTriangular,UnitLowerTriangular}) = m isa T ? m : T(m) -convert(T::Type{<:UpperTriangular}, m::Union{UpperTriangular,UnitUpperTriangular}) = m isa T ? m : T(m) +convert(::Type{T}, m::Union{LowerTriangular,UnitLowerTriangular}) where {T<:LowerTriangular} = m isa T ? m : T(m)::T +convert(::Type{T}, m::Union{UpperTriangular,UnitUpperTriangular}) where {T<:UpperTriangular} = m isa T ? m : T(m)::T -convert(T::Type{<:LowerTriangular}, m::PossibleTriangularMatrix) = m isa T ? m : - istril(m) ? T(m) : throw(ArgumentError("matrix cannot be represented as LowerTriangular")) -convert(T::Type{<:UpperTriangular}, m::PossibleTriangularMatrix) = m isa T ? m : - istriu(m) ? T(m) : throw(ArgumentError("matrix cannot be represented as UpperTriangular")) +convert(::Type{T}, m::PossibleTriangularMatrix) where {T<:LowerTriangular} = m isa T ? m : + istril(m) ? T(m)::T : throw(ArgumentError("matrix cannot be represented as LowerTriangular")) +convert(::Type{T}, m::PossibleTriangularMatrix) where {T<:UpperTriangular} = m isa T ? m : + istriu(m) ? T(m)::T : throw(ArgumentError("matrix cannot be represented as UpperTriangular")) # Constructs two method definitions taking into account (assumed) commutativity # e.g. @commutative f(x::S, y::T) where {S,T} = x+y is the same is defining diff --git a/stdlib/LinearAlgebra/src/structuredbroadcast.jl b/stdlib/LinearAlgebra/src/structuredbroadcast.jl index 95a1842702291..ccf95f88a1bee 100644 --- a/stdlib/LinearAlgebra/src/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/src/structuredbroadcast.jl @@ -126,6 +126,7 @@ fails as `zero(::Tuple{Int})` is not defined. However, """ iszerodefined(::Type) = false iszerodefined(::Type{<:Number}) = true +iszerodefined(::Type{<:AbstractArray{T}}) where T = iszerodefined(T) fzeropreserving(bc) = (v = fzero(bc); !ismissing(v) && (iszerodefined(typeof(v)) ? iszero(v) : v == 0)) # Like sparse matrices, we assume that the zero-preservation property of a broadcasted diff --git a/stdlib/LinearAlgebra/src/svd.jl b/stdlib/LinearAlgebra/src/svd.jl index d0ac4d957e60d..c58c83bcb5a98 100644 --- a/stdlib/LinearAlgebra/src/svd.jl +++ b/stdlib/LinearAlgebra/src/svd.jl @@ -26,10 +26,10 @@ julia> F = svd(A) SVD{Float64, Float64, Matrix{Float64}, Vector{Float64}} U factor: 4×4 Matrix{Float64}: - 0.0 1.0 0.0 0.0 - 1.0 0.0 0.0 0.0 - 0.0 0.0 0.0 -1.0 - 0.0 0.0 1.0 0.0 + 0.0 1.0 0.0 0.0 + 1.0 0.0 0.0 0.0 + 0.0 0.0 0.0 1.0 + 0.0 0.0 -1.0 0.0 singular values: 4-element Vector{Float64}: 3.0 @@ -38,10 +38,10 @@ singular values: 0.0 Vt factor: 4×5 Matrix{Float64}: - -0.0 0.0 1.0 -0.0 0.0 - 0.447214 0.0 0.0 0.0 0.894427 - -0.0 1.0 0.0 -0.0 0.0 - 0.0 0.0 0.0 1.0 0.0 + -0.0 0.0 1.0 -0.0 0.0 + 0.447214 0.0 0.0 0.0 0.894427 + 0.0 -1.0 0.0 0.0 0.0 + 0.0 0.0 0.0 1.0 0.0 julia> F.U * Diagonal(F.S) * F.Vt 4×5 Matrix{Float64}: diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 7347dd6f78639..96638477ce717 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -192,8 +192,8 @@ for (S, H) in ((:Symmetric, :Hermitian), (:Hermitian, :Symmetric)) end end -convert(T::Type{<:Symmetric}, m::Union{Symmetric,Hermitian}) = m isa T ? m : T(m) -convert(T::Type{<:Hermitian}, m::Union{Symmetric,Hermitian}) = m isa T ? m : T(m) +convert(::Type{T}, m::Union{Symmetric,Hermitian}) where {T<:Symmetric} = m isa T ? m : T(m)::T +convert(::Type{T}, m::Union{Symmetric,Hermitian}) where {T<:Hermitian} = m isa T ? m : T(m)::T const HermOrSym{T, S} = Union{Hermitian{T,S}, Symmetric{T,S}} const RealHermSym{T<:Real,S} = Union{Hermitian{T,S}, Symmetric{T,S}} diff --git a/stdlib/LinearAlgebra/src/symmetriceigen.jl b/stdlib/LinearAlgebra/src/symmetriceigen.jl index 8d90f370e06b6..f3a98e0872723 100644 --- a/stdlib/LinearAlgebra/src/symmetriceigen.jl +++ b/stdlib/LinearAlgebra/src/symmetriceigen.jl @@ -1,13 +1,16 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +# preserve HermOrSym wrapper +eigencopy_oftype(A::Hermitian, S) = Hermitian(copy_similar(A, S), sym_uplo(A.uplo)) +eigencopy_oftype(A::Symmetric, S) = Symmetric(copy_similar(A, S), sym_uplo(A.uplo)) + # Eigensolvers for symmetric and Hermitian matrices eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby::Union{Function,Nothing}=nothing) = Eigen(sorteig!(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)..., sortby)...) function eigen(A::RealHermSymComplexHerm; sortby::Union{Function,Nothing}=nothing) - T = eltype(A) - S = eigtype(T) - eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), sortby=sortby) + S = eigtype(eltype(A)) + eigen!(eigencopy_oftype(A, S), sortby=sortby) end eigen!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = @@ -31,9 +34,8 @@ The [`UnitRange`](@ref) `irange` specifies indices of the sorted eigenvalues to will be a *truncated* factorization. """ function eigen(A::RealHermSymComplexHerm, irange::UnitRange) - T = eltype(A) - S = eigtype(T) - eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange) + S = eigtype(eltype(A)) + eigen!(eigencopy_oftype(A, S), irange) end eigen!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = @@ -57,9 +59,8 @@ The following functions are available for `Eigen` objects: [`inv`](@ref), [`det` will be a *truncated* factorization. """ function eigen(A::RealHermSymComplexHerm, vl::Real, vh::Real) - T = eltype(A) - S = eigtype(T) - eigen!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) + S = eigtype(eltype(A)) + eigen!(eigencopy_oftype(A, S), vl, vh) end function eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby::Union{Function,Nothing}=nothing) @@ -69,9 +70,8 @@ function eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}; sortby: end function eigvals(A::RealHermSymComplexHerm; sortby::Union{Function,Nothing}=nothing) - T = eltype(A) - S = eigtype(T) - eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), sortby=sortby) + S = eigtype(eltype(A)) + eigvals!(eigencopy_oftype(A, S), sortby=sortby) end """ @@ -110,9 +110,8 @@ julia> eigvals(A) ``` """ function eigvals(A::RealHermSymComplexHerm, irange::UnitRange) - T = eltype(A) - S = eigtype(T) - eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange) + S = eigtype(eltype(A)) + eigvals!(eigencopy_oftype(A, S), irange) end """ @@ -150,9 +149,8 @@ julia> eigvals(A) ``` """ function eigvals(A::RealHermSymComplexHerm, vl::Real, vh::Real) - T = eltype(A) - S = eigtype(T) - eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) + S = eigtype(eltype(A)) + eigvals!(eigencopy_oftype(A, S), vl, vh) end eigmax(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, size(A, 1):size(A, 1))[1] @@ -166,107 +164,25 @@ function eigen!(A::Hermitian{T,S}, B::Hermitian{T,S}; sortby::Union{Function,Not vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data')) GeneralizedEigen(sorteig!(vals, vecs, sortby)...) end - function eigen!(A::RealHermSymComplexHerm{T,S}, B::AbstractMatrix{T}; sortby::Union{Function,Nothing}=nothing) where {T<:Number,S<:StridedMatrix} + return _choleigen!(A, B, sortby) +end +function eigen!(A::StridedMatrix{T}, B::Union{RealHermSymComplexHerm{T},Diagonal{T}}; sortby::Union{Function,Nothing}=nothing) where {T<:Number} + return _choleigen!(A, B, sortby) +end +function _choleigen!(A, B, sortby) U = cholesky(B).U vals, w = eigen!(UtiAUi!(A, U)) vecs = U \ w GeneralizedEigen(sorteig!(vals, vecs, sortby)...) end -# Perform U' \ A / U in-place. -UtiAUi!(As::Symmetric, Utr::UpperTriangular) = Symmetric(_UtiAsymUi!(As.uplo, parent(As), parent(Utr)), sym_uplo(As.uplo)) -UtiAUi!(As::Hermitian, Utr::UpperTriangular) = Hermitian(_UtiAsymUi!(As.uplo, parent(As), parent(Utr)), sym_uplo(As.uplo)) -UtiAUi!(As::Symmetric, Udi::Diagonal) = Symmetric(_UtiAsymUi_diag!(As.uplo, parent(As), Udi), sym_uplo(As.uplo)) -UtiAUi!(As::Hermitian, Udi::Diagonal) = Hermitian(_UtiAsymUi_diag!(As.uplo, parent(As), Udi), sym_uplo(As.uplo)) - -# U is upper triangular -function _UtiAsymUi!(uplo, A, U) - n = size(A, 1) - μ⁻¹ = 1 / U[1, 1] - αμ⁻² = A[1, 1] * μ⁻¹' * μ⁻¹ - - # Update (1, 1) element - A[1, 1] = αμ⁻² - if n > 1 - Unext = view(U, 2:n, 2:n) - - if uplo === 'U' - # Update submatrix - for j in 2:n, i in 2:j - A[i, j] = ( - A[i, j] - - μ⁻¹' * U[1, j] * A[1, i]' - - μ⁻¹ * A[1, j] * U[1, i]' - + αμ⁻² * U[1, j] * U[1, i]' - ) - end - - # Update vector - for j in 2:n - A[1, j] = A[1, j] * μ⁻¹' - U[1, j] * αμ⁻² - end - ldiv!(view(A', 2:n, 1), UpperTriangular(Unext)', view(A', 2:n, 1)) - else - # Update submatrix - for j in 2:n, i in 2:j - A[j, i] = ( - A[j, i] - - μ⁻¹ * A[i, 1]' * U[1, j]' - - μ⁻¹' * U[1, i] * A[j, 1] - + αμ⁻² * U[1, i] * U[1, j]' - ) - end - - # Update vector - for j in 2:n - A[j, 1] = A[j, 1] * μ⁻¹ - U[1, j]' * αμ⁻² - end - ldiv!(view(A, 2:n, 1), UpperTriangular(Unext)', view(A, 2:n, 1)) - end - - # Recurse - _UtiAsymUi!(uplo, view(A, 2:n, 2:n), Unext) - end - - return A -end +# Perform U' \ A / U in-place, where U::Union{UpperTriangular,Diagonal} +UtiAUi!(A::StridedMatrix, U) = _UtiAUi!(A, U) +UtiAUi!(A::Symmetric, U) = Symmetric(_UtiAUi!(copytri!(parent(A), A.uplo), U), sym_uplo(A.uplo)) +UtiAUi!(A::Hermitian, U) = Hermitian(_UtiAUi!(copytri!(parent(A), A.uplo, true), U), sym_uplo(A.uplo)) -# U is diagonal -function _UtiAsymUi_diag!(uplo, A, U) - n = size(A, 1) - μ⁻¹ = 1 / U[1, 1] - αμ⁻² = A[1, 1] * μ⁻¹' * μ⁻¹ - - # Update (1, 1) element - A[1, 1] = αμ⁻² - if n > 1 - Unext = view(U, 2:n, 2:n) - - if uplo === 'U' - # No need to update any submatrix when U is diagonal - - # Update vector - for j in 2:n - A[1, j] = A[1, j] * μ⁻¹' - end - ldiv!(view(A', 2:n, 1), Diagonal(Unext)', view(A', 2:n, 1)) - else - # No need to update any submatrix when U is diagonal - - # Update vector - for j in 2:n - A[j, 1] = A[j, 1] * μ⁻¹ - end - ldiv!(view(A, 2:n, 1), Diagonal(Unext)', view(A, 2:n, 1)) - end - - # Recurse - _UtiAsymUi!(uplo, view(A, 2:n, 2:n), Unext) - end - - return A -end +_UtiAUi!(A, U) = rdiv!(ldiv!(U', A), U) function eigvals!(A::HermOrSym{T,S}, B::HermOrSym{T,S}; sortby::Union{Function,Nothing}=nothing) where {T<:BlasReal,S<:StridedMatrix} vals = LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : copy(B.data'))[1] diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index d939a5df0da01..a0edfdcd3c40a 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -674,7 +674,7 @@ mul!(C::AbstractMatrix, A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractVec mul!(C::AbstractVecOrMat, A::AbstractTriangular, adjB::Adjoint{<:Any,<:AbstractVecOrMat}) = (B = adjB.parent; lmul!(A, adjoint!(C, B))) -# The three methods are neceesary to avoid ambiguities with definitions in matmul.jl +# The three methods are necessary to avoid ambiguities with definitions in matmul.jl mul!(C::AbstractVector , A::AbstractTriangular, B::AbstractVector) = lmul!(A, copyto!(C, B)) mul!(C::AbstractMatrix , A::AbstractTriangular, B::AbstractVecOrMat) = lmul!(A, copyto!(C, B)) mul!(C::AbstractVecOrMat, A::AbstractTriangular, B::AbstractVecOrMat) = lmul!(A, copyto!(C, B)) diff --git a/stdlib/LinearAlgebra/src/uniformscaling.jl b/stdlib/LinearAlgebra/src/uniformscaling.jl index 661bd28cb8f91..428acf469c9b2 100644 --- a/stdlib/LinearAlgebra/src/uniformscaling.jl +++ b/stdlib/LinearAlgebra/src/uniformscaling.jl @@ -118,7 +118,7 @@ function show(io::IO, ::MIME"text/plain", J::UniformScaling) end copy(J::UniformScaling) = UniformScaling(J.λ) -Base.convert(::Type{UniformScaling{T}}, J::UniformScaling) where {T} = UniformScaling(convert(T, J.λ)) +Base.convert(::Type{UniformScaling{T}}, J::UniformScaling) where {T} = UniformScaling(convert(T, J.λ))::UniformScaling{T} conj(J::UniformScaling) = UniformScaling(conj(J.λ)) real(J::UniformScaling) = UniformScaling(real(J.λ)) diff --git a/stdlib/LinearAlgebra/test/adjtrans.jl b/stdlib/LinearAlgebra/test/adjtrans.jl index 7b782d463768d..e96ea28531d37 100644 --- a/stdlib/LinearAlgebra/test/adjtrans.jl +++ b/stdlib/LinearAlgebra/test/adjtrans.jl @@ -588,24 +588,52 @@ end @test transpose(Int[]) * Int[] == 0 end -@testset "reductions: $adjtrans" for adjtrans in [transpose, adjoint] - mat = rand(ComplexF64, 3,5) - @test sum(adjtrans(mat)) ≈ sum(collect(adjtrans(mat))) - @test sum(adjtrans(mat), dims=1) ≈ sum(collect(adjtrans(mat)), dims=1) - @test sum(adjtrans(mat), dims=(1,2)) ≈ sum(collect(adjtrans(mat)), dims=(1,2)) - - @test sum(imag, adjtrans(mat)) ≈ sum(imag, collect(adjtrans(mat))) - @test sum(imag, adjtrans(mat), dims=1) ≈ sum(imag, collect(adjtrans(mat)), dims=1) - - mat = [rand(ComplexF64,2,2) for _ in 1:3, _ in 1:5] - @test sum(adjtrans(mat)) ≈ sum(collect(adjtrans(mat))) - @test sum(adjtrans(mat), dims=1) ≈ sum(collect(adjtrans(mat)), dims=1) - @test sum(adjtrans(mat), dims=(1,2)) ≈ sum(collect(adjtrans(mat)), dims=(1,2)) - - @test sum(imag, adjtrans(mat)) ≈ sum(imag, collect(adjtrans(mat))) - @test sum(x -> x[1,2], adjtrans(mat)) ≈ sum(x -> x[1,2], collect(adjtrans(mat))) - @test sum(imag, adjtrans(mat), dims=1) ≈ sum(imag, collect(adjtrans(mat)), dims=1) - @test sum(x -> x[1,2], adjtrans(mat), dims=1) ≈ sum(x -> x[1,2], collect(adjtrans(mat)), dims=1) +@testset "reductions: $adjtrans" for adjtrans in (transpose, adjoint) + for (reduction, reduction!, op) in ((sum, sum!, +), (prod, prod!, *), (minimum, minimum!, min), (maximum, maximum!, max)) + T = op in (max, min) ? Float64 : ComplexF64 + mat = rand(T, 3,5) + rd1 = zeros(T, 1, 3) + rd2 = zeros(T, 5, 1) + rd3 = zeros(T, 1, 1) + @test reduction(adjtrans(mat)) ≈ reduction(copy(adjtrans(mat))) + @test reduction(adjtrans(mat), dims=1) ≈ reduction(copy(adjtrans(mat)), dims=1) + @test reduction(adjtrans(mat), dims=2) ≈ reduction(copy(adjtrans(mat)), dims=2) + @test reduction(adjtrans(mat), dims=(1,2)) ≈ reduction(copy(adjtrans(mat)), dims=(1,2)) + + @test reduction!(rd1, adjtrans(mat)) ≈ reduction!(rd1, copy(adjtrans(mat))) + @test reduction!(rd2, adjtrans(mat)) ≈ reduction!(rd2, copy(adjtrans(mat))) + @test reduction!(rd3, adjtrans(mat)) ≈ reduction!(rd3, copy(adjtrans(mat))) + + @test reduction(imag, adjtrans(mat)) ≈ reduction(imag, copy(adjtrans(mat))) + @test reduction(imag, adjtrans(mat), dims=1) ≈ reduction(imag, copy(adjtrans(mat)), dims=1) + @test reduction(imag, adjtrans(mat), dims=2) ≈ reduction(imag, copy(adjtrans(mat)), dims=2) + @test reduction(imag, adjtrans(mat), dims=(1,2)) ≈ reduction(imag, copy(adjtrans(mat)), dims=(1,2)) + + @test Base.mapreducedim!(imag, op, rd1, adjtrans(mat)) ≈ Base.mapreducedim!(imag, op, rd1, copy(adjtrans(mat))) + @test Base.mapreducedim!(imag, op, rd2, adjtrans(mat)) ≈ Base.mapreducedim!(imag, op, rd2, copy(adjtrans(mat))) + @test Base.mapreducedim!(imag, op, rd3, adjtrans(mat)) ≈ Base.mapreducedim!(imag, op, rd3, copy(adjtrans(mat))) + + op in (max, min) && continue + mat = [rand(T,2,2) for _ in 1:3, _ in 1:5] + rd1 = fill(zeros(T, 2, 2), 1, 3) + rd2 = fill(zeros(T, 2, 2), 5, 1) + rd3 = fill(zeros(T, 2, 2), 1, 1) + @test reduction(adjtrans(mat)) ≈ reduction(copy(adjtrans(mat))) + @test reduction(adjtrans(mat), dims=1) ≈ reduction(copy(adjtrans(mat)), dims=1) + @test reduction(adjtrans(mat), dims=2) ≈ reduction(copy(adjtrans(mat)), dims=2) + @test reduction(adjtrans(mat), dims=(1,2)) ≈ reduction(copy(adjtrans(mat)), dims=(1,2)) + + @test reduction(imag, adjtrans(mat)) ≈ reduction(imag, copy(adjtrans(mat))) + @test reduction(x -> x[1,2], adjtrans(mat)) ≈ reduction(x -> x[1,2], copy(adjtrans(mat))) + @test reduction(imag, adjtrans(mat), dims=1) ≈ reduction(imag, copy(adjtrans(mat)), dims=1) + @test reduction(x -> x[1,2], adjtrans(mat), dims=1) ≈ reduction(x -> x[1,2], copy(adjtrans(mat)), dims=1) + end + # see #46605 + Ac = [1 2; 3 4]' + @test mapreduce(identity, (x, y) -> 10x+y, copy(Ac)) == mapreduce(identity, (x, y) -> 10x+y, Ac) == 1234 + @test extrema([3,7,4]') == (3, 7) + @test mapreduce(x -> [x;;;], +, [1, 2, 3]') == sum(x -> [x;;;], [1, 2, 3]') == [6;;;] + @test mapreduce(string, *, [1 2; 3 4]') == mapreduce(string, *, copy([1 2; 3 4]')) == "1234" end end # module TestAdjointTranspose diff --git a/stdlib/LinearAlgebra/test/cholesky.jl b/stdlib/LinearAlgebra/test/cholesky.jl index 8e6cac65f7dfb..d1d00e2326dfb 100644 --- a/stdlib/LinearAlgebra/test/cholesky.jl +++ b/stdlib/LinearAlgebra/test/cholesky.jl @@ -303,6 +303,7 @@ end v = rand(5) @test cholesky(Diagonal(v)) \ B ≈ Diagonal(v) \ B @test B / cholesky(Diagonal(v)) ≈ B / Diagonal(v) + @test inv(cholesky(Diagonal(v)))::Diagonal ≈ Diagonal(1 ./ v) end struct WrappedVector{T} <: AbstractVector{T} diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index e618fe75883ef..3e6f456c3de1e 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -462,13 +462,36 @@ end @test kron(Ad, Ad).diag == kron([1, 2, 3], [1, 2, 3]) end -@testset "kron (issue #46456)" begin - A = Diagonal(randn(10)) - BL = Bidiagonal(randn(10), randn(9), :L) - BU = Bidiagonal(randn(10), randn(9), :U) - C = SymTridiagonal(randn(10), randn(9)) - Cl = SymTridiagonal(randn(10), randn(10)) - D = Tridiagonal(randn(9), randn(10), randn(9)) +# Define a vector type that does not support `deleteat!`, to ensure that `kron` handles this +struct SimpleVector{T} <: AbstractVector{T} + vec::Vector{T} +end +SimpleVector(x::SimpleVector) = SimpleVector(Vector(x.vec)) +SimpleVector{T}(::UndefInitializer, n::Integer) where {T} = SimpleVector(Vector{T}(undef, n)) +Base.:(==)(x::SimpleVector, y::SimpleVector) = x == y +Base.axes(x::SimpleVector) = axes(x.vec) +Base.convert(::Type{Vector{T}}, x::SimpleVector) where {T} = convert(Vector{T}, x.vec) +Base.convert(::Type{Vector}, x::SimpleVector{T}) where {T} = convert(Vector{T}, x) +Base.convert(::Type{Array{T}}, x::SimpleVector) where {T} = convert(Vector{T}, x) +Base.convert(::Type{Array}, x::SimpleVector) = convert(Vector, x) +Base.copyto!(x::SimpleVector, y::SimpleVector) = (copyto!(x.vec, y.vec); x) +Base.eltype(::Type{SimpleVector{T}}) where {T} = T +Base.getindex(x::SimpleVector, ind...) = getindex(x.vec, ind...) +Base.kron(x::SimpleVector, y::SimpleVector) = SimpleVector(kron(x.vec, y.vec)) +Base.promote_rule(::Type{<:AbstractVector{T}}, ::Type{SimpleVector{U}}) where {T,U} = Vector{promote_type(T, U)} +Base.promote_rule(::Type{SimpleVector{T}}, ::Type{SimpleVector{U}}) where {T,U} = SimpleVector{promote_type(T, U)} +Base.setindex!(x::SimpleVector, val, ind...) = (setindex!(x.vec, val, ind...), x) +Base.similar(x::SimpleVector, ::Type{T}) where {T} = SimpleVector(similar(x.vec, T)) +Base.similar(x::SimpleVector, ::Type{T}, dims::Dims{1}) where {T} = SimpleVector(similar(x.vec, T, dims)) +Base.size(x::SimpleVector) = size(x.vec) + +@testset "kron (issue #46456)" for repr in Any[identity, SimpleVector] + A = Diagonal(repr(randn(10))) + BL = Bidiagonal(repr(randn(10)), repr(randn(9)), :L) + BU = Bidiagonal(repr(randn(10)), repr(randn(9)), :U) + C = SymTridiagonal(repr(randn(10)), repr(randn(9))) + Cl = SymTridiagonal(repr(randn(10)), repr(randn(10))) + D = Tridiagonal(repr(randn(9)), repr(randn(10)), repr(randn(9))) @test kron(A, BL)::Bidiagonal == kron(Array(A), Array(BL)) @test kron(A, BU)::Bidiagonal == kron(Array(A), Array(BU)) @test kron(A, C)::SymTridiagonal == kron(Array(A), Array(C)) @@ -1083,4 +1106,27 @@ end @test outTri === mul!(outTri, UTriA, D, 2, 1)::Tri == mul!(out, Matrix(UTriA), D, 2, 1) end +struct SMatrix1{T} <: AbstractArray{T,2} + elt::T +end +Base.:(==)(A::SMatrix1, B::SMatrix1) = A.elt == B.elt +Base.zero(::Type{SMatrix1{T}}) where {T} = SMatrix1(zero(T)) +Base.iszero(A::SMatrix1) = iszero(A.elt) +Base.getindex(A::SMatrix1, inds...) = A.elt +Base.size(::SMatrix1) = (1, 1) +@testset "map for Diagonal matrices (#46292)" begin + A = Diagonal([1]) + @test A isa Diagonal{Int,Vector{Int}} + @test 2*A isa Diagonal{Int,Vector{Int}} + @test A.+1 isa Matrix{Int} + # Numeric element types remain diagonal + B = map(SMatrix1, A) + @test B == fill(SMatrix1(1), 1, 1) + @test B isa Diagonal{SMatrix1{Int},Vector{SMatrix1{Int}}} + # Non-numeric element types become dense + C = map(a -> SMatrix1(string(a)), A) + @test C == fill(SMatrix1(string(1)), 1, 1) + @test C isa Matrix{SMatrix1{String}} +end + end # module TestDiagonal diff --git a/stdlib/LinearAlgebra/test/eigen.jl b/stdlib/LinearAlgebra/test/eigen.jl index 4ee1845ecc385..746b724439217 100644 --- a/stdlib/LinearAlgebra/test/eigen.jl +++ b/stdlib/LinearAlgebra/test/eigen.jl @@ -45,6 +45,16 @@ aimg = randn(n,n)/2 @test eigvecs(f) === f.vectors @test Array(f) ≈ a + for T in (Tridiagonal(a), Hermitian(Tridiagonal(a))) + f = eigen(T) + d, v = f + for i in 1:size(a,2) + @test T*v[:,i] ≈ d[i]*v[:,i] + end + @test det(T) ≈ det(f) + @test inv(T) ≈ inv(f) + end + num_fact = eigen(one(eltya)) @test num_fact.values[1] == one(eltya) h = asym @@ -61,43 +71,60 @@ aimg = randn(n,n)/2 asym_sg = view(asym, 1:n1, 1:n1) a_sg = view(a, 1:n, n1+1:n2) end - f = eigen(asym_sg, a_sg'a_sg) - @test asym_sg*f.vectors ≈ (a_sg'a_sg*f.vectors) * Diagonal(f.values) - @test f.values ≈ eigvals(asym_sg, a_sg'a_sg) - @test prod(f.values) ≈ prod(eigvals(asym_sg/(a_sg'a_sg))) atol=200ε - @test eigvecs(asym_sg, a_sg'a_sg) == f.vectors + ASG2 = a_sg'a_sg + f = eigen(asym_sg, ASG2) + @test asym_sg*f.vectors ≈ (ASG2*f.vectors) * Diagonal(f.values) + @test f.values ≈ eigvals(asym_sg, ASG2) + @test prod(f.values) ≈ prod(eigvals(asym_sg/(ASG2))) atol=200ε + @test eigvecs(asym_sg, ASG2) == f.vectors @test eigvals(f) === f.values @test eigvecs(f) === f.vectors @test_throws ErrorException f.Z - d,v = eigen(asym_sg, a_sg'a_sg) + d,v = eigen(asym_sg, ASG2) @test d == f.values @test v == f.vectors # solver for in-place U' \ A / U (#14896) if !(eltya <: Integer) for atyp in (eltya <: Real ? (Symmetric, Hermitian) : (Hermitian,)) - for utyp in (UpperTriangular, Diagonal) - A = atyp(asym_sg) - U = utyp(a_sg'a_sg) + for utyp in (UpperTriangular, Diagonal), uplo in (:L, :U) + A = atyp(asym_sg, uplo) + U = utyp(ASG2) @test UtiAUi!(copy(A), U) ≈ U' \ A / U end end end # matrices of different types (#14896) - if eltya <: Real - fs = eigen(Symmetric(asym_sg), a_sg'a_sg) - @test fs.values ≈ f.values - @test abs.(fs.vectors) ≈ abs.(f.vectors) # may change sign - gs = eigen(Symmetric(asym_sg), Diagonal(a_sg'a_sg)) - @test Symmetric(asym_sg)*gs.vectors ≈ (Diagonal(a_sg'a_sg)*gs.vectors) * Diagonal(gs.values) + D = Diagonal(ASG2) + for uplo in (:L, :U) + if eltya <: Real + fs = eigen(Symmetric(asym_sg, uplo), ASG2) + @test fs.values ≈ f.values + @test abs.(fs.vectors) ≈ abs.(f.vectors) # may change sign + gs = eigen(Symmetric(asym_sg, uplo), D) + @test Symmetric(asym_sg, uplo)*gs.vectors ≈ (D*gs.vectors) * Diagonal(gs.values) + end + fh = eigen(Hermitian(asym_sg, uplo), ASG2) + @test fh.values ≈ f.values + @test abs.(fh.vectors) ≈ abs.(f.vectors) # may change sign + gh = eigen(Hermitian(asym_sg, uplo), D) + @test Hermitian(asym_sg, uplo)*gh.vectors ≈ (D*gh.vectors) * Diagonal(gh.values) + gd = eigen(Matrix(Hermitian(ASG2, uplo)), D) + @test Hermitian(ASG2, uplo) * gd.vectors ≈ D * gd.vectors * Diagonal(gd.values) + gd = eigen(Hermitian(Tridiagonal(ASG2), uplo), D) + @test Hermitian(Tridiagonal(ASG2), uplo) * gd.vectors ≈ D * gd.vectors * Diagonal(gd.values) end - fh = eigen(Hermitian(asym_sg), a_sg'a_sg) - @test fh.values ≈ f.values - @test abs.(fh.vectors) ≈ abs.(f.vectors) # may change sign - gh = eigen(Hermitian(asym_sg), Diagonal(a_sg'a_sg)) - @test Hermitian(asym_sg)*gh.vectors ≈ (Diagonal(a_sg'a_sg)*gh.vectors) * Diagonal(gh.values) + gd = eigen(D, D) + @test all(≈(1), gd.values) + @test D * gd.vectors ≈ D * gd.vectors * Diagonal(gd.values) + gd = eigen(Matrix(D), D) + @test D * gd.vectors ≈ D * gd.vectors * Diagonal(gd.values) + gd = eigen(D, Matrix(D)) + @test D * gd.vectors ≈ D * gd.vectors * Diagonal(gd.values) + gd = eigen(Tridiagonal(ASG2), Matrix(D)) + @test Tridiagonal(ASG2) * gd.vectors ≈ D * gd.vectors * Diagonal(gd.values) end @testset "Non-symmetric generalized eigenproblem" begin if isa(a, Array) @@ -115,6 +142,9 @@ aimg = randn(n,n)/2 @test eigvecs(a1_nsg, a2_nsg; sortby = sortfunc) == f.vectors @test_throws ErrorException f.Z + g = eigen(a1_nsg, Diagonal(1:n1)) + @test a1_nsg*g.vectors ≈ (Diagonal(1:n1)*g.vectors) * Diagonal(g.values) + d,v = eigen(a1_nsg, a2_nsg; sortby = sortfunc) @test d == f.values @test v == f.vectors diff --git a/stdlib/LinearAlgebra/test/givens.jl b/stdlib/LinearAlgebra/test/givens.jl index c1d0caf7b8883..9f23fe4ffaa61 100644 --- a/stdlib/LinearAlgebra/test/givens.jl +++ b/stdlib/LinearAlgebra/test/givens.jl @@ -3,7 +3,7 @@ module TestGivens using Test, LinearAlgebra, Random -using LinearAlgebra: rmul!, lmul!, Givens +using LinearAlgebra: Givens, Rotation # Test givens rotations @testset for elty in (Float32, Float64, ComplexF32, ComplexF64) @@ -14,7 +14,7 @@ using LinearAlgebra: rmul!, lmul!, Givens end @testset for A in (raw_A, view(raw_A, 1:10, 1:10)) Ac = copy(A) - R = LinearAlgebra.Rotation(LinearAlgebra.Givens{elty}[]) + R = Rotation(Givens{elty}[]) for j = 1:8 for i = j+2:10 G, _ = givens(A, j+1, i, j) @@ -25,14 +25,19 @@ using LinearAlgebra: rmul!, lmul!, Givens @test lmul!(G,Matrix{elty}(I, 10, 10)) == [G[i,j] for i=1:10,j=1:10] @testset "transposes" begin - @test G'*G*Matrix(elty(1)I, 10, 10) ≈ Matrix(I, 10, 10) + @test (@inferred G'*G)*Matrix(elty(1)I, 10, 10) ≈ Matrix(I, 10, 10) @test (G*Matrix(elty(1)I, 10, 10))*G' ≈ Matrix(I, 10, 10) - @test copy(R')*(R*Matrix(elty(1)I, 10, 10)) ≈ Matrix(I, 10, 10) + @test (@inferred copy(R'))*(R*Matrix(elty(1)I, 10, 10)) ≈ Matrix(I, 10, 10) @test_throws ErrorException transpose(G) @test_throws ErrorException transpose(R) end end end + @test (R')' === R + @test R * A ≈ (A' * R')' ≈ lmul!(R, copy(A)) + @test A * R ≈ (R' * A')' ≈ rmul!(copy(A), R) + @test R' * A ≈ lmul!(R', copy(A)) + @test A * R' ≈ rmul!(copy(A), R') @test_throws ArgumentError givens(A, 3, 3, 2) @test_throws ArgumentError givens(one(elty),zero(elty),2,2) G, _ = givens(one(elty),zero(elty),11,12) diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 3d83e2bf91204..78cbf655933cd 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -256,8 +256,7 @@ end @test hvcat((1,1), specialmata, specialmatb) == hvcat((1,1), MA, MB) @test cat(specialmata, specialmatb; dims=(1,2)) == cat(MA, MB; dims=(1,2)) end - # Test concatenating pairwise combinations of special matrices with sparse matrices, - # dense matrices, or dense vectors + # Test concatenating pairwise combinations of special matrices with dense matrices or dense vectors densevec = fill(1., N) densemat = diagm(0 => densevec) for specialmat in specialmats diff --git a/stdlib/LinearAlgebra/test/structuredbroadcast.jl b/stdlib/LinearAlgebra/test/structuredbroadcast.jl index 4aeca31a79a03..4855446bc194b 100644 --- a/stdlib/LinearAlgebra/test/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/test/structuredbroadcast.jl @@ -200,7 +200,7 @@ end Bu2 = 2 .* Bl @test typeof(Bl2) <: Bidiagonal && Bl2.uplo == 'L' - # Example of Nested Brodacasts + # Example of Nested Broadcasts tmp = (1 .* 2) .* (Bidiagonal(1:3, 1:2, 'U') .* (3 .* 4)) .* (5 .* Bidiagonal(1:3, 1:2, 'L')) @test typeof(tmp) <: Tridiagonal diff --git a/stdlib/Logging/src/ConsoleLogger.jl b/stdlib/Logging/src/ConsoleLogger.jl index 359b4019fb17c..747f8a2b22966 100644 --- a/stdlib/Logging/src/ConsoleLogger.jl +++ b/stdlib/Logging/src/ConsoleLogger.jl @@ -117,7 +117,7 @@ function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module # Generate a text representation of the message and all key value pairs, # split into lines. msglines = [(indent=0, msg=l) for l in split(chomp(convert(String, string(message))::String), '\n')] - stream = logger.stream + stream::IO = logger.stream if !(isopen(stream)::Bool) stream = stderr end diff --git a/stdlib/Makefile b/stdlib/Makefile index d45be468626cd..7957520c31ea3 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -20,7 +20,7 @@ $(build_datarootdir)/julia/stdlib/$(VERSDIR): JLLS = DSFMT GMP CURL LIBGIT2 LLVM LIBSSH2 LIBUV MBEDTLS MPFR NGHTTP2 \ BLASTRAMPOLINE OPENBLAS OPENLIBM P7ZIP PCRE LIBSUITESPARSE ZLIB \ - LLVMUNWIND CSL UNWIND + LLVMUNWIND CSL UNWIND LLD # Initialize this with JLLs that aren't in "deps/$(LibName).version" JLL_NAMES := MozillaCACerts_jll diff --git a/stdlib/NetworkOptions.version b/stdlib/NetworkOptions.version index 483d6bd51694b..0cb2701f710e1 100644 --- a/stdlib/NetworkOptions.version +++ b/stdlib/NetworkOptions.version @@ -1,4 +1,4 @@ NETWORKOPTIONS_BRANCH = master -NETWORKOPTIONS_SHA1 = 4d3df6445bbca0556a7a9f2abb0e48ba7d774f5a +NETWORKOPTIONS_SHA1 = 8ce1e104eeddcf9c7ccb387dc4811ddb1c750cc2 NETWORKOPTIONS_GIT_URL := https://github.com/JuliaLang/NetworkOptions.jl.git NETWORKOPTIONS_TAR_URL = https://api.github.com/repos/JuliaLang/NetworkOptions.jl/tarball/$1 diff --git a/stdlib/OpenBLAS_jll/Project.toml b/stdlib/OpenBLAS_jll/Project.toml index 21fa9e9f0a0e6..f04e3491ad22b 100644 --- a/stdlib/OpenBLAS_jll/Project.toml +++ b/stdlib/OpenBLAS_jll/Project.toml @@ -1,6 +1,6 @@ name = "OpenBLAS_jll" uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.20+0" +version = "0.3.21+0" [deps] CompilerSupportLibraries_jll = "e66e0078-7015-5450-92f7-15fbd957f2ae" @@ -8,7 +8,7 @@ Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" [compat] -julia = "1.7" +julia = "1.9" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 5861552d40ae7..cc29b6aa26d2f 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = f22fa37dbc97c67e69a1dda2a3afd088c45702ce +PKG_SHA1 = 3cbbd860afd4c2a50a80a04fa229fe5cd5bddc76 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index c8c6df9179730..9f14961aa2acf 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -89,7 +89,7 @@ struct InvalidFormatStringError <: Exception end function Base.showerror(io::IO, err::InvalidFormatStringError) - io_has_color = get(io, :color, false) + io_has_color = get(io, :color, false)::Bool println(io, "InvalidFormatStringError: ", err.message) print(io, " \"", @view(err.format[begin:prevind(err.format, err.start_color)])) @@ -281,7 +281,7 @@ end @inline function fmt(buf, pos, arg, spec::Spec{T}) where {T <: Strings} leftalign, hash, width, prec = spec.leftalign, spec.hash, spec.width, spec.precision str = string(arg) - slen = textwidth(str) + (hash ? arg isa AbstractString ? 2 : 1 : 0) + slen = textwidth(str)::Int + (hash ? arg isa AbstractString ? 2 : 1 : 0) op = p = prec == -1 ? slen : min(slen, prec) if !leftalign && width > p for _ = 1:(width - p) diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index 705fcb6fa1dc5..3621fe63bcaac 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -992,8 +992,8 @@ function tree!(root::StackFrameTree{T}, all::Vector{UInt64}, lidict::Union{LineI root.count += 1 startframe = i elseif !skip - pushfirst!(build, parent) if recur === :flat || recur === :flatc + pushfirst!(build, parent) # Rewind the `parent` tree back, if this exact ip was already present *higher* in the current tree found = false for j in 1:(startframe - i) diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index 203f377c9ba63..d696c069fbdb7 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -259,6 +259,7 @@ to do so), or pressing Esc and then the key. | `^W` | Delete previous text up to the nearest whitespace | | `meta-w` | Copy the current region in the kill ring | | `meta-W` | "Kill" the current region, placing the text in the kill ring | +| `^U` | "Kill" to beginning of line, placing the text in the kill ring | | `^K` | "Kill" to end of line, placing the text in the kill ring | | `^Y` | "Yank" insert the text from the kill ring | | `meta-y` | Replace a previously yanked text with an older entry from the kill ring | @@ -413,7 +414,7 @@ Tab completion can also help completing fields: ```julia-repl julia> x = 3 + 4im; -julia> julia> x.[TAB][TAB] +julia> x.[TAB][TAB] im re julia> import UUIDs @@ -616,6 +617,20 @@ julia> REPL.activate(CustomMod) var 8 bytes Int64 ``` +## IPython mode + +It is possible to get an interface which is similar to the IPython REPL with numbered input prompts and output prefixes. This is done by calling `REPL.ipython_mode!()`. If you want to have this enabled on startup, add +```julia +atreplinit() do repl + if !isdefined(repl, :interface) + repl.interface = REPL.setup_interface(repl) + end + REPL.ipython_mode!(repl) +end +``` + +to your `startup.jl` file. + ## TerminalMenus TerminalMenus is a submodule of the Julia REPL and enables small, low-profile interactive menus in the terminal. diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index d7d929570df6e..348defe79d197 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -49,6 +49,9 @@ mutable struct Prompt <: TextInterface prompt_prefix::Union{String,Function} # Same as prefix except after the prompt prompt_suffix::Union{String,Function} + output_prefix::Union{String,Function} + output_prefix_prefix::Union{String,Function} + output_prefix_suffix::Union{String,Function} keymap_dict::Dict{Char,Any} repl::Union{AbstractREPL,Nothing} complete::CompletionProvider @@ -322,23 +325,28 @@ end # Show available completions function show_completions(s::PromptState, completions::Vector{String}) - colmax = maximum(map(length, completions)) - num_cols = max(div(width(terminal(s)), colmax+2), 1) - entries_per_col, r = divrem(length(completions), num_cols) - entries_per_col += r != 0 # skip any lines of input after the cursor cmove_down(terminal(s), input_string_newlines_aftercursor(s)) println(terminal(s)) - for row = 1:entries_per_col - for col = 0:num_cols - idx = row + col*entries_per_col - if idx <= length(completions) - cmove_col(terminal(s), (colmax+2)*col+1) + if any(Base.Fix1(occursin, '\n'), completions) + foreach(Base.Fix1(println, terminal(s)), completions) + else + colmax = 2 + maximum(length, completions; init=1) # n.b. length >= textwidth + num_cols = max(div(width(terminal(s)), colmax), 1) + n = length(completions) + entries_per_col = cld(n, num_cols) + idx = 0 + for _ in 1:entries_per_col + for col = 0:(num_cols-1) + idx += 1 + idx > n && break + cmove_col(terminal(s), colmax*col+1) print(terminal(s), completions[idx]) end + println(terminal(s)) end - println(terminal(s)) end + # make space for the prompt for i = 1:input_string_newlines(s) println(terminal(s)) @@ -1093,7 +1101,7 @@ end function edit_transpose_chars(buf::IOBuffer) # Moving left but not transpoing anything is intentional, and matches Emacs's behavior - eof(buf) && char_move_left(buf) + eof(buf) && position(buf) !== 0 && char_move_left(buf) position(buf) == 0 && return false char_move_left(buf) pos = position(buf) @@ -1447,7 +1455,6 @@ default_completion_cb(::IOBuffer) = [] default_enter_cb(_) = true write_prompt(terminal::AbstractTerminal, s::PromptState, color::Bool) = write_prompt(terminal, s.p, color) - function write_prompt(terminal::AbstractTerminal, p::Prompt, color::Bool) prefix = prompt_string(p.prompt_prefix) suffix = prompt_string(p.prompt_suffix) @@ -1459,6 +1466,17 @@ function write_prompt(terminal::AbstractTerminal, p::Prompt, color::Bool) return width end +function write_output_prefix(io::IO, p::Prompt, color::Bool) + prefix = prompt_string(p.output_prefix_prefix) + suffix = prompt_string(p.output_prefix_suffix) + print(io, prefix) + color && write(io, Base.text_colors[:bold]) + width = write_prompt(io, p.output_prefix, color) + color && write(io, Base.text_colors[:normal]) + print(io, suffix) + return width +end + # On Windows, when launching external processes, we cannot control what assumption they make on the # console mode. We thus forcibly reset the console mode at the start of the prompt to ensure they do # not leave the console mode in a corrupt state. @@ -1490,7 +1508,7 @@ end end # returns the width of the written prompt -function write_prompt(terminal::AbstractTerminal, s::Union{AbstractString,Function}, color::Bool) +function write_prompt(terminal::Union{IO, AbstractTerminal}, s::Union{AbstractString,Function}, color::Bool) @static Sys.iswindows() && _reset_console_mode() promptstr = prompt_string(s)::String write(terminal, promptstr) @@ -2586,6 +2604,9 @@ function Prompt(prompt ; prompt_prefix = "", prompt_suffix = "", + output_prefix = "", + output_prefix_prefix = "", + output_prefix_suffix = "", keymap_dict = default_keymap_dict, repl = nothing, complete = EmptyCompletionProvider(), @@ -2594,8 +2615,8 @@ function Prompt(prompt hist = EmptyHistoryProvider(), sticky = false) - return Prompt(prompt, prompt_prefix, prompt_suffix, keymap_dict, repl, - complete, on_enter, on_done, hist, sticky) + return Prompt(prompt, prompt_prefix, prompt_suffix, output_prefix, output_prefix_prefix, output_prefix_suffix, + keymap_dict, repl, complete, on_enter, on_done, hist, sticky) end run_interface(::Prompt) = nothing diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index e9291eb8042ec..c7bc30b8d4b10 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -260,7 +260,12 @@ function display(d::REPLDisplay, mime::MIME"text/plain", x) x = Ref{Any}(x) with_repl_linfo(d.repl) do io io = IOContext(io, :limit => true, :module => active_module(d)::Module) - get(io, :color, false) && write(io, answer_color(d.repl)) + if d.repl isa LineEditREPL + mistate = d.repl.mistate + mode = LineEdit.mode(mistate) + LineEdit.write_output_prefix(io, mode, get(io, :color, false)::Bool) + end + get(io, :color, false)::Bool && write(io, answer_color(d.repl)) if isdefined(d.repl, :options) && isdefined(d.repl.options, :iocontext) # this can override the :limit property set initially io = foldl(IOContext, d.repl.options.iocontext, init=io) @@ -354,8 +359,7 @@ end consumer is an optional function that takes a REPLBackend as an argument """ -function run_repl(repl::AbstractREPL, @nospecialize(consumer = x -> nothing); backend_on_current_task::Bool = true) - backend = REPLBackend() +function run_repl(repl::AbstractREPL, @nospecialize(consumer = x -> nothing); backend_on_current_task::Bool = true, backend = REPLBackend()) backend_ref = REPLBackendRef(backend) cleanup = @task try destroy(backend_ref, t) @@ -1062,7 +1066,7 @@ function setup_interface( shell_prompt_len = length(SHELL_PROMPT) help_prompt_len = length(HELP_PROMPT) - jl_prompt_regex = r"^(?:\(.+\) )?julia> " + jl_prompt_regex = r"^In \[[0-9]+\]: |^(?:\(.+\) )?julia> " pkg_prompt_regex = r"^(?:\(.+\) )?pkg> " # Canonicalize user keymap input @@ -1388,4 +1392,65 @@ function run_frontend(repl::StreamREPL, backend::REPLBackendRef) nothing end +module IPython + +using ..REPL + +__current_ast_transforms() = isdefined(Base, :active_repl_backend) ? Base.active_repl_backend.ast_transforms : REPL.repl_ast_transforms + +function repl_eval_counter(hp) + length(hp.history)-hp.start_idx +end + +function out_transform(x, repl::LineEditREPL, n::Ref{Int}) + return quote + julia_prompt = $repl.interface.modes[1] + mod = $REPL.active_module() + if !isdefined(mod, :Out) + setglobal!(mod, :Out, Dict{Int, Any}()) + end + local __temp_val = $x # workaround https://github.com/JuliaLang/julia/issues/46451 + if __temp_val !== getglobal(mod, :Out) && __temp_val !== nothing # remove this? + getglobal(mod, :Out)[$(n[])] = __temp_val + end + __temp_val + end +end + +function set_prompt(repl::LineEditREPL, n::Ref{Int}) + julia_prompt = repl.interface.modes[1] + julia_prompt.prompt = function() + n[] = repl_eval_counter(julia_prompt.hist)+1 + string("In [", n[], "]: ") + end +end + +function set_output_prefix(repl::LineEditREPL, n::Ref{Int}) + julia_prompt = repl.interface.modes[1] + if REPL.hascolor(repl) + julia_prompt.output_prefix_prefix = Base.text_colors[:red] + end + julia_prompt.output_prefix = () -> string("Out[", n[], "]: ") +end + +function __current_ast_transforms(backend) + if backend === nothing + isdefined(Base, :active_repl_backend) ? Base.active_repl_backend.ast_transforms : REPL.repl_ast_transforms + else + backend.ast_transforms + end +end + + +function ipython_mode!(repl::LineEditREPL=Base.active_repl, backend=nothing) + n = Ref{Int}(0) + set_prompt(repl, n) + set_output_prefix(repl, n) + push!(__current_ast_transforms(backend), ast -> out_transform(ast, repl, n)) + return +end +end + +import .IPython.ipython_mode! + end # module diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 83bc5fa255e9e..798ea1642639b 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -205,6 +205,7 @@ function complete_symbol(sym::String, @nospecialize(ffunc), context_module::Modu if isconcretetype(t) fields = fieldnames(t) for field in fields + isa(field, Symbol) || continue # Tuple type has ::Int field name s = string(field) if startswith(s, name) push!(suggestions, FieldCompletion(t, field)) diff --git a/stdlib/REPL/test/lineedit.jl b/stdlib/REPL/test/lineedit.jl index 4b9ba05b2b1e6..3d68ad1316e02 100644 --- a/stdlib/REPL/test/lineedit.jl +++ b/stdlib/REPL/test/lineedit.jl @@ -376,6 +376,8 @@ let buf = IOBuffer() LineEdit.edit_transpose_chars(buf) @test content(buf) == "βγαδε" + + # Transposing a one-char buffer should behave like Emacs seek(buf, 0) @inferred(LineEdit.edit_clear(buf)) edit_insert(buf, "a") @@ -385,6 +387,13 @@ let buf = IOBuffer() LineEdit.edit_transpose_chars(buf) @test content(buf) == "a" @test position(buf) == 0 + + # Transposing an empty buffer shouldn't implode + seek(buf, 0) + LineEdit.edit_clear(buf) + LineEdit.edit_transpose_chars(buf) + @test content(buf) == "" + @test position(buf) == 0 end @testset "edit_word_transpose" begin @@ -906,3 +915,17 @@ end @test get_last_word("a[b[]]") == "b" @test get_last_word("a[]") == "a[]" end + +@testset "issue #45836" begin + term = FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer()) + promptstate = REPL.LineEdit.init_state(term, REPL.LineEdit.mode(new_state())) + strings = ["abcdef", "123456", "ijklmn"] + REPL.LineEdit.show_completions(promptstate, strings) + completion = String(take!(term.out_stream)) + @test completion == "\033[0B\n\rabcdef\r\033[8C123456\r\033[16Cijklmn\n" + strings2 = ["abcdef", "123456\nijklmn"] + promptstate = REPL.LineEdit.init_state(term, REPL.LineEdit.mode(new_state())) + REPL.LineEdit.show_completions(promptstate, strings2) + completion2 = String(take!(term.out_stream)) + @test completion2 == "\033[0B\nabcdef\n123456\nijklmn\n" +end diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index fcc571d8a44ef..0312e59419b1b 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -707,6 +707,11 @@ fake_repl() do stdin_write, stdout_read, repl wait(c) @test Main.A == 2 + # Test removal of prefix in single statement paste + sendrepl2("\e[200~In [12]: A = 2.2\e[201~\n") + wait(c) + @test Main.A == 2.2 + # Test removal of prefix in multiple statement paste sendrepl2("""\e[200~ julia> mutable struct T17599; a::Int; end @@ -1548,3 +1553,37 @@ fake_repl() do stdin_write, stdout_read, repl LineEdit.edit_input(s, input_f) @test buffercontents(LineEdit.buffer(s)) == "1234αβ56γ" end + +# Non standard output_prefix, tested via `ipython_mode!` +fake_repl() do stdin_write, stdout_read, repl + repl.interface = REPL.setup_interface(repl) + + backend = REPL.REPLBackend() + repltask = @async begin + REPL.run_repl(repl; backend) + end + + REPL.ipython_mode!(repl, backend) + + global c = Condition() + sendrepl2(cmd) = write(stdin_write, "$cmd\n notify($(curmod_prefix)c)\n") + + sendrepl2("\"z\" * \"z\"\n") + wait(c) + s = String(readuntil(stdout_read, "\"zz\""; keep=true)) + @test contains(s, "In [1]") + @test contains(s, "Out[1]: \"zz\"") + + sendrepl2("\"y\" * \"y\"\n") + wait(c) + s = String(readuntil(stdout_read, "\"yy\""; keep=true)) + @test contains(s, "Out[3]: \"yy\"") + + sendrepl2("Out[1] * Out[3]\n") + wait(c) + s = String(readuntil(stdout_read, "\"zzyy\""; keep=true)) + @test contains(s, "Out[5]: \"zzyy\"") + + write(stdin_write, '\x04') + Base.wait(repltask) +end diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 5d6232e4b7626..721ea06854a80 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -293,6 +293,12 @@ let @test isempty(c) end +# issue 46800: (3,2). errors in the REPL +let + c, r = test_complete("(3,2).") + @test isempty(c) +end + # inexistent completion inside a string @test_nocompletion("Base.print(\"lol") @@ -524,7 +530,7 @@ let s = "CompletionFoo.test4(CompletionFoo.test_y_array[1]()[1], CompletionFoo.t @test c[1] == string(first(methods(Main.CompletionFoo.test4, Tuple{String, String}))) end -# Test that string escaption is handled correct +# Test that string escaping is handled correct let s = """CompletionFoo.test4("\\"",""" c, r, res = test_complete(s) @test !res diff --git a/stdlib/Random/src/RNGs.jl b/stdlib/Random/src/RNGs.jl index f79f113bc95eb..02ea1477961ac 100644 --- a/stdlib/Random/src/RNGs.jl +++ b/stdlib/Random/src/RNGs.jl @@ -466,7 +466,7 @@ end ##### Array : internal functions -# internal array-like type to circumevent the lack of flexibility with reinterpret +# internal array-like type to circumvent the lack of flexibility with reinterpret struct UnsafeView{T} <: DenseArray{T,1} ptr::Ptr{T} len::Int diff --git a/stdlib/Random/src/Random.jl b/stdlib/Random/src/Random.jl index 02bc609e55679..b9adb5ae39f54 100644 --- a/stdlib/Random/src/Random.jl +++ b/stdlib/Random/src/Random.jl @@ -215,7 +215,7 @@ end # TODO: make constraining constructors to enforce that those # types are <: Sampler{T} -##### Adapter to generate a randome value in [0, n] +##### Adapter to generate a random value in [0, n] struct LessThan{T<:Integer,S} <: Sampler{T} sup::T diff --git a/stdlib/Random/src/generation.jl b/stdlib/Random/src/generation.jl index ddbf6dce98bec..61e722a7719db 100644 --- a/stdlib/Random/src/generation.jl +++ b/stdlib/Random/src/generation.jl @@ -132,7 +132,7 @@ rand(r::AbstractRNG, sp::SamplerTrivial{<:UniformBits{T}}) where {T} = # rand_generic methods are intended to help RNG implementors with common operations # we don't call them simply `rand` as this can easily contribute to create -# amibuities with user-side methods (forcing the user to resort to @eval) +# ambiguities with user-side methods (forcing the user to resort to @eval) rand_generic(r::AbstractRNG, T::Union{Bool,Int8,UInt8,Int16,UInt16,Int32,UInt32}) = rand(r, UInt52Raw()) % T[] diff --git a/stdlib/SharedArrays/src/SharedArrays.jl b/stdlib/SharedArrays/src/SharedArrays.jl index a961be4e534b3..90de5fbac75be 100644 --- a/stdlib/SharedArrays/src/SharedArrays.jl +++ b/stdlib/SharedArrays/src/SharedArrays.jl @@ -374,7 +374,7 @@ function SharedArray{TS,N}(A::Array{TA,N}) where {TS,TA,N} copyto!(S, A) end -convert(T::Type{<:SharedArray}, a::Array) = T(a) +convert(T::Type{<:SharedArray}, a::Array) = T(a)::T function deepcopy_internal(S::SharedArray, stackdict::IdDict) haskey(stackdict, S) && return stackdict[S] diff --git a/stdlib/SparseArrays.version b/stdlib/SparseArrays.version index fde765d570f09..060aac7e89342 100644 --- a/stdlib/SparseArrays.version +++ b/stdlib/SparseArrays.version @@ -1,4 +1,4 @@ SPARSEARRAYS_BRANCH = main -SPARSEARRAYS_SHA1 = 91814c1e84421a9c43b2776fc9dc96ec25104ac8 +SPARSEARRAYS_SHA1 = 1bae96dc8f9a8ca8b7879eef4cf71e186598e982 SPARSEARRAYS_GIT_URL := https://github.com/JuliaSparse/SparseArrays.jl.git SPARSEARRAYS_TAR_URL = https://api.github.com/repos/JuliaSparse/SparseArrays.jl/tarball/$1 diff --git a/stdlib/SuiteSparse.version b/stdlib/SuiteSparse.version index 73b16ba750915..a5d7d781eff3d 100644 --- a/stdlib/SuiteSparse.version +++ b/stdlib/SuiteSparse.version @@ -1,4 +1,4 @@ SUITESPARSE_BRANCH = master -SUITESPARSE_SHA1 = ed89e0fe3d8908cede058f42f872ba60159af0a6 +SUITESPARSE_SHA1 = e8285dd13a6d5b5cf52d8124793fc4d622d07554 SUITESPARSE_GIT_URL := https://github.com/JuliaSparse/SuiteSparse.jl.git SUITESPARSE_TAR_URL = https://api.github.com/repos/JuliaSparse/SuiteSparse.jl/tarball/$1 diff --git a/stdlib/TOML/test/testfiles/valid/arrays-hetergeneous.jl b/stdlib/TOML/test/testfiles/valid/arrays-heterogeneous.jl similarity index 100% rename from stdlib/TOML/test/testfiles/valid/arrays-hetergeneous.jl rename to stdlib/TOML/test/testfiles/valid/arrays-heterogeneous.jl diff --git a/stdlib/TOML/test/testfiles/valid/arrays-hetergeneous.json b/stdlib/TOML/test/testfiles/valid/arrays-heterogeneous.json similarity index 100% rename from stdlib/TOML/test/testfiles/valid/arrays-hetergeneous.json rename to stdlib/TOML/test/testfiles/valid/arrays-heterogeneous.json diff --git a/stdlib/TOML/test/testfiles/valid/arrays-hetergeneous.toml b/stdlib/TOML/test/testfiles/valid/arrays-heterogeneous.toml similarity index 100% rename from stdlib/TOML/test/testfiles/valid/arrays-hetergeneous.toml rename to stdlib/TOML/test/testfiles/valid/arrays-heterogeneous.toml diff --git a/stdlib/TOML/test/toml_test.jl b/stdlib/TOML/test/toml_test.jl index 45fbd20dbcdab..7ad28a2b7af7b 100644 --- a/stdlib/TOML/test/toml_test.jl +++ b/stdlib/TOML/test/toml_test.jl @@ -46,7 +46,7 @@ end @test check_valid("array-string-quote-comma") @test check_valid("array-string-with-comma") @test check_valid("array-table-array-string-backslash") -@test check_valid("arrays-hetergeneous") +@test check_valid("arrays-heterogeneous") @test check_valid("arrays-nested") @test check_valid("arrays") @test check_valid("bool") diff --git a/stdlib/Tar.version b/stdlib/Tar.version index 7ba08fd461f88..8af321176ea5d 100644 --- a/stdlib/Tar.version +++ b/stdlib/Tar.version @@ -1,4 +1,4 @@ TAR_BRANCH = master -TAR_SHA1 = 56062695b92920c8b75e997fb0c8c3b015d04b78 +TAR_SHA1 = 951955b7fbe0d79e4e8a1405b6816e4081a6976d TAR_GIT_URL := https://github.com/JuliaIO/Tar.jl.git TAR_TAR_URL = https://api.github.com/repos/JuliaIO/Tar.jl/tarball/$1 diff --git a/stdlib/Test/docs/src/index.md b/stdlib/Test/docs/src/index.md index 077d350554775..1db2f1ab967f1 100644 --- a/stdlib/Test/docs/src/index.md +++ b/stdlib/Test/docs/src/index.md @@ -332,6 +332,148 @@ Test.detect_ambiguities Test.detect_unbound_args ``` +## Workflow for Testing Packages + +Using the tools available to us in the previous sections, here is a potential workflow of creating a package and adding tests to it. + +### Generating an Example Package + +For this workflow, we will create a package called `Example`: + +```julia +pkg> generate Example +shell> cd Example +shell> mkdir test +pkg> activate . +``` + +### Creating Sample Functions + +The number one requirement for testing a package is to have functionality to test. +For that, we will add some simple functions to `Example` that we can test. +Add the following to `src/Example.jl`: + +```julia +module Example + +function greet() + "Hello world!" +end + +function simple_add(a, b) + a + b +end + +function type_multiply(a::Float64, b::Float64) + a * b +end + +end +``` + +### Creating a Test Environment + +From within the root of the `Example` package, navigate to the `test` directory, activate a new environment there, and add the `Test` package to the environment: + +```julia +shell> cd test +pkg> activate . +(test) pkg> add Test +``` + +### Testing Our Package + +Now, we are ready to add tests to `Example`. +It is standard practice to create a file within the `test` directory called `runtests.jl` which contains the test sets we want to run. +Go ahead and create that file within the `test` directory and add the following code to it: + +```julia +using Example +using Test + +@testset "Example tests" begin + + @testset "Math tests" begin + include("math_tests.jl") + end + + @testset "Greeting tests" begin + include("greeting_tests.jl") + end +end +``` + +We will need to create those two included files, `math_tests.jl` and `greeting_tests.jl`, and add some tests to them. + +> **Note:** Notice how we did not have to specify add `Example` into the `test` environment's `Project.toml`. +> This is a benefit of Julia's testing system that you could [read about more here](https://pkgdocs.julialang.org/dev/creating-packages/). + +#### Writing Tests for `math_tests.jl` + +Using our knowledge of `Test.jl`, here are some example tests we could add to `math_tests.jl`: + +```julia +@testset "Testset 1" begin + @test 2 == simple_add(1, 1) + @test 3.5 == simple_add(1, 2.5) + @test_throws MethodError simple_add(1, "A") + @test_throws MethodError simple_add(1, 2, 3) +end + +@testset "Testset 2" begin + @test 1.0 == type_multiply(1.0, 1.0) + @test isa(type_multiply(2.0, 2.0), Float64) + @test_throws MethodError type_multiply(1, 2.5) +end +``` + +#### Writing Tests for `greeting_tests.jl` + +Using our knowledge of `Test.jl`, here are some example tests we could add to `math_tests.jl`: + +```julia +@testset "Testset 3" begin + @test "Hello world!" == greet() + @test_throws MethodError greet("Antonia") +end +``` + +### Testing Our Package + +Now that we have added our tests and our `runtests.jl` script in `test`, we can test our `Example` package by going back to the root of the `Example` package environment and reactivating the `Example` environment: + +```julia +shell> cd .. +pkg> activate . +``` + +From there, we can finally run our test suite as follows: + +```julia +(Example) pkg> test + Testing Example + Status `/tmp/jl_Yngpvy/Project.toml` + [fa318bd2] Example v0.1.0 `/home/src/Projects/tmp/errata/Example` + [8dfed614] Test `@stdlib/Test` + Status `/tmp/jl_Yngpvy/Manifest.toml` + [fa318bd2] Example v0.1.0 `/home/src/Projects/tmp/errata/Example` + [2a0f44e3] Base64 `@stdlib/Base64` + [b77e0a4c] InteractiveUtils `@stdlib/InteractiveUtils` + [56ddb016] Logging `@stdlib/Logging` + [d6f4376e] Markdown `@stdlib/Markdown` + [9a3f8284] Random `@stdlib/Random` + [ea8e919c] SHA `@stdlib/SHA` + [9e88b42a] Serialization `@stdlib/Serialization` + [8dfed614] Test `@stdlib/Test` + Testing Running tests... +Test Summary: | Pass Total +Example tests | 9 9 + Testing Example tests passed +``` + +And if all went correctly, you should see a similar output as above. +Using `Test.jl`, more complicated tests can be added for packages but this should ideally point developers in the direction of how to get started with testing their own created packages. + ```@meta DocTestSetup = nothing ``` diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 69714de01de50..8a3d028d51769 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1204,10 +1204,11 @@ function get_test_counts(ts::DefaultTestSet) end end ts.anynonpass = (fails + errors + c_fails + c_errors > 0) - duration = if isnothing(ts.time_end) + (; time_start, time_end) = ts + duration = if isnothing(time_end) "" else - dur_s = ts.time_end - ts.time_start + dur_s = time_end - time_start if dur_s < 60 string(round(dur_s, digits = 1), "s") else @@ -1314,7 +1315,7 @@ end # With begin/end or function call When @testset is used, with begin/end or a single function call, the macro -starts a new test set in which to evaulate the given expression. +starts a new test set in which to evaluate the given expression. If no custom testset type is given it defaults to creating a `DefaultTestSet`. `DefaultTestSet` records all the results and, if there are any `Fail`s or @@ -1333,6 +1334,9 @@ when they all pass (the default is `false`). child testsets to return immediately (the default is `false`). This can also be set globally via the env var `JULIA_TEST_FAILFAST`. +!!! compat "Julia 1.8" + `@testset foo()` requires at least Julia 1.8. + !!! compat "Julia 1.9" `failfast` requires at least Julia 1.9. @@ -1383,7 +1387,7 @@ individual tests fail. Transparent test sets do not introduce additional levels of nesting in the test set hierarchy and are passed through directly to the parent test set (with the context object appended to any failing tests.) - !!! compat "Julia 1.9" +!!! compat "Julia 1.9" `@testset let` requires at least Julia 1.9. ## Examples @@ -1518,7 +1522,7 @@ end function failfast_print() printstyled("\nFail-fast enabled:"; color = Base.error_color(), bold=true) - printstyled(" Fail or Error occured\n\n"; color = Base.error_color()) + printstyled(" Fail or Error occurred\n\n"; color = Base.error_color()) end """ @@ -2126,49 +2130,6 @@ function _check_bitarray_consistency(B::BitArray{N}) where N return true end -# 0.7 deprecations - -begin - approx_full(x::AbstractArray) = x - approx_full(x::Number) = x - approx_full(x) = full(x) - - function test_approx_eq(va, vb, Eps, astr, bstr) - va = approx_full(va) - vb = approx_full(vb) - la, lb = length(LinearIndices(va)), length(LinearIndices(vb)) - if la != lb - error("lengths of ", astr, " and ", bstr, " do not match: ", - "\n ", astr, " (length $la) = ", va, - "\n ", bstr, " (length $lb) = ", vb) - end - diff = real(zero(eltype(va))) - for (xa, xb) = zip(va, vb) - if isfinite(xa) && isfinite(xb) - diff = max(diff, abs(xa-xb)) - elseif !isequal(xa,xb) - error("mismatch of non-finite elements: ", - "\n ", astr, " = ", va, - "\n ", bstr, " = ", vb) - end - end - - if !isnan(Eps) && !(diff <= Eps) - sdiff = string("|", astr, " - ", bstr, "| <= ", Eps) - error("assertion failed: ", sdiff, - "\n ", astr, " = ", va, - "\n ", bstr, " = ", vb, - "\n difference = ", diff, " > ", Eps) - end - end - - array_eps(a::AbstractArray{Complex{T}}) where {T} = eps(float(maximum(x->(isfinite(x) ? abs(x) : T(NaN)), a))) - array_eps(a) = eps(float(maximum(x->(isfinite(x) ? abs(x) : oftype(x,NaN)), a))) - - test_approx_eq(va, vb, astr, bstr) = - test_approx_eq(va, vb, 1E4*length(LinearIndices(va))*max(array_eps(va), array_eps(vb)), astr, bstr) -end - include("logging.jl") end # module diff --git a/stdlib/Test/src/logging.jl b/stdlib/Test/src/logging.jl index 1afd726e09df4..4e444874d0fb8 100644 --- a/stdlib/Test/src/logging.jl +++ b/stdlib/Test/src/logging.jl @@ -120,9 +120,9 @@ end # Log testing tools # Failure result type for log testing -mutable struct LogTestFailure <: Result +struct LogTestFailure <: Result orig_expr - source::Union{Nothing,LineNumberNode} + source::LineNumberNode patterns logs end @@ -153,8 +153,8 @@ function record(ts::DefaultTestSet, t::LogTestFailure) println() end # Hack: convert to `Fail` so that test summarization works correctly - push!(ts.results, Fail(:test, t.orig_expr, t.logs, nothing, nothing, t.source)) - t + push!(ts.results, Fail(:test, t.orig_expr, t.logs, nothing, nothing, t.source, false)) + return t end """ diff --git a/stdlib/libLLVM_jll/Project.toml b/stdlib/libLLVM_jll/Project.toml index 0ff44a6fe7bcc..8332d68102f8e 100644 --- a/stdlib/libLLVM_jll/Project.toml +++ b/stdlib/libLLVM_jll/Project.toml @@ -1,6 +1,6 @@ name = "libLLVM_jll" uuid = "8f36deef-c2a5-5394-99ed-8e07531fb29a" -version = "14.0.5+3" +version = "14.0.6+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/libblastrampoline_jll/Project.toml b/stdlib/libblastrampoline_jll/Project.toml index 9f96421b2089a..dc5fbe9b4712d 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.1.1+0" +version = "5.2.0+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 5e4612314e8d4..604470b50e686 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -525,6 +525,10 @@ function test_primitives(::Type{T}, shape, ::Type{TestAbstractArray}) where T @test_throws MethodError convert(Union{}, X) end +@testset "CanonicalIndexError is a Exception" begin + @test Base.CanonicalIndexError <: Exception +end + mutable struct TestThrowNoGetindex{T} <: AbstractVector{T} end @testset "ErrorException if getindex is not defined" begin Base.length(::TestThrowNoGetindex) = 2 @@ -1811,3 +1815,7 @@ end a, b = zeros(2, 2, 2), zeros(2, 2) @test_broken IRUtils.fully_eliminated(_has_offset_axes, Base.typesof(a, a, b, b)) end + +# type stable [x;;] (https://github.com/JuliaLang/julia/issues/45952) +f45952(x) = [x;;] +@inferred f45952(1.0) diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 40781b71b543e..369dbc7394272 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -157,9 +157,6 @@ end ambs = detect_ambiguities(Ambig5) @test length(ambs) == 2 - -using LinearAlgebra, SparseArrays, SuiteSparse - # Test that Core and Base are free of ambiguities # not using isempty so this prints more information when it fails @testset "detect_ambiguities" begin @@ -358,7 +355,7 @@ let ambig = Ref{Int32}(0) end f35983(::Type{Int16}, ::Any) = 3 @test length(Base.methods_including_ambiguous(f35983, (Type, Type))) == 2 -@test length(Base.methods(f35983, (Type, Type))) == 2 +@test length(Base.methods(f35983, (Type, Type))) == 1 let ambig = Ref{Int32}(0) ms = Base._methods_by_ftype(Tuple{typeof(f35983), Type, Type}, nothing, -1, typemax(UInt), true, Ref{UInt}(typemin(UInt)), Ref{UInt}(typemax(UInt)), ambig) @test length(ms) == 2 @@ -398,4 +395,16 @@ end @test isempty(detect_ambiguities(M43040; recursive=true)) +cc46601(T::Type{<:Core.IntrinsicFunction}, x) = 1 +cc46601(::Type{T}, x::Number) where {T<:AbstractChar} = 2 +cc46601(T::Type{<:Nothing}, x) = 3 +cc46601(::Type{T}, x::T) where {T<:Number} = 4 +cc46601(::Type{T}, arg) where {T<:VecElement} = 5 +cc46601(::Type{T}, x::Number) where {T<:Number} = 6 +@test length(methods(cc46601, Tuple{Type{<:Integer}, Integer})) == 2 +@test length(Base.methods_including_ambiguous(cc46601, Tuple{Type{<:Integer}, Integer})) == 6 +cc46601(::Type{T}, x::Int) where {T<:AbstractString} = 7 +@test length(methods(cc46601, Tuple{Type{<:Integer}, Integer})) == 2 +@test length(Base.methods_including_ambiguous(cc46601, Tuple{Type{<:Integer}, Integer})) == 7 + nothing diff --git a/test/arrayops.jl b/test/arrayops.jl index 40473a363f41f..c2698b3c70a90 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -708,7 +708,7 @@ end ap = PermutedDimsArray(Array(a), (2,1,3)) @test strides(ap) == (3,1,12) - for A in [rand(1,2,3,4),rand(2,2,2,2),rand(5,6,5,6),rand(1,1,1,1)] + for A in [rand(1,2,3,4),rand(2,2,2,2),rand(5,6,5,6),rand(1,1,1,1), [rand(ComplexF64, 2,2) for _ in 1:2, _ in 1:3, _ in 1:2, _ in 1:4]] perm = randperm(4) @test isequal(A,permutedims(permutedims(A,perm),invperm(perm))) @test isequal(A,permutedims(permutedims(A,invperm(perm)),perm)) @@ -716,6 +716,10 @@ end @test sum(permutedims(A,perm)) ≈ sum(PermutedDimsArray(A,perm)) @test sum(permutedims(A,perm), dims=2) ≈ sum(PermutedDimsArray(A,perm), dims=2) @test sum(permutedims(A,perm), dims=(2,4)) ≈ sum(PermutedDimsArray(A,perm), dims=(2,4)) + + @test prod(permutedims(A,perm)) ≈ prod(PermutedDimsArray(A,perm)) + @test prod(permutedims(A,perm), dims=2) ≈ prod(PermutedDimsArray(A,perm), dims=2) + @test prod(permutedims(A,perm), dims=(2,4)) ≈ prod(PermutedDimsArray(A,perm), dims=(2,4)) end m = [1 2; 3 4] @@ -765,6 +769,18 @@ end @test circshift(src, 1) == src src = zeros(Bool, (4,0)) @test circshift(src, 1) == src + + # 1d circshift! (https://github.com/JuliaLang/julia/issues/46533) + a = [1:5;] + @test circshift!(a, 1) === a + @test a == circshift([1:5;], 1) == [5, 1, 2, 3, 4] + a = [1:5;] + @test circshift!(a, -2) === a + @test a == circshift([1:5;], -2) == [3, 4, 5, 1, 2] + a = [1:5;] + oa = OffsetVector(copy(a), -1) + @test circshift!(oa, 1) === oa + @test oa == circshift(OffsetVector(a, -1), 1) end @testset "circcopy" begin @@ -1136,7 +1152,7 @@ end @test isequal(setdiff([1,2,3,4], [7,8,9]), [1,2,3,4]) @test isequal(setdiff([1,2,3,4], Int64[]), Int64[1,2,3,4]) @test isequal(setdiff([1,2,3,4], [1,2,3,4,5]), Int64[]) - @test isequal(symdiff([1,2,3], [4,3,4]), [1,2]) + @test isequal(symdiff([1,2,3], [4,3,4]), [1,2,4]) @test isequal(symdiff(['e','c','a'], ['b','a','d']), ['e','c','b','d']) @test isequal(symdiff([1,2,3], [4,3], [5]), [1,2,4,5]) @test isequal(symdiff([1,2,3,4,5], [1,2,3], [3,4]), [3,5]) @@ -1485,6 +1501,9 @@ end @test isempty(eoa) end +@testset "filter curried #41173" begin + @test -5:5 |> filter(iseven) == -4:2:4 +end @testset "logical keepat!" begin # Vector a = Vector(1:10) diff --git a/test/bitset.jl b/test/bitset.jl index 6c7947ebc37af..ca8e06adc1ec4 100644 --- a/test/bitset.jl +++ b/test/bitset.jl @@ -65,11 +65,13 @@ end @test !(-1 in BitSet(1:10)) end -# # issue #8570 -# This requires 2^29 bytes of storage, which is too much for a simple test -# s = BitSet(typemax(Int32)) -# @test length(s) === 1 -# for b in s; b; end +@testset "issue #8570" begin + let s + @test 400 > @allocated s = BitSet(typemax(Int32)) + @test length(s) === 1 + @test only(s) == typemax(Int32) + end +end @testset "union!, symdiff!" begin i = BitSet([1, 2, 3]) diff --git a/test/ccall.jl b/test/ccall.jl index 3a1b6ff3db733..e3d52cc1498db 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1125,12 +1125,12 @@ struct Struct_AA64_2 v2::Float64 end -# This is a homogenious short vector aggregate +# This is a homogeneous short vector aggregate struct Struct_AA64_3 v1::VecReg{8,Int8} v2::VecReg{2,Float32} end -# This is NOT a homogenious short vector aggregate +# This is NOT a homogeneous short vector aggregate struct Struct_AA64_4 v2::VecReg{2,Float32} v1::VecReg{8,Int16} @@ -1590,6 +1590,32 @@ function caller22734(ptr) end @test caller22734(ptr22734) === 32.0 +# issue #46786 -- non-isbitstypes passed "by-value" +struct NonBits46786 + x::Union{Int16,NTuple{3,UInt8}} +end +let ptr = @cfunction(identity, NonBits46786, (NonBits46786,)) + obj1 = NonBits46786((0x01,0x02,0x03)) + obj2 = ccall(ptr, NonBits46786, (NonBits46786,), obj1) + @test obj1 === obj2 +end +let ptr = @cfunction(identity, Base.RefValue{NonBits46786}, (Base.RefValue{NonBits46786},)) + obj1 = Base.RefValue(NonBits46786((0x01,0x02,0x03))) + obj2 = ccall(ptr, Base.RefValue{NonBits46786}, (Base.RefValue{NonBits46786},), obj1) + @test obj1 !== obj2 + @test obj1.x === obj2.x +end + +mutable struct MutNonBits46786 + x::Union{Int16,NTuple{3,UInt8}} +end +let ptr = @cfunction(identity, MutNonBits46786, (MutNonBits46786,)) + obj1 = MutNonBits46786((0x01,0x02,0x03)) + obj2 = ccall(ptr, MutNonBits46786, (MutNonBits46786,), obj1) + @test obj1 !== obj2 + @test obj1.x === obj2.x +end + # 26297#issuecomment-371165725 # test that the first argument to cglobal is recognized as a tuple literal even through # macro expansion @@ -1791,7 +1817,7 @@ end str_identity = @cfunction(identity, Cstring, (Cstring,)) foo = @ccall $str_identity("foo"::Cstring)::Cstring @test unsafe_string(foo) == "foo" - # test interpolation of an expresison that returns a pointer. + # test interpolation of an expression that returns a pointer. foo = @ccall $(@cfunction(identity, Cstring, (Cstring,)))("foo"::Cstring)::Cstring @test unsafe_string(foo) == "foo" diff --git a/test/choosetests.jl b/test/choosetests.jl index 3617b4b31bfb4..95ca708b1d142 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -140,8 +140,9 @@ function choosetests(choices = []) "strings/io", "strings/types"]) # do subarray before sparse but after linalg filtertests!(tests, "subarray") - filtertests!(tests, "compiler", ["compiler/inference", "compiler/effects", - "compiler/validation", "compiler/heap", "compiler/ssair", "compiler/irpasses", + filtertests!(tests, "compiler", [ + "compiler/datastructures", "compiler/inference", "compiler/effects", + "compiler/validation", "compiler/ssair", "compiler/irpasses", "compiler/codegen", "compiler/inline", "compiler/contextual", "compiler/AbstractInterpreter", "compiler/EscapeAnalysis/local", "compiler/EscapeAnalysis/interprocedural"]) diff --git a/test/clangsa/GCPushPop.cpp b/test/clangsa/GCPushPop.cpp index f8dcfdafa5aa9..ac9f3bfb354b8 100644 --- a/test/clangsa/GCPushPop.cpp +++ b/test/clangsa/GCPushPop.cpp @@ -3,6 +3,7 @@ // RUN: clang -D__clang_gcanalyzer__ --analyze -Xanalyzer -analyzer-output=text -Xclang -load -Xclang libGCCheckerPlugin%shlibext -Xclang -verify -I%julia_home/src -I%julia_home/src/support -I%julia_home/usr/include ${CLANGSA_FLAGS} ${CPPFLAGS} ${CFLAGS} -Xclang -analyzer-checker=core,julia.GCChecker --analyzer-no-default-checks -x c++ %s #include "julia.h" +#include void missingPop() { jl_value_t *x = NULL; @@ -34,3 +35,22 @@ void jl_gc_run_finalizers_in_list(jl_ptls_t ptls, arraylist_t *list) // run_finalizer(ptls, items[i], items[i + 1]); JL_GC_POP(); } + +void safepoint(void); +bool testfunc1() JL_NOTSAFEPOINT +{ + struct implied_struct1 { // expected-note{{Tried to call method defined here}} + std::string s; + struct implied_constructor { } x; + } x; // expected-warning{{Calling potential safepoint as CXXConstructorCall from function annotated JL_NOTSAFEPOINT}} + // expected-note@-1{{Calling potential safepoint as CXXConstructorCall from function annotated JL_NOTSAFEPOINT}} + return 1; +} +bool testfunc2() JL_NOTSAFEPOINT +{ + struct implied_struct2 { // expected-note{{Tried to call method defined here}} + std::string s; + } x{""}; + return 1; // expected-warning{{Calling potential safepoint as CXXDestructorCall from function annotated JL_NOTSAFEPOINT}} + // expected-note@-1{{Calling potential safepoint as CXXDestructorCall from function annotated JL_NOTSAFEPOINT}} +} diff --git a/test/compiler/AbstractInterpreter.jl b/test/compiler/AbstractInterpreter.jl index 9250f6d22fae2..5407772cb88a4 100644 --- a/test/compiler/AbstractInterpreter.jl +++ b/test/compiler/AbstractInterpreter.jl @@ -127,14 +127,14 @@ import .CC: struct TaintLattice{PL<:AbstractLattice} <: CC.AbstractLattice parent::PL end -CC.widen(𝕃::TaintLattice) = 𝕃.parent +CC.widenlattice(𝕃::TaintLattice) = 𝕃.parent CC.is_valid_lattice(𝕃::TaintLattice, @nospecialize(elm)) = is_valid_lattice(widenlattice(𝕃), elem) || isa(elm, Taint) struct InterTaintLattice{PL<:AbstractLattice} <: CC.AbstractLattice parent::PL end -CC.widen(𝕃::InterTaintLattice) = 𝕃.parent +CC.widenlattice(𝕃::InterTaintLattice) = 𝕃.parent CC.is_valid_lattice(𝕃::InterTaintLattice, @nospecialize(elm)) = is_valid_lattice(widenlattice(𝕃), elem) || isa(elm, InterTaint) @@ -156,6 +156,9 @@ struct Taint end end Taint(@nospecialize(typ), id::Int) = Taint(typ, push!(BitSet(), id)) +function Base.:(==)(a::Taint, b::Taint) + return a.typ == b.typ && a.slots == b.slots +end struct InterTaint typ @@ -169,6 +172,9 @@ struct InterTaint end end InterTaint(@nospecialize(typ), id::Int) = InterTaint(typ, push!(BitSet(), id)) +function Base.:(==)(a::InterTaint, b::InterTaint) + return a.typ == b.typ && a.slots == b.slots +end const AnyTaint = Union{Taint, InterTaint} @@ -229,4 +235,6 @@ function CC.widenreturn(𝕃::InferenceLattice{<:InterTaintLattice}, @nospeciali return CC.widenreturn(widenlattice(𝕃), rt, bestguess, nargs, slottypes, changes) end +@test CC.tmerge(typeinf_lattice(TaintInterpreter()), Taint(Int, 1), Taint(Int, 2)) == Taint(Int, BitSet(1:2)) + # code_typed(ifelse, (Bool, Int, Int); interp=TaintInterpreter()) diff --git a/test/compiler/EscapeAnalysis/EAUtils.jl b/test/compiler/EscapeAnalysis/EAUtils.jl index 17a70faeb91b5..902af88a3b936 100644 --- a/test/compiler/EscapeAnalysis/EAUtils.jl +++ b/test/compiler/EscapeAnalysis/EAUtils.jl @@ -70,8 +70,7 @@ import Core: import .CC: InferenceResult, OptimizationState, IRCode, copy as cccopy, @timeit, convert_to_ircode, slot2reg, compact!, ssa_inlining_pass!, sroa_pass!, - adce_pass!, type_lift_pass!, JLOptions, verify_ir, verify_linetable, - SemiConcreteResult + adce_pass!, type_lift_pass!, JLOptions, verify_ir, verify_linetable import .EA: analyze_escapes, ArgEscapeCache, EscapeInfo, EscapeState, is_ipo_profitable # when working outside of Core.Compiler, @@ -177,11 +176,9 @@ function cache_escapes!(interp::EscapeAnalyzer, end function get_escape_cache(interp::EscapeAnalyzer) - return function (linfo::Union{InferenceResult,MethodInstance,SemiConcreteResult}) + return function (linfo::Union{InferenceResult,MethodInstance}) if isa(linfo, InferenceResult) ecache = get(interp.cache, linfo, nothing) - elseif isa(linfo, SemiConcreteResult) - ecache = get(interp.cache, linfo, nothing) else ecache = get(GLOBAL_ESCAPE_CACHE, linfo, nothing) end @@ -204,7 +201,7 @@ function run_passes_with_ea(interp::EscapeAnalyzer, ci::CodeInfo, sv::Optimizati cache_escapes!(interp, caller, state, cccopy(ir)) end catch err - @error "error happened within [IPO EA], insepct `Main.ir` and `Main.nargs`" + @error "error happened within [IPO EA], inspect `Main.ir` and `Main.nargs`" @eval Main (ir = $ir; nargs = $nargs) rethrow(err) end @@ -215,14 +212,14 @@ function run_passes_with_ea(interp::EscapeAnalyzer, ci::CodeInfo, sv::Optimizati interp.state = state interp.linfo = sv.linfo end - @timeit "Inlining" ir = ssa_inlining_pass!(ir, ir.linetable, sv.inlining, ci.propagate_inbounds) + @timeit "Inlining" ir = ssa_inlining_pass!(ir, sv.inlining, ci.propagate_inbounds) # @timeit "verify 2" verify_ir(ir) @timeit "compact 2" ir = compact!(ir) if caller.linfo.specTypes === interp.entry_tt && interp.optimize try @timeit "[Local EA]" state = analyze_escapes(ir, nargs, true, get_escape_cache(interp)) catch err - @error "error happened within [Local EA], insepct `Main.ir` and `Main.nargs`" + @error "error happened within [Local EA], inspect `Main.ir` and `Main.nargs`" @eval Main (ir = $ir; nargs = $nargs) rethrow(err) end diff --git a/test/compiler/contextual.jl b/test/compiler/contextual.jl index e89b56e4bf6de..b2f51b2047563 100644 --- a/test/compiler/contextual.jl +++ b/test/compiler/contextual.jl @@ -1,5 +1,8 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +# Cassette +# ======== + module MiniCassette # A minimal demonstration of the cassette mechanism. Doesn't support all the # fancy features, but sufficient to exercise this code path in the compiler. @@ -129,17 +132,12 @@ foo(i) = i+bar(Val(1)) # Check that misbehaving pure functions propagate their error Base.@pure func1() = 42 Base.@pure func2() = (this_is_an_exception; func1()) - -let method = which(func2, ()) - mi = Core.Compiler.specialize_method(method, Tuple{typeof(func2)}, Core.svec()) - mi.inInference = true -end func3() = func2() @test_throws UndefVarError func3() - -## overlay method tables +# overlay method tables +# ===================== module OverlayModule @@ -157,7 +155,7 @@ end # parametric function def @overlay mt tan(x::T) where {T} = 3 -end +end # module OverlayModule methods = Base._methods_by_ftype(Tuple{typeof(sin), Float64}, nothing, 1, Base.get_world_counter()) @test only(methods).method.module === Base.Math diff --git a/test/compiler/heap.jl b/test/compiler/datastructures.jl similarity index 56% rename from test/compiler/heap.jl rename to test/compiler/datastructures.jl index 4c8a515cf98d7..0e75cfb7ace81 100644 --- a/test/compiler/heap.jl +++ b/test/compiler/datastructures.jl @@ -1,3 +1,27 @@ +using Test + +@testset "CachedMethodTable" begin + # cache result should be separated per `limit` and `sig` + # https://github.com/JuliaLang/julia/pull/46799 + interp = Core.Compiler.NativeInterpreter() + table = Core.Compiler.method_table(interp) + sig = Tuple{typeof(*), Any, Any} + result1 = Core.Compiler.findall(sig, table; limit=-1) + result2 = Core.Compiler.findall(sig, table; limit=Core.Compiler.get_max_methods(*, @__MODULE__, interp)) + @test result1 !== Core.Compiler.missing && !Core.Compiler.isempty(result1.matches) + @test result2 === Core.Compiler.missing +end + +@testset "BitSetBoundedMinPrioritySet" begin + bsbmp = Core.Compiler.BitSetBoundedMinPrioritySet(5) + Core.Compiler.push!(bsbmp, 2) + Core.Compiler.push!(bsbmp, 2) + @test Core.Compiler.popfirst!(bsbmp) == 2 + Core.Compiler.push!(bsbmp, 1) + @test Core.Compiler.popfirst!(bsbmp) == 1 + @test Core.Compiler.isempty(bsbmp) +end + @testset "basic heap functionality" begin v = [2,3,1] @test Core.Compiler.heapify!(v, Core.Compiler.Forward) === v diff --git a/test/compiler/effects.jl b/test/compiler/effects.jl index d0ca45d98bcae..1a5043f49ddba 100644 --- a/test/compiler/effects.jl +++ b/test/compiler/effects.jl @@ -28,7 +28,7 @@ end return nothing end -# Test that ambigous calls don't accidentally get nothrow effect +# Test that ambiguous calls don't accidentally get nothrow effect ambig_effects_test(a::Int, b) = 1 ambig_effects_test(a, b::Int) = 1 ambig_effects_test(a, b) = 1 @@ -204,6 +204,9 @@ function compare_inconsistent(x::T) where T end @test !compare_inconsistent(3) +# Effect modeling for Core.compilerbarrier +@test Base.infer_effects(Base.inferencebarrier, Tuple{Any}) |> Core.Compiler.is_removable_if_unused + # allocation/access of uninitialized fields should taint the :consistent-cy struct Maybe{T} x::T @@ -348,7 +351,7 @@ end |> !Core.Compiler.is_foldable entry_to_be_invalidated('a') end -@test !Core.Compiler.builtin_nothrow(Core.get_binding_type, Any[Rational{Int}, Core.Const(:foo)], Any) +@test !Core.Compiler.builtin_nothrow(Core.Compiler.fallback_lattice, Core.get_binding_type, Any[Rational{Int}, Core.Const(:foo)], Any) # Nothrow for assignment to globals global glob_assign_int::Int = 0 @@ -367,7 +370,7 @@ end # we should taint `nothrow` if the binding doesn't exist and isn't fixed yet, # as the cached effects can be easily wrong otherwise -# since the inference curently doesn't track "world-age" of global variables +# since the inference currently doesn't track "world-age" of global variables @eval global_assignment_undefinedyet() = $(GlobalRef(@__MODULE__, :UNDEFINEDYET)) = 42 setglobal!_nothrow_undefinedyet() = setglobal!(@__MODULE__, :UNDEFINEDYET, 42) let effects = Base.infer_effects() do @@ -654,4 +657,14 @@ end # @testset "effects analysis on array construction" begin end # @testset "effects analysis on array ops" begin # Test that builtin_effects handles vararg correctly -@test !Core.Compiler.is_nothrow(Core.Compiler.builtin_effects(Core.isdefined, Any[String, Vararg{Any}], Bool)) +@test !Core.Compiler.is_nothrow(Core.Compiler.builtin_effects(Core.Compiler.fallback_lattice, Core.isdefined, Any[String, Vararg{Any}], Bool)) + +# Test that :new can be eliminated even if an sparam is unknown +struct SparamUnused{T} + x + SparamUnused(x::T) where {T} = new{T}(x) +end +mksparamunused(x) = (SparamUnused(x); nothing) +let src = code_typed1(mksparamunused, (Any,)) + @test count(isnew, src.code) == 0 +end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 514766f48b9a8..7aa8ea2b2b20e 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -379,7 +379,7 @@ struct A15259 x y end -# check that allocation was ellided +# check that allocation was elided @eval f15259(x,y) = (a = $(Expr(:new, :A15259, :x, :y)); (a.x, a.y, getfield(a,1), getfield(a, 2))) @test isempty(filter(x -> isa(x,Expr) && x.head === :(=) && isa(x.args[2], Expr) && x.args[2].head === :new, @@ -1588,6 +1588,7 @@ g23024(TT::Tuple{DataType}) = f23024(TT[1], v23024) @test g23024((UInt8,)) === 2 @test !Core.Compiler.isconstType(Type{typeof(Union{})}) # could be Core.TypeofBottom or Type{Union{}} at runtime +@test !isa(Core.Compiler.getfield_tfunc(Type{Core.TypeofBottom}, Core.Compiler.Const(:name)), Core.Compiler.Const) @test Base.return_types(supertype, (Type{typeof(Union{})},)) == Any[Any] # issue #23685 @@ -4077,16 +4078,6 @@ g_max_methods(x) = f_max_methods(x) @test Core.Compiler.return_type(g_max_methods, Tuple{Int}) === Int @test Core.Compiler.return_type(g_max_methods, Tuple{Any}) === Any -# Unit tests for BitSetBoundedMinPrioritySet -let bsbmp = Core.Compiler.BitSetBoundedMinPrioritySet(5) - Core.Compiler.push!(bsbmp, 2) - Core.Compiler.push!(bsbmp, 2) - @test Core.Compiler.popfirst!(bsbmp) == 2 - Core.Compiler.push!(bsbmp, 1) - @test Core.Compiler.popfirst!(bsbmp) == 1 - @test Core.Compiler.isempty(bsbmp) -end - # Make sure return_type_tfunc doesn't accidentally cause bad inference if used # at top level. @test let @@ -4097,7 +4088,7 @@ end == Rational # vararg-tuple comparison within `PartialStruct` # https://github.com/JuliaLang/julia/issues/44965 let t = Core.Compiler.tuple_tfunc(Any[Core.Const(42), Vararg{Any}]) - @test Core.Compiler.issimplertype(t, t) + @test Core.Compiler.issimplertype(Core.Compiler.fallback_lattice, t, t) end # check the inference convergence with an empty vartable: @@ -4170,8 +4161,8 @@ for setting = (:type, :const, :conditional) end # https://github.com/JuliaLang/julia/issues/46426 -@noinline Base.@assume_effects :nothrow typebarrier() = Base.inferencebarrier(0.0) -@noinline Base.@assume_effects :nothrow constbarrier() = Base.compilerbarrier(:const, 0.0) +@noinline typebarrier() = Base.inferencebarrier(0.0) +@noinline constbarrier() = Base.compilerbarrier(:const, 0.0) let src = code_typed1() do typebarrier() end @@ -4201,3 +4192,44 @@ end end call_pure_annotated_loop(x) = Val{pure_annotated_loop(x, 1)}() @test only(Base.return_types(call_pure_annotated_loop, Tuple{Int})) === Val{1} + +function isa_kindtype(T::Type{<:AbstractVector}) + if isa(T, DataType) + # `T` here should be inferred as `DataType` rather than `Type{<:AbstractVector}` + return T.name.name # should be inferred as ::Symbol + end + return nothing +end +@test only(Base.return_types(isa_kindtype)) === Union{Nothing,Symbol} + +invoke_concretized1(a::Int) = a > 0 ? :int : nothing +invoke_concretized1(a::Integer) = a > 0 ? "integer" : nothing +# check if `invoke(invoke_concretized1, Tuple{Integer}, ::Int)` is foldable +@test Base.infer_effects((Int,)) do a + @invoke invoke_concretized1(a::Integer) +end |> Core.Compiler.is_foldable +@test Base.return_types() do + @invoke invoke_concretized1(42::Integer) +end |> only === String + +invoke_concretized2(a::Int) = a > 0 ? :int : nothing +invoke_concretized2(a::Integer) = a > 0 ? :integer : nothing +# check if `invoke(invoke_concretized2, Tuple{Integer}, ::Int)` is foldable +@test Base.infer_effects((Int,)) do a + @invoke invoke_concretized2(a::Integer) +end |> Core.Compiler.is_foldable +@test let + Base.Experimental.@force_compile + @invoke invoke_concretized2(42::Integer) +end === :integer + +# Test that abstract_apply doesn't fail to fully infer if the result is unused +struct FiniteIteration + n::Int +end +Base.iterate(f::FiniteIteration, i::Int = 0) = i < f.n ? (i, i+1) : nothing +function unused_apply_iterate() + tuple(FiniteIteration(4)...) + return nothing +end +@test fully_eliminated(unused_apply_iterate, ()) diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 13f9a1145c10a..0e406693b21b3 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -601,7 +601,7 @@ g41299(f::Tf, args::Vararg{Any,N}) where {Tf,N} = f(args...) @test_throws TypeError g41299(>:, 1, 2) # https://github.com/JuliaLang/julia/issues/42078 -# idempotency of callsite inling +# idempotency of callsite inlining function getcache(mi::Core.MethodInstance) cache = Core.Compiler.code_cache(Core.Compiler.NativeInterpreter()) codeinf = Core.Compiler.get(cache, mi, nothing) @@ -638,7 +638,7 @@ let end begin - # more idempotency of callsite inling + # more idempotency of callsite inlining # ----------------------------------- # this test case requires forced constant propagation for callsite inlined function call, # particularly, in the following example, the inlinear will look up `+ₚ(::Point, ::Const(Point(2.25, 4.75)))` @@ -927,7 +927,7 @@ let # aggressive inlining of single, abstract method match (with constant-prop'e # both callsite should be inlined with constant-prop'ed result @test count(isinvoke(:isType), src.code) == 2 @test count(isinvoke(:has_free_typevars), src.code) == 0 - # `isGoodType(y::Any)` isn't fully convered, thus a runtime type check and fallback dynamic dispatch should be inserted + # `isGoodType(y::Any)` isn't fully covered, thus a runtime type check and fallback dynamic dispatch should be inserted @test count(iscall((src,isGoodType2)), src.code) == 1 end @@ -1184,7 +1184,8 @@ end # Test that we can inline a finalizer for a struct that does not otherwise escape @noinline nothrow_side_effect(x) = - @Base.assume_effects :total !:effect_free @ccall jl_(x::Any)::Cvoid + Base.@assume_effects :total !:effect_free @ccall jl_(x::Any)::Cvoid +@test Core.Compiler.is_finalizer_inlineable(Base.infer_effects(nothrow_side_effect, (Nothing,))) mutable struct DoAllocNoEscape function DoAllocNoEscape() @@ -1286,22 +1287,42 @@ end # Test finalizers with static parameters mutable struct DoAllocNoEscapeSparam{T} - x::T - function finalizer_sparam(d::DoAllocNoEscapeSparam{T}) where {T} + x + @inline function finalizer_sparam(d::DoAllocNoEscapeSparam{T}) where {T} nothrow_side_effect(nothing) nothrow_side_effect(T) end - function DoAllocNoEscapeSparam{T}(x::T) where {T} + @inline function DoAllocNoEscapeSparam(x::T) where {T} finalizer(finalizer_sparam, new{T}(x)) end end -DoAllocNoEscapeSparam(x::T) where {T} = DoAllocNoEscapeSparam{T}(x) let src = code_typed1(Tuple{Any}) do x for i = 1:1000 DoAllocNoEscapeSparam(x) end end - @test count(isnew, src.code) == 0 + @test count(x->isexpr(x, :static_parameter), src.code) == 0 # A bad inline might leave left-over :static_parameter + nnothrow_invokes = count(isinvoke(:nothrow_side_effect), src.code) + @test count(iscall(f->!isa(singleton_type(argextype(f, src)), Core.Builtin)), src.code) == + count(iscall((src, nothrow_side_effect)), src.code) == 2 - nnothrow_invokes + # TODO: Our effect modeling is not yet strong enough to fully eliminate this + @test_broken count(isnew, src.code) == 0 +end + +# Test finalizer varargs +function varargs_finalizer(args...) + nothrow_side_effect(args[1]) +end +mutable struct DoAllocNoEscapeNoVarargs + function DoAllocNoEscapeNoInline() + finalizer(noinline_finalizer, new()) + end +end +let src = code_typed1() do + for i = 1:1000 + DoAllocNoEscapeNoInline() + end + end end # Test noinline finalizer @@ -1344,6 +1365,206 @@ let src = code_typed1() do @test !any(isinvoke(:finalizer), src.code) end +const FINALIZATION_COUNT = Ref(0) +init_finalization_count!() = FINALIZATION_COUNT[] = 0 +get_finalization_count() = FINALIZATION_COUNT[] +@noinline add_finalization_count!(x) = FINALIZATION_COUNT[] += x +@noinline Base.@assume_effects :nothrow safeprint(io::IO, x...) = (@nospecialize; print(io, x...)) +@test Core.Compiler.is_finalizer_inlineable(Base.infer_effects(add_finalization_count!, (Int,))) + +mutable struct DoAllocWithField + x::Int + function DoAllocWithField(x::Int) + finalizer(new(x)) do this + add_finalization_count!(this.x) + end + end +end +mutable struct DoAllocWithFieldInter + x::Int +end +function register_finalizer!(obj::DoAllocWithFieldInter) + finalizer(obj) do this + add_finalization_count!(this.x) + end +end + +function const_finalization(io) + for i = 1:1000 + o = DoAllocWithField(1) + safeprint(io, o.x) + end +end +let src = code_typed1(const_finalization, (IO,)) + @test count(isinvoke(:add_finalization_count!), src.code) == 1 +end +let + init_finalization_count!() + const_finalization(IOBuffer()) + @test get_finalization_count() == 1000 +end + +# Test that finalizers that don't do anything are just erased from the IR +function useless_finalizer() + x = Ref(1) + finalizer(x) do x + nothing + end + return x +end +let src = code_typed1(useless_finalizer, ()) + @test count(iscall((src, Core.finalizer)), src.code) == 0 + @test length(src.code) == 2 +end + +# tests finalizer inlining when def/uses involve control flow +function cfg_finalization1(io) + for i = -999:1000 + o = DoAllocWithField(i) + if i == 1000 + safeprint(io, o.x, '\n') + elseif i > 0 + safeprint(io, o.x) + end + end +end +let src = code_typed1(cfg_finalization1, (IO,)) + @test count(isinvoke(:add_finalization_count!), src.code) == 1 +end +let + init_finalization_count!() + cfg_finalization1(IOBuffer()) + @test get_finalization_count() == 1000 +end + +function cfg_finalization2(io) + for i = -999:1000 + o = DoAllocWithField(1) + o.x = i # with `setfield!` + if i == 1000 + safeprint(io, o.x, '\n') + elseif i > 0 + safeprint(io, o.x) + end + end +end +let src = code_typed1(cfg_finalization2, (IO,)) + @test count(isinvoke(:add_finalization_count!), src.code) == 1 +end +let + init_finalization_count!() + cfg_finalization2(IOBuffer()) + @test get_finalization_count() == 1000 +end + +function cfg_finalization3(io) + for i = -999:1000 + o = DoAllocWithFieldInter(i) + register_finalizer!(o) + if i == 1000 + safeprint(io, o.x, '\n') + elseif i > 0 + safeprint(io, o.x) + end + end +end +let src = code_typed1(cfg_finalization3, (IO,)) + @test count(isinvoke(:add_finalization_count!), src.code) == 1 +end +let + init_finalization_count!() + cfg_finalization3(IOBuffer()) + @test get_finalization_count() == 1000 +end + +function cfg_finalization4(io) + for i = -999:1000 + o = DoAllocWithFieldInter(1) + o.x = i # with `setfield!` + register_finalizer!(o) + if i == 1000 + safeprint(io, o.x, '\n') + elseif i > 0 + safeprint(io, o.x) + end + end +end +let src = code_typed1(cfg_finalization4, (IO,)) + @test count(isinvoke(:add_finalization_count!), src.code) == 1 +end +let + init_finalization_count!() + cfg_finalization4(IOBuffer()) + @test get_finalization_count() == 1000 +end + +function cfg_finalization5(io) + for i = -999:1000 + o = DoAllocWithFieldInter(i) + if i == 1000 + safeprint(io, o.x, '\n') + elseif i > 0 + safeprint(io, o.x) + end + register_finalizer!(o) + end +end +let src = code_typed1(cfg_finalization5, (IO,)) + @test count(isinvoke(:add_finalization_count!), src.code) == 1 +end +let + init_finalization_count!() + cfg_finalization5(IOBuffer()) + @test get_finalization_count() == 1000 +end + +function cfg_finalization6(io) + for i = -999:1000 + o = DoAllocWithField(0) + if i == 1000 + o.x = i # with `setfield!` + elseif i > 0 + safeprint(io, o.x, '\n') + end + end +end +let src = code_typed1(cfg_finalization6, (IO,)) + @test count(isinvoke(:add_finalization_count!), src.code) == 1 +end +let + init_finalization_count!() + cfg_finalization6(IOBuffer()) + @test get_finalization_count() == 1000 +end + + +function cfg_finalization7(io) + for i = -999:1000 + o = DoAllocWithField(0) + o.x = 0 + if i == 1000 + o.x = i # with `setfield!` + end + o.x = i + if i == 999 + o.x = i + end + o.x = 0 + if i == 1000 + o.x = i + end + end +end +let src = code_typed1(cfg_finalization7, (IO,)) + @test count(isinvoke(:add_finalization_count!), src.code) == 1 +end +let + init_finalization_count!() + cfg_finalization7(IOBuffer()) + @test get_finalization_count() == 1000 +end + + # optimize `[push!|pushfirst!](::Vector{Any}, x...)` @testset "optimize `$f(::Vector{Any}, x...)`" for f = Any[push!, pushfirst!] @eval begin @@ -1451,3 +1672,92 @@ end @test !any(@nospecialize(x) -> isexpr(x, :call) && length(x.args) == 1, src.code) end end + +# Test that semi-concrete eval can inline constant results +function twice_sitofp(x::Int, y::Int) + x = Base.sitofp(Float64, x) + y = Base.sitofp(Float64, y) + return (x, y) +end +call_twice_sitofp(x::Int) = twice_sitofp(x, 2) + +let src = code_typed1(call_twice_sitofp, (Int,)) + @test count(iscall((src, Base.sitofp)), src.code) == 1 +end + +# Test getfield modeling of Type{Ref{_A}} where _A +@test Core.Compiler.getfield_tfunc(Type, Core.Compiler.Const(:parameters)) !== Union{} +@test !isa(Core.Compiler.getfield_tfunc(Type{Tuple{Union{Int, Float64}, Int}}, Core.Compiler.Const(:name)), Core.Compiler.Const) +@test fully_eliminated(Base.ismutable, Tuple{Base.RefValue}) + +# TODO: Remove compute sparams for vararg_retrival +fvarargN_inline(x::Tuple{Vararg{Int, N}}) where {N} = N +fvarargN_inline(args...) = fvarargN_inline(args) +let src = code_typed1(fvarargN_inline, (Tuple{Vararg{Int}},)) + @test_broken count(iscall((src, Core._compute_sparams)), src.code) == 0 && + count(iscall((src, Core._svec_ref)), src.code) == 0 && + count(iscall((src, Core.nfields)), src.code) == 1 +end + +# Test effect annotation of declined inline unionsplit +f_union_unmatched(x::Union{Nothing, Type{T}}) where {T} = nothing +let src = code_typed1((Any,)) do x + if isa(x, Union{Nothing, Type}) + f_union_unmatched(x) + end + nothing + end + @test count(iscall((src, f_union_unmatched)), src.code) == 0 +end + +# modifyfield! handling +# ===================== + +isinvokemodify(y) = @nospecialize(x) -> isinvokemodify(y, x) +isinvokemodify(sym::Symbol, @nospecialize(x)) = isinvokemodify(mi->mi.def.name===sym, x) +isinvokemodify(pred::Function, @nospecialize(x)) = isexpr(x, :invoke_modify) && pred(x.args[1]::MethodInstance) + +mutable struct Atomic{T} + @atomic x::T +end +let src = code_typed1((Atomic{Int},)) do a + @atomic a.x + 1 + end + @test count(isinvokemodify(:+), src.code) == 1 +end +let src = code_typed1((Atomic{Int},)) do a + @atomic a.x += 1 + end + @test count(isinvokemodify(:+), src.code) == 1 +end +let src = code_typed1((Atomic{Int},)) do a + @atomic a.x max 10 + end + @test count(isinvokemodify(:max), src.code) == 1 +end +# simple union split handling +mymax(x::T, y::T) where T<:Real = max(x, y) +mymax(x::T, y::Real) where T<:Real = convert(T, max(x, y))::T +let src = code_typed1((Atomic{Int},Union{Int,Float64})) do a, b + @atomic a.x mymax b + end + @test count(isinvokemodify(:mymax), src.code) == 2 +end + +# apply `ssa_inlining_pass` multiple times +let interp = Core.Compiler.NativeInterpreter() + # check if callsite `@noinline` annotation works + ir, = Base.code_ircode((Int,Int); optimize_until="inlining", interp) do a, b + @noinline a*b + end |> only + i = findfirst(isinvoke(:*), ir.stmts.inst) + @test i !== nothing + + # ok, now delete the callsite flag, and see the second inlining pass can inline the call + @eval Core.Compiler $ir.stmts[$i][:flag] &= ~IR_FLAG_NOINLINE + inlining = Core.Compiler.InliningState(Core.Compiler.OptimizationParams(interp), nothing, + Core.Compiler.code_cache(interp), interp) + ir = Core.Compiler.ssa_inlining_pass!(ir, inlining, false) + @test count(isinvoke(:*), ir.stmts.inst) == 0 + @test count(iscall((ir, Core.Intrinsics.mul_int)), ir.stmts.inst) == 1 +end diff --git a/test/compiler/irpasses.jl b/test/compiler/irpasses.jl index f39137a391b08..1e5948182adb1 100644 --- a/test/compiler/irpasses.jl +++ b/test/compiler/irpasses.jl @@ -960,7 +960,7 @@ let # effect-freeness computation for array allocation end end - # shouldn't eliminate errorneous dead allocations + # shouldn't eliminate erroneous dead allocations bad_dims = [-1, typemax(Int)] for dim in bad_dims, N in 1:10 dims = ntuple(i->dim, N) diff --git a/test/compiler/irutils.jl b/test/compiler/irutils.jl index b44a656ea7b34..76f883d6cea2c 100644 --- a/test/compiler/irutils.jl +++ b/test/compiler/irutils.jl @@ -17,7 +17,12 @@ function iscall((src, f)::Tuple{IR,Base.Callable}, @nospecialize(x)) where IR<:U singleton_type(argextype(x, src)) === f end end -iscall(pred::Base.Callable, @nospecialize(x)) = isexpr(x, :call) && pred(x.args[1]) +function iscall(pred::Base.Callable, @nospecialize(x)) + if isexpr(x, :(=)) + x = x.args[2] + end + return isexpr(x, :call) && pred(x.args[1]) +end # check if `x` is a statically-resolved call of a function whose name is `sym` isinvoke(y) = @nospecialize(x) -> isinvoke(y, x) diff --git a/test/compiler/ssair.jl b/test/compiler/ssair.jl index 1acd490a47295..ddb2fd2f13e09 100644 --- a/test/compiler/ssair.jl +++ b/test/compiler/ssair.jl @@ -5,6 +5,8 @@ using Core.IR const Compiler = Core.Compiler using .Compiler: CFG, BasicBlock, NewSSAValue +include(normpath(@__DIR__, "irutils.jl")) + make_bb(preds, succs) = BasicBlock(Compiler.StmtRange(0, 0), preds, succs) function make_ci(code) @@ -69,8 +71,10 @@ let cfg = CFG(BasicBlock[ ], Int[]) dfs = Compiler.DFS(cfg.blocks) @test dfs.from_pre[dfs.to_parent_pre[dfs.to_pre[5]]] == 4 - let correct_idoms = Compiler.naive_idoms(cfg.blocks) + let correct_idoms = Compiler.naive_idoms(cfg.blocks), + correct_pidoms = Compiler.naive_idoms(cfg.blocks, true) @test Compiler.construct_domtree(cfg.blocks).idoms_bb == correct_idoms + @test Compiler.construct_postdomtree(cfg.blocks).idoms_bb == correct_pidoms # For completeness, reverse the order of pred/succ in the CFG and verify # the answer doesn't change (it does change the which node is chosen # as the semi-dominator, since it changes the DFS numbering). @@ -82,6 +86,7 @@ let cfg = CFG(BasicBlock[ d && (blocks[5] = make_bb(reverse(blocks[5].preds), blocks[5].succs)) cfg′ = CFG(blocks, cfg.index) @test Compiler.construct_domtree(cfg′.blocks).idoms_bb == correct_idoms + @test Compiler.construct_postdomtree(cfg′.blocks).idoms_bb == correct_pidoms end end end @@ -414,3 +419,80 @@ let test_userefs(body) end + +let ir = Base.code_ircode((Bool,Any)) do c, x + println(x, 1) #1 + if c + println(x, 2) #2 + else + println(x, 3) #3 + end + println(x, 4) #4 + end |> only |> first + # IR legality check + @test length(ir.cfg.blocks) == 4 + for i = 1:4 + @test any(ir.cfg.blocks[i].stmts) do j + inst = ir.stmts[j][:inst] + iscall((ir, println), inst) && + inst.args[3] == i + end + end + # domination analysis + domtree = Core.Compiler.construct_domtree(ir.cfg.blocks) + @test Core.Compiler.dominates(domtree, 1, 2) + @test Core.Compiler.dominates(domtree, 1, 3) + @test Core.Compiler.dominates(domtree, 1, 4) + for i = 2:4 + for j = 1:4 + i == j && continue + @test !Core.Compiler.dominates(domtree, i, j) + end + end + # post domination analysis + post_domtree = Core.Compiler.construct_postdomtree(ir.cfg.blocks) + @test Core.Compiler.postdominates(post_domtree, 4, 1) + @test Core.Compiler.postdominates(post_domtree, 4, 2) + @test Core.Compiler.postdominates(post_domtree, 4, 3) + for i = 1:3 + for j = 1:4 + i == j && continue + @test !Core.Compiler.postdominates(post_domtree, i, j) + end + end +end + +@testset "issue #46967: undef stmts introduced by compaction" begin + # generate some IR + function foo(i) + j = i+42 + j == 1 ? 1 : 2 + end + ir = only(Base.code_ircode(foo, (Int,)))[1] + instructions = length(ir.stmts) + + # get the addition instruction + add_stmt = ir.stmts[1] + @test Meta.isexpr(add_stmt[:inst], :call) && add_stmt[:inst].args[3] == 42 + + # replace the addition with a slightly different one + inst = Core.Compiler.NewInstruction(Expr(:call, add_stmt[:inst].args[1], add_stmt[:inst].args[2], 999), Int) + node = Core.Compiler.insert_node!(ir, 1, inst) + Core.Compiler.setindex!(add_stmt, node, :inst) + + # perform compaction (not by calling compact! because with DCE the bug doesn't trigger) + compact = Core.Compiler.IncrementalCompact(ir) + state = Core.Compiler.iterate(compact) + while state !== nothing + state = Core.Compiler.iterate(compact, state[2]) + end + ir = Core.Compiler.complete(compact) + + # test that the inserted node was compacted + @test Core.Compiler.length(ir.new_nodes) == 0 + + # test that we performed copy propagation, but that the undef node was trimmed + @test length(ir.stmts) == instructions + + @test show(devnull, ir) === nothing +end diff --git a/test/core.jl b/test/core.jl index e409eef85233d..35b029f93da44 100644 --- a/test/core.jl +++ b/test/core.jl @@ -674,14 +674,14 @@ end f21900_cnt = 0 function f21900() for i = 1:1 - x = 0 + x_global_undefined_error = 0 end global f21900_cnt += 1 - x # should be global + x_global_undefined_error # should be global global f21900_cnt += -1000 nothing end -@test_throws UndefVarError(:x) f21900() +@test_throws UndefVarError(:x_global_undefined_error) f21900() @test f21900_cnt == 1 # use @eval so this runs as a toplevel scope block @@ -784,7 +784,7 @@ end mutable struct Type11167{T,N} end function count11167() let cache = Type11167.body.body.name.cache - return sum(i -> isassigned(cache, i), 0:length(cache)) + return count(!isnothing, cache) end end @test count11167() == 0 @@ -6914,9 +6914,9 @@ g27209(x) = f27209(x ? nothing : 1.0) # Issue 27240 @inline function foo27240() if rand(Bool) - return foo_nonexistant_27240 + return foo_nonexistent_27240 else - return bar_nonexistant_27240 + return bar_nonexistent_27240 end end bar27240() = foo27240() @@ -7831,3 +7831,9 @@ end # Correct isdefined error for isdefined of Module of Int fld f_isdefined_one(@nospecialize(x)) = isdefined(x, 1) @test (try; f_isdefined_one(@__MODULE__); catch err; err; end).got === 1 + +# Unspecialized retrieval of vararg length +fvarargN(x::Tuple{Vararg{Int, N}}) where {N} = N +fvarargN(args...) = fvarargN(args) +finvokevarargN() = Base.inferencebarrier(fvarargN)(1, 2, 3) +@test finvokevarargN() == 3 diff --git a/test/deprecation_exec.jl b/test/deprecation_exec.jl index 2f6cd34ec8b8d..4f19f9415ba29 100644 --- a/test/deprecation_exec.jl +++ b/test/deprecation_exec.jl @@ -181,7 +181,7 @@ begin #@deprecated error message # `Old{T}(args...) where {...} = new(args...)` or # `(Old{T} where {...})(args...) = new(args...)`. # Since nobody has requested this feature yet, make sure that it throws, until we - # conciously define + # consciously define @test_throws( "invalid usage of @deprecate", @eval @deprecate Foo{T} where {T <: Int} g true diff --git a/test/file.jl b/test/file.jl index e29b3099d3ed9..9f834d77799ff 100644 --- a/test/file.jl +++ b/test/file.jl @@ -42,7 +42,7 @@ if !Sys.iswindows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER # creation of symlink to directory that does not yet exist new_dir = joinpath(subdir, "new_dir") foo_file = joinpath(subdir, "new_dir", "foo") - nedlink = joinpath(subdir, "non_existant_dirlink") + nedlink = joinpath(subdir, "nonexistent_dirlink") symlink("new_dir", nedlink; dir_target=true) try readdir(nedlink) @@ -1453,7 +1453,7 @@ rm(dir) #################### mktempdir() do dir name1 = joinpath(dir, "apples") - name2 = joinpath(dir, "bannanas") + name2 = joinpath(dir, "bananas") @test !ispath(name1) @test touch(name1) == name1 @test isfile(name1) @@ -1651,7 +1651,7 @@ end if Sys.iswindows() @testset "mkdir/rm permissions" begin - # test delete permission in system folders (i.e. impliclty test chmod permissions) + # test delete permission in system folders (i.e. implicitly test chmod permissions) # issue #38433 @test withenv("TMP" => "C:\\") do mktempdir() do dir end diff --git a/test/gmp.jl b/test/gmp.jl index 1125f57b195b3..be11c70e5064f 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -227,6 +227,7 @@ let a, b @test 0 == sum(BigInt[]) isa BigInt @test prod(b) == foldl(*, b) @test 1 == prod(BigInt[]) isa BigInt + @test prod(BigInt[0, 0, 0]) == 0 # issue #46665 end @testset "Iterated arithmetic" begin diff --git a/test/intrinsics.jl b/test/intrinsics.jl index 10d3a5fedc867..dec4412ffd4d5 100644 --- a/test/intrinsics.jl +++ b/test/intrinsics.jl @@ -169,14 +169,14 @@ end @test_intrinsic Core.Intrinsics.fptoui UInt Float16(3.3) UInt(3) end -if Sys.ARCH == :aarch64 +if Sys.ARCH == :aarch64 || Sys.ARCH === :powerpc64le || Sys.ARCH === :ppc64le # On AArch64 we are following the `_Float16` ABI. Buthe these functions expect `Int16`. # TODO: SHould we have `Chalf == Int16` and `Cfloat16 == Float16`? - extendhfsf2(x::Float16) = ccall("extern __extendhfsf2", llvmcall, Float32, (Int16,), reinterpret(Int16, x)) - gnu_h2f_ieee(x::Float16) = ccall("extern __gnu_h2f_ieee", llvmcall, Float32, (Int16,), reinterpret(Int16, x)) - truncsfhf2(x::Float32) = reinterpret(Float16, ccall("extern __truncsfhf2", llvmcall, Int16, (Float32,), x)) - gnu_f2h_ieee(x::Float32) = reinterpret(Float16, ccall("extern __gnu_f2h_ieee", llvmcall, Int16, (Float32,), x)) - truncdfhf2(x::Float64) = reinterpret(Float16, ccall("extern __truncdfhf2", llvmcall, Int16, (Float64,), x)) + extendhfsf2(x::Float16) = ccall("extern __extendhfsf2", llvmcall, Float32, (UInt16,), reinterpret(UInt16, x)) + gnu_h2f_ieee(x::Float16) = ccall("extern __gnu_h2f_ieee", llvmcall, Float32, (UInt16,), reinterpret(UInt16, x)) + truncsfhf2(x::Float32) = reinterpret(Float16, ccall("extern __truncsfhf2", llvmcall, UInt16, (Float32,), x)) + gnu_f2h_ieee(x::Float32) = reinterpret(Float16, ccall("extern __gnu_f2h_ieee", llvmcall, UInt16, (Float32,), x)) + truncdfhf2(x::Float64) = reinterpret(Float16, ccall("extern __truncdfhf2", llvmcall, UInt16, (Float64,), x)) else extendhfsf2(x::Float16) = ccall("extern __extendhfsf2", llvmcall, Float32, (Float16,), x) gnu_h2f_ieee(x::Float16) = ccall("extern __gnu_h2f_ieee", llvmcall, Float32, (Float16,), x) diff --git a/test/llvmpasses/.gitignore b/test/llvmpasses/.gitignore index aa144c71f85f8..4b99de76c491b 100644 --- a/test/llvmpasses/.gitignore +++ b/test/llvmpasses/.gitignore @@ -1 +1,2 @@ /Output/ +.lit_test_times.txt \ No newline at end of file diff --git a/test/llvmpasses/late-lower-gc.ll b/test/llvmpasses/late-lower-gc.ll index cb159f17ef5e9..cbc7c1c6726a8 100644 --- a/test/llvmpasses/late-lower-gc.ll +++ b/test/llvmpasses/late-lower-gc.ll @@ -125,6 +125,29 @@ top: ; CHECK: ret i32 } +; COM: the bugs here may be caught by death-by-verify-assertion +define {} addrspace(10)* @gclift_switch({} addrspace(13)* addrspace(10)* %input, i1 %unpredictable) { + top: + %0 = call {}*** @julia.get_pgcstack() + br i1 %unpredictable, label %mid1, label %mid2 + mid1: + br label %mid2 + mid2: + %root = phi {} addrspace(13)* addrspace(10)* [ %input, %top ], [ %input, %mid1 ] + %unrelated = phi i1 [ %unpredictable, %top ], [ %unpredictable, %mid1 ] + %1 = addrspacecast {} addrspace(13)* addrspace(10)* %root to {} addrspace(13)* addrspace(11)* + %2 = bitcast {} addrspace(13)* addrspace(11)* %1 to {} addrspace(11)* + switch i1 %unpredictable, label %end [ + i1 1, label %end + i1 0, label %end + ] + end: + %phi = phi {} addrspace(11)* [ %2, %mid2 ], [ %2, %mid2 ], [ %2, %mid2 ] + %ret = bitcast {} addrspace(13)* addrspace(10)* %input to {} addrspace(10)* + ; CHECK: %gclift + ret {} addrspace(10)* %ret +} + !0 = !{i64 0, i64 23} !1 = !{!1} !2 = !{!7} ; scope list diff --git a/test/llvmpasses/pipeline-o0.jl b/test/llvmpasses/pipeline-o0.jl new file mode 100644 index 0000000000000..ff9cd0aace704 --- /dev/null +++ b/test/llvmpasses/pipeline-o0.jl @@ -0,0 +1,30 @@ +# RUN: julia --startup-file=no -O0 --check-bounds=yes %s %t -O && llvm-link -S %t/* | FileCheck %s +# RUN: julia --startup-file=no -O1 --check-bounds=yes %s %t -O && llvm-link -S %t/* | FileCheck %s +# RUN: julia --startup-file=no -O2 --check-bounds=yes %s %t -O && llvm-link -S %t/* | FileCheck %s +# RUN: julia --startup-file=no -O3 --check-bounds=yes %s %t -O && llvm-link -S %t/* | FileCheck %s + +include(joinpath("..", "testhelpers", "llvmpasses.jl")) + +# CHECK-LABEL: @julia_simple +# CHECK-NOT: julia.get_pgcstack +# CHECK: asm +# CHECK-NOT: julia.gc_alloc_obj +# CHECK: ijl_gc_pool_alloc +# COM: we want something vaguely along the lines of asm load from the fs register -> allocate bytes +function simple() + Ref(0) +end + +# CHECK-LABEL: @julia_buildarray +# CHECK-NOT: julia.write_barrier +# CHECK: gc_queue_root +function buildarray() + out = [] + for i in 1:100 + push!(out, Ref(0)) + end + out +end + +emit(simple) +emit(buildarray) diff --git a/test/llvmpasses/pipeline-o2-allocs.jl b/test/llvmpasses/pipeline-o2-allocs.jl new file mode 100644 index 0000000000000..b87ce17d4bf0c --- /dev/null +++ b/test/llvmpasses/pipeline-o2-allocs.jl @@ -0,0 +1,57 @@ +# RUN: julia --startup-file=no -O2 --check-bounds=yes %s %t -O && llvm-link -S %t/* | FileCheck %s +# RUN: julia --startup-file=no -O3 --check-bounds=yes %s %t -O && llvm-link -S %t/* | FileCheck %s + +include(joinpath("..", "testhelpers", "llvmpasses.jl")) + +# CHECK-LABEL: @julia_split +# CHECK: alloc +# CHECK-NOT: alloc +# CHECK: ret +function split(maybe) + if maybe + Ref(1) + else + Ref(2) + end +end + +# CHECK-LABEL: @julia_loop_alloc +# CHECK: phi +# CHECK-NOT: phi +function loop_alloc(N) + ref = Ref(zero(typeof(N))) + N <= zero(typeof(N)) && return ref + for i in one(typeof(N)):N + ref = Ref(i) + end + ref +end + +# CHECK-LABEL: @julia_loop_const +# CHECK-NOT: br +function loop_const() + ref = Ref(0) + for i in 1:1000 + ref = Ref(0) + end + ref +end + +# CHECK-LABEL: @julia_nopreserve +# CHECK-NOT: alloc +# CHECK-NOT: julia.gc_preserve_begin +# CHECK-NOT: julia.gc_preserve_end +function nopreserve() + ref = Ref(0) + GC.@preserve ref begin + end +end + +# COM: this cordons off the atttributes/function delarations from the actual +# COM: IR that we really want to check +# CHECK: attributes + +emit(split, Bool) +emit(loop_alloc, Int64) +emit(loop_const) +emit(nopreserve) diff --git a/test/llvmpasses/pipeline-o2.jl b/test/llvmpasses/pipeline-o2.jl new file mode 100644 index 0000000000000..85f5035a3249d --- /dev/null +++ b/test/llvmpasses/pipeline-o2.jl @@ -0,0 +1,150 @@ +# RUN: julia --startup-file=no -O2 --check-bounds=yes %s %t -O && llvm-link -S %t/* | FileCheck %s --check-prefixes=ALL +# RUN: julia --startup-file=no -O3 --check-bounds=yes %s %t -O && llvm-link -S %t/* | FileCheck %s --check-prefixes=ALL + +# RUN: julia --startup-file=no -O2 --check-bounds=no %s %t -O && llvm-link -S %t/* | FileCheck %s --check-prefixes=ALL,BC_OFF +# RUN: julia --startup-file=no -O3 --check-bounds=no %s %t -O && llvm-link -S %t/* | FileCheck %s --check-prefixes=ALL,BC_OFF + +# RUN: julia --startup-file=no -O2 --check-bounds=auto %s %t -O && llvm-link -S %t/* | FileCheck %s --check-prefixes=ALL,BC_AUTO +# RUN: julia --startup-file=no -O3 --check-bounds=auto %s %t -O && llvm-link -S %t/* | FileCheck %s --check-prefixes=ALL,BC_AUTO + +include(joinpath("..", "testhelpers", "llvmpasses.jl")) + +# COM: Ensure safe iteration over one array is not boundschecked and is vectorized + +# ALL-LABEL: @julia_iterate_read +# ALL-NOT: bounds_error +# ALL: vector.body +function iterate_read(arr) + total = zero(eltype(arr)) + for i in eachindex(arr) + total += arr[i] + end + total +end + +# ALL-LABEL: @julia_iterate_write +# ALL-NOT: bounds_error +# ALL: vector.body +function iterate_write(arr, out) + for i in eachindex(arr, out) + out[i] = arr[i] + end +end + +# ALL-LABEL: @"julia_iterate_write! +# ALL-NOT: bounds_error +# ALL: vector.body +function iterate_write!(arr) + for i in eachindex(arr) + arr[i] *= 2 + end +end + +# COM: Ensure safe iteration over multiple arrays is not boundschecked and is vectorized + +# ALL-LABEL: @julia_multiiterate_read +# ALL-NOT: bounds_error +# ALL: vector.body +function multiiterate_read(arr1, arr2) + total = zero(eltype(arr1)) + for i in eachindex(arr1, arr2) + total += arr1[i] + total += arr2[i] + end + total +end + +# ALL-LABEL: @japi1_multiiterate_write +# ALL-NOT: bounds_error +# ALL: vector.body +function multiiterate_write(arr1, arr2, arr3) + for i in eachindex(arr1, arr2, arr3) + arr3[i] += arr1[i] + arr3[i] += arr2[i] + end +end + +# ALL-LABEL: @"julia_multiiterate_write! +# ALL-NOT: bounds_error +# ALL: vector.body +function multiiterate_write!(arr1, arr2) + for i in eachindex(arr1, arr2) + arr1[i] += arr2[i] + end +end + +# COM: memset checks + +# COM: INT64 +# ALL-LABEL: define nonnull {} addrspace(10)* @julia_zeros +# ALL-NOT: bounds_error +# COM: memset is not used with bounds checks on (too late in the pipeline) +# BC_OFF: llvm.memset +# BC_AUTO: llvm.memset + +# COM: INT32 +# ALL-LABEL: define nonnull {} addrspace(10)* @julia_zeros +# ALL-NOT: bounds_error +# COM: memset is not used with bounds checks on (too late in the pipeline) +# BC_OFF: llvm.memset +# BC_AUTO: llvm.memset + +# COM: INT16 +# ALL-LABEL: define nonnull {} addrspace(10)* @julia_zeros +# ALL-NOT: bounds_error +# COM: memset is not used with bounds checks on (too late in the pipeline) +# BC_OFF: llvm.memset +# BC_AUTO: llvm.memset + +# COM: check reductive indvars/vectorization + +# ALL-LABEL: @julia_sumloop +# ALL: mul +function sumloop(N) + total = zero(typeof(N)) + for i in one(typeof(N)):N + total += i + end + total +end +# ALL-LABEL: @julia_simd_sumloop +# ALL: vector.body +function simd_sumloop(N) + total = zero(typeof(N)) + @simd for i in one(typeof(N)):N + total += i + end + total +end + +# COM: check hoisting and loop deletion functionality + +# ALL-LABEL: @julia_loopedlength +# ALL-NOT: br +# ALL: ret +function loopedlength(arr) + len = length(arr) + for i in 1:length(arr) + len = length(arr) + end + len +end + +emit(iterate_read, Vector{Int64}) +emit(iterate_write, Vector{Int64}, Vector{Int64}) +emit(iterate_write!, Vector{Int64}) + +emit(multiiterate_read, Vector{Int64}, Vector{Int64}) +emit(multiiterate_write, Vector{Int64}, Vector{Int64}, Vector{Int64}) +emit(multiiterate_write!, Vector{Int64}, Vector{Int64}) + +emit(zeros, Type{Int64}, Int64) +emit(zeros, Type{Int32}, Int64) +emit(zeros, Type{Int16}, Int64) +# COM: Int8 is hardcoded to memset anyways + +emit(sumloop, Int64) +# COM: Float64 doesn't vectorize for some reason +emit(simd_sumloop, Float32) + +emit(loopedlength, Vector{Int64}) diff --git a/test/loading.jl b/test/loading.jl index 0f5efc09973f0..d057f0b3c3702 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -662,7 +662,7 @@ finally Base.set_active_project(old_act_proj) popfirst!(LOAD_PATH) end -@test Base.pkgorigins[Base.PkgId(UUID("69145d58-7df6-11e8-0660-cf7622583916"), "TestPkg")].version == v"1.2.3" +@test pkgversion(TestPkg) == v"1.2.3" @testset "--project and JULIA_PROJECT paths should be absolutified" begin mktempdir() do dir; cd(dir) do @@ -986,7 +986,7 @@ end @test Base.locate_package(pkg, env) === nothing finally copy!(LOAD_PATH, old_load_path) - copy!(DEPOT_PATH, old_load_path) + copy!(DEPOT_PATH, old_depot_path) end end end diff --git a/test/math.jl b/test/math.jl index b7870dc72b08d..055f143cea39d 100644 --- a/test/math.jl +++ b/test/math.jl @@ -1280,7 +1280,7 @@ struct BadFloatWrapper <: AbstractFloat x::Float64 end -@testset "not impelemented errors" begin +@testset "not implemented errors" begin x = BadFloatWrapper(1.9) for f in (sin, cos, tan, sinh, cosh, tanh, atan, acos, asin, asinh, acosh, atanh, exp, log1p, expm1, log) #exp2, exp10 broken for now @test_throws MethodError f(x) diff --git a/test/misc.jl b/test/misc.jl index 8a0ad13403bcd..75055f62c4968 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -237,14 +237,16 @@ end # test that @sync is lexical (PR #27164) const x27164 = Ref(0) -do_something_async_27164() = @async(begin sleep(1); x27164[] = 2; end) +const c27164 = Base.Event() +do_something_async_27164() = @async(begin wait(c27164); x27164[] = 2; end) let t = nothing @sync begin + @async (sleep(0.1); x27164[] = 1) t = do_something_async_27164() - @async (sleep(0.05); x27164[] = 1) end @test x27164[] == 1 + notify(c27164) fetch(t) @test x27164[] == 2 end diff --git a/test/missing.jl b/test/missing.jl index 13ed684f1fc05..474e10620732f 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -529,7 +529,7 @@ end @test mapreduce(cos, *, collect(skipmissing(A))) ≈ mapreduce(cos, *, skipmissing(A)) end - # Patterns that exercize code paths for inputs with 1 or 2 non-missing values + # Patterns that exercise code paths for inputs with 1 or 2 non-missing values @test sum(skipmissing([1, missing, missing, missing])) === 1 @test sum(skipmissing([missing, missing, missing, 1])) === 1 @test sum(skipmissing([1, missing, missing, missing, 2])) === 3 diff --git a/test/numbers.jl b/test/numbers.jl index 1fa940c65b93a..926abf85b246d 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -103,7 +103,7 @@ end min = Top(T,Base.min) max = Top(T,Base.max) (==) = Top(T,_compare) - (===) = Top(T,Base.isequal) # we only use === to compare -0.0/0.0, `isequal` should be equalvient + (===) = Top(T,Base.isequal) # we only use === to compare -0.0/0.0, `isequal` should be equivalent @test minmax(3., 5.) == (3., 5.) @test minmax(5., 3.) == (3., 5.) @test minmax(3., NaN) ≣ (NaN, NaN) @@ -1071,6 +1071,15 @@ end @test Float64(10633823966279328163822077199654060033) == 1.063382396627933e37 #nextfloat(0x1p123) @test Float64(-10633823966279328163822077199654060032) == -1.0633823966279327e37 @test Float64(-10633823966279328163822077199654060033) == -1.063382396627933e37 + + # Test lsb/msb gaps of 54 (wont fit in 64 bit mantissa) + @test Float64(Int128(9007199254740993)) == 9.007199254740992e15 + @test Float64(UInt128(9007199254740993)) == 9.007199254740992e15 + # Test 2^104-1 and 2^104 (2^104 is cutoff for which case is run in the conversion algorithm) + @test Float64(Int128(20282409603651670423947251286015)) == 2.028240960365167e31 + @test Float64(Int128(20282409603651670423947251286016)) == 2.028240960365167e31 + @test Float64(UInt128(20282409603651670423947251286015)) == 2.028240960365167e31 + @test Float64(UInt128(20282409603651670423947251286016)) == 2.028240960365167e31 end @testset "Float vs Int128 comparisons" begin @test Int128(1e30) == 1e30 diff --git a/test/operators.jl b/test/operators.jl index 8192e13b73a7f..7ca958aa24fa3 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -274,6 +274,9 @@ end end @test fldmod1(4.0, 3) == fldmod1(4, 3) + + # issue 28973 + @test fld1(0.4, 0.9) == fld1(nextfloat(0.4), 0.9) == 1.0 end @testset "Fix12" begin diff --git a/test/precompile.jl b/test/precompile.jl index b453128b207a0..fc73231a3e308 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -817,6 +817,10 @@ precompile_test_harness("code caching") do dir build_stale(37) stale('c') + ## Reporting tests (unrelated to the above) + nbits(::Int8) = 8 + nbits(::Int16) = 16 + end """ ) @@ -835,6 +839,11 @@ precompile_test_harness("code caching") do dir # force precompilation useA() + ## Reporting tests + call_nbits(x::Integer) = $StaleA.nbits(x) + map_nbits() = map(call_nbits, Integer[Int8(1), Int16(1)]) + map_nbits() + end """ ) @@ -856,9 +865,12 @@ precompile_test_harness("code caching") do dir Base.compilecache(Base.PkgId(string(pkg))) end @eval using $StaleA + MA = getfield(@__MODULE__, StaleA) + Base.eval(MA, :(nbits(::UInt8) = 8)) @eval using $StaleC + invalidations = ccall(:jl_debug_method_invalidation, Any, (Cint,), 1) @eval using $StaleB - MA = getfield(@__MODULE__, StaleA) + ccall(:jl_debug_method_invalidation, Any, (Cint,), 0) MB = getfield(@__MODULE__, StaleB) MC = getfield(@__MODULE__, StaleC) world = Base.get_world_counter() @@ -883,6 +895,32 @@ precompile_test_harness("code caching") do dir m = only(methods(MC.call_buildstale)) mi = m.specializations[1] @test hasvalid(mi, world) # was compiled with the new method + + # Reporting test + @test all(i -> isassigned(invalidations, i), eachindex(invalidations)) + idxs = findall(==("insert_backedges"), invalidations) + m = only(methods(MB.call_nbits)) + idxsbits = filter(idxs) do i + mi = invalidations[i-1] + mi.def == m + end + idx = only(idxsbits) + for mi in m.specializations + mi === nothing && continue + hv = hasvalid(mi, world) + @test mi.specTypes.parameters[end] === Integer ? !hv : hv + end + + tagbad = invalidations[idx+1] + buildid = invalidations[idx+2] + @test isa(buildid, UInt64) + j = findfirst(==(tagbad), invalidations) + @test invalidations[j+1] == buildid + @test isa(invalidations[j-2], Type) + @test invalidations[j-1] == "insert_backedges_callee" + + m = only(methods(MB.map_nbits)) + @test !hasvalid(m.specializations[1], world+1) # insert_backedges invalidations also trigger their backedges end precompile_test_harness("invoke") do dir @@ -892,6 +930,8 @@ precompile_test_harness("invoke") do dir """ module $InvokeModule export f, g, h, q, fnc, gnc, hnc, qnc # nc variants do not infer to a Const + export f44320, g44320 + export getlast # f is for testing invoke that occurs within a dependency f(x::Real) = 0 f(x::Int) = x < 5 ? 1 : invoke(f, Tuple{Real}, x) @@ -910,6 +950,21 @@ precompile_test_harness("invoke") do dir # q will have some callers invalidated q(x::Integer) = 0 qnc(x::Integer) = rand()-1 + # Issue #44320 + f44320(::Int) = 1 + f44320(::Any) = 2 + g44320() = invoke(f44320, Tuple{Any}, 0) + g44320() + + # Adding new specializations should not invalidate `invoke`s + function getlast(itr) + x = nothing + for y in itr + x = y + end + return x + end + getlast(a::AbstractArray) = invoke(getlast, Tuple{Any}, a) end """) write(joinpath(dir, "$CallerModule.jl"), @@ -934,6 +989,11 @@ precompile_test_harness("invoke") do dir internalnc(x::Real) = rand()-1 internalnc(x::Int) = x < 5 ? rand()+1 : invoke(internalnc, Tuple{Real}, x) + # Issue #44320 + f44320(::Real) = 3 + + call_getlast(x) = getlast(x) + # force precompilation begin Base.Experimental.@force_compile @@ -949,6 +1009,7 @@ precompile_test_harness("invoke") do dir callqnci(3) internal(3) internalnc(3) + call_getlast([1,2,3]) end # Now that we've precompiled, invalidate with a new method that overrides the `invoke` dispatch @@ -960,6 +1021,9 @@ precompile_test_harness("invoke") do dir end """) Base.compilecache(Base.PkgId(string(CallerModule))) + @eval using $InvokeModule: $InvokeModule + MI = getfield(@__MODULE__, InvokeModule) + @eval $MI.getlast(a::UnitRange) = a.stop @eval using $CallerModule M = getfield(@__MODULE__, CallerModule) @@ -1010,6 +1074,12 @@ precompile_test_harness("invoke") do dir m = only(methods(M.callqnci)) @test m.specializations[1].specTypes == Tuple{typeof(M.callqnci), Int} + m = only(methods(M.g44320)) + @test m.specializations[1].cache.max_world == typemax(UInt) + + m = which(MI.getlast, (Any,)) + @test m.specializations[1].cache.max_world == typemax(UInt) + # Precompile specific methods for arbitrary arg types invokeme(x) = 1 invokeme(::Int) = 2 @@ -1452,5 +1522,46 @@ precompile_test_harness("__init__ cachepath") do load_path @test isa((@eval (using InitCachePath; InitCachePath)), Module) end +# Test that precompilation can handle invalidated methods created from `precompile`, +# not via backedges. +precompile_test_harness("Issue #46558") do load_path + write(joinpath(load_path, "Foo46558.jl"), + """ + module Foo46558 + foo(x::Real) = 1 + end + """) + write(joinpath(load_path, "Bar46558.jl"), + """ + module Bar46558 + using Foo46558 + precompile(Foo46558.foo, (Int,)) + end + """) + Base.compilecache(Base.PkgId("Foo46558")) + Base.compilecache(Base.PkgId("Bar46558")) + Foo = (@eval (using Foo46558; Foo46558)) + @eval ($Foo.foo)(x::Int) = 2 + Bar = (@eval (using Bar46558; Bar46558)) + @test (@eval $Foo.foo(1)) == 2 +end + +precompile_test_harness("issue #46296") do load_path + write(joinpath(load_path, "CodeInstancePrecompile.jl"), + """ + module CodeInstancePrecompile + + mi = first(methods(identity)).specializations[1] + ci = Core.CodeInstance(mi, Any, nothing, nothing, zero(Int32), typemin(UInt), + typemax(UInt), zero(UInt32), zero(UInt32), nothing, 0x00) + + __init__() = @assert ci isa Core.CodeInstance + + end + """) + Base.compilecache(Base.PkgId("CodeInstancePrecompile")) + (@eval (using CodeInstancePrecompile)) +end + empty!(Base.DEPOT_PATH) append!(Base.DEPOT_PATH, original_depot_path) diff --git a/test/ranges.jl b/test/ranges.jl index 404a908adf6b3..c4cd4664f5f95 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -518,8 +518,10 @@ end @test !(3.5 in 1:5) @test (3 in 1:5) @test (3 in 5:-1:1) - #@test (3 in 3+0*(1:5)) - #@test !(4 in 3+0*(1:5)) + @test (3 in 3 .+ 0*(1:5)) + @test !(4 in 3 .+ 0*(1:5)) + @test 0. in (0. .* (1:10)) + @test !(0.1 in (0. .* (1:10))) let r = 0.0:0.01:1.0 @test (r[30] in r) @@ -536,8 +538,17 @@ end x = (NaN16, Inf32, -Inf64, 1//0, -1//0) @test !(x in r) end + + @test 1e40 ∉ 0:1.0 # Issue #45747 + @test 1e20 ∉ 0:1e-20:1e-20 + @test 1e20 ∉ 0:1e-20 + @test 1.0 ∉ 0:1e-20:1e-20 + @test 0.5 ∉ 0:1e-20:1e-20 + @test 1 ∉ 0:1e-20:1e-20 + + @test_broken 17.0 ∈ 0:1e40 # Don't support really long ranges end - @testset "in() works across types, including non-numeric types (#21728)" begin + @testset "in() works across types, including non-numeric types (#21728 and #45646)" begin @test 1//1 in 1:3 @test 1//1 in 1.0:3.0 @test !(5//1 in 1:3) @@ -558,6 +569,22 @@ end @test !(Complex(1, 0) in Date(2017, 01, 01):Dates.Day(1):Date(2017, 01, 05)) @test !(π in Date(2017, 01, 01):Dates.Day(1):Date(2017, 01, 05)) @test !("a" in Date(2017, 01, 01):Dates.Day(1):Date(2017, 01, 05)) + + # We use Ducks because of their propensity to stand in a row and because we know + # that no additional methods (e.g. isfinite) are defined specifically for Ducks. + struct Duck + location::Int + end + Base.:+(x::Duck, y::Int) = Duck(x.location + y) + Base.:-(x::Duck, y::Int) = Duck(x.location - y) + Base.:-(x::Duck, y::Duck) = x.location - y.location + Base.isless(x::Duck, y::Duck) = isless(x.location, y.location) + + @test Duck(3) ∈ Duck(1):2:Duck(5) + @test Duck(3) ∈ Duck(5):-2:Duck(2) + @test Duck(4) ∉ Duck(5):-2:Duck(1) + @test Duck(4) ∈ Duck(1):Duck(5) + @test Duck(0) ∉ Duck(1):Duck(5) end end @testset "indexing range with empty range (#4309)" begin diff --git a/test/reduce.jl b/test/reduce.jl index 78988dbdc4225..c03013f880013 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -263,7 +263,6 @@ let x = [4,3,5,2] @test maximum(x) == 5 @test minimum(x) == 2 @test extrema(x) == (2, 5) - @test Core.Compiler.extrema(x) == (2, 5) @test maximum(abs2, x) == 25 @test minimum(abs2, x) == 4 diff --git a/test/reflection.jl b/test/reflection.jl index 1b944f7eb79f4..b6f8e17ab8419 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -1010,3 +1010,5 @@ ambig_effects_test(a, b) = 1 @test (Base.infer_effects(setfield!, ()); true) # `builtin_effects` shouldn't throw on empty `argtypes` @test (Base.infer_effects(Core.Intrinsics.arraylen, ()); true) # `intrinsic_effects` shouldn't throw on empty `argtypes` end + +@test Base._methods_by_ftype(Tuple{}, -1, Base.get_world_counter()) == Any[] diff --git a/test/reinterpretarray.jl b/test/reinterpretarray.jl index f3f28993c313a..e9803b9bd9ceb 100644 --- a/test/reinterpretarray.jl +++ b/test/reinterpretarray.jl @@ -180,7 +180,7 @@ end else @test_throws "Parent's strides" strides(reinterpret(Int64, view(A, 1:8, viewax2))) end - # non-integer-multipled classified + # non-integer-multiplied classified if mod(step(viewax2), 3) == 0 @test check_strides(reinterpret(NTuple{3,Int16}, view(A, 2:7, viewax2))) else diff --git a/test/sets.jl b/test/sets.jl index 1a86b5abd746f..b52d813623231 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -393,9 +393,10 @@ end @test symdiff(Set([1]), BitSet()) isa Set{Int} @test symdiff(BitSet([1]), Set{Int}()) isa BitSet @test symdiff([1], BitSet()) isa Vector{Int} - # symdiff must NOT uniquify - @test symdiff([1, 2, 1]) == symdiff!([1, 2, 1]) == [2] - @test symdiff([1, 2, 1], [2, 2]) == symdiff!([1, 2, 1], [2, 2]) == [2] + #symdiff does uniquify + @test symdiff([1, 2, 1]) == symdiff!([1, 2, 1]) == [1,2] + @test symdiff([1, 2, 1], [2, 2]) == symdiff!([1, 2, 1], [2, 2]) == [1] + @test symdiff([1, 2, 1], [2, 2]) == symdiff!([1, 2, 1], [2, 2]) == [1] # Base.hasfastin @test all(Base.hasfastin, Any[Dict(1=>2), Set(1), BitSet(1), 1:9, 1:2:9, diff --git a/test/show.jl b/test/show.jl index b44ba0f84d51c..30c06817bff54 100644 --- a/test/show.jl +++ b/test/show.jl @@ -769,6 +769,12 @@ let repr = sprint(show, "text/html", methods(f16580)) @test occursin("f16580(x, y...; z, w, q...)", repr) end +# Just check it doesn't error +f46594(::Vararg{T, 2}) where T = 1 +let repr = sprint(show, "text/html", first(methods(f46594))) + @test occursin("f46594(::Vararg{T, 2}) where T", replace(repr, r""=>"")) +end + function triangular_methodshow(x::T1, y::T2) where {T2<:Integer, T1<:T2} end let repr = sprint(show, "text/plain", methods(triangular_methodshow)) @@ -1269,12 +1275,6 @@ end let repr = sprint(dump, Core.svec()) @test repr == "empty SimpleVector\n" end -let sv = Core.svec(:a, :b, :c) - # unsafe replacement of :c with #undef to test handling of incomplete SimpleVectors - unsafe_store!(convert(Ptr{Ptr{Cvoid}}, Base.pointer_from_objref(sv)) + 3 * sizeof(Ptr), C_NULL) - repr = sprint(dump, sv) - @test repr == "SimpleVector\n 1: Symbol a\n 2: Symbol b\n 3: #undef\n" -end let repr = sprint(dump, sin) @test repr == "sin (function of type typeof(sin))\n" end @@ -1438,7 +1438,7 @@ struct var"#X#" end var"#f#"() = 2 struct var"%X%" end # Invalid name without '#' -# (Just to make this test more sustainable,) we don't necesssarily need to test the exact +# (Just to make this test more sustainable,) we don't necessarily need to test the exact # output format, just ensure that it prints at least the parts we expect: @test occursin(".var\"#X#\"", static_shown(var"#X#")) # Leading `.` tests it printed a module name. @test occursin(r"Set{var\"[^\"]+\"} where var\"[^\"]+\"", static_shown(Set{<:Any})) @@ -2299,6 +2299,8 @@ end @eval f1(var"a.b") = 3 @test occursin("f1(var\"a.b\")", sprint(_show, methods(f1))) + @test sprint(_show, Method[]) == "0-element Vector{Method}" + italic(s) = mime == MIME("text/html") ? "$s" : s @eval f2(; var"123") = 5 @@ -2410,3 +2412,70 @@ end @test isempty(read(f, String)) # make sure we don't unnecessarily lean anything into `stdout` end end + +@testset "IRCode: fix coloring of invalid SSA values" begin + # get some ir + function foo(i) + j = i+42 + j == 1 ? 1 : 2 + end + ir = only(Base.code_ircode(foo, (Int,)))[1] + + # replace an instruction + add_stmt = ir.stmts[1] + inst = Core.Compiler.NewInstruction(Expr(:call, add_stmt[:inst].args[1], add_stmt[:inst].args[2], 999), Int) + node = Core.Compiler.insert_node!(ir, 1, inst) + Core.Compiler.setindex!(add_stmt, node, :inst) + + # the new node should be colored green (as it's uncompacted IR), + # and its uses shouldn't be colored at all (since they're just plain valid references) + str = sprint(; context=:color=>true) do io + show(io, ir) + end + @test contains(str, "\e[32m%6 =") + @test contains(str, "%1 = %6") + + # if we insert an invalid node, it should be colored appropriately + Core.Compiler.setindex!(add_stmt, Core.Compiler.SSAValue(node.id+1), :inst) + str = sprint(; context=:color=>true) do io + show(io, ir) + end + @test contains(str, "%1 = \e[31m%7") +end + +@testset "issue #46947: IncrementalCompact double display of just-compacted nodes" begin + # get some IR + foo(i) = i == 1 ? 1 : 2 + ir = only(Base.code_ircode(foo, (Int,)))[1] + + instructions = length(ir.stmts) + lines_shown(obj) = length(findall('\n', sprint(io->show(io, obj)))) + @test lines_shown(ir) == instructions + + # insert a couple of instructions + let inst = Core.Compiler.NewInstruction(Expr(:identity, 1), Nothing) + Core.Compiler.insert_node!(ir, 2, inst) + end + let inst = Core.Compiler.NewInstruction(Expr(:identity, 2), Nothing) + Core.Compiler.insert_node!(ir, 2, inst) + end + let inst = Core.Compiler.NewInstruction(Expr(:identity, 3), Nothing) + Core.Compiler.insert_node!(ir, 4, inst) + end + instructions += 3 + @test lines_shown(ir) == instructions + + # compact the IR, ensuring we always show the same number of lines + # (the instructions + a separator line) + compact = Core.Compiler.IncrementalCompact(ir) + @test lines_shown(compact) == instructions + 1 + state = Core.Compiler.iterate(compact) + while state !== nothing + @test lines_shown(compact) == instructions + 1 + state = Core.Compiler.iterate(compact, state[2]) + end + @test lines_shown(compact) == instructions + 1 + + ir = Core.Compiler.complete(compact) + @test lines_shown(compact) == instructions + 1 +end diff --git a/test/strings/io.jl b/test/strings/io.jl index 91ad83b24e328..af63362db2c0d 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -190,8 +190,8 @@ end @testset "sprint with context" begin function f(io::IO) - println(io, "compact => ", get(io, :compact, false)) - println(io, "limit => ", get(io, :limit, false)) + println(io, "compact => ", get(io, :compact, false)::Bool) + println(io, "limit => ", get(io, :limit, false)::Bool) end str = sprint(f) diff --git a/test/subtype.jl b/test/subtype.jl index 51b0875acb6a7..9a4a5cce5e323 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1834,9 +1834,6 @@ end Type{Some{T}} where T, Union{}) -# issue #24333 -@test_broken (Type{Union{Ref,Cvoid}} <: Type{Union{T,Cvoid}} where T) - # issue #38423 let Either{L, R} = Union{Ref{L}, Val{R}} @@ -2171,3 +2168,84 @@ let @test env_tuple(TT2, TT0) === Base.setindex(all_var(TT0), Int, 1) @test env_tuple(TT2, TT1) === Base.setindex(all_var(TT1), Int, 2) end + +#issue #46735 +T46735{B<:Real} = Pair{<:Union{B, Val{<:B}}, <:Union{AbstractMatrix{B}, AbstractMatrix{Vector{B}}}} +@testintersect(T46735{B} where {B}, T46735, !Union{}) +@testintersect(T46735{B} where {B<:Integer}, T46735, !Union{}) +S46735{B<:Val, M<:AbstractMatrix} = Tuple{<:Union{B, <:Val{<:B}},M,<:(Union{AbstractMatrix{B}, AbstractMatrix{<:Vector{<:B}}})} +@testintersect(S46735{B} where {B}, S46735, !Union{}) +@testintersect(S46735{B, M} where {B, M}, S46735, !Union{}) +A46735{B<:Val, M<:AbstractMatrix} = Tuple{<:Union{B, <:Val{<:B}},M,Union{AbstractMatrix{B}, AbstractMatrix{<:Vector{<:B}}}} +@testintersect(A46735{B} where {B}, A46735, !Union{}) +@testintersect(A46735{B, M} where {B, M}, A46735, !Union{}) + +#issue #46871 #38497 +struct A46871{T, N, M} <: AbstractArray{T, N} end +struct B46871{T, N} <: Ref{A46871{T, N, N}} end +for T in (B46871{Int, N} where {N}, B46871{Int}) # intentional duplication + @testintersect(T, Ref{<:AbstractArray{<:Real, 3}}, B46871{Int, 3}) +end +abstract type C38497{e,g<:Tuple,i} end +struct Q38497{o,e<:NTuple{o},g} <: C38497{e,g,Array{o}} end +@testintersect(Q38497{<:Any, Tuple{Int}}, C38497, Q38497{1, Tuple{Int}, <:Tuple}) + +#issue #33138 +@test Vector{Vector{Tuple{T,T}} where Int<:T<:Int} <: Vector{Vector{Tuple{S1,S1} where S<:S1<:S}} where S + +#issue #46970 +@test only(intersection_env(Union{S, Matrix{Int}} where S<:Matrix, Matrix)[2]) isa TypeVar +T46784{B<:Val, M<:AbstractMatrix} = Tuple{<:Union{B, <:Val{<:B}}, M, Union{AbstractMatrix{B}, AbstractMatrix{<:Vector{<:B}}}} +@testintersect(T46784{T,S} where {T,S}, T46784, !Union{}) +@test_broken T46784 <: T46784{T,S} where {T,S} + +@testset "known subtype/intersect issue" begin + #issue 45874 + let S = Pair{Val{P}, AbstractVector{<:Union{P,<:AbstractMatrix{P}}}} where P, + T = Pair{Val{R}, AbstractVector{<:Union{P,<:AbstractMatrix{P}}}} where {P,R} + @test_broken S <: T + @test_broken typeintersect(S,T) === S + end + + #issue 44395 + @test_broken typeintersect( + Tuple{Type{T}, T} where {T <: Vector{Union{T, R}} where {R<:Real, T<:Real}}, + Tuple{Type{Vector{Union{T, R}}}, Matrix{Union{T, R}}} where {R<:Real, T<:Real}, + ) === Union{} + + #issue 41561 + @test_broken typeintersect(Tuple{Vector{VT}, Vector{VT}} where {N1, VT<:AbstractVector{N1}}, + Tuple{Vector{VN} where {N, VN<:AbstractVector{N}}, Vector{Vector{Float64}}}) !== Union{} + #issue 40865 + @test_broken Tuple{Set{Ref{Int}}, Set{Ref{Int}}} <: Tuple{Set{KV}, Set{K}} where {K,KV<:Union{K,Ref{K}}} + @test_broken Tuple{Set{Val{Int}}, Set{Val{Int}}} <: Tuple{Set{KV}, Set{K}} where {K,KV<:Union{K,Val{K}}} + + #issue 39099 + A = Tuple{Tuple{Int, Int, Vararg{Int, N}}, Tuple{Int, Vararg{Int, N}}, Tuple{Vararg{Int, N}}} where N + B = Tuple{NTuple{N, Int}, NTuple{N, Int}, NTuple{N, Int}} where N + @test_broken !(A <: B) + + #issue 36185 + @test_broken typeintersect((Tuple{Type{T},Array{Union{T,Missing},N}} where {T,N}), + (Tuple{Type{T},Array{Union{T,Nothing},N}} where {T,N})) <: Any + + #issue 35698 + @test_broken typeintersect(Type{Tuple{Array{T,1} where T}}, UnionAll) + + #issue 33137 + @test_broken (Tuple{Q,Int} where Q<:Int) <: Tuple{T,T} where T + + #issue 26487 + @test_broken typeintersect(Tuple{Type{Tuple{T,Val{T}}}, Val{T}} where T, Tuple{Type{Tuple{Val{T},T}}, Val{T}} where T) <: Any + + # issue 24333 + @test_broken (Type{Union{Ref,Cvoid}} <: Type{Union{T,Cvoid}} where T) + + # issue 22123 + t1 = Ref{Ref{Ref{Union{Int64, T}}} where T} + t2 = Ref{Ref{Ref{Union{T, S}}} where T} where S + @test_broken t1 <: t2 + + # issue 21153 + @test_broken (Tuple{T1,T1} where T1<:(Val{T2} where T2)) <: (Tuple{Val{S},Val{S}} where S) +end diff --git a/test/testdefs.jl b/test/testdefs.jl index 1d36d8893e199..0f8ef610d02c8 100644 --- a/test/testdefs.jl +++ b/test/testdefs.jl @@ -21,7 +21,44 @@ function runtests(name, path, isolate=true; seed=nothing) res_and_time_data = @timed @testset "$name" begin # Random.seed!(nothing) will fail seed != nothing && Random.seed!(seed) + + original_depot_path = copy(Base.DEPOT_PATH) + original_load_path = copy(Base.LOAD_PATH) + original_env = copy(ENV) + Base.include(m, "$path.jl") + + if Base.DEPOT_PATH != original_depot_path + msg = "The `$(name)` test set mutated Base.DEPOT_PATH and did not restore the original values" + @error( + msg, + original_depot_path, + Base.DEPOT_PATH, + testset_name = name, + testset_path = path, + ) + error(msg) + end + if Base.LOAD_PATH != original_load_path + msg = "The `$(name)` test set mutated Base.LOAD_PATH and did not restore the original values" + @error( + msg, + original_load_path, + Base.LOAD_PATH, + testset_name = name, + testset_path = path, + ) + error(msg) + end + if copy(ENV) != original_env + msg = "The `$(name)` test set mutated ENV and did not restore the original values" + @error( + msg, + testset_name = name, + testset_path = path, + ) + error(msg) + end end rss = Sys.maxrss() #res_and_time_data[1] is the testset diff --git a/test/testhelpers/Furlongs.jl b/test/testhelpers/Furlongs.jl index 8ac22c6244cd3..15950a9f9ca4b 100644 --- a/test/testhelpers/Furlongs.jl +++ b/test/testhelpers/Furlongs.jl @@ -25,15 +25,15 @@ Base.promote_type(::Type{Furlong{p,T}}, ::Type{Furlong{p,S}}) where {p,T,S} = Furlong{p,promote_type(T,S)} # only Furlong{0} forms a ring and isa Number -Base.convert(::Type{T}, y::Number) where {T<:Furlong{0}} = T(y) +Base.convert(::Type{T}, y::Number) where {T<:Furlong{0}} = T(y)::T Base.convert(::Type{Furlong}, y::Number) = Furlong{0}(y) Base.convert(::Type{Furlong{<:Any,T}}, y::Number) where {T<:Number} = Furlong{0,T}(y) Base.convert(::Type{T}, y::Number) where {T<:Furlong} = typeassert(y, T) # throws, since cannot convert a Furlong{0} to a Furlong{p} # other Furlong{p} form a group -Base.convert(::Type{T}, y::Furlong) where {T<:Furlong{0}} = T(y) +Base.convert(::Type{T}, y::Furlong) where {T<:Furlong{0}} = T(y)::T Base.convert(::Type{Furlong}, y::Furlong) = y Base.convert(::Type{Furlong{<:Any,T}}, y::Furlong{p}) where {p,T<:Number} = Furlong{p,T}(y) -Base.convert(::Type{T}, y::Furlong) where {T<:Furlong} = T(y) +Base.convert(::Type{T}, y::Furlong) where {T<:Furlong} = T(y)::T Base.one(x::Furlong{p,T}) where {p,T} = one(T) Base.one(::Type{Furlong{p,T}}) where {p,T} = one(T) diff --git a/test/worlds.jl b/test/worlds.jl index 93445e07699c0..3c60f006faef2 100644 --- a/test/worlds.jl +++ b/test/worlds.jl @@ -226,13 +226,13 @@ g38435(x) = f38435(x, x) f38435(::Int, ::Int) = 3.0 @test g38435(1) === 3.0 +# Invalidation +# ============ -## Invalidation tests - -function instance(f, types) +function method_instance(f, types=Base.default_tt(f)) m = which(f, types) inst = nothing - tt = Tuple{typeof(f), types...} + tt = Base.signature_type(f, types) specs = m.specializations if isa(specs, Nothing) elseif isa(specs, Core.SimpleVector) @@ -290,30 +290,30 @@ f35855(::Float64) = 2 applyf35855([1]) applyf35855([1.0]) applyf35855(Any[1]) -wint = worlds(instance(applyf35855, (Vector{Int},))) -wfloat = worlds(instance(applyf35855, (Vector{Float64},))) -wany2 = worlds(instance(applyf35855, (Vector{Any},))) +wint = worlds(method_instance(applyf35855, (Vector{Int},))) +wfloat = worlds(method_instance(applyf35855, (Vector{Float64},))) +wany2 = worlds(method_instance(applyf35855, (Vector{Any},))) src2 = code_typed(applyf35855, (Vector{Any},))[1] f35855(::String) = 3 applyf35855(Any[1]) -@test worlds(instance(applyf35855, (Vector{Int},))) == wint -@test worlds(instance(applyf35855, (Vector{Float64},))) == wfloat -wany3 = worlds(instance(applyf35855, (Vector{Any},))) +@test worlds(method_instance(applyf35855, (Vector{Int},))) == wint +@test worlds(method_instance(applyf35855, (Vector{Float64},))) == wfloat +wany3 = worlds(method_instance(applyf35855, (Vector{Any},))) src3 = code_typed(applyf35855, (Vector{Any},))[1] @test !(wany3 == wany2) || equal(src3, src2) # code doesn't change unless you invalidate f35855(::AbstractVector) = 4 applyf35855(Any[1]) -wany4 = worlds(instance(applyf35855, (Vector{Any},))) +wany4 = worlds(method_instance(applyf35855, (Vector{Any},))) src4 = code_typed(applyf35855, (Vector{Any},))[1] @test !(wany4 == wany3) || equal(src4, src3) # code doesn't change unless you invalidate f35855(::Dict) = 5 applyf35855(Any[1]) -wany5 = worlds(instance(applyf35855, (Vector{Any},))) +wany5 = worlds(method_instance(applyf35855, (Vector{Any},))) src5 = code_typed(applyf35855, (Vector{Any},))[1] @test (wany5 == wany4) == equal(src5, src4) f35855(::Set) = 6 # with current settings, this shouldn't invalidate applyf35855(Any[1]) -wany6 = worlds(instance(applyf35855, (Vector{Any},))) +wany6 = worlds(method_instance(applyf35855, (Vector{Any},))) src6 = code_typed(applyf35855, (Vector{Any},))[1] @test wany6 == wany5 @test equal(src6, src5) @@ -322,11 +322,11 @@ applyf35855_2(c) = f35855_2(c[1]) f35855_2(::Int) = 1 f35855_2(::Float64) = 2 applyf35855_2(Any[1]) -wany3 = worlds(instance(applyf35855_2, (Vector{Any},))) +wany3 = worlds(method_instance(applyf35855_2, (Vector{Any},))) src3 = code_typed(applyf35855_2, (Vector{Any},))[1] f35855_2(::AbstractVector) = 4 applyf35855_2(Any[1]) -wany4 = worlds(instance(applyf35855_2, (Vector{Any},))) +wany4 = worlds(method_instance(applyf35855_2, (Vector{Any},))) src4 = code_typed(applyf35855_2, (Vector{Any},))[1] @test !(wany4 == wany3) || equal(src4, src3) # code doesn't change unless you invalidate @@ -343,25 +343,60 @@ end (::Type{X})(x::Real) where {T, X<:FixedPoint35855{T}} = X(round(T, typemax(T)*x), 0) @test worlds(mi) == w -mi = instance(convert, (Type{Nothing}, String)) +mi = method_instance(convert, (Type{Nothing}, String)) w = worlds(mi) abstract type Colorant35855 end Base.convert(::Type{C}, c) where {C<:Colorant35855} = false @test worlds(mi) == w -# NamedTuple and extensions of eltype +## NamedTuple and extensions of eltype outer(anyc) = inner(anyc[]) inner(s::Union{Vector,Dict}; kw=false) = inneri(s, kwi=maximum(s), kwb=kw) inneri(s, args...; kwargs...) = inneri(IOBuffer(), s, args...; kwargs...) inneri(io::IO, s::Union{Vector,Dict}; kwi=0, kwb=false) = (print(io, first(s), " "^kwi, kwb); String(take!(io))) @test outer(Ref{Any}([1,2,3])) == "1 false" -mi = instance(Core.kwfunc(inneri), (NamedTuple{(:kwi,:kwb),TT} where TT<:Tuple{Any,Bool}, typeof(inneri), Vector{T} where T)) +mi = method_instance(Core.kwfunc(inneri), (NamedTuple{(:kwi,:kwb),TT} where TT<:Tuple{Any,Bool}, typeof(inneri), Vector{T} where T)) w = worlds(mi) abstract type Container{T} end Base.eltype(::Type{C}) where {T,C<:Container{T}} = T @test worlds(mi) == w +## invoke call + +_invoke46741(a::Int) = a > 0 ? :int : println(a) +_invoke46741(a::Integer) = a > 0 ? :integer : println(a) +invoke46741(a) = @invoke _invoke46741(a::Integer) +@test invoke46741(42) === :integer +invoke46741_world = worlds(method_instance(invoke46741, (Int,))) +_invoke46741(a::Int) = a > 0 ? :int2 : println(a) +@test invoke46741(42) === :integer +@test worlds(method_instance(invoke46741, (Int,))) == invoke46741_world +_invoke46741(a::UInt) = a > 0 ? :uint2 : println(a) +@test invoke46741(42) === :integer +@test worlds(method_instance(invoke46741, (Int,))) == invoke46741_world +_invoke46741(a::Integer) = a > 0 ? :integer2 : println(a) +@test invoke46741(42) === :integer2 +@test worlds(method_instance(invoke46741, (Int,))) ≠ invoke46741_world + +# const-prop'ed call +_invoke46741(a::Int) = a > 0 ? :int : println(a) +_invoke46741(a::Integer) = a > 0 ? :integer : println(a) +invoke46741() = @invoke _invoke46741(42::Integer) +@test invoke46741() === :integer +invoke46741_world = worlds(method_instance(invoke46741, ())) +_invoke46741(a::Int) = a > 0 ? :int2 : println(a) +@test invoke46741() === :integer +@test worlds(method_instance(invoke46741, ())) == invoke46741_world +_invoke46741(a::UInt) = a > 0 ? :uint2 : println(a) +@test invoke46741() === :integer +@test worlds(method_instance(invoke46741, ())) == invoke46741_world +_invoke46741(a::Integer) = a > 0 ? :integer2 : println(a) +@test invoke46741() === :integer2 +@test worlds(method_instance(invoke46741, ())) ≠ invoke46741_world + # invoke_in_world +# =============== + f_inworld(x) = "world one; x=$x" g_inworld(x; y) = "world one; x=$x, y=$y" wc_aiw1 = get_world_counter()