Skip to content

Commit

Permalink
feat: java
Browse files Browse the repository at this point in the history
  • Loading branch information
doinkythederp committed Nov 12, 2024
1 parent 962ce8b commit ad7873d
Show file tree
Hide file tree
Showing 264 changed files with 32,904 additions and 32,620 deletions.
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "wasm3-rs"]
path = wasm3-rs
url = https://github.com/wasm3/wasm3-rs.git
[submodule "packages/wasm3-sys/wasm3"]
path = packages/wasm3-sys/wasm3
url = https://github.com/wasm3/wasm3.git
3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"rust-analyzer.check.targets": [
"${workspaceFolder}/armv7a-vex-v5.json",
"wasm32-unknown-unknown"
"${workspaceFolder}/armv7a-vex-v5.json"
],
"rust-analyzer.check.allTargets": false,
"rust-analyzer.cargo.features": "all",
Expand Down
10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
[workspace]
members = ["packages/*"]
default-members = [
"packages/runtime",
"packages/startup",
"packages/wasm3",
"packages/wasm3-sys",
]
exclude = ["wasm3-rs"]
resolver = "2"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[profile.release]
debug = true
lto = true

[workspace.dependencies]
vex-sdk = "0.23.0"

Expand Down
3 changes: 2 additions & 1 deletion packages/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ compress = true
vexide.workspace = true
vex-sdk.workspace = true
vexide_wasm_startup = { version = "0.1.0", path = "../startup" }
wasm3 = { path = "../../wasm3-rs", features = [
wasm3 = { path = "../wasm3", features = [
"build-bindgen",
], default-features = false }
hashbrown = "0.15.1"
printf-compat = { version = "0.1.1", default-features = false }
bytemuck = "1.19.0"
8 changes: 8 additions & 0 deletions packages/runtime/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![no_std]
#![feature(c_variadic)]

extern crate alloc;

mod libc_support;
pub mod platform;
pub mod teavm;
37 changes: 10 additions & 27 deletions packages/runtime/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_main]
#![no_std]
#![feature(c_variadic)]

use alloc::borrow::ToOwned;
use core::{
Expand All @@ -9,43 +8,27 @@ use core::{
time::Duration,
};

use runtime::{
platform,
teavm::{self, teamvm_main},
};
use vexide::{core::program::exit, prelude::*};
use vexide_wasm_startup::{startup, CodeSignature, ProgramFlags, ProgramOwner, ProgramType};

extern crate alloc;

mod libc_support;

unsafe extern "C" {
static __user_ram_end: c_char;
}

async fn main(_peripherals: Peripherals) {
println!("Starting...");
println!("Link Addr: 0x{:x?}", unsafe {
vex_sdk::vexSystemLinkAddrGet()
});
sleep(Duration::from_secs(1)).await;

// unsafe {
// let lib_start = addr_of!(__user_ram_end);
// let string = CStr::from_ptr(lib_start);
// println!("String: {string:?}");
// }

// sleep(Duration::from_secs(1)).await;
let wasm_bytes = platform::read_user_program();

let env = wasm3::Environment::new().expect("Unable to create environment");
let rt = env.create_runtime(1024).expect("Unable to create runtime");
let mut store = env.create_store(4096).expect("Unable to create runtime");
let module = env
.parse_module(include_bytes!("../../test-program/test_program.wasm").to_owned())
.parse_module(wasm_bytes)
.expect("Unable to parse module");

let instance = rt.load_module(module).expect("Unable to load module");
let func = instance
.find_function::<(i32, i32), i32>("add")
.expect("Unable to find function");
println!("Wasm says that 3 + 6 is {}", func.call(3, 6).unwrap())
let mut instance = store.instantiate(module).expect("Unable to load module");
teavm::link_teavm(&mut store, &mut instance).expect("Unable to link teavm");
teavm::teamvm_main(&mut store, &mut instance, &[]).expect("Unable to run main");
}

#[link_section = ".code_signature"]
Expand Down
11 changes: 11 additions & 0 deletions packages/runtime/src/platform.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use core::ptr;

const LINKED_FILE: *const u32 = 0x7800000 as *const u32;

pub fn read_user_program() -> &'static [u8] {
unsafe {
let len = ptr::read_volatile(LINKED_FILE);
let file_base: *const u8 = LINKED_FILE.offset(1).cast();
core::slice::from_raw_parts(file_base, len as usize)
}
}
127 changes: 127 additions & 0 deletions packages/runtime/src/teavm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#![allow(non_snake_case)]

use alloc::string::String;
use core::str;

use vexide::core::{print, println, time::Instant};
use wasm3::{error::Trap, Function, Instance, Store, WasmArg, WasmArgs, WasmType};

pub fn link_teavm(store: &mut Store, instance: &mut Instance) -> wasm3::error::Result<()> {
let teavm_stringData = instance.find_function::<i32, i32>(store, "teavm_stringData")?;
let teavm_arrayLength = instance.find_function::<i32, i32>(store, "teavm_arrayLength")?;

instance.link_closure(
store,
"teavm",
"putwcharsOut",
|mut ctx, (chars, count): (u32, u32)| {
let mem = ctx.memory_mut();
let string = str::from_utf8(&mem[chars as usize..(chars + count) as usize]).unwrap();
print!("{string}");
Ok(())
},
)?;

let epoch = Instant::now();

instance.link_closure(store, "teavm", "currentTimeMillis", move |_ctx, ()| {
let secs = epoch.elapsed().as_secs_f64();
Ok(secs * 1000.0)
})?;

instance.link_closure(store, "teavm", "logString", move |mut ctx, string: i32| {
let array_ptr = teavm_stringData.call(&mut ctx, string).unwrap() as usize;
let len = teavm_arrayLength.call(&mut ctx, array_ptr as i32).unwrap() as usize;
let bytes = len * size_of::<u16>();

let memory = ctx.memory();
let array = &memory[array_ptr..array_ptr + bytes];
let string = String::from_utf16_lossy(bytemuck::cast_slice(array));

print!("{string}");

Ok(())
})?;

instance.link_closure(store, "teavm", "logInt", move |_ctx, int: i32| {
print!("{int}");
Ok(())
})?;

instance.link_closure(store, "teavm", "logOutOfMemory", move |_ctx, ()| {
println!("Out of memory");
Ok(())
})?;

Ok(())
}

fn wrap<T: WasmArg, R: WasmType>(
func: Function<T, R>,
catch: Function<(), i32>,
) -> impl Fn(&mut Store, T) -> wasm3::error::Result<R> {
move |store, args| {
let result = func.call(&mut *store, args)?;
let exception = catch.call(&mut *store)?;
if exception != 0 {
panic!("Java code threw an exception");
}
Ok(result)
}
}

pub fn teamvm_main(
store: &mut Store,
instance: &mut Instance,
args: &[&str],
) -> wasm3::error::Result<()> {
let teavm_catchException = instance.find_function::<(), i32>(store, "teavm_catchException")?;
let teavm_allocateStringArray = wrap(
instance.find_function::<i32, i32>(store, "teavm_allocateStringArray")?,
teavm_catchException,
);
let teavm_objectArrayData = wrap(
instance.find_function::<i32, i32>(store, "teavm_objectArrayData")?,
teavm_catchException,
);
let teavm_allocateString = wrap(
instance.find_function::<i32, i32>(store, "teavm_allocateString")?,
teavm_catchException,
);
let teavm_stringData = wrap(
instance.find_function::<i32, i32>(store, "teavm_stringData")?,
teavm_catchException,
);

// all this to make a (String[] args)

let java_args = teavm_allocateStringArray(&mut *store, args.len() as i32)? as usize;
let args_bytes = args.len() * size_of::<i32>();
for (i, &arg) in args.iter().enumerate() {
let java_arg = teavm_allocateString(&mut *store, arg.len() as i32)?;
let string_data = teavm_stringData(&mut *store, java_arg)?;
let arg_address = teavm_objectArrayData(&mut *store, string_data)? as usize;
let arg_bytes = arg.len() * size_of::<u16>();

let memory = store.memory_mut();
let arg_slice: &mut [u16] =
bytemuck::cast_slice_mut(&mut memory[arg_address..arg_address + arg_bytes]);
for (i, byte) in arg.encode_utf16().enumerate() {
arg_slice[i] = byte;
}

let args_data: &mut [i32] =
bytemuck::cast_slice_mut(&mut memory[java_args..java_args + args_bytes]);
args_data[i] = java_arg;
}

let start = instance.find_function::<i32, ()>(store, "start")?;
start.call(&mut *store, java_args as i32)?;

let exception = teavm_catchException.call(&mut *store)?;
if exception != 0 {
panic!("Java code threw an exception");
}

Ok(())
}
2 changes: 1 addition & 1 deletion packages/startup/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,5 @@ pub unsafe fn startup() {
}

// Print the banner
println!("vexide startup complete!");
// println!("multiv startup complete!");
}
Binary file modified packages/test-program/test_program.wasm
Binary file not shown.
32 changes: 32 additions & 0 deletions packages/wasm3-sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "wasm3-sys"
version = "0.5.0"
authors = ["Lukas Tobias Wirth <[email protected]>"]
edition = "2018"
description = "Raw ffi bindings for wasm3"
homepage = "https://github.com/wasm3/wasm3-rs"
repository = "https://github.com/wasm3/wasm3-rs"
categories = ["external-ffi-bindings"]
build = "build.rs"
license = "MIT"
links = "wasm3"
include = ["wasm3/source/**/*", "src/**/*", "Cargo.toml", "build.rs"]

[features]
# wasi = []
use-32bit-slots = []
build-bindgen = ["bindgen"]

[dependencies]
cty = "0.2"

[build-dependencies]
cc = "1"
shlex = "1.3.0"

[build-dependencies.bindgen]
version = "0.70.1"
optional = true

[package.metadata.docs.rs]
all-features = true
Loading

0 comments on commit ad7873d

Please sign in to comment.