Skip to content

Commit 1c61360

Browse files
Bitcasts, fixed export _retArea, make sure async fails.
1 parent 14a4554 commit 1c61360

2 files changed

Lines changed: 120 additions & 22 deletions

File tree

crates/d/src/lib.rs

Lines changed: 112 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::mem::{replace, take};
66
use std::path::PathBuf;
77
use wit_bindgen_core::{
88
Direction, Files, InterfaceGenerator, Source, Types, WorldGenerator,
9-
abi::{self, Bindgen, WasmType},
9+
abi::{self, Bindgen, Bitcast, WasmType},
1010
wit_parser::*,
1111
};
1212

@@ -322,6 +322,9 @@ impl D {
322322
direction,
323323

324324
wasm_import_module,
325+
326+
return_pointer_area_size: Default::default(),
327+
return_pointer_area_align: Default::default(),
325328
}
326329
}
327330

@@ -598,6 +601,9 @@ impl WorldGenerator for D {
598601
}
599602
}
600603

604+
let ret_area_decl = r#gen.emit_ret_area_if_needed();
605+
606+
r#gen.src.push_str(&ret_area_decl);
601607
r#gen.src.push_str("}\n");
602608

603609
let mut interface_filepath = PathBuf::from_iter(fqn.split("."));
@@ -618,10 +624,19 @@ impl WorldGenerator for D {
618624
) -> Result<()> {
619625
let mut r#gen = self.interface(resolve, Some(Direction::Export), None, Some("$root"));
620626
for (_name, func) in funcs {
621-
r#gen.export_func(func);
627+
match func.kind {
628+
FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
629+
r#gen.export_func(func);
630+
}
631+
_ => {}
632+
}
622633
}
623634

635+
let ret_area_decl = r#gen.emit_ret_area_if_needed();
636+
624637
self.function_exports_src = take(&mut r#gen.src);
638+
self.function_exports_src.push_str(&ret_area_decl);
639+
625640
Ok(())
626641
}
627642

@@ -720,6 +735,9 @@ struct DInterfaceGenerator<'a> {
720735
fqn: &'a str,
721736

722737
sizes: SizeAlign,
738+
739+
return_pointer_area_size: ArchitectureSize,
740+
return_pointer_area_align: Alignment,
723741
}
724742

