give the new exposed symbols to the surgical linker

This commit is contained in:
Folkert 2023-02-25 19:35:46 +01:00
parent fee5e978f7
commit 454f3c603e
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
11 changed files with 163 additions and 75 deletions

View file

@ -7,7 +7,8 @@ use memmap2::{Mmap, MmapMut};
use object::Object;
use roc_build::link::{get_target_triple_str, rebuild_host, LinkType};
use roc_error_macros::internal_error;
use roc_load::{EntryPoint, ExecutionMode, LoadConfig, Threading};
use roc_load::{EntryPoint, ExecutionMode, ExposedToHost, LoadConfig, Threading};
use roc_module::symbol::Interns;
use roc_mono::ir::OptLevel;
use roc_packaging::cache::RocCacheDir;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
@ -59,8 +60,25 @@ pub fn build_and_preprocess_host(
target: &Triple,
platform_main_roc: &Path,
preprocessed_host_path: &Path,
exposed_to_host: Vec<String>,
exported_closure_types: Vec<String>,
exposed_symbols: ExposedSymbols,
) {
let stub_dll_symbols = exposed_symbols.stub_dll_symbols();
build_and_preprocess_host_lowlevel(
opt_level,
target,
platform_main_roc,
preprocessed_host_path,
&stub_dll_symbols,
)
}
pub fn build_and_preprocess_host_lowlevel(
opt_level: OptLevel,
target: &Triple,
platform_main_roc: &Path,
preprocessed_host_path: &Path,
stub_dll_symbols: &[String],
) {
let stub_lib = if let target_lexicon::OperatingSystem::Windows = target.operating_system {
platform_main_roc.with_file_name("libapp.dll")
@ -74,7 +92,6 @@ pub fn build_and_preprocess_host(
platform_main_roc.with_file_name("dynhost")
};
let stub_dll_symbols = make_stub_dll_symbols(exposed_to_host, exported_closure_types);
generate_dynamic_lib(target, &stub_dll_symbols, &stub_lib);
rebuild_host(opt_level, target, platform_main_roc, Some(&stub_lib));
@ -137,7 +154,7 @@ pub fn generate_stub_lib(
let exposed_to_host = loaded
.exposed_to_host
.values
.top_level_values
.keys()
.map(|x| x.as_str(&loaded.interns).to_string())
.collect();
@ -155,6 +172,11 @@ pub fn generate_stub_lib(
})
.collect();
let exposed_symbols = ExposedSymbols {
top_level_values: exposed_to_host,
exported_closure_types,
};
if let EntryPoint::Executable { platform_path, .. } = &loaded.entry_point {
let stub_lib = if let target_lexicon::OperatingSystem::Windows = triple.operating_system {
platform_path.with_file_name("libapp.obj")
@ -162,7 +184,7 @@ pub fn generate_stub_lib(
platform_path.with_file_name("libapp.so")
};
let stub_dll_symbols = make_stub_dll_symbols(exposed_to_host, exported_closure_types);
let stub_dll_symbols = exposed_symbols.stub_dll_symbols();
generate_dynamic_lib(triple, &stub_dll_symbols, &stub_lib);
} else {
unreachable!();
@ -170,33 +192,88 @@ pub fn generate_stub_lib(
Ok(0)
}
fn make_stub_dll_symbols(
exposed_to_host: Vec<String>,
exported_closure_types: Vec<String>,
) -> Vec<String> {
let mut custom_names = Vec::new();
pub struct ExposedSymbols {
// usually just `mainForhost`
pub top_level_values: Vec<String>,
for sym in exposed_to_host {
custom_names.extend([
format!("roc__{}_1_exposed", sym),
format!("roc__{}_1_exposed_generic", sym),
format!("roc__{}_size", sym),
]);
// old type exposing mechanism
pub exported_closure_types: Vec<String>,
}
impl ExposedSymbols {
pub fn from_exposed_to_host(interns: &Interns, exposed_to_host: &ExposedToHost) -> Vec<String> {
let mut custom_names = Vec::new();
for x in exposed_to_host.top_level_values.keys() {
let sym = x.as_str(interns);
for closure_type in &exported_closure_types {
custom_names.extend([
format!("roc__{}_1_{}_caller", sym, closure_type),
format!("roc__{}_1_{}_size", sym, closure_type),
format!("roc__{}_1_{}_result_size", sym, closure_type),
format!("roc__{}_1_exposed", sym),
format!("roc__{}_1_exposed_generic", sym),
format!("roc__{}_size", sym),
]);
let exported_closure_types = exposed_to_host
.closure_types
.iter()
.map(|x| format!("{}_{}", x.module_string(interns), x.as_str(interns)));
for closure_type in exported_closure_types {
custom_names.extend([
format!("roc__{}_1_{}_caller", sym, closure_type),
format!("roc__{}_1_{}_size", sym, closure_type),
format!("roc__{}_1_{}_result_size", sym, closure_type),
]);
}
}
for x in &exposed_to_host.getters {
let sym = x.as_str(interns);
custom_names.extend([
format!("{sym}"),
format!("{sym}_generic"),
format!("roc__{sym}_size"),
]);
}
for (top_level_value, lambda_set_id) in &exposed_to_host.lambda_sets {
let sym = top_level_value.as_str(interns);
let id = lambda_set_id.0;
custom_names.extend([format!("roc__{sym}_{id}_caller")]);
}
// on windows (PE) binary search is used on the symbols,
// so they must be in alphabetical order
custom_names.sort_unstable();
custom_names
}
// on windows (PE) binary search is used on the symbols,
// so they must be in alphabetical order
custom_names.sort_unstable();
fn stub_dll_symbols(&self) -> Vec<String> {
let mut custom_names = Vec::new();
custom_names
for sym in &self.top_level_values {
custom_names.extend([
format!("roc__{}_1_exposed", sym),
format!("roc__{}_1_exposed_generic", sym),
format!("roc__{}_size", sym),
]);
for closure_type in &self.exported_closure_types {
custom_names.extend([
format!("roc__{}_1_{}_caller", sym, closure_type),
format!("roc__{}_1_{}_size", sym, closure_type),
format!("roc__{}_1_{}_result_size", sym, closure_type),
]);
}
}
// on windows (PE) binary search is used on the symbols,
// so they must be in alphabetical order
custom_names.sort_unstable();
custom_names
}
}
fn generate_dynamic_lib(target: &Triple, stub_dll_symbols: &[String], stub_lib_path: &Path) {