Skip to content

Commit 683da41

Browse files
authored
Make Compiler an independent package (that lives in the julia repo) (JuliaLang#56409)
This is a further extension to JuliaLang#56128 to make the compiler into a proper stdlib, useable outside of `Base` as `using Compiler` in the same way that `JuliaSyntax` works already. There's a few remaining questions around how loading works, but mechanically, this PR is complete. For those remaining questions, I'll probably put up a separate PR that would migrate JuliaSyntax to it and then simply adopt that here once we've figured out the correct semantics.
2 parents f336314 + cd7250d commit 683da41

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1339
-1136
lines changed

Compiler/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name = "Compiler"
2+
uuid = "807dbc54-b67e-4c79-8afb-eafe4df6f2e1"
3+
version = "0.0.1"

Compiler/src/Compiler.jl

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
# When generating an incremental precompile file, we first check whether we
4+
# already have a copy of this *exact* code in the system image. If so, we
5+
# simply generates a pkgimage that has the dependency edges we recorded in
6+
# the system image and simply returns that copy of the compiler. If not,
7+
# we proceed to load/precompile this as an ordinary package.
8+
if isdefined(Base, :generating_output) && Base.generating_output(true) &&
9+
Base.samefile(Base._compiler_require_dependencies[1][2], @eval @__FILE__) &&
10+
!Base.any_includes_stale(
11+
map(Base.CacheHeaderIncludes, Base._compiler_require_dependencies),
12+
"sysimg", nothing)
13+
14+
Base.prepare_compiler_stub_image!()
15+
append!(Base._require_dependencies, Base._compiler_require_dependencies)
16+
# There isn't much point in precompiling native code - downstream users will
17+
# specialize their own versions of the compiler code and we don't activate
18+
# the compiler by default anyway, so let's save ourselves some disk space.
19+
ccall(:jl_suppress_precompile, Cvoid, (Cint,), 1)
20+
21+
else
22+
23+
@eval baremodule Compiler
24+
25+
# Needs to match UUID defined in Project.toml
26+
ccall(:jl_set_module_uuid, Cvoid, (Any, NTuple{2, UInt64}), Compiler,
27+
(0x807dbc54_b67e_4c79, 0x8afb_eafe4df6f2e1))
28+
29+
using Core.Intrinsics, Core.IR
30+
31+
import Core: print, println, show, write, unsafe_write,
32+
_apply_iterate, svec, apply_type, Builtin, IntrinsicFunction,
33+
MethodInstance, CodeInstance, MethodTable, MethodMatch, PartialOpaque,
34+
TypeofVararg, Core, SimpleVector, donotdelete, compilerbarrier,
35+
memoryref_isassigned, memoryrefnew, memoryrefoffset, memoryrefget,
36+
memoryrefset!, typename
37+
38+
using Base
39+
using Base: Ordering, vect, EffectsOverride, BitVector, @_gc_preserve_begin, @_gc_preserve_end, RefValue,
40+
@nospecializeinfer, @_foldable_meta, fieldindex, is_function_def, indexed_iterate, isexpr, methods,
41+
get_world_counter, JLOptions, _methods_by_ftype, unwrap_unionall, cconvert, unsafe_convert,
42+
issingletontype, isType, rewrap_unionall, has_free_typevars, isvarargtype, hasgenerator,
43+
IteratorSize, SizeUnknown, _array_for, Bottom, generating_output, diff_names,
44+
ismutationfree, NUM_EFFECTS_OVERRIDES, _NAMEDTUPLE_NAME, datatype_fieldtypes,
45+
argument_datatype, isfieldatomic, unwrapva, iskindtype, _bits_findnext, copy_exprargs,
46+
Generator, Filter, ismutabletypename, isvatuple, datatype_fieldcount,
47+
isconcretedispatch, isdispatchelem, datatype_layoutsize,
48+
datatype_arrayelem, unionlen, isidentityfree, _uniontypes, uniontypes, OneTo, Callable,
49+
DataTypeFieldDesc, datatype_nfields, datatype_pointerfree, midpoint, is_valid_intrinsic_elptr,
50+
allocatedinline, isbitsunion, widen_diagonal, unconstrain_vararg_length,
51+
rename_unionall, may_invoke_generator, is_meta_expr_head, is_meta_expr, quoted,
52+
specialize_method, hasintersect, is_nospecializeinfer, is_nospecialized,
53+
get_nospecializeinfer_sig, tls_world_age, uniontype_layout, kwerr,
54+
moduleroot, is_file_tracked, decode_effects_override, lookup_binding_partition,
55+
is_some_imported, binding_kind, is_some_guard, is_some_const_binding, partition_restriction,
56+
BINDING_KIND_GLOBAL, structdiff
57+
using Base.Order
58+
import Base: getindex, setindex!, length, iterate, push!, isempty, first, convert, ==,
59+
copy, popfirst!, in, haskey, resize!, copy!, append!, last, get!, size,
60+
get, iterate, findall, min_world, max_world, _topmod
61+
62+
const getproperty = Core.getfield
63+
const setproperty! = Core.setfield!
64+
const swapproperty! = Core.swapfield!
65+
const modifyproperty! = Core.modifyfield!
66+
const replaceproperty! = Core.replacefield!
67+
const _DOCS_ALIASING_WARNING = ""
68+
69+
ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Compiler, false)
70+
71+
eval(x) = Core.eval(Compiler, x)
72+
eval(m, x) = Core.eval(m, x)
73+
74+
function include(x::String)
75+
if !isdefined(Base, :end_base_include)
76+
# During bootstrap, all includes are relative to `base/`
77+
x = Base.strcat(Base.strcat(Base.BUILDROOT, "../usr/share/julia/Compiler/src/"), x)
78+
end
79+
Base.include(Compiler, x)
80+
end
81+
82+
function include(mod::Module, x::String)
83+
if !isdefined(Base, :end_base_include)
84+
x = Base.strcat(Base.strcat(Base.BUILDROOT, "../usr/share/julia/Compiler/src/"), x)
85+
end
86+
Base.include(mod, x)
87+
end
88+
89+
90+
macro _boundscheck() Expr(:boundscheck) end
91+
92+
# These types are used by reflection.jl and expr.jl too, so declare them here.
93+
# Note that `@assume_effects` is available only after loading namedtuple.jl.
94+
abstract type MethodTableView end
95+
abstract type AbstractInterpreter end
96+
97+
function return_type end
98+
function is_return_type(Core.@nospecialize(f))
99+
f === return_type && return true
100+
if isdefined(Base, :Compiler) && Compiler !== Base.Compiler
101+
# Also model the return_type function of the builtin Compiler the same.
102+
# This isn't completely sound. We don't actually have any idea what the
103+
# base compiler will do at runtime. In the fullness of time, we should
104+
# re-work the semantics to make the cache primary and thus avoid having
105+
# to reason about what the compiler may do at runtime, but we're not
106+
# fully there yet.
107+
return f === Base.Compiler.return_type
108+
end
109+
return false
110+
end
111+
112+
include("sort.jl")
113+
114+
# We don't include some.jl, but this definition is still useful.
115+
something(x::Nothing, y...) = something(y...)
116+
something(x::Any, y...) = x
117+
118+
############
119+
# compiler #
120+
############
121+
122+
baremodule BuildSettings
123+
using Core: ARGS, include
124+
using ..Compiler: >, getindex, length
125+
126+
global MAX_METHODS::Int = 3
127+
128+
if length(ARGS) > 2 && ARGS[2] === "--buildsettings"
129+
include(BuildSettings, ARGS[3])
130+
end
131+
end
132+
133+
if false
134+
import Base: Base, @show
135+
else
136+
macro show(ex...)
137+
blk = Expr(:block)
138+
for s in ex
139+
push!(blk.args, :(println(stdout, $(QuoteNode(s)), " = ",
140+
begin local value = $(esc(s)) end)))
141+
end
142+
isempty(ex) || push!(blk.args, :value)
143+
blk
144+
end
145+
end
146+
147+
include("cicache.jl")
148+
include("methodtable.jl")
149+
include("effects.jl")
150+
include("types.jl")
151+
include("utilities.jl")
152+
include("validation.jl")
153+
154+
include("ssair/basicblock.jl")
155+
include("ssair/domtree.jl")
156+
include("ssair/ir.jl")
157+
include("ssair/tarjan.jl")
158+
159+
include("abstractlattice.jl")
160+
include("stmtinfo.jl")
161+
include("inferenceresult.jl")
162+
include("inferencestate.jl")
163+
164+
include("typeutils.jl")
165+
include("typelimits.jl")
166+
include("typelattice.jl")
167+
include("tfuncs.jl")
168+
169+
include("abstractinterpretation.jl")
170+
include("typeinfer.jl")
171+
include("optimize.jl")
172+
173+
include("bootstrap.jl")
174+
include("reflection_interface.jl")
175+
176+
if isdefined(Base, :IRShow)
177+
@eval module IRShow
178+
import ..Compiler
179+
using Core.IR
180+
using ..Base
181+
import .Compiler: IRCode, CFG, scan_ssa_use!,
182+
isexpr, compute_basic_blocks, block_for_inst, IncrementalCompact,
183+
Effects, ALWAYS_TRUE, ALWAYS_FALSE, DebugInfoStream, getdebugidx,
184+
VarState, InvalidIRError, argextype, widenconst, singleton_type,
185+
sptypes_from_meth_instance, EMPTY_SPTYPES, InferenceState,
186+
NativeInterpreter, CachedMethodTable, LimitedAccuracy, Timings
187+
# During bootstrap, Base will later include this into its own "IRShow module"
188+
Compiler.include(IRShow, "ssair/show.jl")
189+
end
190+
end
191+
192+
end
193+
194+
end