725743
impl<'a> DInterfaceGenerator<'a> {
@@ -1095,11 +1113,15 @@ impl<'a> DInterfaceGenerator<'a> {
10951113
fn export_func(&mut self, func: &Function) {
10961114
match &func.kind {
10971115
FunctionKind::Freestanding => {}
1116+
FunctionKind::Constructor(_) => {
1117+
todo!("Export FunctionKind::Constructor - {}\n", func.name);
1118+
}
10981119
FunctionKind::Method(_) => {}
1120+
FunctionKind::Static(_) => {
1121+
todo!("Export FunctionKind::Static - {}\n", func.name);
1122+
}
10991123
kind => {
1100-
self.src
1101-
.push_str(&format!("// TODO: Export {kind:?} - {}\n", func.name));
1102-
return;
1124+
todo!("Export {kind:?} - {}\n", func.name);
11031125
}
11041126
}
11051127

@@ -1205,14 +1227,37 @@ impl<'a> DInterfaceGenerator<'a> {
12051227
&mut f,
12061228
false,
12071229
);
1230+
12081231
let ret_area_decl = f.emit_ret_area_if_needed();
12091232

1210-
let FunctionBindgen { src, .. } = f;
1233+
let FunctionBindgen {
1234+
src,
1235+
return_pointer_area_size,
1236+
return_pointer_area_align,
1237+
..
1238+
} = f;
1239+
self.return_pointer_area_size = self.return_pointer_area_size.max(return_pointer_area_size);
1240+
self.return_pointer_area_align = self
1241+
.return_pointer_area_align
1242+
.max(return_pointer_area_align);
1243+
12111244
self.src.push_str(&ret_area_decl);
12121245
self.src.push_str(&src.to_string());
12131246

12141247
self.src.push_str("}\n");
12151248
}
1249+
1250+
fn emit_ret_area_if_needed(&self) -> String {
1251+
if !self.return_pointer_area_size.is_empty() {
1252+
format!(
1253+
"\nalign({}) private void[{}] _exportsRetArea;\n",
1254+
self.return_pointer_area_align.format("size_t.sizeof"),
1255+
self.return_pointer_area_size.format("size_t.sizeof")
1256+
)
1257+
} else {
1258+
String::new()
1259+
}
1260+
}
12161261
}
12171262

12181263
impl<'a> InterfaceGenerator<'a> for DInterfaceGenerator<'a> {
@@ -1894,7 +1939,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
18941939

18951940
fn store(&mut self, ty: &str, offset: ArchitectureSize, operands: &[String]) {
18961941
self.push_str(&format!(
1897-
"*(cast({ty}*)({} + {})) = cast({ty})({});\n",
1942+
"*cast({ty}*)({} + {}) = cast({ty})({});\n",
18981943
operands[1],
18991944
offset.format("size_t.sizeof"),
19001945
operands[0]
@@ -1915,22 +1960,58 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
19151960
/// The scratch space is reused but never accessed simultaneously.
19161961
fn emit_ret_area_if_needed(&self) -> String {
19171962
if !self.return_pointer_area_size.is_empty() {
1918-
format!(
1919-
"{}align({}) void[{}] _retArea = void;\n",
1920-
if self.r#gen.direction == Some(Direction::Export) {
1921-
"static "
1922-
} else {
1923-
""
1924-
},
1925-
self.return_pointer_area_align.format("size_t.sizeof"),
1926-
self.return_pointer_area_size.format("size_t.sizeof")
1927-
)
1963+
match self.r#gen.direction {
1964+
Some(Direction::Import) => format!(
1965+
"align({}) void[{}] _retArea = void;\n",
1966+
self.return_pointer_area_align.format("size_t.sizeof"),
1967+
self.return_pointer_area_size.format("size_t.sizeof")
1968+
),
1969+
Some(Direction::Export) => "alias _retArea = _exportsRetArea;\n".to_string(),
1970+
None => {
1971+
unreachable!();
1972+
}
1973+
}
19281974
} else {
19291975
String::new()
19301976
}
19311977
}
19321978
}
19331979

1980+
fn perform_cast(op: &str, cast: &Bitcast) -> String {
1981+
match cast {
1982+
Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
1983+
format!("cast(uint)({op}).reinterpretCast!float")
1984+
}
1985+
Bitcast::F32ToI32 | Bitcast::F32ToI64 => {
1986+
format!("({op}).reinterpretCast!uint")
1987+
}
1988+
Bitcast::I64ToF64 => {
1989+
format!("({op}).reinterpretCast!double")
1990+
}
1991+
Bitcast::F64ToI64 => {
1992+
format!("({op}).reinterpretCast!ulong")
1993+
}
1994+
Bitcast::I32ToI64 | Bitcast::LToI64 | Bitcast::PToP64 => {
1995+
format!("cast(ulong)({op})")
1996+
}
1997+
Bitcast::I64ToI32 | Bitcast::PToI32 | Bitcast::LToI32 => {
1998+
format!("cast(uint)({op})")
1999+
}
2000+
Bitcast::P64ToI64 | Bitcast::None | Bitcast::I64ToP64 => op.to_string(),
2001+
Bitcast::P64ToP | Bitcast::I32ToP | Bitcast::LToP => {
2002+
format!("cast(void*)({op})")
2003+
}
2004+
Bitcast::PToL | Bitcast::I32ToL | Bitcast::I64ToL => {
2005+
format!("cast(size_t)({op})")
2006+
}
2007+
Bitcast::Sequence(sequence) => {
2008+
let [first, second] = &**sequence;
2009+
let inner = perform_cast(op, first);
2010+
perform_cast(&inner, second)
2011+
}
2012+
}
2013+
}
2014+
19342015
impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
19352016
type Operand = String;
19362017

