## mythryl-compiler-compiler-g.pkg
# Compiled by:
#
src/app/makelib/makelib.sublib# Here we define a special app which 'make's
# the compiler itself, a task which presents
# special-case problems such as bootstrapping
# a valid initial runtime state from nothing.
#
# (To 'make' any Mythryl program other than the
# compiler, we use the
#
src/app/makelib/main/makelib-g.pkg# app.)
#
#
#
# In this file, we do essentially the following:
#
#
# 1) Parse the "primordial" library specfile
#
# src/lib/core/init/init.cmi
#
# by calling
#
# process_mythryl_primordial_library from
src/app/makelib/mythryl-compiler-compiler/process-mythryl-primordial-library.pkg#
# init.cmi has a special syntax and defines
# various life-critical things like TRUE that
# must be in place before vanilla .lib file
# processing can take place.
#
#
# 2) Compile the primordial library if a usable
# freezefile is not already available for it.
#
#
# 3) Load the primordial library into memory.
#
#
# 4) Call
#
# parse_libfile_tree_and_return_interlibrary_dependency_graph
# from
#
src/app/makelib/parse/libfile-parser-g.pkg#
# on the compiler's root .lib file
#
#
src/etc/mythryl-compiler-root.lib#
# (which then recursively runs all
# the other .lib files in the compiler)
# to ensure that all the libraries
# which are to be linked into the
#
# bin/mythryld
#
# "executable" heap image are up to date.
#
# In the usual lone_primary case we pass this
# function a FREEZE_ALL arg which forces it to make
# .frozen freezefiles for all (real) libraries lacking them,
# which in turn forces all .pkg and .api sourcefiles to
# compile if they have not already done so.
#
# In the (common) limiting case this requires
# recompiling all the relevant .api and .pkg
# sourcefiles and packing the resulting .compiled
# files into .frozen library freezefiles.
#
#
# 5) Write out two diskfiles named
#
# COMPILED_FILES_TO_LOAD
# LIBRARY_CONTENTS
#
# containing all the information needed to
# link the compiler libraries together to
# form the bin/mythryld "executable".
#
# Later, the
#
# sh/make-compiler-executable
#
# script will hand the above two files to
#
# bin/mythryl-runtime-intel32
#
# to generate the actual bin/mythryld
# "executable" heap image, but that is
# outside of our purview; we are just
# a subroutine invoked by the
#
# sh/make-compiler-libraries
#
# script.
#
#
# (mythryl-compiler-compiler-g.pkg also contains a fair amount
# of non-working code intended to support parallel
# and distributed compiles, which probably should be
# ripped out and rewritten from scratch. XXX BUGGO FIXME.)
#
#
# [ At some point we should tweak the code to hide the
# special-case kludging around here from the user,
# so that at the command-line level, compiling and
# linking the compiler looks just like compiling
# and linking any other program. XXX BUGGO FIXME. ]
#
#
#
# Api:
#
# We get sealed as Mythryl_Compiler_Compiler # Mythryl_Compiler_Compiler is from
src/lib/core/internal/mythryl-compiler-compiler.api#
#
#
# Generic invocation context:
#
# The generic we define is invoked in
#
#
src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-intel32-posix.pkg#
# to define mythryl_compiler_compiler_for_intel32_posix -- the other platforms
# define similar platform-specific backends.
#
# One of these gets defined as make_compiler (the default
# bootstrap compiler) via conditional inclusion in
#
#
src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-this-platform.lib#
# which gets invoked by sh/make-compiler-libraries
# which gets invoked by a toplevel 'make compiler'
#
#
#
# Generic arguments:
#
# "mythryl_compiler" is defined by
#
# package mythryl_compiler = mythryl_compiler_for_intel32_posix;
# in
#
src/lib/compiler/toplevel/compiler/mythryl-compiler-for-intel32-posix.pkg#
# which gets conditionally included by
#
#
src/lib/core/compiler/mythryl-compiler-for-this-platform.lib#
# (The above is for "intel32-linux" platforms:
# The pattern is similar on other platforms.)
#
# "read_eval_print_from_stream" is backend::interact::read_eval_print_from_stream
# which read_eval_print_loops_g defines in
#
#
src/lib/compiler/toplevel/interact/read-eval-print-loops-g.pkg#
# as a simple wrapper around the read_eval_print_from_stream
# function defined by read_eval_print_loop_g in
#
#
src/lib/compiler/toplevel/interact/read-eval-print-loop-g.pkg#
#
# Runtime invocation context:
#
# One path is via
#
src/lib/core/internal/make-mythryld-executable.pkg "make_mythryl_compiler_etc::make_compiler_etc root_directory"
#
src/lib/core/internal/make-mythryl-compiler-etc.pkg make_compiler::make_compiler' (...)
#
# The most usual invocation is via a manual linux commandline
# "make compiler"
# Makefile ->
# sh/make-compiler-libraries
# which first constructs the bootstrap compiler by running mythryld on
#
src/lib/core/compiler/mythryl-compiler-for-this-platform.lib# and then invokes it via a script-embedded
# make_compiler::make_compiler ()
#
# Either way, we quickly wind up at make_compiler'()
# at the bottom of this file, and away we go.
stipulate
package err = error_message; # error_message is from
src/lib/compiler/front/basics/errormsg/error-message.pkg package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package fzp = freeze_policy; # freeze_policy is from
src/app/makelib/parse/freeze-policy.pkg package flt = frozenlib_tome; # frozenlib_tome is from
src/app/makelib/freezefile/frozenlib-tome.pkg package frn = find_reachable_sml_nodes; # find_reachable_sml_nodes is from
src/app/makelib/depend/find-reachable-sml-nodes.pkg package fts = frozenlib_tome_set; # frozenlib_tome_set is from
src/app/makelib/freezefile/frozenlib-tome-set.pkg package lg = inter_library_dependency_graph; # inter_library_dependency_graph is from
src/app/makelib/depend/inter-library-dependency-graph.pkg package log = logger; # logger is from
src/lib/src/lib/thread-kit/src/lib/logger.pkg package lsi = library_source_index; # library_source_index is from
src/app/makelib/stuff/library-source-index.pkg package mcc = mythryl_compiler_compiler_configuration; # mythryl_compiler_compiler_configuration is from
src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-configuration.pkg package md = makelib_defaults; # makelib_defaults is from
src/app/makelib/stuff/makelib-defaults.pkg package mtq = makelib_thread_boss; # makelib_thread_boss is from
src/app/makelib/concurrency/makelib-thread-boss.pkg package ms = makelib_state; # makelib_state is from
src/app/makelib/main/makelib-state.pkg package pl = process_mythryl_primordial_library; # process_mythryl_primordial_library is from
src/app/makelib/mythryl-compiler-compiler/process-mythryl-primordial-library.pkg package sa = supported_architectures; # supported_architectures is from
src/lib/compiler/front/basics/main/supported-architectures.pkg package sg = intra_library_dependency_graph; # intra_library_dependency_graph is from
src/app/makelib/depend/intra-library-dependency-graph.pkg package spm = source_path_map; # source_path_map is from
src/app/makelib/paths/source-path-map.pkg #
find_set_of_compiled_files_for_executable
=
find_set_of_compiled_files_for_executable::find_set_of_compiled_files_for_executable;
# Logging support. To log messages from this file scatter
#
# to_log {. sprintf "Whatever"; }; # Do not add trailing newline to message string.
#
# calls through the code as appropriate and then either
# uncomment the below
#
# my _ = log::enable compiler_compiler_logging;
#
# line or do
#
# logger::enable (the (logger::find_logtree_node_by_name "compiler_compiler::logging"));
#
# from the Mythryl interactive prompt.
#
compiler_compiler_logging
=
log::make_logtree_leaf
{ parent => fil::all_logging,
name => "compiler_compiler::logging",
default => TRUE # Change to TRUE or call (log::enable compiler_compiler_logging) to enable logging in this file.
};
#
to_log = log::log_if compiler_compiler_logging 0;
herein
# find_set_of_compiled_files_for_executable is from
src/app/makelib/mythryl-compiler-compiler/find-set-of-compiledfiles-for-executable.pkg # mythryl_compiler_compiler_for_intel32_posix is from
src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-intel32-posix.pkg # anchor_dictionary is from
src/app/makelib/paths/anchor-dictionary.pkg # lib7 is from
src/lib/std/lib7.pkg # Mythryl_Compiler is from
src/lib/compiler/toplevel/compiler/mythryl-compiler.api # os::Kind = POSIX
| WIN32 | MACOS | OS2 | BEOS;
# for intel32-posix, 'mythryl_compiler' will be mythryl_compiler_for_intel32_posix, arriving
# via
src/lib/core/mythryl-compiler-compiler/mythryl-compiler-compiler-for-intel32-posix.pkg generic package mythryl_compiler_compiler_g (
# ===========================
#
# # mythryl_compiler_for_intel32_posix is from
src/lib/compiler/toplevel/compiler/mythryl-compiler-for-intel32-posix.pkg # # mythryl_compiler_for_intel32_win32 is from
src/lib/compiler/toplevel/compiler/mythryl-compiler-for-intel32-win32.pkg # # mythryl_compiler_for_pwrpc32 is from
src/lib/compiler/toplevel/compiler/mythryl-compiler-for-pwrpc32.pkg # # mythryl_compiler_for_sparc32 is from
src/lib/compiler/toplevel/compiler/mythryl-compiler-for-sparc32.pkg # # Mythryl_Compiler is from
src/lib/compiler/toplevel/compiler/mythryl-compiler.api package mythryl_compiler: Mythryl_Compiler; # We get the host architecture and abi from this.
os_kind: platform_properties::os::Kind;
# This is currently always
# makelib_internal::load_plugin; # makelib_internal is from
src/lib/core/internal/makelib-internal.pkg # -- I'm not sure if/why it needs to
# be a parameter here:
#
load_plugin # load_plugin def in
src/app/makelib/main/makelib-g.pkg :
anchor_dictionary::Path_Root -> String -> Bool;
)
{
package myc = mythryl_compiler; # "myc" == "mythryl_compiler"
# How to compile ascii source to executable binary:
#
read_eval_print_from_stream = myc::rpl::read_eval_print_from_stream
: fil::Input_Stream -> Void;
# Set up a little dictionary defining
# half a dozen platform properties
# like architecture ("intel32" or such):
#
package mps # "mps" == "makelib preprocessor state"
=
makelib_preprocessor_state_g (
#
architecture = myc::target_architecture; # PWRPC32/SPARC32/INTEL32.
os_kind = os_kind;
abi_variant = myc::abi_variant;
);
# makelib_preprocessor_state_g is from
src/app/makelib/main/makelib-preprocessor-state-g.pkg # winix__premicrothread is from
src/lib/std/winix--premicrothread.pkg # filename_policy is from
src/app/makelib/main/filename-policy.pkg # backend_index is from
src/app/makelib/mythryl-compiler-compiler/backend-index.pkg # Cross-platform file I/O:
#
package f = winix__premicrothread::file;
package p = backend_index;
package ad = anchor_dictionary; # anchor_dictionary is from
src/app/makelib/paths/anchor-dictionary.pkg machine_architecture # PWRPC32/SPARC32/INTEL32.
=
myc::target_architecture;
osname # "posix"/"macos"/"win32"/...
=
filename_policy::os_kind_to_string os_kind;
platform # 'platform' string is architecture plus OS, e.g. "intel32-posix" XXX BUGGO FIXME should rename 'platform' to 'arch_os' or such -- clearer.
=
cat [ architecture_name,
"-",
osname
]
where
architecture_name = sa::architecture_name machine_architecture;
end;
package ffr
=
freezefile_roster_g ();
# freezefile_roster_g is from
src/app/makelib/freezefile/freezefile-roster-g.pkg # anchor_dictionary is from
src/app/makelib/paths/anchor-dictionary.pkg package cdo # "cdo" == "compile_(in_)dependency_order".
=
compile_in_dependency_order_g ( # compile_in_dependency_order_g is from
src/app/makelib/compile/compile-in-dependency-order-g.pkg #
package myc = mythryl_compiler; # "myc" == "mythryl_compiler".
package ffr = ffr; # "ffr" == "freezefile_roster".
#
read_eval_print_from_stream
=
read_eval_print_from_stream;
);
package t2c
=
thawedlib_tome__to__compiledfile__map_g (
#
architecture = myc::target_architecture; # PWRPC32/SPARC32/INTEL32.
);
# thawedlib_tome__to__compiledfile__map_g is from
src/app/makelib/compile/thawedlib-tome--to--compiledfile-contents--map-g.pkg # compile_in_dependency_order_g is from
src/app/makelib/compile/compile-in-dependency-order-g.pkg package fzf # "fzf" == "freezefile".
=
freezefile_g ( # freezefile_g is from
src/app/makelib/freezefile/freezefile-g.pkg #
architecture # PWRPC32/SPARC32/INTEL32.
=
myc::target_architecture;
package ffr = ffr; # "ffr" == "freezefile_roster".
# compile_in_dependency_order_g is from
src/app/makelib/compile/compile-in-dependency-order-g.pkg # link_in_dependency_order_g is from
src/app/makelib/compile/link-in-dependency-order-g.pkg # A function which allows
#
# fzf::save_freezefile
#
# to recompile any thawed real library
# handed to it:
#
fun compile_library
#
(makelib_state: ms::Makelib_State)
#
(root_library: lg::Inter_Library_Dependency_Graph)
=
{
# printf "compile_library/AAA\n";
(t2c::make__thawedlib_tome__to__compiledfile__map ())
->
{ set__compiledfile__for__thawedlib_tome,
get__compiledfile__for__thawedlib_tome
};
fun dummy_thawedlib_tome_watcher _ _
=
();
# printf "compile_library/BBB\n";
my { compile_library_catalog_in_dependency_order, ... }
=
cdo::make_dependency_order_compile_fns
{
root_library,
#
maybe_drop_thawedlib_tome_from_linker_map
=> dummy_thawedlib_tome_watcher,
#
set__compiledfile__for__thawedlib_tome
};
# printf "compile_library/CCC: before call to compile_library_catalog_in_dependency_order\n";
result =
case (compile_library_catalog_in_dependency_order makelib_state)
#
THE _ => THE get__compiledfile__for__thawedlib_tome;
NULL => NULL;
esac;
# printf "compile_library/ZZZ: after call to compile_library_catalog_in_dependency_order\n";
result;
};
get_symbol_and_inlining_mapstacks
=
cdo::get_symbol_and_inlining_mapstacks;
);
package vff
=
verify_freezefile_g (package freezefile = fzf;);
# verify_freezefile_g def in
src/app/makelib/freezefile/verify-freezefile-g.pkg # libfile_parser_g def in
src/app/makelib/parse/libfile-parser-g.pkg # winix__premicrothread is from
src/lib/std/winix--premicrothread.pkg package lfp
=
libfile_parser_g (
#
package freezefile = fzf;
package freezefile_roster = ffr;
#
fun pending () = symbol_map::empty;
#
drop_stale_entries_from_compiler_and_linker_maps
=
cdo::drop_stale_entries_from_compiler_map;
);
# include package freeze_policy;
#
fun list_compiled_files_to_load dependency_graph_root
=
find_set_of_compiled_files_for_executable
#
filepath_to_string
#
dependency_graph_root
where
fun filepath_to_string filepath
=
{
# Convert absolute paths to ROOT-relative ones.
#
# NB: These were nice relative paths until
# I started frigging around with anchors,
# presumably an upstream fix somewhere
# would restore the status quo ante and
# obviate this kludge: XXX BUGGO FIXME
#
root = (the (ad::get_anchor (ad::dictionary, "ROOT"))) + "/";
#
filepath = if (string::is_prefix root filepath)
#
string::extract (filepath, string::length_in_bytes root, NULL);
else
filepath;
fi;
case (winix__premicrothread::path::from_string filepath)
#
{ disk_volume => "",
is_absolute => FALSE,
arcs => arc1 ! arcn
}
=>
{ fun win32name ()
=
cat ( arc1 !
fold_backward
(\\ (a, r) = "\\" ! a ! r)
[]
arcn
);
case os_kind
#
platform_properties::os::WIN32
=>
win32name ();
_ =>
winix__premicrothread::path::to_string
{
is_absolute => FALSE,
disk_volume => "",
arcs => arc1 ! arcn
};
esac;
};
_ =>
raise exception DIE ("src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg/list_compiled_files_to_load/list_name: bad name: " + filepath);
esac;
};
end; # fun list_compiled_files_to_load
# find_set_of_compiled_files_for_executable is from
src/app/makelib/mythryl-compiler-compiler/find-set-of-compiledfiles-for-executable.pkg # compile_in_dependency_order_g def in
src/app/makelib/compile/compile-in-dependency-order-g.pkg # libfile_parser_g def in
src/app/makelib/parse/libfile-parser-g.pkg # freezefile_roster_g def in
src/app/makelib/freezefile/freezefile-roster-g.pkg # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg #
fun clear_internal_state ()
=
{ cdo::clear_state ();
lfp::clear_state ();
ffr::clear_state ();
};
stipulate
#
current_generated_filename_infix
=
REF NULL; # XXX BUGGO FIXME more icky thread-hostile embedded state :(
herein
fun reset_state_if_generated_filename_infix_changed
generated_filename_infix
=
case *current_generated_filename_infix
#
NULL => current_generated_filename_infix
:=
THE generated_filename_infix;
#
THE generated_filename_infix'
=>
if (generated_filename_infix != generated_filename_infix')
#
fil::say {.
cat [ " mythryl-compiler-compiler-g.pkg: New generated_filename_infix is `",
generated_filename_infix,
"'; Resetting make_compiler state.]\n"
];
};
clear_internal_state ();
current_generated_filename_infix
:=
THE generated_filename_infix;
fi;
esac;
end;
#
fun make_compiler {
primary, # TRUE iff we're in the primary makelib process, FALSE if we're in a compile server.
libfile, # NULL for default (src/etc/mythryl-compiler-root.lib) else THE libfile_path_as_a_string.
null_or_generated_filename_infix # Normally NULL (defaulting to ""); if this is THE ".pwrpc32-macos", instead of "foo.pkg.compiled" we'll generate "foo.pkg.pwrpc32-macos.compiled".
} # Could also be used by the sh/make-fixpoint script to generate multiple generations of compiler.
=
{
# 2007-12-02 CrT: We can probably get rid of the build_directory argument at this point. XXX BUGGO FIXME
generated_filename_infix
=
the_else (
null_or_generated_filename_infix,
mcc::default_generated_filename_infix # ""
);
reset_state_if_generated_filename_infix_changed
#
generated_filename_infix;
mythryl_primordial_library
=
mcc::mythryl_primordial_library; # "$ROOT/src/lib/core/init/init.cmi"
mythryl_compiler_root_library_filename
=
mcc::mythryl_compiler_root_library_filename; # "$ROOT/src/etc/mythryl-compiler-root.lib"
#
#
# In practice, mythryl_compiler_root_library_filename points to
#
#
src/etc/mythryl-compiler-root.lib #
# which in turn is a trivial wrapper for
#
#
src/lib/core/internal/interactive-system.lib #
# This is important because it is the
# core specification of the entire
# compiler executable image that we're
# building here. :)
# Should we keep on compiling after
# encountering our first syntax error?
#
keep_going_after_compile_errors
=
md::keep_going_after_compile_errors.get ();
#
compiled_files_to_load_filename # "COMPILED_FILES_TO_LOAD"
=
mcc::compiled_files_to_load_filename;
#
picklehash_map_filename = mcc::picklehash_map_filename; # "LIBRARY_CONTENTS"
anchor_dictionary = ad::dictionary; # More icky thread-hostile global mutable state! (Except we never mutate it...) XXX BUGGO FIXME.
ad::sync ();
#
fun make_standard_source_path file_path
=
ad::from_standard anchor_dictionary file_path;
mythryl_primordial_library
=
make_standard_source_path mythryl_primordial_library;
mythryl_compiler_root_library_filename
=
case libfile
#
THE filename => ad::decode anchor_dictionary filename;
NULL => make_standard_source_path mythryl_compiler_root_library_filename;
esac;
filename_policy = filename_policy::policy;
#
fun make_makelib_session { we_are_a_subprocess }
=
{ makelib_thread_boss = mtq::make_makelib_thread_boss ();
#
{ find_makelib_preprocessor_symbol
=>
mps::find_makelib_preprocessor_symbol,
#
anchor_dictionary,
filename_policy,
platform, # 'platform' string is architecture plus OS, e.g. "intel32-linux"
keep_going_after_compile_errors,
we_are_a_subprocess => REF we_are_a_subprocess,
makelib_thread_boss
};
};
# The library_source_index essentially maps
# filenames to superficial file contents
# info -- line and column numbers etc:
#
library_source_index
=
lsi::make_library_source_index ();
# Where to send error messages:
#
plaint_sink
=
err::default_plaint_sink ();
# Build an initial makelib_state, so that we can
# deal with the pervasive dictionary and friends...
#
makelib_state
=
{ library_source_index,
plaint_sink,
makelib_session => make_makelib_session { we_are_a_subprocess => FALSE },
#
timestamp_of_youngest_sourcefile_in_library => REF timestamp::ancient # Used to decide whether a library rebuild is needed, in
src/app/makelib/main/makelib-g.pkg };
#
fun make_main_compile { pervasive => pervasive_node, others, source_code }
=
{
fun recompile_primordial_library ()
=
{ compile_tome_tin_after_dependencies'
=
cdo::compile_tome_tin_after_dependencies ();
#
fun compile_tome_tin_after_dependencies'' compiledfile
=
the (compile_tome_tin_after_dependencies' makelib_state compiledfile);
pervasive
=
compile_tome_tin_after_dependencies'' pervasive_node;
#
fun rt2ie (node, symbol_and_inlining_mapstacks: sg::Tome_Compile_Result)
=
{ symbolmapstack
=
symbol_and_inlining_mapstacks.symbolmapstack_thunk ();
my (tome_symbolmapstack, make_domain)
=
symbolmapstack__to__tome_symbolmapstack::convert
symbolmapstack;
domain = make_domain ();
{ domain,
#
ie => { masked_tome_thunk => \\ () = { exports_mask => NULL, tome_tin => node },
tome_symbolmapstack,
exports_mask => domain
}: lg::Fat_Tome
};
};
#
fun add_exports (compiledfile, exports)
=
{ my { ie, domain }
=
rt2ie (compiledfile, compile_tome_tin_after_dependencies'' compiledfile);
#
fun insert_imports_exports (symbol, m)
=
symbol_map::set (m, symbol, ie);
symbol_set::fold_forward
insert_imports_exports
exports
domain;
};
# symbol_set is from
src/app/makelib/stuff/symbol-set.pkg # symbol_map is from
src/app/makelib/stuff/symbol-map.pkg # pervasive_symbol is from
src/app/makelib/main/pervasive-symbol.pkg special_exports
=
{ fun make_imports_exports (pervasive_node, pervasive)
=
.ie (rt2ie (pervasive_node, pervasive));
symbol_map::set (
symbol_map::empty,
pervasive_symbol::pervasive_package_symbol,
make_imports_exports
(pervasive_node, pervasive)
);
};
exports
=
fold_forward
add_exports
special_exports
others;
main_library
=
lg::MAIN_LIBRARY
{
makelib_version_intlist => NULL,
#
frozen_vs_thawed_stuff
=>
lg::THAWEDLIB_STUFF
{
sublibraries => []
}
};
lg::LIBRARY
{
catalog => exports,
more => main_library,
libfile => mythryl_primordial_library,
sources => spm::empty, # A hack -- sources never used for this library.
sublibraries => []
};
# string_set is from
src/lib/src/string-set.pkg # source_path_map is from
src/app/makelib/paths/source-path-map.pkg }; # fun recompile_primordial_library in fun make_main_compile in fun make_compiler
# Just go and load the primordial makefile
# freezefile or signal failure:
#
fun load_primordial_library ()
=
case (fzf::load_freezefile
#
{ get_library => \\ _ = raise exception DIE "make_compiler: load_primordial_library",
saw_errors => REF FALSE
}
#
( makelib_state,
mythryl_primordial_library
, NULL # 'version' info XXX BUGGO DELETEME
, [] # MUSTDIE
) )
THE (g as lg::LIBRARY _ ) => THE g;
NULL => NULL;
THE lg::BAD_LIBRARY => NULL;
esac;
# Don't try to load the primordial
# libfile's freezefile:
# Instead, recompile directly:
#
fun compile_primordial_library ()
=
{ # Function recompile_primordial_library
# will not use servers but since
# compile dagwalks invoke the scheduler
# anyway, we must still clear pending tasks
# when we hit an error or an interrupt:
#
primordial_library
=
recompile_primordial_library ();
freezefile_arg
=
{ library => primordial_library,
saw_errors => REF FALSE
, renamings => [] # MUSTDIE
};
# freezefile is defined above. See also
src/app/makelib/freezefile/freezefile-g.pkg if (not primary)
#
primordial_library;
else
to_log {. sprintf "Calling fzf::save_freezefile -- compile_primordial_library in src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg"; };
result =
case (fzf::save_freezefile makelib_state freezefile_arg)
#
THE primordial_library
=>
{ lfp::clear_state ();
primordial_library;
};
NULL => raise exception DIE "make_compiler: cannot build initial library";
esac;
to_log {. sprintf "Done calling fzf::save_freezefile -- compile_primordial_library in src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg"; };
result;
fi;
}; # fun compile_primordial_library in fun make_main_compile in fun make_compiler
# Try loading the primordial library from
# its freezefile if possible; recompile it
# if loading fails:
#
fun load_or_compile_primordial_library ()
=
case (load_primordial_library ())
#
THE g => g;
NULL => compile_primordial_library ();
esac;
# Ok, now, based on "paranoid" and
# freezefile verification, call the
# appropriate function (s)
# to get the primordial library:
#
primordial_library
=
if (not primary)
#
the (load_primordial_library ()); # Failure caught at the end.
else
export_nodes = pervasive_node ! others;
verify_arg = (mythryl_primordial_library, export_nodes, [], source_path_set::empty, NULL);
em = frozenlib_tome_map::empty;
# source_path_set is from
src/app/makelib/paths/source-path-set.pkg # frozenlib_tome_map is from
src/app/makelib/freezefile/frozenlib-tome-map.pkg # verify_freezefile_g is from
src/app/makelib/freezefile/verify-freezefile-g.pkg # library_source_index is from
src/app/makelib/stuff/library-source-index.pkg if (vff::verify' makelib_state em verify_arg)
#
load_or_compile_primordial_library ();
else compile_primordial_library ();
fi;
fi;
library_source_index
=
lsi::make_library_source_index ();
lsi::register
library_source_index
(mythryl_primordial_library, source_code);
# 2007-12-02 CrT: All this 'server' stuff should be chopped.
# it has never been debugged, doesn't work,
# and the design is poor -- instead of having
# each server reconstruct the compiler state on
# its own, we should just fork() to create the
# compile servers.
#
# Ultimately it would be nice to
# just use hostthreads in-process, but we have
# to clean up a lot of global-variable idiocy
# to make that possible.
#
fun parse_arg_0 { we_are_a_subprocess } { freeze_policy, paranoid }
=
{ makelib_file_to_read => mythryl_compiler_root_library_filename, # Primary .libi file --
src/etc/mythryl-compiler-root.lib #
load_plugin,
library_source_index,
makelib_session => make_makelib_session { we_are_a_subprocess },
freeze_policy,
primordial_library,
paranoid
};
parse_arg = parse_arg_0 { we_are_a_subprocess => FALSE };
server_parse_arg = parse_arg_0 { we_are_a_subprocess => TRUE };
# libfile_parser_g def in
src/app/makelib/parse/libfile-parser-g.pkg interlibrary_dependency_graph # There's actually a makelib_state tucked in there as well.
=
if (not primary)
#
lfp::parse_libfile_tree_and_return_interlibrary_dependency_graph
(
server_parse_arg { freeze_policy => fzp::FREEZE_NONE, paranoid => FALSE } # Server case
);
else
lfp::parse_libfile_tree_and_return_interlibrary_dependency_graph
(
parse_arg { freeze_policy => fzp::FREEZE_ALL, paranoid => TRUE }
);
fi;
# We're in fun make_main_compile in fun make_compiler
case interlibrary_dependency_graph
#
NULL => NULL; # Couldn't parse .lib tree, so just give up.
#
THE (libfile_dependency_graph, makelib_state)
=>
{ # Write to disk the COMPILED_FILES_TO_LOAD
# and LIBRARY_CONTENTS files.
#
# These tell bin/mythryl-runtime-intel32 how to build the
# bin/mythryld "executable" heap image:
#
print "Writing out COMPILED_FILES_TO_LOAD and LIBRARY_CONTENTS files -- mythryl-compiler-compiler-g.pkg\n";
fun write__compiled_files_to_load__and__library_contents
#
( libfile_dependency_graph,
makelib_state
)
=
{ (list_compiled_files_to_load libfile_dependency_graph)
->
{ l => compiled_files_to_load,
ss
};
compiled_files_to_load
=
map #2 compiled_files_to_load;
stipulate
frozen_libraries
=
frn::freezefiles_of libfile_dependency_graph;
#
fun in_set bi
=
fts::member (ss, bi);
herein
frontiers
=
spm::map
(frn::frontier in_set)
frozen_libraries;
end;
# file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg # Generate the COMPILED_FILES_TO_LOAD file:
#
fun write_compiled_files_to_load output_stream
=
{ fun write_string string
=
fil::write (output_stream, string + "\n");
item_count
=
length compiled_files_to_load;
#
fun maximum_length (string, n)
=
int::max (size string, n);
maximum_line_length
=
fold_forward
maximum_length
0
compiled_files_to_load;
apply write_string [
"# This file was built by src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg: write_compiled_files_to_load",
"# for consumption by mythryl-runtime-intel32: src/c/main/load-compiledfiles.c: read_in_compiled_file_list__may_heapclean.",
"#",
"# It gives a list of .compiled files to be linked together to form a Lib7 executable (heap image).",
"#",
"# Each line after the header specifies one .compiled file to load.",
"#",
"# The lines are topogically sorted so that no .compiled file depends upon a later one.",
"#",
"# An .compiled file is specified as either a simple filename, or else as a",
"# FREEZEFILENAME@OFFSET: LIBRARY_DESCRIPTION triple giving the offset of the",
"# compiledfile image within some library file, where LIBRARY_DESCRIPTION in turn",
"# is a LIBFILE@OFFSET (SOURCEFILE) triple giving the makefile which created",
"# the library and the name of the source file which was compiled to produce",
"# the .compiled file. (The second OFFSET is redundant with the first.)",
(cat ["FILES=", int::to_string item_count]),
(cat ["MAX_LINE_LENGTH=", int::to_string maximum_line_length ]),
""
];
apply write_string compiled_files_to_load;
}; # fun write_compiled_files_to_load in fun write__compiled_files_to_load__and__library_contents in fun make_main_compile in fun make_compiler
# Generate the LIBRARY_CONTENTS file:
#
fun write_library_contents_file s
=
{ apply
(\\ text = fil::write (s, text))
[
"# This file lists the contents of each library in this directory tree.\n",
"# Each line lists the contents of one library.\n",
"#\n",
"# The first entry on each line is the name of\n",
"# the makelib file which generated the library.\n",
"#\n",
"# The remaining entries on each line are OFFSET: PICKLEHASH pairs\n",
"# representing .compiled files, where OFFSET is the byte offset\n",
"# of the compiledfile image within the library file, and PICKLEHASH\n",
"# is a 16-byte hash of that image, expressed as a 32-char hex string.\n",
"#\n",
"# This file was generated by src/app/makelib/mythryl-compiler-compiler/mythryl-compiler-compiler-g.pkg: write_library_contents_file.\n",
"# It will typically be read by src/app/makelib/main/makelib-g.pkg: read_picklehash_map.\n",
"# It is not really intended for human consumption. :)\n"
];
spm::keyed_apply
(write_picklehash_line s)
frontiers;
}
where
fun write_picklehash_line s (p, set)
=
if (not (fts::is_empty set))
#
fil::write (s, ad::encode p);
fts::apply (write_picklehash s) set;
fil::write (s, "\n");
fi
where
fun write_picklehash s (tome: flt::Frozenlib_Tome)
=
{ description = flt::describe_frozenlib_tome tome;
compiledfile
=
t2c::get_compiledfile_from_freezefile {
#
freezefile_name => tome.freezefile_name,
offset => tome.byte_offset_in_freezefile,
description
};
# compiledfile is from
src/lib/compiler/execution/compiledfile/compiledfile.pkg case (compiledfile::hash_of_pickled_exports compiledfile)
#
NULL => ();
#
THE picklehash
=>
apply
(\\ str = fil::write (s, str))
[ " ",
int::to_string tome.byte_offset_in_freezefile,
":",
picklehash::to_hex picklehash
];
esac;
# file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg # int is from
src/lib/std/int.pkg # picklehash is from
src/lib/compiler/front/basics/map/picklehash.pkg };
end;
end; # fun write_library_contents_file in fun write__compiled_files_to_load__and__library_contents in fun make_main_compile in fun make_compiler
# autodir is from
src/app/makelib/stuff/autodir.pkg # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg safely::do
{ close_it => fil::close_output,
open_it => {. autodir::open_text_output compiled_files_to_load_filename; },
cleanup => \\ _ = (winix__premicrothread::file::remove_file compiled_files_to_load_filename
except _ = ())
}
write_compiled_files_to_load;
safely::do
{ close_it => fil::close_output,
open_it => {. autodir::open_text_output picklehash_map_filename; },
cleanup => \\ _ = (winix__premicrothread::file::remove_file picklehash_map_filename
except _ = ())
}
write_library_contents_file;
TRUE;
}; # fun write__compiled_files_to_load__and__library_contents in fun make_main_compile in fun make_compiler
# Don't do another dagwalk
# if this is a lone primary:
#
fun just_build_library ()
=
write__compiled_files_to_load__and__library_contents
#
( libfile_dependency_graph,
makelib_state
);
# The following thunk is executed
# in primary process only;
# compile servers just throw it away:
#
fun freeze ()
=
{ my { compile_all_fat_tomes_in_library_in_dependency_order, ... }
=
cdo::make_dependency_order_compile_fns
{
root_library => libfile_dependency_graph,
maybe_drop_thawedlib_tome_from_linker_map => \\ _ = \\ _ = (),
set__compiledfile__for__thawedlib_tome => \\ _ = ()
};
if (compile_all_fat_tomes_in_library_in_dependency_order makelib_state)
#
cdo::clear_state ();
freeze' ();
else
FALSE;
fi;
}
where
# Phase 2 (freezing):
#
fun freeze' ()
=
# Now we re-parse everything with freezing
# turned on (and servers turned off):
# parse_libfile_tree_and_return_interlibrary_dependency_graph defined above.
case (lfp::parse_libfile_tree_and_return_interlibrary_dependency_graph
(
parse_arg { freeze_policy => fzp::FREEZE_ALL, paranoid => FALSE }
) )
#
NULL => FALSE;
#
THE (libfile_dependency_graph, makelib_state)
=>
write__compiled_files_to_load__and__library_contents
#
(libfile_dependency_graph, makelib_state);
esac;
end;
THE ( ( libfile_dependency_graph,
makelib_state,
anchor_dictionary
),
just_build_library
);
};
esac;
} # fun make_main_compile in fun make_compiler
except
# Catch any failure in runtime or any compiler server
# failure to load primordial_library library:
#
NULL_OR = { cdo::clear_state ();
NULL;
};
# compile_in_dependency_order_g is from
src/app/makelib/compile/compile-in-dependency-order-g.pkg case (pl::process_mythryl_primordial_library
makelib_state
mythryl_primordial_library
)
#
THE x => make_main_compile x;
NULL => NULL;
esac;
}; # fun make_compiler
# freezefile_roster_g is from
src/app/makelib/freezefile/freezefile-roster-g.pkg fun make_mythryl_compiler' null_or_generated_filename_infix # Normally NULL (defaulting to ""), might be (e.g.) THE ".pwrpc32-macos" when cross-compiling.
=
{ ffr::clear_state ();
#
case (make_compiler {
primary => TRUE, # We're in the root makelib process, not in a secondary compile-server process.
libfile => NULL, # Use default root .lib file, normally
src/etc/mythryl-compiler-root.lib null_or_generated_filename_infix # Normally NULL (defaults to ""); if this is THE ".pwrpc32-macos", instead of "foo.pkg.compiled" we'll generate "foo.pkg.pwrpc32-macos.compiled".
}
) # 'make fixpoint' successively sets it to (THE "build7-1"), (THE "build7-2")...
#
NULL => FALSE;
#
THE (_, thunk)
=>
thunk (); # == either just_build_library() or freeze() -- see above.
esac;
};
# To take advantage of multiple cores/CPUs/workstations,
# makelib can spawn and use multiple "compile server" processes,
# allowing multiple compiles to take place in parallel.
#
# Rather than load all platform-specific backends into memory
# at the start, these servers economize on memory by loading
# them only as needed -- the logic to do this is in
#
#
src/app/makelib/mythryl-compiler-compiler/backend-per-platform.pkg #
# In order to be useful, as they load these backends must
# enter themselves into a dynamic registry so as to be
# accessible to makelib proper. That registry is implemented in
#
#
src/app/makelib/mythryl-compiler-compiler/backend-index.pkg #
# and it is now time to enter ourself into it.
#
# First we define the function which the toplevel compile-server
# logic will call to invoke us, then we enter it into the registry:
#
stipulate
# freezefile_roster_g is from
src/app/makelib/freezefile/freezefile-roster-g.pkg # makelib_preprocessor_state_g is from
src/app/makelib/main/makelib-preprocessor-state-g.pkg fun backend_function NULL
=>
{ clear_internal_state ();
NULL;
};
backend_function
(THE
( generated_filename_infix, # Normally ""; if this is (e.g.) ".pwrpc32-macos", instead of "foo.pkg.compiled" we'll generate "foo.pkg.pwrpc32-macos.compiled".
libfile # 'libfile' string is .lib file to compile, in practice "src/etc/mythryl-compiler-root.lib" or "$ROOT/src/etc/mythryl-compiler-root.lib".
) )
=>
{
ffr::clear_state ();
# #define CMB_SERVER_MODE 1
#
(mps::find_makelib_preprocessor_symbol "CMB_SERVER_MODE").set # This gets checked (only) in
src/lib/core/internal/lib7-version.lib (THE 1);
case ( make_compiler
{
primary => FALSE, # We're running in a compile server process, not in the primary process.
libfile => THE libfile,
#
null_or_generated_filename_infix
=>
THE generated_filename_infix
}
)
#
THE ((g, makelib_state, anchor_dictionary), _)
=>
{ compile_tome_tin_after_dependencies'
=
cdo::compile_tome_tin_after_dependencies ();
#
fun compile_tome_tin_after_dependencies'' compiledfile
=
not_null (compile_tome_tin_after_dependencies' makelib_state compiledfile);
THE (g, compile_tome_tin_after_dependencies'', anchor_dictionary);
};
NULL => NULL;
esac;
};
end;
# compile_in_dependency_order_g is from
src/app/makelib/compile/compile-in-dependency-order-g.pkg # backend_index is from
src/app/makelib/mythryl-compiler-compiler/backend-index.pkg # "p" is backend_index
herein my _ =
p::register_per_platform_backend_function
platform
backend_function;
end;
# Toplevel entrypoint for recompiling compiler; we arrive
# here directly from make_compiler::make_compiler (); call in
# sh/make-compiler-libraries
# which gets invoked by compiler-libraries case in
# Makefile
# which gets invoked by compiler case in
# Makefile
# which we invoke by hand at the linux commandline.
#
fun make_mythryl_compiler ()
=
make_mythryl_compiler' NULL; # NULL is the null_or_generated_filename_infix arg.
find_makelib_preprocessor_symbol
=
mps::find_makelib_preprocessor_symbol;
# makelib_preprocessor_state_g is from
src/app/makelib/main/makelib-preprocessor-state-g.pkg };
end;
## (C) 1999 Lucent Technologies, Bell Laboratories
## Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.