mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 05:34:11 +03:00
update shared-quicksort
This commit is contained in:
parent
a53254de40
commit
6f94f7d63b
23
examples/shared-quicksort/platform/Cargo.lock
generated
Normal file
23
examples/shared-quicksort/platform/Cargo.lock
generated
Normal file
@ -0,0 +1,23 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "host"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"roc_std 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "roc_std"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc 0.2.79 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum libc 0.2.79 (registry+https://github.com/rust-lang/crates.io-index)" = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
|
13
examples/shared-quicksort/platform/Cargo.toml
Normal file
13
examples/shared-quicksort/platform/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "host"
|
||||
version = "0.1.0"
|
||||
authors = ["Richard Feldman <oss@rtfeldman.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
roc_std = { path = "../../../roc_std" }
|
||||
|
||||
[workspace]
|
@ -1,49 +0,0 @@
|
||||
# Rebuilding the host from source
|
||||
|
||||
Here are the current steps to rebuild this host. These
|
||||
steps can likely be moved into a `build.rs` script after
|
||||
turning `host.rs` into a `cargo` project, but that hasn't
|
||||
been attempted yet.
|
||||
|
||||
## Compile the Rust and C sources
|
||||
|
||||
Currently this host has both a `host.rs` and a `host.c`.
|
||||
This is only because we haven't figured out a way to convince
|
||||
Rust to emit a `.o` file that doesn't define a `main` entrypoint,
|
||||
but which is capable of being linked into one later.
|
||||
|
||||
As a workaround, we have `host.rs` expose a function called
|
||||
`rust_main` instead of `main`, and all `host.c` does is provide
|
||||
an actual `main` which imports and then calls `rust_main` from
|
||||
the compiled `host.rs`. It's not the most elegant workaround,
|
||||
but [asking on `users.rust-lang.org`](https://users.rust-lang.org/t/error-when-compiling-linking-with-o-files/49635/4)
|
||||
didn't turn up any nicer approaches. Maybe they're out there though!
|
||||
|
||||
To make this workaround happen, we need to compile both `host.rs`
|
||||
and `host.c`. First, `cd` into `platform/host/src/` and then run:
|
||||
|
||||
```
|
||||
$ clang -c host.c -o c_host.o
|
||||
$ rustc host.rs -o rust_host.o
|
||||
```
|
||||
|
||||
Now we should have `c_host.o` and `rust_host.o` in the curent directory.
|
||||
|
||||
## Link together the `.o` files
|
||||
|
||||
Next, combine `c_host.o` and `rust_host.o` into `host.o` using `ld -r` like so:
|
||||
|
||||
```
|
||||
$ ld -r c_host.o rust_host.o -o host.o
|
||||
```
|
||||
|
||||
Move `host.o` into the appropriate `platform/` subdirectory
|
||||
based on your architecture and operating system. For example,
|
||||
on macOS, you'd move `host.o` into the `platform/host/x86_64-unknown-darwin10/` directory.
|
||||
|
||||
## All done!
|
||||
|
||||
Congratulations! You now have an updated host.
|
||||
|
||||
It's now fine to delete `c_host.o` and `rust_host.o`,
|
||||
since they were only needed to produce `host.o`.
|
@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# compile c_host.o and rust_host.o
|
||||
clang -c host.c -o c_host.o
|
||||
rustc host.rs -o rust_host.o
|
||||
|
||||
# link them together into host.o
|
||||
ld -r c_host.o rust_host.o -o host.o
|
||||
|
||||
# clean up
|
||||
rm -f c_host.o
|
||||
rm -f rust_host.o
|
@ -1,47 +0,0 @@
|
||||
#![crate_type = "staticlib"]
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
||||
extern "C" {
|
||||
#[allow(improper_ctypes)]
|
||||
#[link_name = "quicksort_1"]
|
||||
fn quicksort(list: Box<[i64]>) -> Box<[i64]>;
|
||||
}
|
||||
|
||||
const NUM_NUMS: usize = 10_000;
|
||||
|
||||
#[no_mangle]
|
||||
pub fn rust_main() -> isize {
|
||||
let nums: Box<[i64]> = {
|
||||
let mut nums = Vec::with_capacity(NUM_NUMS);
|
||||
|
||||
for index in 0..nums.capacity() {
|
||||
let num = index as i64 % 123;
|
||||
|
||||
nums.push(num);
|
||||
}
|
||||
nums.into()
|
||||
};
|
||||
|
||||
println!("Running Roc quicksort on {} numbers...", nums.len());
|
||||
let start_time = SystemTime::now();
|
||||
let answer = unsafe { quicksort(nums) };
|
||||
let end_time = SystemTime::now();
|
||||
let duration = end_time.duration_since(start_time).unwrap();
|
||||
|
||||
println!(
|
||||
"Roc quicksort took {:.4} ms to compute this answer: {:?}",
|
||||
duration.as_secs_f64() * 1000.0,
|
||||
// truncate the answer, so stdout is not swamped
|
||||
&answer[0..20]
|
||||
);
|
||||
|
||||
// the pointer is to the first _element_ of the list,
|
||||
// but the refcount precedes it. Thus calling free() on
|
||||
// this pointer would segfault/cause badness. Therefore, we
|
||||
// leak it for now
|
||||
Box::leak(answer);
|
||||
|
||||
// Exit code
|
||||
0
|
||||
}
|
52
examples/shared-quicksort/platform/src/lib.rs
Normal file
52
examples/shared-quicksort/platform/src/lib.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use roc_std::RocCallResult;
|
||||
use roc_std::RocList;
|
||||
use std::time::SystemTime;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "quicksort_1_exposed"]
|
||||
fn quicksort(list: RocList<i64>, output: &mut RocCallResult<RocList<i64>>) -> ();
|
||||
}
|
||||
|
||||
const NUM_NUMS: usize = 100;
|
||||
|
||||
#[no_mangle]
|
||||
pub fn rust_main() -> isize {
|
||||
let nums: RocList<i64> = {
|
||||
let mut nums = Vec::with_capacity(NUM_NUMS);
|
||||
|
||||
for index in 0..nums.capacity() {
|
||||
let num = index as i64 % 12;
|
||||
|
||||
nums.push(num);
|
||||
}
|
||||
|
||||
RocList::from_slice(&nums)
|
||||
};
|
||||
|
||||
println!("Running Roc quicksort on {} numbers...", nums.len());
|
||||
let start_time = SystemTime::now();
|
||||
let answer = unsafe {
|
||||
use std::mem::MaybeUninit;
|
||||
let mut output = MaybeUninit::uninit();
|
||||
|
||||
quicksort(nums, &mut *output.as_mut_ptr());
|
||||
|
||||
match output.assume_init().into() {
|
||||
Ok(value) => value,
|
||||
Err(msg) => panic!("roc failed with message {}", msg),
|
||||
}
|
||||
};
|
||||
|
||||
let end_time = SystemTime::now();
|
||||
let duration = end_time.duration_since(start_time).unwrap();
|
||||
|
||||
println!(
|
||||
"Roc quicksort took {:.4} ms to compute this answer: {:?}",
|
||||
duration.as_secs_f64() * 1000.0,
|
||||
// truncate the answer, so stdout is not swamped
|
||||
&answer.as_slice()[0..20]
|
||||
);
|
||||
|
||||
// Exit code
|
||||
0
|
||||
}
|
Loading…
Reference in New Issue
Block a user