Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
# Conflicts:
#	crates/csharp/src/lib.rs
  • Loading branch information
yowl committed Jan 18, 2024
2 parents 11dd441 + 7c9c462 commit a11e714
Show file tree
Hide file tree
Showing 12 changed files with 863 additions and 326 deletions.
576 changes: 338 additions & 238 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ edition = "2021"
[workspace.dependencies]
anyhow = "1.0.72"
bitflags = "2.3.3"
heck = { version = "0.4", features = ["unicode"] }
heck = { version = "0.4", features = ["unicode"] }
pulldown-cmark = { version = "0.9", default-features = false }
clap = { version = "4.3.19", features = ["derive"] }
env_logger = "0.10.0"
Expand Down Expand Up @@ -82,3 +82,5 @@ wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", features = ['
wasmtime-wasi = { git = "https://github.com/bytecodealliance/wasmtime"}
test-artifacts = { path = 'crates/test-rust-wasm/artifacts' }
wit-parser = { workspace = true }
wasmparser = "0.118.0"
wasm-encoder = { workspace = true }
62 changes: 41 additions & 21 deletions crates/c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -765,14 +765,21 @@ fn interface_identifier(
ns.push_str("_");
ns.push_str(&pkg.name.name.to_snake_case());
ns.push_str("_");
if let Some(version) = &pkg.name.version {
let version = version
.to_string()
.replace('.', "_")
.replace('-', "_")
.replace('+', "_");
ns.push_str(&version);
ns.push_str("_");
let pkg_has_multiple_versions = resolve.packages.iter().any(|(_, p)| {
p.name.namespace == pkg.name.namespace
&& p.name.name == pkg.name.name
&& p.name.version != pkg.name.version
});
if pkg_has_multiple_versions {
if let Some(version) = &pkg.name.version {
let version = version
.to_string()
.replace('.', "_")
.replace('-', "_")
.replace('+', "_");
ns.push_str(&version);
ns.push_str("_");
}
}
ns.push_str(&iface.name.as_ref().unwrap().to_snake_case());
ns
Expand Down Expand Up @@ -1967,6 +1974,11 @@ impl InterfaceGenerator<'_> {
}
}

struct DroppableBorrow {
name: String,
ty: TypeId,
}

struct FunctionBindgen<'a, 'b> {
gen: &'a mut InterfaceGenerator<'b>,
locals: Ns,
Expand All @@ -1984,7 +1996,10 @@ struct FunctionBindgen<'a, 'b> {

/// Borrows observed during lifting an export, that will need to be dropped when the guest
/// function exits.
borrows: Vec<(String, TypeId)>,
borrows: Vec<DroppableBorrow>,

/// Forward declarations for temporary storage of borrow copies.
borrow_decls: wit_bindgen_core::Source,
}

impl<'a, 'b> FunctionBindgen<'a, 'b> {
Expand All @@ -2007,6 +2022,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
ret_store_cnt: 0,
import_return_pointer_area_size: 0,
import_return_pointer_area_align: 0,
borrow_decls: Default::default(),
borrows: Vec::new(),
}
}
Expand Down Expand Up @@ -2264,8 +2280,13 @@ impl Bindgen for FunctionBindgen<'_, '_> {
if !self.gen.in_import && self.gen.autodrop_enabled() {
// Here we've received a borrow of an imported resource, which is the
// kind we'll need to drop when the exported function is returning.
let target = dealias(self.gen.resolve, *id);
self.borrows.push((op.clone(), target));
let ty = dealias(self.gen.resolve, *id);

let name = self.locals.tmp("borrow");
uwriteln!(self.borrow_decls, "int32_t {name} = 0;");
uwriteln!(self.src, "{name} = {op};");

self.borrows.push(DroppableBorrow { name, ty });
}
}
}
Expand Down Expand Up @@ -2372,10 +2393,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
for (i, (case, (block, block_results))) in
variant.cases.iter().zip(blocks).enumerate()
{
if let Some(ty) = case.ty.as_ref() {
self.assert_no_droppable_borrows("variant", ty);
}

uwriteln!(self.src, "case {}: {{", i);
self.src.push_str(&block);
assert!(block_results.len() == (case.ty.is_some() as usize));
Expand Down Expand Up @@ -2431,8 +2448,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}

Instruction::OptionLift { ty, .. } => {
self.assert_no_droppable_borrows("option", &Type::Id(*ty));

let (mut some, some_results) = self.blocks.pop().unwrap();
let (mut none, none_results) = self.blocks.pop().unwrap();
assert!(none_results.len() == 0);
Expand Down Expand Up @@ -2520,8 +2535,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}

