mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 20:28:02 +00:00
Merge pull request #6448 from roc-lang/dev-backend-glue-new
glue with the dev backend works again
This commit is contained in:
commit
eadc0d37cd
6 changed files with 138 additions and 43 deletions
|
@ -2949,7 +2949,11 @@ impl<
|
|||
self.load_layout_alignment(list_layout, Symbol::DEV_TMP);
|
||||
|
||||
// Load element_width argument (usize).
|
||||
self.load_layout_stack_size(*ret_layout, Symbol::DEV_TMP2);
|
||||
let element_layout = match self.interner().get_repr(*ret_layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(e)) => e,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.load_layout_stack_size(element_layout, Symbol::DEV_TMP2);
|
||||
|
||||
// Load UpdateMode.Immutable argument (0u8)
|
||||
let u8_layout = Layout::U8;
|
||||
|
@ -4871,14 +4875,28 @@ impl<
|
|||
|
||||
// move a zero into the lower 8 bytes
|
||||
ASM::mov_reg64_imm64(buf, tmp_reg, 0x0);
|
||||
ASM::mov_base32_reg64(buf, base_offset, tmp_reg);
|
||||
ASM::mov_base32_reg64(buf, base_offset + 8, tmp_reg);
|
||||
|
||||
ASM::mov_base32_reg64(buf, base_offset + 8, src_reg);
|
||||
ASM::mov_base32_reg64(buf, base_offset, src_reg);
|
||||
|
||||
self.free_symbol(&tmp);
|
||||
|
||||
return;
|
||||
}
|
||||
(U128, I128) | (I128, U128) => {
|
||||
let to_offset = self.storage_manager.claim_stack_area_layout(
|
||||
self.layout_interner,
|
||||
*dst,
|
||||
Layout::from_int_width(target),
|
||||
);
|
||||
|
||||
let (from_offset, size) = self.storage_manager.stack_offset_and_size(src);
|
||||
|
||||
self.storage_manager
|
||||
.copy_to_stack_offset(buf, size, from_offset, to_offset);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,28 @@ pub fn build_module<'a, 'r>(
|
|||
layout_interner: &'r mut STLayoutInterner<'a>,
|
||||
target: &Triple,
|
||||
procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||
) -> Object<'a> {
|
||||
let module_object = build_module_help(env, interns, layout_interner, target, procedures);
|
||||
|
||||
if std::env::var("ROC_DEV_WRITE_OBJ").is_ok() {
|
||||
let module_out = module_object
|
||||
.write()
|
||||
.expect("failed to build output object");
|
||||
|
||||
let file_path = std::env::temp_dir().join("app.o");
|
||||
println!("gen-test object file written to {}", file_path.display());
|
||||
std::fs::write(&file_path, module_out).expect("failed to write object to file");
|
||||
}
|
||||
|
||||
module_object
|
||||
}
|
||||
|
||||
fn build_module_help<'a, 'r>(
|
||||
env: &'r Env<'a>,
|
||||
interns: &'r mut Interns,
|
||||
layout_interner: &'r mut STLayoutInterner<'a>,
|
||||
target: &Triple,
|
||||
procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||
) -> Object<'a> {
|
||||
match target {
|
||||
Triple {
|
||||
|
|
|
@ -821,6 +821,30 @@ fn list_append_longer_list() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_append_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
[
|
||||
{ name: "foo", content: "cfoo" },
|
||||
{ name: "bar", content: "cbar" },
|
||||
{ name: "baz", content: "cbaz" },
|
||||
]
|
||||
|> List.append { name: "spam", content: "cspam" }
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&[
|
||||
(RocStr::from("cfoo"), RocStr::from("foo"),),
|
||||
(RocStr::from("cbar"), RocStr::from("bar"),),
|
||||
(RocStr::from("cbaz"), RocStr::from("baz"),),
|
||||
(RocStr::from("cspam"), RocStr::from("spam"),),
|
||||
]),
|
||||
RocList<(RocStr, RocStr)>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_prepend() {
|
||||
|
|
|
@ -2320,7 +2320,7 @@ num_conversion_tests! {
|
|||
to_i64_truncate_wraps, "10_000_000_000_000_000_000i128", -8446744073709551616
|
||||
)
|
||||
"Num.toI128", i128, (
|
||||
to_i128_same_width, "15u128", 15
|
||||
to_i128_same_width, "15u128", 15, ["gen-dev"]
|
||||
to_i128_extend, "15i8", 15
|
||||
)
|
||||
"Num.toU8", u8, (
|
||||
|
@ -2347,8 +2347,9 @@ num_conversion_tests! {
|
|||
to_u64_truncate_wraps, "10_000_000_000_000_000_000_000i128", 1864712049423024128
|
||||
)
|
||||
"Num.toU128", u128, (
|
||||
to_u128_same_width, "15i128", 15
|
||||
to_u128_same_width, "15i128", 15, ["gen-dev"]
|
||||
to_u128_extend, "15i8", 15
|
||||
to_u128_big, "11562537357600483583u64", 11562537357600483583, ["gen-dev"]
|
||||
)
|
||||
"Num.toNat", usize, (
|
||||
to_nat_same_width, "15i64", 15, ["gen-wasm", "gen-dev"]
|
||||
|
|
|
@ -215,12 +215,6 @@ pub fn helper(
|
|||
let builtins_host_tempfile =
|
||||
roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
|
||||
|
||||
if std::env::var("ROC_DEV_WRITE_OBJ").is_ok() {
|
||||
let file_path = std::env::temp_dir().join("app.o");
|
||||
println!("gen-test object file written to {}", file_path.display());
|
||||
std::fs::copy(&app_o_file, file_path).unwrap();
|
||||
}
|
||||
|
||||
let (mut child, dylib_path) = link(
|
||||
&target,
|
||||
app_o_file.clone(),
|
||||
|
|
|
@ -131,46 +131,19 @@ pub fn generate(
|
|||
}
|
||||
|
||||
let lib = unsafe { Library::new(lib_path) }.unwrap();
|
||||
type MakeGlueReturnType =
|
||||
roc_std::RocResult<roc_std::RocList<roc_type::File>, roc_std::RocStr>;
|
||||
type MakeGlue = unsafe extern "C" fn(
|
||||
*mut RocCallResult<MakeGlueReturnType>,
|
||||
&roc_std::RocList<roc_type::Types>,
|
||||
);
|
||||
|
||||
let make_glue: libloading::Symbol<MakeGlue> = unsafe {
|
||||
lib.get("roc__makeGlueForHost_1_exposed_generic".as_bytes())
|
||||
.unwrap_or_else(|_| panic!("Unable to load glue function"))
|
||||
};
|
||||
let roc_types: roc_std::RocList<roc_type::Types> =
|
||||
types.iter().map(|x| x.into()).collect();
|
||||
let mut files =
|
||||
RocCallResult::new(roc_std::RocResult::err(roc_std::RocStr::empty()));
|
||||
unsafe { make_glue(&mut files, &roc_types) };
|
||||
|
||||
// Roc will free data passed into it. So forget that data.
|
||||
std::mem::forget(roc_types);
|
||||
// NOTE: DO NOT DROP LIB! the return value will include static roc strings that
|
||||
// are only kept alive when the dynamic library is not unloaded!
|
||||
let files = call_roc_make_glue(&lib, backend, roc_types);
|
||||
|
||||
let files: Result<roc_std::RocList<roc_type::File>, roc_std::RocStr> =
|
||||
match Result::from(files) {
|
||||
Err((msg, tag)) => match tag {
|
||||
CrashTag::Roc => panic!(r#"Roc failed with message: "{msg}""#),
|
||||
CrashTag::User => panic!(r#"User crash with message: "{msg}""#),
|
||||
},
|
||||
Ok(x) => x.into(),
|
||||
};
|
||||
|
||||
let files = files.unwrap_or_else(|err| {
|
||||
eprintln!("Glue generation failed: {err}");
|
||||
|
||||
process::exit(1);
|
||||
});
|
||||
for roc_type::File { name, content } in &files {
|
||||
let valid_name = PathBuf::from(name.as_str())
|
||||
.components()
|
||||
.all(|comp| matches!(comp, Component::CurDir | Component::Normal(_)));
|
||||
if !valid_name {
|
||||
eprintln!("File name was invalid: {}", &name);
|
||||
if !valid_name || name.is_empty() {
|
||||
eprintln!("File name was invalid: {:?}", &name);
|
||||
|
||||
process::exit(1);
|
||||
}
|
||||
|
@ -243,6 +216,69 @@ pub fn generate(
|
|||
}
|
||||
}
|
||||
|
||||
fn call_roc_make_glue(
|
||||
lib: &Library,
|
||||
backend: CodeGenBackend,
|
||||
roc_types: roc_std::RocList<roc_type::Types>,
|
||||
) -> roc_std::RocList<roc_type::File> {
|
||||
let roc_call_result = match backend {
|
||||
CodeGenBackend::Assembly(_) => {
|
||||
type MakeGlueReturnType = RocCallResult<
|
||||
roc_std::RocResult<roc_std::RocList<roc_type::File>, roc_std::RocStr>,
|
||||
>;
|
||||
type MakeGlue =
|
||||
unsafe extern "C" fn(roc_std::RocList<roc_type::Types>) -> MakeGlueReturnType;
|
||||
|
||||
let name_of_main = "test_main";
|
||||
|
||||
let make_glue: libloading::Symbol<MakeGlue> = unsafe {
|
||||
lib.get(name_of_main.as_bytes())
|
||||
.unwrap_or_else(|_| panic!("Unable to load glue function"))
|
||||
};
|
||||
|
||||
unsafe { make_glue(roc_types) }
|
||||
}
|
||||
CodeGenBackend::Llvm(_) => {
|
||||
type MakeGlueReturnType =
|
||||
roc_std::RocResult<roc_std::RocList<roc_type::File>, roc_std::RocStr>;
|
||||
type MakeGlue = unsafe extern "C" fn(
|
||||
*mut RocCallResult<MakeGlueReturnType>,
|
||||
&roc_std::RocList<roc_type::Types>,
|
||||
);
|
||||
|
||||
let name_of_main = "roc__makeGlueForHost_1_exposed_generic";
|
||||
|
||||
let make_glue: libloading::Symbol<MakeGlue> = unsafe {
|
||||
lib.get(name_of_main.as_bytes())
|
||||
.unwrap_or_else(|_| panic!("Unable to load glue function"))
|
||||
};
|
||||
let mut files = RocCallResult::new(roc_std::RocResult::err(roc_std::RocStr::empty()));
|
||||
unsafe { make_glue(&mut files, &roc_types) };
|
||||
|
||||
// Roc will free data passed into it. So forget that data.
|
||||
std::mem::forget(roc_types);
|
||||
|
||||
files
|
||||
}
|
||||
|
||||
CodeGenBackend::Wasm => todo!(),
|
||||
};
|
||||
|
||||
match Result::from(roc_call_result) {
|
||||
Err((msg, tag)) => match tag {
|
||||
CrashTag::Roc => panic!(r#"Roc failed with message: "{msg}""#),
|
||||
CrashTag::User => panic!(r#"User crash with message: "{msg}""#),
|
||||
},
|
||||
Ok(files_or_error) => match Result::from(files_or_error) {
|
||||
Err(err) => {
|
||||
eprintln!("Glue generation failed: {err}");
|
||||
process::exit(1);
|
||||
}
|
||||
Ok(files) => files,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn number_lambda_sets(subs: &Subs, initial: Variable) -> Vec<Variable> {
|
||||
let mut lambda_sets = vec![];
|
||||
let mut stack = vec![initial];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue