Skip to content

Commit

Permalink
Use Span when working with primative lists
Browse files Browse the repository at this point in the history
Signed-off-by: James Sturtevant <[email protected]>
  • Loading branch information
jsturtevant committed Jan 23, 2025
1 parent aa25aad commit bd38027
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 38 deletions.
73 changes: 52 additions & 21 deletions crates/csharp/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub(crate) struct FunctionBindgen<'a, 'b> {
import_return_pointer_area_size: usize,
import_return_pointer_area_align: usize,
pub(crate) resource_drops: Vec<(String, String)>,
is_block: bool,
fixed_statments: Vec<Fixed>,
}

impl<'a, 'b> FunctionBindgen<'a, 'b> {
Expand Down Expand Up @@ -57,6 +59,8 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
import_return_pointer_area_size: 0,
import_return_pointer_area_align: 0,
resource_drops: Vec::new(),
is_block: false,
fixed_statments: Vec::new(),
}
}

Expand Down Expand Up @@ -99,7 +103,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
.map(
|(i, (((name, ty), Block { body, results, .. }), payload))| {
let payload = if let Some(ty) = self.interface_gen.non_empty_type(ty.as_ref()) {
let ty = self.interface_gen.name_with_qualifier(ty, true, true);
let ty = self.interface_gen.type_name_with_qualifier(ty, true);
let name = name.to_upper_camel_case();

format!("{ty} {payload} = {op}.As{name};")
Expand Down Expand Up @@ -497,12 +501,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
results.push(result);
}
Instruction::TupleLift { .. } => {
let mut result = String::from("(");

uwriteln!(result, "{}", operands.join(", "));

result.push_str(")");
results.push(result);
results.push(format!("({})", operands.join(", ")));
}

Instruction::TupleLower { tuple, ty: _ } => {
Expand Down Expand Up @@ -722,18 +721,32 @@ impl Bindgen for FunctionBindgen<'_, '_> {
Direction::Import => {
let ptr: String = self.locals.tmp("listPtr");
let handle: String = self.locals.tmp("gcHandle");
// Despite the name GCHandle.Alloc here this does not actually allocate memory on the heap.
// It pins the array with the garbage collector so that it can be passed to unmanaged code.
// It is required to free the pin after use which is done in the Cleanup section.
self.needs_cleanup = true;
uwrite!(
self.src,
"
var {handle} = {list}.Pin();
var {ptr} = {handle}.Pointer;
cleanups.Add(()=> {handle}.Dispose());
"
);

if self.is_block {
// With variants we can't use span since the Fixed statment can't always be applied to all the variants
// Despite the name GCHandle.Alloc here this does not actually allocate memory on the heap.
// It pins the array with the garbage collector so that it can be passed to unmanaged code.
// It is required to free the pin after use which is done in the Cleanup section.
self.needs_cleanup = true;
uwrite!(
self.src,
"
var {handle} = GCHandle.Alloc({list}, GCHandleType.Pinned);
var {ptr} = {handle}.AddrOfPinnedObject();
cleanups.Add(()=> {handle}.Free());
"
);
}else {
uwrite!(
self.src,
"
"
);
self.fixed_statments.push(Fixed {
item_to_pin: list.clone(),
ptr_name: ptr.clone(),
});
}
results.push(format!("(nint){ptr}"));
results.push(format!("({list}).Length"));
}
Expand Down Expand Up @@ -845,7 +858,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {

let list = &operands[0];
let size = self.interface_gen.csharp_gen.sizes.size(element).size_wasm32();
let ty = self.interface_gen.name_with_qualifier(element, true, true);
let ty = self.interface_gen.type_name_with_qualifier(element, true);
let index = self.locals.tmp("index");

let address = self.locals.tmp("address");
Expand Down Expand Up @@ -1005,6 +1018,12 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}

Instruction::Return { amt: _, func } => {
if self.fixed_statments.len() > 0 {
let fixed: String = self.fixed_statments.iter().map(|f| format!("{} = {}", f.ptr_name, f.item_to_pin)).collect::<Vec<_>>().join(", ");
self.src.insert_str(0, &format!("fixed (void* {fixed})
{{"));
}

if self.needs_cleanup {
self.src.insert_str(0, "var cleanups = new List<Action>();
");
Expand All @@ -1023,11 +1042,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
self.handle_result_import(operands);
}
_ => {
let results = operands.join(", ");
let results: String = operands.join(", ");
uwriteln!(self.src, "return ({results});")
}
}
}

if self.fixed_statments.len() > 0 {
uwriteln!(self.src, "}}");
}
}

Instruction::Malloc { .. } => unimplemented!(),
Expand Down Expand Up @@ -1218,6 +1241,8 @@ impl Bindgen for FunctionBindgen<'_, '_> {
element: self.locals.tmp("element"),
base: self.locals.tmp("basePtr"),
});

self.is_block = true;
}

fn finish_block(&mut self, operands: &mut Vec<String>) {
Expand All @@ -1233,6 +1258,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
element,
base,
});
self.is_block = false;
}

fn sizes(&self) -> &SizeAlign {
Expand Down Expand Up @@ -1305,6 +1331,11 @@ struct Block {
base: String,
}

struct Fixed {
item_to_pin: String,
ptr_name: String,
}

struct BlockStorage {
body: String,
element: String,
Expand Down
26 changes: 9 additions & 17 deletions crates/csharp/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,6 @@ impl InterfaceGenerator<'_> {
{access} {extra_modifiers} {modifiers} unsafe {result_type} {camel_name}({params})
{{
{src}
//TODO: free alloc handle (interopString) if exists
}}
"#
);
Expand Down Expand Up @@ -550,14 +549,11 @@ impl InterfaceGenerator<'_> {
&& self.direction == Direction::Import
&& is_param
{
format!("ReadOnlyMemory<{}>", self.type_name(ty))
format!("Span<{}>", self.type_name(ty))
} else if crate::world_generator::is_primitive(ty) {
format!("{}[]", self.type_name(ty))
} else {
format!(
"List<{}>",
self.name_with_qualifier(ty, qualifier, is_param)
)
format!("List<{}>", self.type_name_with_qualifier(ty, qualifier))
}
}
TypeDefKind::Tuple(tuple) => {
Expand All @@ -566,17 +562,13 @@ impl InterfaceGenerator<'_> {

let params = match count {
0 => String::new(),
1 => self.name_with_qualifier(
tuple.types.first().unwrap(),
qualifier,
is_param,
),
1 => self.type_name_with_qualifier(tuple.types.first().unwrap(), qualifier),
_ => format!(
"({})",
tuple
.types
.iter()
.map(|ty| self.name_with_qualifier(ty, qualifier, is_param))
.map(|ty| self.type_name_with_qualifier(ty, qualifier))
.collect::<Vec<_>>()
.join(", ")
),
Expand All @@ -591,7 +583,7 @@ impl InterfaceGenerator<'_> {
} else {
false
};
let base_ty = self.name_with_qualifier(base_ty, qualifier, is_param);
let base_ty = self.type_name_with_qualifier(base_ty, qualifier);
if nesting {
format!("Option<{base_ty}>")
} else {
Expand All @@ -602,7 +594,7 @@ impl InterfaceGenerator<'_> {
self.csharp_gen.needs_result = true;
let mut name = |ty: &Option<Type>| {
ty.as_ref()
.map(|ty| self.name_with_qualifier(ty, qualifier, is_param))
.map(|ty| self.type_name_with_qualifier(ty, qualifier))
.unwrap_or_else(|| "None".to_owned())
};
let ok = name(&result.ok);
Expand All @@ -612,7 +604,7 @@ impl InterfaceGenerator<'_> {
}
TypeDefKind::Handle(handle) => {
let (Handle::Own(id) | Handle::Borrow(id)) = handle;
self.name_with_qualifier(&Type::Id(*id), qualifier, is_param)
self.type_name_with_qualifier(&Type::Id(*id), qualifier)
}
_ => {
if let Some(name) = &ty.name {
Expand Down Expand Up @@ -938,7 +930,7 @@ impl<'a> CoreInterfaceGenerator<'a> for InterfaceGenerator<'a> {
.map(|field| {
format!(
"{} {}",
self.name_with_qualifier(&field.ty, false, true),
self.type_name(&field.ty),
field.name.to_csharp_ident()
)
})
Expand All @@ -964,7 +956,7 @@ impl<'a> CoreInterfaceGenerator<'a> for InterfaceGenerator<'a> {
.map(|field| {
format!(
"{access} readonly {} {};",
self.name_with_qualifier(&field.ty, false, true),
self.type_name(&field.ty),
field.name.to_csharp_ident()
)
})
Expand Down

0 comments on commit bd38027

Please sign in to comment.