Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
{
"type": "lldb",
"request": "launch",
"name": "Debug CLI",
"name": "CLI",
"preLaunchTask": "BuildCompiler",
"cargo": {
"args": [
Expand All @@ -32,7 +32,7 @@
{
"type": "lldb",
"request": "launch",
"name": "Debug playground",
"name": "Playground",
"preLaunchTask": "BuildCompiler",
"cargo": {
"args": [
Expand Down
54 changes: 54 additions & 0 deletions core/wasm-codegen/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

fn main() {
let platform = if cfg!(target_os = "linux") {
Expand Down Expand Up @@ -69,6 +70,9 @@ fn main() {
.permissions();
perms.set_mode(0o755);
fs::set_permissions(&dest_llc, perms).expect("Failed to set executable permissions");

// Set RPATH to look in the same directory as the binary
set_rpath(&dest_llc);
}

println!("cargo:info=Copied inf-llc to {}", dest_llc.display());
Expand Down Expand Up @@ -98,6 +102,12 @@ fn main() {
perms.set_mode(0o755);
fs::set_permissions(&dest_rust_lld, perms)
.expect("Failed to set executable permissions");

// Copy LLVM libraries to make rust-lld self-contained
copy_llvm_libraries(bin_dir);

// Set RPATH to look in the same directory as the binary
set_rpath(&dest_rust_lld);
}

println!("cargo:info=Copied rust-lld to {}", dest_rust_lld.display());
Expand Down Expand Up @@ -142,3 +152,47 @@ fn main() {
println!("cargo:rerun-if-changed={}", source_rust_lld.display());
println!("cargo:rerun-if-changed={}", source_lib_llvm.display());
}

fn copy_llvm_libraries(bin_dir: PathBuf) {
// Get the Rust toolchain's lib directory
if let Ok(output) = Command::new("rustc").arg("--print").arg("sysroot").output()
&& output.status.success()
{
let sysroot = String::from_utf8_lossy(&output.stdout).trim().to_string();
let lib_dir = PathBuf::from(sysroot).join("lib");

if lib_dir.exists() {
// Copy LLVM shared libraries
if let Ok(entries) = fs::read_dir(&lib_dir) {
for entry in entries.flatten() {
let path = entry.path();
if let Some(file_name) = path.file_name() {
let name_str = file_name.to_string_lossy();
// Copy LLVM libraries (both .so and .so.version files)
if name_str.contains("libLLVM") && name_str.contains(".so") {
let dest_path = bin_dir.join(file_name);
if let Err(e) = fs::copy(&path, &dest_path) {
eprintln!("Warning: Failed to copy {}: {}", path.display(), e);
} else {
println!(
"cargo:info=Copied LLVM library {} to {}",
path.display(),
dest_path.display()
);
}
}
}
}
}
}
}
}

fn set_rpath(binary_path: &PathBuf) {
// Set RPATH to $ORIGIN so the binary looks for libraries in its own directory
let _ = Command::new("patchelf")
.arg("--set-rpath")
.arg("$ORIGIN")
.arg(binary_path)
.output();
}
19 changes: 16 additions & 3 deletions core/wasm-codegen/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,22 @@ pub(crate) fn compile_to_wasm(
}
let rust_lld_path = get_rust_lld_path()?;
let wasm_path = temp_dir.path().join(output_fname).with_extension("wasm");
let mut lld_cmd = Command::new(&rust_lld_path);
configure_llvm_env(&mut lld_cmd)?;
let wasm_lld_output = lld_cmd

// Make rust-lld self-contained by pointing the dynamic linker to the directory
// where rust-lld and the copied LLVM libraries live (see build.rs).
let mut wasm_ld_cmd = Command::new(&wasm_ld_path);
if let Some(bin_dir) = wasm_ld_path.parent() {
if let Ok(existing_ld_path) = std::env::var("LD_LIBRARY_PATH") {
wasm_ld_cmd.env(
"LD_LIBRARY_PATH",
format!("{}:{existing_ld_path}", bin_dir.display()),
);
} else {
wasm_ld_cmd.env("LD_LIBRARY_PATH", bin_dir.as_os_str());
}
}

let wasm_ld_output = wasm_ld_cmd
.arg("-flavor")
.arg("wasm")
.arg(&obj_path)
Expand Down
3 changes: 2 additions & 1 deletion tools/playground-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ repository = { workspace = true }
[dependencies]
actix-web = "4"
actix-cors = "0.7.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
inference.workspace = true
inf-wast.workspace = true
wat-fmt.workspace = true
wasm-fmt.workspace = true
serde.workspace = true
88 changes: 49 additions & 39 deletions tools/playground-server/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,72 @@
use actix_cors::Cors;
use actix_web::{post, web, App, HttpResponse, HttpServer, Responder};
use actix_web::{App, HttpResponse, HttpServer, Responder, post, web};
use serde::{Deserialize, Serialize};

use inference::{codegen, parse, wasm_to_v};

#[derive(Deserialize)]
struct CompileRequest {
code: String,
}

#[derive(Deserialize, Serialize)]
struct Response {
wat: String,
ll: String,
wasm: Vec<u8>,
wasm_str: String,
v: String,
errors: Vec<String>,
}

fn parse_inf_file(_: &str) -> Response {
// let mut wasm = vec![];
let v = String::new();
fn parse_inf_file(inf_code: &str) -> Response {
let errors = vec![];

// let wat = match compile_to_wat(input) {
// Ok(w) => w,
// Err(e) => {
// errors.push(e.to_string());
// return Response {
// wat: String::new(),
// wasm: vec![],
// wasm_str: String::new(),
// v: String::new(),
// errors,
// };
// }
// };
let parse_result = match parse(inf_code) {
Ok(result) => result,
Err(e) => {
return Response {
ll: String::new(),
wasm: vec![],
wasm_str: String::new(),
v: String::new(),
errors: vec![e.to_string()],
};
}
};

// if !wat.is_empty() {
// wat_to_wasm(&wat)
// .map(|w| wasm = w)
// .unwrap_or_else(|e| errors.push(e.to_string()));
let wasm_bytes = match codegen(&parse_result) {
Ok(bytes) => bytes,
Err(e) => {
return Response {
ll: String::new(),
wasm: vec![],
wasm_str: String::new(),
v: String::new(),
errors: vec![e.to_string()],
};
}
};

// wasm_to_v("playground", &wasm)
// .map(|v_str| v = v_str)
// .unwrap_or_else(|e| errors.push(e.to_string()));
let v = match wasm_to_v("playground", &wasm_bytes) {
Ok(v_str) => v_str,
Err(e) => {
return Response {
ll: String::new(),
wasm: vec![],
wasm_str: String::new(),
v: String::new(),
errors: vec![e.to_string()],
};
}
};

// let wat = wat_format(&wat);
// let wasm_str = wasm_format(&wasm);
// Response {
// wat,
// wasm,
// wasm_str,
// v,
// errors,
// }
// } else {
Response {
wat: String::new(),
wasm: vec![],
wasm_str: String::new(),
ll: String::new(),
wasm: wasm_bytes.clone(),
wasm_str: wasm_bytes
.iter()
.map(|b| format!("{:02x}", b))
.collect::<String>(),
v,
errors,
}
Expand All @@ -78,13 +87,14 @@ async fn main() -> std::io::Result<()> {
.wrap(
Cors::default()
.allowed_origin("http://localhost:3000")
.allowed_origin("http://localhost:3001")
.allowed_methods(vec!["POST", "GET"])
.allowed_headers(vec!["Content-Type"])
.supports_credentials(),
)
.service(compile_code)
})
.bind(("127.0.0.1", 8080))?
.bind(("127.0.0.1", 8181))?
.run()
.await
}
Expand Down
Loading