Instruction::ResultLift { result, ty, .. } => {
self.assert_no_droppable_borrows("result", &Type::Id(*ty));

let (mut err, err_results) = self.blocks.pop().unwrap();
assert!(err_results.len() == (result.err.is_some() as usize));
let (mut ok, ok_results) = self.blocks.pop().unwrap();
Expand Down Expand Up @@ -2837,8 +2850,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
}
},
Instruction::Return { amt, .. } => {
for (op, ty) in self.borrows.iter() {
uwriteln!(self.src, "{}({op});", self.gen.gen.resources[ty].drop_fn);
// Emit all temporary borrow decls
let src = std::mem::replace(&mut self.src, std::mem::take(&mut self.borrow_decls));
self.src.append_src(&src);

for DroppableBorrow { name, ty } in self.borrows.iter() {
let drop_fn = self.gen.gen.resources[ty].drop_fn.as_str();
uwriteln!(self.src, "if ({name} != 0) {{");
uwriteln!(self.src, " {drop_fn}({name});");
uwriteln!(self.src, "}}");
}

assert!(*amt <= 1);
Expand Down
3 changes: 3 additions & 0 deletions crates/csharp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ anyhow = { workspace = true }

[dev-dependencies]
test-helpers = { path = '../test-helpers' }
wasm-encoder = { workspace = true }
wasmparser = "0.118.0"

[features]
default = ["aot"]
aot = []
mono = []
148 changes: 144 additions & 4 deletions crates/csharp/src/csproj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@ use std::{fs, path::PathBuf};

use heck::ToUpperCamelCase;

pub struct CSProject {
pub struct CSProject;

pub struct CSProjectLLVMBuilder {
name: String,
dir: PathBuf,
aot: bool,
clean_targets: bool,
world_name: String,
}

pub struct CSProjectMonoBuilder {
name: String,
dir: PathBuf,
aot: bool,
Expand All @@ -12,8 +22,8 @@ pub struct CSProject {
}

impl CSProject {
pub fn new(dir: PathBuf, name: &str, world_name: &str) -> CSProject {
CSProject {
pub fn new(dir: PathBuf, name: &str, world_name: &str) -> CSProjectLLVMBuilder {
CSProjectLLVMBuilder {
name: name.to_string(),
dir,
aot: false,
Expand All @@ -22,6 +32,18 @@ impl CSProject {
}
}

pub fn new_mono(dir: PathBuf, name: &str, world_name: &str) -> CSProjectMonoBuilder {
CSProjectMonoBuilder {
name: name.to_string(),
dir,
aot: false,
clean_targets: false,
world_name: world_name.to_string(),
}
}
}

impl CSProjectLLVMBuilder {
pub fn generate(&self) -> Result<()> {
let name = &self.name;
let world = &self.world_name.replace("-", "_");
Expand Down Expand Up @@ -149,7 +171,125 @@ impl CSProject {
self.aot = true;
}

pub fn clean(&mut self) {
pub fn clean(&mut self) -> &mut Self {
self.clean_targets = true;

self
}
}

impl CSProjectMonoBuilder {
pub fn generate(&self) -> Result<()> {
let name = &self.name;
let world = &self.world_name.replace("-", "_");
let snake_world = world.to_upper_camel_case();

let aot = self.aot;

fs::write(
self.dir.join("rd.xml"),
format!(
r#"<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="{name}">
</Assembly>
</Application>
</Directives>"#
),
)?;

let maybe_aot = match aot {
true => format!("<WasmBuildNative>{aot}</WasmBuildNative>"),
false => String::new(),
};

let mut csproj = format!(
"<Project Sdk=\"Microsoft.NET.Sdk\">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
<TargetOs>wasi</TargetOs>
{maybe_aot}
<WasmNativeStrip>false</WasmNativeStrip>
<IsBrowserWasmProject>false</IsBrowserWasmProject>
<WasmSingleFileBundle>true</WasmSingleFileBundle>
<RootNamespace>{name}</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
<AssemblyName>{name}</AssemblyName>
</PropertyGroup>
<ItemGroup>
<NativeLibrary Include=\"{world}_component_type.o\" />
</ItemGroup>
<ItemGroup>
<RdXmlFile Include=\"rd.xml\" />
</ItemGroup>
"
);

if self.aot {
fs::write(
self.dir.join("nuget.config"),
r#"<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="globalPackagesFolder" value=".packages" />
</config>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json" />
</packageSources>
</configuration>"#,
)?;
}

if self.clean_targets {
let mut wasm_filename = self.dir.join(name);
wasm_filename.set_extension("wasm");
// In CI we run out of disk space if we don't clean up the files, we don't need to keep any of it around.
csproj.push_str(&format!(
"<Target Name=\"CleanAndDelete\" AfterTargets=\"Clean\">
<!-- Remove obj folder -->
<RemoveDir Directories=\"$(BaseIntermediateOutputPath)\" />
<!-- Remove bin folder -->
<RemoveDir Directories=\"$(BaseOutputPath)\" />
<RemoveDir Directories=\"{}\" />
<RemoveDir Directories=\".packages\" />
</Target>",
wasm_filename.display()
));
}

csproj.push_str(
r#"</Project>
"#,
);

let camel = snake_world.to_upper_camel_case();
fs::write(self.dir.join(format!("{camel}.csproj")), csproj)?;

Ok(())
}

pub fn aot(&mut self) {
self.aot = true;
}

pub fn clean(&mut self) -> &mut Self {
self.clean_targets = true;

self
}
}
Loading

0 comments on commit a11e714

Please sign in to comment.