mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-13 09:49:11 +03:00
make the surgical linker aware of custom exported closure names
This commit is contained in:
parent
eb08c12099
commit
73bc50c952
@ -105,6 +105,21 @@ pub fn build_file<'a>(
|
||||
// To do this we will need to preprocess files just for their exported symbols.
|
||||
// Also, we should no longer need to do this once we have platforms on
|
||||
// a package repository, as we can then get precompiled hosts from there.
|
||||
|
||||
let exposed_values = loaded
|
||||
.exposed_to_host
|
||||
.values
|
||||
.keys()
|
||||
.map(|x| x.as_str(&loaded.interns).to_string())
|
||||
.collect();
|
||||
|
||||
let exposed_closure_types = loaded
|
||||
.exposed_to_host
|
||||
.closure_types
|
||||
.iter()
|
||||
.map(|x| x.as_str(&loaded.interns).to_string())
|
||||
.collect();
|
||||
|
||||
let rebuild_thread = spawn_rebuild_thread(
|
||||
opt_level,
|
||||
surgically_link,
|
||||
@ -112,11 +127,8 @@ pub fn build_file<'a>(
|
||||
host_input_path.clone(),
|
||||
binary_path.clone(),
|
||||
target,
|
||||
loaded
|
||||
.exposed_to_host
|
||||
.keys()
|
||||
.map(|x| x.as_str(&loaded.interns).to_string())
|
||||
.collect(),
|
||||
exposed_values,
|
||||
exposed_closure_types,
|
||||
target_valgrind,
|
||||
);
|
||||
|
||||
@ -291,6 +303,7 @@ fn spawn_rebuild_thread(
|
||||
binary_path: PathBuf,
|
||||
target: &Triple,
|
||||
exported_symbols: Vec<String>,
|
||||
exported_closure_types: Vec<String>,
|
||||
target_valgrind: bool,
|
||||
) -> std::thread::JoinHandle<u128> {
|
||||
let thread_local_target = target.clone();
|
||||
@ -305,6 +318,7 @@ fn spawn_rebuild_thread(
|
||||
&thread_local_target,
|
||||
host_input_path.as_path(),
|
||||
exported_symbols,
|
||||
exported_closure_types,
|
||||
target_valgrind,
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -146,8 +146,8 @@ pub fn gen_and_eval<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert_eq!(exposed_to_host.len(), 1);
|
||||
let (main_fn_symbol, main_fn_var) = exposed_to_host.iter().next().unwrap();
|
||||
debug_assert_eq!(exposed_to_host.values.len(), 1);
|
||||
let (main_fn_symbol, main_fn_var) = exposed_to_host.values.iter().next().unwrap();
|
||||
let main_fn_symbol = *main_fn_symbol;
|
||||
let main_fn_var = *main_fn_var;
|
||||
|
||||
|
@ -87,7 +87,7 @@ mod cli_run {
|
||||
|
||||
let compile_out = run_roc(&[&["build", file.to_str().unwrap()], &all_flags[..]].concat());
|
||||
if !compile_out.stderr.is_empty() {
|
||||
panic!("{}", compile_out.stderr);
|
||||
panic!("roc build had stderr: {}", compile_out.stderr);
|
||||
}
|
||||
|
||||
assert!(compile_out.status.success(), "bad status {:?}", compile_out);
|
||||
|
@ -753,49 +753,52 @@ fn link_linux(
|
||||
|
||||
// NOTE: order of arguments to `ld` matters here!
|
||||
// The `-l` flags should go after the `.o` arguments
|
||||
Ok((
|
||||
Command::new("ld")
|
||||
// Don't allow LD_ env vars to affect this
|
||||
.env_clear()
|
||||
.env("PATH", &env_path)
|
||||
// Keep NIX_ env vars
|
||||
.envs(
|
||||
env::vars()
|
||||
.filter(|&(ref k, _)| k.starts_with("NIX_"))
|
||||
.collect::<HashMap<String, String>>(),
|
||||
)
|
||||
.args(&[
|
||||
"--gc-sections",
|
||||
"--eh-frame-hdr",
|
||||
"-A",
|
||||
arch_str(target),
|
||||
"-pie",
|
||||
libcrt_path.join("crti.o").to_str().unwrap(),
|
||||
libcrt_path.join("crtn.o").to_str().unwrap(),
|
||||
])
|
||||
.args(&base_args)
|
||||
.args(&["-dynamic-linker", ld_linux])
|
||||
.args(input_paths)
|
||||
// ld.lld requires this argument, and does not accept --arch
|
||||
// .args(&["-L/usr/lib/x86_64-linux-gnu"])
|
||||
.args(&[
|
||||
// Libraries - see https://github.com/rtfeldman/roc/pull/554#discussion_r496365925
|
||||
// for discussion and further references
|
||||
"-lc",
|
||||
"-lm",
|
||||
"-lpthread",
|
||||
"-ldl",
|
||||
"-lrt",
|
||||
"-lutil",
|
||||
"-lc_nonshared",
|
||||
libgcc_path.to_str().unwrap(),
|
||||
// Output
|
||||
"-o",
|
||||
output_path.as_path().to_str().unwrap(), // app (or app.so or app.dylib etc.)
|
||||
])
|
||||
.spawn()?,
|
||||
output_path,
|
||||
))
|
||||
|
||||
let mut command = Command::new("ld");
|
||||
|
||||
command
|
||||
// Don't allow LD_ env vars to affect this
|
||||
.env_clear()
|
||||
.env("PATH", &env_path)
|
||||
// Keep NIX_ env vars
|
||||
.envs(
|
||||
env::vars()
|
||||
.filter(|&(ref k, _)| k.starts_with("NIX_"))
|
||||
.collect::<HashMap<String, String>>(),
|
||||
)
|
||||
.args(&[
|
||||
"--gc-sections",
|
||||
"--eh-frame-hdr",
|
||||
"-A",
|
||||
arch_str(target),
|
||||
"-pie",
|
||||
libcrt_path.join("crti.o").to_str().unwrap(),
|
||||
libcrt_path.join("crtn.o").to_str().unwrap(),
|
||||
])
|
||||
.args(&base_args)
|
||||
.args(&["-dynamic-linker", ld_linux])
|
||||
.args(input_paths)
|
||||
// ld.lld requires this argument, and does not accept --arch
|
||||
// .args(&["-L/usr/lib/x86_64-linux-gnu"])
|
||||
.args(&[
|
||||
// Libraries - see https://github.com/rtfeldman/roc/pull/554#discussion_r496365925
|
||||
// for discussion and further references
|
||||
"-lc",
|
||||
"-lm",
|
||||
"-lpthread",
|
||||
"-ldl",
|
||||
"-lrt",
|
||||
"-lutil",
|
||||
"-lc_nonshared",
|
||||
libgcc_path.to_str().unwrap(),
|
||||
// Output
|
||||
"-o",
|
||||
output_path.as_path().to_str().unwrap(), // app (or app.so or app.dylib etc.)
|
||||
]);
|
||||
|
||||
let output = command.spawn()?;
|
||||
|
||||
Ok((output, output_path))
|
||||
}
|
||||
|
||||
fn link_macos(
|
||||
|
@ -290,7 +290,7 @@ pub fn gen_from_mono_module_llvm(
|
||||
// in gen_tests, the compiler provides roc_panic
|
||||
// and sets up the setjump/longjump exception handling
|
||||
is_gen_test: false,
|
||||
exposed_to_host: loaded.exposed_to_host.keys().copied().collect(),
|
||||
exposed_to_host: loaded.exposed_to_host.values.keys().copied().collect(),
|
||||
};
|
||||
|
||||
roc_gen_llvm::llvm::build::build_procedures(
|
||||
@ -495,6 +495,7 @@ fn gen_from_mono_module_dev_wasm32(
|
||||
|
||||
let exposed_to_host = loaded
|
||||
.exposed_to_host
|
||||
.values
|
||||
.keys()
|
||||
.copied()
|
||||
.collect::<MutSet<_>>();
|
||||
@ -544,7 +545,7 @@ fn gen_from_mono_module_dev_assembly(
|
||||
let env = roc_gen_dev::Env {
|
||||
arena,
|
||||
module_id,
|
||||
exposed_to_host: exposed_to_host.keys().copied().collect(),
|
||||
exposed_to_host: exposed_to_host.values.keys().copied().collect(),
|
||||
lazy_literals,
|
||||
generate_allocators,
|
||||
};
|
||||
|
@ -737,11 +737,19 @@ pub struct MonomorphizedModule<'a> {
|
||||
pub mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>,
|
||||
pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||
pub entry_point: EntryPoint<'a>,
|
||||
pub exposed_to_host: MutMap<Symbol, Variable>,
|
||||
pub exposed_to_host: ExposedToHost,
|
||||
pub sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
|
||||
pub timings: MutMap<ModuleId, ModuleTiming>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ExposedToHost {
|
||||
/// usually `mainForHost`
|
||||
pub values: MutMap<Symbol, Variable>,
|
||||
/// exposed closure types, typically `Fx`
|
||||
pub closure_types: Vec<Symbol>,
|
||||
}
|
||||
|
||||
impl<'a> MonomorphizedModule<'a> {
|
||||
pub fn total_problems(&self) -> usize {
|
||||
let mut total = 0;
|
||||
@ -837,7 +845,7 @@ enum Msg<'a> {
|
||||
/// all modules are now monomorphized, we are done
|
||||
FinishedAllSpecialization {
|
||||
subs: Subs,
|
||||
exposed_to_host: MutMap<Symbol, Variable>,
|
||||
exposed_to_host: ExposedToHost,
|
||||
},
|
||||
|
||||
FailedToParse(FileError<'a, SyntaxError<'a>>),
|
||||
@ -875,7 +883,7 @@ struct State<'a> {
|
||||
pub module_cache: ModuleCache<'a>,
|
||||
pub dependencies: Dependencies<'a>,
|
||||
pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||
pub exposed_to_host: MutMap<Symbol, Variable>,
|
||||
pub exposed_to_host: ExposedToHost,
|
||||
|
||||
/// This is the "final" list of IdentIds, after canonicalization and constraint gen
|
||||
/// have completed for a given module.
|
||||
@ -1008,7 +1016,7 @@ enum BuildTask<'a> {
|
||||
module_id: ModuleId,
|
||||
ident_ids: IdentIds,
|
||||
decls: Vec<Declaration>,
|
||||
exposed_to_host: MutMap<Symbol, Variable>,
|
||||
exposed_to_host: ExposedToHost,
|
||||
},
|
||||
MakeSpecializations {
|
||||
module_id: ModuleId,
|
||||
@ -1475,7 +1483,7 @@ where
|
||||
module_cache: ModuleCache::default(),
|
||||
dependencies: Dependencies::default(),
|
||||
procedures: MutMap::default(),
|
||||
exposed_to_host: MutMap::default(),
|
||||
exposed_to_host: ExposedToHost::default(),
|
||||
exposed_types,
|
||||
arc_modules,
|
||||
arc_shorthands,
|
||||
@ -1937,12 +1945,17 @@ fn update<'a>(
|
||||
};
|
||||
|
||||
if is_host_exposed {
|
||||
state.exposed_to_host.extend(
|
||||
state.exposed_to_host.values.extend(
|
||||
solved_module
|
||||
.exposed_vars_by_symbol
|
||||
.iter()
|
||||
.map(|(k, v)| (*k, *v)),
|
||||
);
|
||||
|
||||
state
|
||||
.exposed_to_host
|
||||
.closure_types
|
||||
.extend(solved_module.aliases.keys().copied());
|
||||
}
|
||||
|
||||
if is_host_exposed && state.goal_phase == Phase::SolveTypes {
|
||||
@ -2177,7 +2190,7 @@ fn update<'a>(
|
||||
fn finish_specialization(
|
||||
state: State,
|
||||
subs: Subs,
|
||||
exposed_to_host: MutMap<Symbol, Variable>,
|
||||
exposed_to_host: ExposedToHost,
|
||||
) -> Result<MonomorphizedModule, LoadingProblem> {
|
||||
let module_ids = Arc::try_unwrap(state.arc_modules)
|
||||
.unwrap_or_else(|_| panic!("There were still outstanding Arc references to module_ids"))
|
||||
@ -2235,8 +2248,8 @@ fn finish_specialization(
|
||||
let entry_point = {
|
||||
let symbol = match platform_data {
|
||||
None => {
|
||||
debug_assert_eq!(exposed_to_host.len(), 1);
|
||||
*exposed_to_host.iter().next().unwrap().0
|
||||
debug_assert_eq!(exposed_to_host.values.len(), 1);
|
||||
*exposed_to_host.values.iter().next().unwrap().0
|
||||
}
|
||||
Some(PlatformData { provides, .. }) => provides,
|
||||
};
|
||||
@ -3884,7 +3897,7 @@ fn build_pending_specializations<'a>(
|
||||
mut layout_cache: LayoutCache<'a>,
|
||||
ptr_bytes: u32,
|
||||
// TODO remove
|
||||
exposed_to_host: MutMap<Symbol, Variable>,
|
||||
exposed_to_host: ExposedToHost,
|
||||
) -> Msg<'a> {
|
||||
let find_specializations_start = SystemTime::now();
|
||||
|
||||
@ -3924,7 +3937,7 @@ fn build_pending_specializations<'a>(
|
||||
&mut module_thunks,
|
||||
&mut mono_env,
|
||||
def,
|
||||
&exposed_to_host,
|
||||
&exposed_to_host.values,
|
||||
false,
|
||||
),
|
||||
DeclareRec(defs) => {
|
||||
@ -3935,7 +3948,7 @@ fn build_pending_specializations<'a>(
|
||||
&mut module_thunks,
|
||||
&mut mono_env,
|
||||
def,
|
||||
&exposed_to_host,
|
||||
&exposed_to_host.values,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
@ -142,10 +142,11 @@ pub fn build_and_preprocess_host(
|
||||
target: &Triple,
|
||||
host_input_path: &Path,
|
||||
exposed_to_host: Vec<String>,
|
||||
exported_closure_types: Vec<String>,
|
||||
target_valgrind: bool,
|
||||
) -> io::Result<()> {
|
||||
let dummy_lib = host_input_path.with_file_name("libapp.so");
|
||||
generate_dynamic_lib(target, exposed_to_host, &dummy_lib)?;
|
||||
generate_dynamic_lib(target, exposed_to_host, exported_closure_types, &dummy_lib)?;
|
||||
rebuild_host(
|
||||
opt_level,
|
||||
target,
|
||||
@ -193,6 +194,7 @@ pub fn link_preprocessed_host(
|
||||
fn generate_dynamic_lib(
|
||||
_target: &Triple,
|
||||
exposed_to_host: Vec<String>,
|
||||
exported_closure_types: Vec<String>,
|
||||
dummy_lib_path: &Path,
|
||||
) -> io::Result<()> {
|
||||
let dummy_obj_file = Builder::new().prefix("roc_lib").suffix(".o").tempfile()?;
|
||||
@ -203,25 +205,37 @@ fn generate_dynamic_lib(
|
||||
write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little);
|
||||
|
||||
let text_section = out_object.section_id(write::StandardSection::Text);
|
||||
|
||||
let mut add_symbol = |name: &String| {
|
||||
out_object.add_symbol(write::Symbol {
|
||||
name: name.as_bytes().to_vec(),
|
||||
value: 0,
|
||||
size: 0,
|
||||
kind: SymbolKind::Text,
|
||||
scope: SymbolScope::Dynamic,
|
||||
weak: false,
|
||||
section: write::SymbolSection::Section(text_section),
|
||||
flags: SymbolFlags::None,
|
||||
});
|
||||
};
|
||||
|
||||
for sym in exposed_to_host {
|
||||
for name in &[
|
||||
format!("roc__{}_1_exposed", sym),
|
||||
format!("roc__{}_1_exposed_generic", sym),
|
||||
format!("roc__{}_1_Fx_caller", sym),
|
||||
format!("roc__{}_1_Fx_size", sym),
|
||||
format!("roc__{}_1_Fx_result_size", sym),
|
||||
format!("roc__{}_size", sym),
|
||||
] {
|
||||
out_object.add_symbol(write::Symbol {
|
||||
name: name.as_bytes().to_vec(),
|
||||
value: 0,
|
||||
size: 0,
|
||||
kind: SymbolKind::Text,
|
||||
scope: SymbolScope::Dynamic,
|
||||
weak: false,
|
||||
section: write::SymbolSection::Section(text_section),
|
||||
flags: SymbolFlags::None,
|
||||
});
|
||||
add_symbol(name);
|
||||
}
|
||||
|
||||
for closure_type in &exported_closure_types {
|
||||
for name in &[
|
||||
format!("roc__{}_1_{}_caller", sym, closure_type),
|
||||
format!("roc__{}_1_{}_size", sym, closure_type),
|
||||
format!("roc__{}_1_{}_result_size", sym, closure_type),
|
||||
] {
|
||||
add_symbol(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
std::fs::write(
|
||||
|
Loading…
Reference in New Issue
Block a user