base/compiler/abstractinterpretation.jl renamed to Compiler/src/abstractinterpretation.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,7 +2047,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs
20472047
elsetype = rt === Const(true) ? Bottom : widenslotwrapper(aty)
20482048
return Conditional(a, thentype, elsetype)
20492049
end
2050-
elseif f === Core.Compiler.not_int
2050+
elseif f === Core.Intrinsics.not_int
20512051
aty = argtypes[2]
20522052
if isa(aty, Conditional)
20532053
thentype = rt === Const(false) ? Bottom : aty.elsetype
@@ -2119,7 +2119,7 @@ function form_partially_defined_struct(@nospecialize(obj), @nospecialize(name))
21192119
else
21202120
fldidx > nminfld || return nothing
21212121
end
2122-
return PartialStruct(objt0, Any[obj isa PartialStruct && ilength(obj.fields) ?
2122+
return PartialStruct(fallback_lattice, objt0, Any[obj isa PartialStruct && ilength(obj.fields) ?
21232123
obj.fields[i] : fieldtype(objt0,i) for i = 1:fldidx])
21242124
end
21252125

@@ -2955,7 +2955,7 @@ function abstract_eval_new(interp::AbstractInterpreter, e::Expr, vtypes::Union{V
29552955
# - any refinement information is available (`anyrefine`), or when
29562956
# - `nargs` is greater than `n_initialized` derived from the struct type
29572957
# information alone
2958-
rt = PartialStruct(rt, ats)
2958+
rt = PartialStruct(𝕃ᵢ, rt, ats)
29592959
end
29602960
else
29612961
rt = refine_partial_type(rt)
@@ -2990,7 +2990,7 @@ function abstract_eval_splatnew(interp::AbstractInterpreter, e::Expr, vtypes::Un
29902990
all(i::Int -> (𝕃ᵢ, (at.fields::Vector{Any})[i], fieldtype(t, i)), 1:n)
29912991
end))
29922992
nothrow = isexact
2993-
rt = PartialStruct(rt, at.fields::Vector{Any})
2993+
rt = PartialStruct(𝕃ᵢ, rt, at.fields::Vector{Any})
29942994
end
29952995
else
29962996
rt = refine_partial_type(rt)
@@ -3524,7 +3524,7 @@ end
35243524
end
35253525
fields[i] = a
35263526
end
3527-
anyrefine && return PartialStruct(rt.typ, fields)
3527+
anyrefine && return PartialStruct(𝕃ᵢ, rt.typ, fields)
35283528
end
35293529
if isa(rt, PartialOpaque)
35303530
return rt # XXX: this case was missed in #39512
File renamed without changes.

Compiler/src/bootstrap.jl

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
# make sure that typeinf is executed before turning on typeinf_ext
4+
# this ensures that typeinf_ext doesn't recurse before it can add the item to the workq
5+
# especially try to make sure any recursive and leaf functions have concrete signatures,
6+
# since we won't be able to specialize & infer them at runtime
7+
8+
activate_codegen!() = ccall(:jl_set_typeinf_func, Cvoid, (Any,), typeinf_ext_toplevel)
9+
10+
function bootstrap!()
11+
let time() = ccall(:jl_clock_now, Float64, ())
12+
println("Compiling the compiler. This may take several minutes ...")
13+
interp = NativeInterpreter()
14+
15+
# analyze_escapes_tt = Tuple{typeof(analyze_escapes), IRCode, Int, TODO}
16+
optimize_tt = Tuple{typeof(optimize), NativeInterpreter, OptimizationState{NativeInterpreter}, InferenceResult}
17+
fs = Any[
18+
# we first create caches for the optimizer, because they contain many loop constructions
19+
# and they're better to not run in interpreter even during bootstrapping
20+
#=analyze_escapes_tt,=# optimize_tt,
21+
# then we create caches for inference entries
22+
typeinf_ext, typeinf, typeinf_edge,
23+
]
24+
# tfuncs can't be inferred from the inference entries above, so here we infer them manually
25+
for x in T_FFUNC_VAL
26+
push!(fs, x[3])
27+
end
28+
for i = 1:length(T_IFUNC)
29+
if isassigned(T_IFUNC, i)
30+
x = T_IFUNC[i]
31+
push!(fs, x[3])
32+
else
33+
println(stderr, "WARNING: tfunc missing for ", reinterpret(IntrinsicFunction, Int32(i)))
34+
end
35+
end
36+
starttime = time()
37+
for f in fs
38+
if isa(f, DataType) && f.name === typename(Tuple)
39+
tt = f
40+
else
41+
tt = Tuple{typeof(f), Vararg{Any}}
42+
end
43+
for m in _methods_by_ftype(tt, 10, get_world_counter())::Vector
44+
# remove any TypeVars from the intersection
45+
m = m::MethodMatch
46+
typ = Any[m.spec_types.parameters...]
47+
for i = 1:length(typ)
48+
typ[i] = unwraptv(typ[i])
49+
end
50+
typeinf_type(interp, m.method, Tuple{typ...}, m.sparams)
51+
end
52+
end
53+
endtime = time()
54+
println("Base.Compiler ──── ", sub_float(endtime,starttime), " seconds")
55+
end
56+
activate_codegen!()
57+
end
58+
59+
function activate!(; reflection=true, codegen=false)
60+
if reflection
61+
Base.REFLECTION_COMPILER[] = Compiler
62+
end
63+
if codegen
64+
activate_codegen!()
65+
end
66+
end
File renamed without changes.

base/compiler/effects.jl renamed to Compiler/src/effects.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,13 +351,13 @@ function decode_effects(e::UInt32)
351351
return Effects(
352352
UInt8((e >> 0) & 0x07),
353353
UInt8((e >> 3) & 0x03),
354-
_Bool((e >> 5) & 0x01),
355-
_Bool((e >> 6) & 0x01),
356-
_Bool((e >> 7) & 0x01),
354+
Bool((e >> 5) & 0x01),
355+
Bool((e >> 6) & 0x01),
356+
Bool((e >> 7) & 0x01),
357357
UInt8((e >> 8) & 0x03),
358358
UInt8((e >> 10) & 0x03),
359359
UInt8((e >> 12) & 0x03),
360-
_Bool((e >> 14) & 0x01))
360+
Bool((e >> 14) & 0x01))
361361
end
362362

363363
decode_statement_effects_override(ssaflag::UInt32) =
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)