@@ -1942,7 +2023,7 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
19422023
results: &mut Vec<Self::Operand>,
19432024
) {
19442025
let mut top_as = |cvt: &str| {
1945-
results.push(format!("(cast({cvt})({}))", operands.pop().unwrap()));
2026+
results.push(format!("cast({cvt})({})", operands.pop().unwrap()));
19462027
};
19472028

19482029
match inst {
@@ -1955,6 +2036,12 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
19552036
}
19562037

19572038
abi::Instruction::I32Const { val } => results.push(val.to_string()),
2039+
abi::Instruction::Bitcasts { casts } => {
2040+
for (cast, op) in casts.iter().zip(operands) {
2041+
let op = perform_cast(op, cast);
2042+
results.push(op);
2043+
}
2044+
}
19582045
abi::Instruction::ConstZero { tys } => {
19592046
for ty in tys.iter() {
19602047
results.push(
@@ -2027,7 +2114,7 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
20272114
abi::Instruction::CharFromI32 => top_as("dchar"),
20282115
abi::Instruction::F32FromCoreF32 => results.push(operands.pop().unwrap()),
20292116
abi::Instruction::F64FromCoreF64 => results.push(operands.pop().unwrap()),
2030-
abi::Instruction::BoolFromI32 => results.push(format!("({} != 0)", operands[0])),
2117+
abi::Instruction::BoolFromI32 => results.push(format!("({}) != 0", operands[0])),
20312118

20322119
abi::Instruction::ListCanonLower { .. } | abi::Instruction::StringLower { .. } => {
20332120
results.push(format!("cast(void*)({}.ptr)", operands[0]));
@@ -2059,7 +2146,7 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
20592146
"foreach ({block_element}_idx, const ref {block_element}; {list_src}) {{\n"
20602147
));
20612148
self.push_str(&format!(
2062-
"auto {base} = {list} + {block_element}_idx * {size_str};\n"
2149+
"auto {base} = {list} + {block_element}_idx * ({size_str});\n"
20632150
));
20642151
self.push_str(&body);
20652152
//self.push_str(&format!("_targetElem = {};", body.1[0]));
@@ -2681,10 +2768,13 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
26812768
todo!("instr: Malloc")
26822769
}
26832770
abi::Instruction::GuestDeallocate { .. } => {
2684-
todo!("instr: GuestDeallocate")
2771+
self.push_str(&format!("free({});", operands[0]));
26852772
}
26862773
abi::Instruction::GuestDeallocateString { .. } => {
2687-
todo!("instr: GuestDeallocateString")
2774+
todo!("instr: GuestDeallocateString");
2775+
//self.push_str(&format!("if (({}) > 0) {{\n", operands[1]));
2776+
//self.push_str(&format!("free({});", operands[0]));
2777+
//self.push_str("}\n");
26882778
}
26892779
abi::Instruction::GuestDeallocateList { .. } => {
26902780
todo!("instr: GuestDeallocateList")

crates/d/src/wit_common.d

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,19 @@ public:
231231

232232

233233
package(wit):
234+
234235
extern(C) {
235236
void* malloc(size_t size);
236237
void free(void* ptr);
237238
}
238239

240+
// from numem.casting
241+
pragma(inline, true)
242+
auto ref T reinterpretCast(T, U)(auto ref U from) @trusted if (T.sizeof == U.sizeof) {
243+
union tmp { U from; T to; }
244+
return tmp(from).to;
245+
}
246+
239247
auto mallocSlice(T)(size_t count) {
240248
auto ptr = malloc(count*T.sizeof);
241249
if (ptr is null) return null;

0 commit comments

Comments
 (0)