fix function getters

This commit is contained in:
Folkert 2023-02-25 15:47:20 +01:00
parent 033618f3f4
commit 35980e50b8
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
5 changed files with 218 additions and 220 deletions

View file

@ -3949,8 +3949,6 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>(
let params = c_function.get_params();
dbg!(&params);
let param_types = Vec::from_iter_in(roc_function.get_type().get_param_types(), env.arena);
let (params, param_types) = match (&roc_return, &cc_return) {
@ -4151,7 +4149,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
Some(env.context.i64_type().as_basic_type_enum()),
&[],
);
let size_function_name: String = format!("roc__{}_size", ident_string);
let size_function_name: String = format!("roc__{}_size", c_function_name);
let size_function = add_func(
env.context,
@ -4644,8 +4642,6 @@ pub fn build_procedures<'a, 'ctx, 'env>(
let name = getter_fn.get_name().to_str().unwrap();
let getter_name = symbol.as_str(&env.interns);
dbg!(&getter_name);
// Add the getter function to the module.
let _ = expose_function_to_host_help_c_abi(
env,

View file

@ -3008,7 +3008,6 @@ fn specialize_host_specializations<'a>(
layout_cache: &mut LayoutCache<'a>,
host_specializations: HostSpecializations<'a>,
) {
dbg!(&host_specializations.symbol_or_lambdas);
let (store, it) = host_specializations.decompose();
let offset_variable = StorageSubs::merge_into(store, env.subs);
@ -11425,7 +11424,8 @@ fn unique_glue_symbol(
let _result = write!(&mut string, "roc__getter_{}_{}", module_name, unique_id);
debug_assert_eq!(_result, Ok(())); // This should never fail, but doesn't hurt to debug-check!
let ident_id = ident_ids.get_or_insert(string.into_bump_str());
let bump_string = string.into_bump_str();
let ident_id = ident_ids.get_or_insert(bump_string);
Symbol::new(home, ident_id)
}

View file

@ -1047,27 +1047,51 @@ pub struct {name} {{
let getter_name = &accessor.getter;
let ret = type_name(*field, types);
let returns_via_pointer = true;
let body = if returns_via_pointer {
let body = if let RocType::Function(_) = types.get_type(*field) {
format!(
r#"extern "C" {{
#[link_name = "{getter_name}"]
r#"
extern "C" {{
#[link_name = "roc__{getter_name}_size"]
fn size() -> usize;
#[link_name = "{getter_name}_generic"]
fn getter(_: *mut u8, _: *const {name});
}}
// dumb heap allocation for now
let mut bytes = vec![0xAAu8; size()];
getter(bytes.as_mut_ptr(), self);
{ret} {{
closure_data: bytes,
}}
"#
)
} else if returns_via_pointer {
format!(
r#"
extern "C" {{
#[link_name = "{getter_name}_generic"]
fn getter(_: *mut {ret}, _: *const {name});
}}
let mut ret = core::mem::MaybeUninit::uninit();
getter(ret.as_mut_ptr(), self);
ret.assume_init()"#
ret.assume_init()
"#
)
} else {
format!(
r#"extern "C" {{
r#"
extern "C" {{
#[link_name = "{getter_name}"]
fn getter(_: *const {name}) -> {ret};
}}
getter(self)"#
getter(self)
"#
)
};
@ -1849,7 +1873,7 @@ fn add_function(
writeln!(buf, "impl {name} {{").unwrap();
write!(buf, "{INDENT}pub fn force_thunk(self").unwrap();
write!(buf, "{INDENT}pub fn force_thunk(mut self").unwrap();
for (i, argument_type) in roc_fn.args.iter().enumerate() {
write!(buf, ", arg_{i}: {}", type_name(*argument_type, types)).unwrap();
}
@ -1858,17 +1882,17 @@ fn add_function(
writeln!(buf, "{INDENT}{INDENT}extern \"C\" {{").unwrap();
// fn extern_name(output: *mut return_type, arg1: arg1_type, ..., closure_data: *mut u8);
write!(
buf,
"{INDENT}{INDENT}{INDENT} fn {extern_name}(output: *mut {return_type_str}, "
)
.unwrap();
write!(buf, "{INDENT}{INDENT}{INDENT} fn {extern_name}(").unwrap();
for (i, argument_type) in roc_fn.args.iter().enumerate() {
write!(buf, "arg_{i}: {}, ", type_name(*argument_type, types)).unwrap();
write!(buf, "arg_{i}: &{}, ", type_name(*argument_type, types)).unwrap();
}
writeln!(buf, "closure_data: *mut u8);").unwrap();
writeln!(
buf,
"closure_data: *mut u8, output: *mut {return_type_str});"
)
.unwrap();
// {argument_types} "
@ -1882,17 +1906,17 @@ fn add_function(
)
.unwrap();
write!(
buf,
"{INDENT}{INDENT}unsafe {{ {extern_name}(output.as_mut_ptr(), "
)
.unwrap();
write!(buf, "{INDENT}{INDENT}unsafe {{ {extern_name}(").unwrap();
for (i, _) in roc_fn.args.iter().enumerate() {
write!(buf, "arg_{i}, ").unwrap();
write!(buf, "&arg_{i}, ").unwrap();
}
writeln!(buf, "self.closure_data) }};").unwrap();
writeln!(
buf,
"self.closure_data.as_mut_ptr(), output.as_mut_ptr()) }};"
)
.unwrap();
writeln!(buf, "{INDENT}{INDENT}unsafe {{ output.assume_init() }}").unwrap();
@ -1977,7 +2001,7 @@ fn type_name(id: TypeId, types: &Types) -> String {
RocType::RocSet(elem_id) => format!("roc_std::RocSet<{}>", type_name(*elem_id, types)),
RocType::RocList(elem_id) => format!("roc_std::RocList<{}>", type_name(*elem_id, types)),
RocType::RocBox(elem_id) => format!("roc_std::RocBox<{}>", type_name(*elem_id, types)),
RocType::Unsized => "*mut u8".to_string(),
RocType::Unsized => "Vec<u8>".to_string(),
RocType::RocResult(ok_id, err_id) => {
format!(
"roc_std::RocResult<{}, {}>",

View file

@ -15,7 +15,7 @@ use roc_mono::{
ir::LambdaSetId,
layout::{
cmp_fields, ext_var_is_empty_tag_union, round_up_to_alignment, Builtin, Discriminant,
InLayout, LambdaSet, Layout, LayoutCache, LayoutInterner, TLLayoutInterner, UnionLayout,
InLayout, Layout, LayoutCache, LayoutInterner, TLLayoutInterner, UnionLayout,
},
};
use roc_target::TargetInfo;

View file

@ -59,7 +59,6 @@ pub struct Op {
pointer: *mut union_Op,
}
#[cfg(any(
target_arch = "arm",
target_arch = "aarch64",
@ -87,7 +86,6 @@ union union_Op {
target_arch = "x86_64"
))]
//TODO HAS CLOSURE 2
#[cfg(any(
target_arch = "arm",
target_arch = "aarch64",
@ -95,20 +93,21 @@ union union_Op {
target_arch = "x86",
target_arch = "x86_64"
))]
#[repr(C)]
pub struct RocFunction_66 {
pub closure_data: *mut u8,
pub closure_data: Vec<u8>,
}
impl RocFunction_66 {
pub fn force_thunk(self, arg_0: ()) -> Op {
pub fn force_thunk(mut self, arg_0: ()) -> Op {
extern "C" {
fn roc__mainForHost_0_caller(output: *mut Op, arg_0: (), closure_data: *mut u8);
fn roc__mainForHost_0_caller(arg_0: &(), closure_data: *mut u8, output: *mut Op);
}
let mut output = std::mem::MaybeUninit::uninit();
unsafe { roc__mainForHost_0_caller(output.as_mut_ptr(), arg_0, self.closure_data) };
unsafe {
roc__mainForHost_0_caller(&arg_0, self.closure_data.as_mut_ptr(), output.as_mut_ptr())
};
unsafe { output.assume_init() }
}
}
@ -120,20 +119,21 @@ impl RocFunction_66 {
target_arch = "x86",
target_arch = "x86_64"
))]
#[repr(C)]
pub struct RocFunction_67 {
pub closure_data: *mut u8,
pub closure_data: Vec<u8>,
}
impl RocFunction_67 {
pub fn force_thunk(self, arg_0: ()) -> Op {
pub fn force_thunk(mut self, arg_0: ()) -> Op {
extern "C" {
fn roc__mainForHost_1_caller(output: *mut Op, arg_0: (), closure_data: *mut u8);
fn roc__mainForHost_1_caller(arg_0: &(), closure_data: *mut u8, output: *mut Op);
}
let mut output = std::mem::MaybeUninit::uninit();
unsafe { roc__mainForHost_1_caller(output.as_mut_ptr(), arg_0, self.closure_data) };
unsafe {
roc__mainForHost_1_caller(&arg_0, self.closure_data.as_mut_ptr(), output.as_mut_ptr())
};
unsafe { output.assume_init() }
}
}
@ -161,28 +161,18 @@ impl Op {
if untagged.is_null() {
None
} else {
unsafe {
Some(&*untagged.sub(1))
}
unsafe { Some(&*untagged.sub(1)) }
}
}
#[cfg(any(
target_arch = "arm",
target_arch = "wasm32",
target_arch = "x86"
))]
#[cfg(any(target_arch = "arm", target_arch = "wasm32", target_arch = "x86"))]
/// Returns which variant this tag union holds. Note that this never includes a payload!
pub fn discriminant(&self) -> discriminant_Op {
// The discriminant is stored in the unused bytes at the end of the recursive pointer
unsafe { core::mem::transmute::<u8, discriminant_Op>((self.pointer as u8) & 0b11) }
}
#[cfg(any(
target_arch = "arm",
target_arch = "wasm32",
target_arch = "x86"
))]
#[cfg(any(target_arch = "arm", target_arch = "wasm32", target_arch = "x86"))]
/// Internal helper
fn tag_discriminant(pointer: *mut union_Op, discriminant: discriminant_Op) -> *mut union_Op {
// The discriminant is stored in the unused bytes at the end of the union pointer
@ -192,11 +182,7 @@ impl Op {
tagged as *mut union_Op
}
#[cfg(any(
target_arch = "arm",
target_arch = "wasm32",
target_arch = "x86"
))]
#[cfg(any(target_arch = "arm", target_arch = "wasm32", target_arch = "x86"))]
/// Internal helper
fn union_pointer(&self) -> *mut union_Op {
// The discriminant is stored in the unused bytes at the end of the union pointer
@ -229,14 +215,12 @@ impl Op {
debug_assert_eq!(self.discriminant(), discriminant_Op::StderrWrite);
extern "C" {
#[link_name = "roc__getter__2"]
#[link_name = "roc__getter__2_generic"]
fn getter(_: *mut roc_std::RocStr, _: *const Op);
}
let mut ret = core::mem::MaybeUninit::uninit();
getter(ret.as_mut_ptr(), self);
ret.assume_init()
}
@ -254,15 +238,21 @@ impl Op {
debug_assert_eq!(self.discriminant(), discriminant_Op::StderrWrite);
extern "C" {
#[link_name = "roc__getter__3"]
fn getter(_: *mut RocFunction_67, _: *const Op);
#[link_name = "roc__roc__getter__3_size"]
fn size() -> usize;
#[link_name = "roc__getter__3_generic"]
fn getter(_: *mut u8, _: *const Op);
}
let mut ret = core::mem::MaybeUninit::uninit();
// dumb heap allocation for now
let mut bytes = vec![0xAAu8; size()];
getter(ret.as_mut_ptr(), self);
getter(bytes.as_mut_ptr(), self);
ret.assume_init()
RocFunction_67 {
closure_data: bytes,
}
}
#[cfg(any(
@ -281,7 +271,7 @@ impl Op {
let ptr = roc_std::roc_alloc_refcounted::<union_Op>();
*ptr = union_Op {
StderrWrite: core::mem::ManuallyDrop::new(arg)
StderrWrite: core::mem::ManuallyDrop::new(arg),
};
Self {
@ -290,11 +280,7 @@ impl Op {
}
}
#[cfg(any(
target_arch = "arm",
target_arch = "wasm32",
target_arch = "x86"
))]
#[cfg(any(target_arch = "arm", target_arch = "wasm32", target_arch = "x86"))]
/// Unsafely assume this `Op` has a `.discriminant()` of `StderrWrite` and convert it to `StderrWrite`'s payload.
/// (Always examine `.discriminant()` first to make sure this is the correct variant!)
/// Panics in debug builds if the `.discriminant()` doesn't return `StderrWrite`.
@ -318,11 +304,7 @@ impl Op {
payload
}
#[cfg(any(
target_arch = "arm",
target_arch = "wasm32",
target_arch = "x86"
))]
#[cfg(any(target_arch = "arm", target_arch = "wasm32", target_arch = "x86"))]
/// Unsafely assume this `Op` has a `.discriminant()` of `StderrWrite` and return its payload.
/// (Always examine `.discriminant()` first to make sure this is the correct variant!)
/// Panics in debug builds if the `.discriminant()` doesn't return `StderrWrite`.
@ -351,14 +333,12 @@ impl Op {
debug_assert_eq!(self.discriminant(), discriminant_Op::StdoutWrite);
extern "C" {
#[link_name = "roc__getter__2"]
#[link_name = "roc__getter__2_generic"]
fn getter(_: *mut roc_std::RocStr, _: *const Op);
}
let mut ret = core::mem::MaybeUninit::uninit();
getter(ret.as_mut_ptr(), self);
ret.assume_init()
}
@ -376,15 +356,21 @@ impl Op {
debug_assert_eq!(self.discriminant(), discriminant_Op::StdoutWrite);
extern "C" {
#[link_name = "roc__getter__3"]
fn getter(_: *mut RocFunction_66, _: *const Op);
#[link_name = "roc__roc__getter__3_size"]
fn size() -> usize;
#[link_name = "roc__getter__3_generic"]
fn getter(_: *mut u8, _: *const Op);
}
let mut ret = core::mem::MaybeUninit::uninit();
// dumb heap allocation for now
let mut bytes = vec![0xAAu8; size()];
getter(ret.as_mut_ptr(), self);
getter(bytes.as_mut_ptr(), self);
ret.assume_init()
RocFunction_66 {
closure_data: bytes,
}
}
#[cfg(any(
@ -403,7 +389,7 @@ impl Op {
let ptr = roc_std::roc_alloc_refcounted::<union_Op>();
*ptr = union_Op {
StdoutWrite: core::mem::ManuallyDrop::new(arg)
StdoutWrite: core::mem::ManuallyDrop::new(arg),
};
Self {
@ -412,11 +398,7 @@ impl Op {
}
}
#[cfg(any(
target_arch = "arm",
target_arch = "wasm32",
target_arch = "x86"
))]
#[cfg(any(target_arch = "arm", target_arch = "wasm32", target_arch = "x86"))]
/// Unsafely assume this `Op` has a `.discriminant()` of `StdoutWrite` and convert it to `StdoutWrite`'s payload.
/// (Always examine `.discriminant()` first to make sure this is the correct variant!)
/// Panics in debug builds if the `.discriminant()` doesn't return `StdoutWrite`.
@ -440,11 +422,7 @@ impl Op {
payload
}
#[cfg(any(
target_arch = "arm",
target_arch = "wasm32",
target_arch = "x86"
))]
#[cfg(any(target_arch = "arm", target_arch = "wasm32", target_arch = "x86"))]
/// Unsafely assume this `Op` has a `.discriminant()` of `StdoutWrite` and return its payload.
/// (Always examine `.discriminant()` first to make sure this is the correct variant!)
/// Panics in debug builds if the `.discriminant()` doesn't return `StdoutWrite`.
@ -459,20 +437,14 @@ impl Op {
&payload
}
#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
/// Returns which variant this tag union holds. Note that this never includes a payload!
pub fn discriminant(&self) -> discriminant_Op {
// The discriminant is stored in the unused bytes at the end of the recursive pointer
unsafe { core::mem::transmute::<u8, discriminant_Op>((self.pointer as u8) & 0b111) }
}
#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
/// Internal helper
fn tag_discriminant(pointer: *mut union_Op, discriminant: discriminant_Op) -> *mut union_Op {
// The discriminant is stored in the unused bytes at the end of the union pointer
@ -482,20 +454,14 @@ impl Op {
tagged as *mut union_Op
}
#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
/// Internal helper
fn union_pointer(&self) -> *mut union_Op {
// The discriminant is stored in the unused bytes at the end of the union pointer
((self.pointer as usize) & (!0b111 as usize)) as *mut union_Op
}
#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
/// Unsafely assume this `Op` has a `.discriminant()` of `StderrWrite` and convert it to `StderrWrite`'s payload.
/// (Always examine `.discriminant()` first to make sure this is the correct variant!)
/// Panics in debug builds if the `.discriminant()` doesn't return `StderrWrite`.
@ -519,10 +485,7 @@ impl Op {
payload
}
#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
/// Unsafely assume this `Op` has a `.discriminant()` of `StderrWrite` and return its payload.
/// (Always examine `.discriminant()` first to make sure this is the correct variant!)
/// Panics in debug builds if the `.discriminant()` doesn't return `StderrWrite`.
@ -537,10 +500,7 @@ impl Op {
&payload
}
#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
/// Unsafely assume this `Op` has a `.discriminant()` of `StdoutWrite` and convert it to `StdoutWrite`'s payload.
/// (Always examine `.discriminant()` first to make sure this is the correct variant!)
/// Panics in debug builds if the `.discriminant()` doesn't return `StdoutWrite`.
@ -564,10 +524,7 @@ impl Op {
payload
}
#[cfg(any(
target_arch = "aarch64",
target_arch = "x86_64"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
/// Unsafely assume this `Op` has a `.discriminant()` of `StdoutWrite` and return its payload.
/// (Always examine `.discriminant()` first to make sure this is the correct variant!)
/// Panics in debug builds if the `.discriminant()` doesn't return `StdoutWrite`.
@ -603,15 +560,21 @@ impl Drop for Op {
// Drop the payload first.
match self.discriminant() {
discriminant_Op::Done => {}
discriminant_Op::StderrWrite => unsafe { core::mem::ManuallyDrop::drop(&mut (&mut *self.union_pointer()).StderrWrite) },
discriminant_Op::StdoutWrite => unsafe { core::mem::ManuallyDrop::drop(&mut (&mut *self.union_pointer()).StdoutWrite) },
discriminant_Op::StderrWrite => unsafe {
core::mem::ManuallyDrop::drop(&mut (&mut *self.union_pointer()).StderrWrite)
},
discriminant_Op::StdoutWrite => unsafe {
core::mem::ManuallyDrop::drop(&mut (&mut *self.union_pointer()).StdoutWrite)
},
}
// Dealloc the pointer
let alignment = core::mem::align_of::<Self>().max(core::mem::align_of::<roc_std::Storage>());
let alignment =
core::mem::align_of::<Self>().max(core::mem::align_of::<roc_std::Storage>());
unsafe { crate::roc_dealloc(storage.as_ptr().cast(), alignment as u32); }
unsafe {
crate::roc_dealloc(storage.as_ptr().cast(), alignment as u32);
}
} else {
// Write the storage back.
storage.set(new_storage);
@ -638,8 +601,12 @@ impl PartialEq for Op {
unsafe {
match self.discriminant() {
discriminant_Op::Done => true,
discriminant_Op::StderrWrite => (&*self.union_pointer()).StderrWrite == (&*other.union_pointer()).StderrWrite,
discriminant_Op::StdoutWrite => (&*self.union_pointer()).StdoutWrite == (&*other.union_pointer()).StdoutWrite,
discriminant_Op::StderrWrite => {
(&*self.union_pointer()).StderrWrite == (&*other.union_pointer()).StderrWrite
}
discriminant_Op::StdoutWrite => {
(&*self.union_pointer()).StdoutWrite == (&*other.union_pointer()).StdoutWrite
}
}
}
}
@ -662,8 +629,12 @@ impl PartialOrd for Op {
unsafe {
match self.discriminant() {
discriminant_Op::Done => Some(core::cmp::Ordering::Equal),
discriminant_Op::StderrWrite => (&*self.union_pointer()).StderrWrite.partial_cmp(&(&*other.union_pointer()).StderrWrite),
discriminant_Op::StdoutWrite => (&*self.union_pointer()).StdoutWrite.partial_cmp(&(&*other.union_pointer()).StdoutWrite),
discriminant_Op::StderrWrite => (&*self.union_pointer())
.StderrWrite
.partial_cmp(&(&*other.union_pointer()).StderrWrite),
discriminant_Op::StdoutWrite => (&*self.union_pointer())
.StdoutWrite
.partial_cmp(&(&*other.union_pointer()).StdoutWrite),
}
}
}
@ -686,8 +657,12 @@ impl Ord for Op {
unsafe {
match self.discriminant() {
discriminant_Op::Done => core::cmp::Ordering::Equal,
discriminant_Op::StderrWrite => (&*self.union_pointer()).StderrWrite.cmp(&(&*other.union_pointer()).StderrWrite),
discriminant_Op::StdoutWrite => (&*self.union_pointer()).StdoutWrite.cmp(&(&*other.union_pointer()).StdoutWrite),
discriminant_Op::StderrWrite => (&*self.union_pointer())
.StderrWrite
.cmp(&(&*other.union_pointer()).StderrWrite),
discriminant_Op::StdoutWrite => (&*self.union_pointer())
.StdoutWrite
.cmp(&(&*other.union_pointer()).StdoutWrite),
}
}
}
@ -711,7 +686,7 @@ impl Clone for Op {
}
Self {
pointer: self.pointer
pointer: self.pointer,
}
}
}
@ -724,7 +699,8 @@ impl core::hash::Hash for Op {
target_arch = "x86",
target_arch = "x86_64"
))]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { match self.discriminant() {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
match self.discriminant() {
discriminant_Op::Done => discriminant_Op::Done.hash(state),
discriminant_Op::StderrWrite => unsafe {
discriminant_Op::StderrWrite.hash(state);
@ -752,10 +728,12 @@ impl core::fmt::Debug for Op {
unsafe {
match self.discriminant() {
discriminant_Op::Done => f.write_str("Done"),
discriminant_Op::StderrWrite => f.debug_tuple("StderrWrite")
discriminant_Op::StderrWrite => f
.debug_tuple("StderrWrite")
// TODO HAS CLOSURE
.finish(),
discriminant_Op::StdoutWrite => f.debug_tuple("StdoutWrite")
discriminant_Op::StdoutWrite => f
.debug_tuple("StdoutWrite")
// TODO HAS CLOSURE
.finish(),
}