mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-21 07:49:17 +03:00
Resolve conflicts
This commit is contained in:
commit
f2983f1360
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -56,6 +56,13 @@ jobs:
|
||||
with:
|
||||
command: test
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
name: cargo test -- --ignored
|
||||
continue-on-error: true
|
||||
with:
|
||||
command: test
|
||||
args: -- --ignored
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
name: cargo test --release
|
||||
with:
|
||||
|
@ -1,23 +1,37 @@
|
||||
# Building the Roc compiler from source
|
||||
|
||||
|
||||
## Installing LLVM, valgrind, libunwind, and libc++-dev
|
||||
## Installing LLVM, Zig, valgrind, libunwind, and libc++-dev
|
||||
|
||||
To build the compiler, you need these installed:
|
||||
|
||||
* `libunwind` (macOS should already have this one installed)
|
||||
* `libc++-dev`
|
||||
* [`zig`](https://ziglang.org/download/)
|
||||
* a particular version of LLVM
|
||||
* a particular version of Zig (see below)
|
||||
* a particular version of LLVM (see below)
|
||||
|
||||
To run the test suite (via `cargo test`), you additionally need to install:
|
||||
|
||||
* [`valgrind`](https://www.valgrind.org/) (needs special treatment to [install on macOS](https://stackoverflow.com/a/61359781)]
|
||||
* [`valgrind`](https://www.valgrind.org/) (needs special treatment to [install on macOS](https://stackoverflow.com/a/61359781)
|
||||
Alternatively, you can use `cargo test --no-fail-fast` or `cargo test -p specific_tests` to skip over the valgrind failures & tests.
|
||||
|
||||
### libunwind & libc++-dev
|
||||
|
||||
MacOS systems should already have `libunwind`, but other systems will need to install it (On Ubuntu, this can be donw with `sudo apt-get install libunwind-dev`).
|
||||
Some systems may already have `libc++-dev` on them, but if not, you may need to install it. (On Ubuntu, this can be done with `sudo apt-get install libc++-dev`.)
|
||||
MacOS systems should already have `libunwind`, but other systems will need to install it (e.g. with `sudo apt-get install libunwind-dev`).
|
||||
|
||||
To install Zig on macOS, use `brew install zig`. To install on Ubuntu, checkout [zig's docs](https://github.com/dryzig/zig-debian/blob/master/README.md).
|
||||
### Zig
|
||||
We use a specific version of Zig, a build off the the commit `0088efc4b`. The latest tagged version of Zig, 0.6.0, doesn't include the feature to emit LLVM ir, which is a core feature of how we use Zig. To download this specific version, you can use the following links:
|
||||
* [linux](https://ziglang.org/builds/zig-linux-x86_64-0.6.0+0088efc4b.tar.xz)
|
||||
* [macOS](https://ziglang.org/builds/zig-macos-x86_64-0.6.0+0088efc4b.tar.xz)
|
||||
|
||||
Alternatively, any recent master branch build should work. To install the latest master branch build you can use:
|
||||
* `brew install zig --HEAD` (on macos)
|
||||
* `snap install zig --classic --edge` (on ubunutu)
|
||||
|
||||
Once 0.7.0 is released, we'll switch back to installing the tagged releases and this process will get easier.
|
||||
|
||||
### LLVM
|
||||
|
||||
To see which version of LLVM you need, take a look at `Cargo.toml`, in particular the `branch` section of the `inkwell` dependency. It should have something like `llvmX-Y` where X and Y are the major and minor revisions of LLVM you need.
|
||||
|
||||
|
23
Cargo.lock
generated
23
Cargo.lock
generated
@ -2318,6 +2318,7 @@ dependencies = [
|
||||
"roc_uniq",
|
||||
"serde",
|
||||
"serde-xml-rs",
|
||||
"serial_test",
|
||||
"strip-ansi-escapes",
|
||||
"target-lexicon",
|
||||
"tempfile",
|
||||
@ -2804,6 +2805,28 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b15f74add9a9d4a3eb2bf739c9a427d266d3895b53d992c3a7c234fec2ff1f1"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot 0.10.2",
|
||||
"serial_test_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test_derive"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65f59259be9fc1bf677d06cc1456e97756004a1a5a577480f71430bd7c17ba33"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.21",
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.40",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.8.2"
|
||||
|
@ -61,11 +61,10 @@ add-apt-repository "${REPO_NAME}"
|
||||
apt-get update
|
||||
apt-get install -y clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clangd-$LLVM_VERSION libc++abi-dev libunwind-dev valgrind
|
||||
|
||||
# install zig
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 379CE192D401AB61
|
||||
echo 'deb https://dl.bintray.com/dryzig/zig-ubuntu bionic main' | tee -a /etc/apt/sources.list
|
||||
apt update
|
||||
apt install zig
|
||||
# install zig - can't use apt-get since we require at least a specific commit later then the most recent tag (0.6.0)
|
||||
wget -c https://ziglang.org/builds/zig-linux-x86_64-0.6.0+0088efc4b.tar.xz --no-check-certificate
|
||||
tar -xf zig-linux-x86_64-0.6.0+0088efc4b.tar.xz
|
||||
ln -s "$PWD/zig-linux-x86_64-0.6.0+0088efc4b/zig" /usr/local/bin/zig
|
||||
|
||||
# symlink llvm tools
|
||||
ln -s /usr/bin/llvm-as-10 /usr/local/bin/llvm-as
|
||||
|
@ -89,4 +89,5 @@ quickcheck_macros = "0.8"
|
||||
strip-ansi-escapes = "0.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde-xml-rs = "0.4"
|
||||
serial_test = "0.5"
|
||||
tempfile = "3.1.0"
|
||||
|
@ -12,123 +12,174 @@ mod helpers;
|
||||
#[cfg(test)]
|
||||
mod cli_run {
|
||||
use crate::helpers::{
|
||||
example_file, extract_valgrind_errors, run_cmd, run_roc, run_with_valgrind, Out,
|
||||
example_file, extract_valgrind_errors, run_cmd, run_roc, run_with_valgrind,
|
||||
};
|
||||
use serial_test::serial;
|
||||
|
||||
#[test]
|
||||
fn run_hello_world() {
|
||||
fn check_hello_world_output(out: Out) {
|
||||
if !out.stderr.is_empty() {
|
||||
panic!(out.stderr);
|
||||
}
|
||||
assert!(out.status.success());
|
||||
fn check_output(
|
||||
folder: &str,
|
||||
file: &str,
|
||||
flags: &[&str],
|
||||
expected_ending: &str,
|
||||
use_valgrind: bool,
|
||||
) {
|
||||
let compile_out = run_roc(
|
||||
&[
|
||||
&["build", example_file(folder, file).to_str().unwrap()],
|
||||
flags,
|
||||
]
|
||||
.concat(),
|
||||
);
|
||||
if !compile_out.stderr.is_empty() {
|
||||
panic!(compile_out.stderr);
|
||||
}
|
||||
assert!(compile_out.status.success());
|
||||
|
||||
let out = if use_valgrind {
|
||||
let (valgrind_out, raw_xml) =
|
||||
run_with_valgrind(&[example_file("hello-world", "app").to_str().unwrap()]);
|
||||
|
||||
let ending = "Hello, World!!!!!!!!!!!!!\n";
|
||||
if !&valgrind_out.stdout.ends_with(ending) {
|
||||
panic!(
|
||||
"expected output to end with {:?} but instead got {:?}",
|
||||
ending, &valgrind_out.stdout
|
||||
);
|
||||
}
|
||||
run_with_valgrind(&[example_file(folder, "app").to_str().unwrap()]);
|
||||
let memory_errors = extract_valgrind_errors(&raw_xml);
|
||||
if !memory_errors.is_empty() {
|
||||
panic!("{:?}", memory_errors);
|
||||
}
|
||||
assert!(valgrind_out.status.success());
|
||||
valgrind_out
|
||||
} else {
|
||||
run_cmd(example_file(folder, "app").to_str().unwrap(), &[])
|
||||
};
|
||||
if !&out.stdout.ends_with(expected_ending) {
|
||||
panic!(
|
||||
"expected output to end with {:?} but instead got {:#?}",
|
||||
expected_ending, out
|
||||
);
|
||||
}
|
||||
check_hello_world_output(run_roc(&[
|
||||
"build",
|
||||
example_file("hello-world", "Hello.roc").to_str().unwrap(),
|
||||
]));
|
||||
check_hello_world_output(run_roc(&[
|
||||
"build",
|
||||
"--optimize",
|
||||
example_file("hello-world", "Hello.roc").to_str().unwrap(),
|
||||
]));
|
||||
assert!(out.status.success());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(hello_world)]
|
||||
fn run_hello_world() {
|
||||
check_output(
|
||||
"hello-world",
|
||||
"Hello.roc",
|
||||
&[],
|
||||
"Hello, World!!!!!!!!!!!!!\n",
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(hello_world)]
|
||||
fn run_hello_world_optimized() {
|
||||
check_output(
|
||||
"hello-world",
|
||||
"Hello.roc",
|
||||
&[],
|
||||
"Hello, World!!!!!!!!!!!!!\n",
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(quicksort)]
|
||||
fn run_quicksort() {
|
||||
fn check_quicksort_output(out: Out) {
|
||||
if !out.stderr.is_empty() {
|
||||
panic!(out.stderr);
|
||||
}
|
||||
assert!(out.status.success());
|
||||
|
||||
// let (valgrind_out, raw_xml) =
|
||||
// run_with_valgrind(&[example_file("quicksort", "app").to_str().unwrap()]);
|
||||
let valgrind_out = run_cmd(example_file("quicksort", "app").to_str().unwrap(), &[]);
|
||||
let ending = "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n";
|
||||
if !&valgrind_out.stdout.ends_with(ending) {
|
||||
panic!(
|
||||
"expected output to end with {:?} but instead got {:?}",
|
||||
ending, &valgrind_out.stdout
|
||||
);
|
||||
}
|
||||
// let memory_errors = extract_valgrind_errors(&raw_xml);
|
||||
// if !memory_errors.is_empty() {
|
||||
// panic!("{:?}", memory_errors);
|
||||
// }
|
||||
assert!(valgrind_out.status.success());
|
||||
}
|
||||
|
||||
// TODO: Uncomment this once we are correctly freeing the RocList even when in dev build.
|
||||
/*
|
||||
check_quicksort_output(run_roc(&[
|
||||
"build",
|
||||
example_file("quicksort", "Quicksort.roc").to_str().unwrap(),
|
||||
]));
|
||||
*/
|
||||
check_quicksort_output(run_roc(&[
|
||||
"build",
|
||||
"--optimize",
|
||||
example_file("quicksort", "Quicksort.roc").to_str().unwrap(),
|
||||
]));
|
||||
check_output(
|
||||
"quicksort",
|
||||
"Quicksort.roc",
|
||||
&[],
|
||||
"[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(quicksort)]
|
||||
fn run_quicksort_optimized() {
|
||||
check_output(
|
||||
"quicksort",
|
||||
"Quicksort.roc",
|
||||
&["--optimize"],
|
||||
"[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(quicksort)]
|
||||
// TODO: Stop ignoring this test once we are correctly freeing the RocList even when in dev build.
|
||||
#[ignore]
|
||||
fn run_quicksort_valgrind() {
|
||||
check_output(
|
||||
"quicksort",
|
||||
"Quicksort.roc",
|
||||
&[],
|
||||
"[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(quicksort)]
|
||||
// TODO: Stop ignoring this test once valgrind supports AVX512.
|
||||
#[ignore]
|
||||
fn run_quicksort_optimized_valgrind() {
|
||||
check_output(
|
||||
"quicksort",
|
||||
"Quicksort.roc",
|
||||
&["--optimize"],
|
||||
"[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(multi_module)]
|
||||
fn run_multi_module() {
|
||||
fn check_muti_module_output(out: Out) {
|
||||
if !out.stderr.is_empty() {
|
||||
panic!(out.stderr);
|
||||
}
|
||||
assert!(out.status.success());
|
||||
check_output(
|
||||
"multi-module",
|
||||
"Quicksort.roc",
|
||||
&[],
|
||||
"[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
// let (valgrind_out, raw_xml) =
|
||||
// run_with_valgrind(&[example_file("multi-module", "app").to_str().unwrap()]);
|
||||
let valgrind_out = run_cmd(example_file("multi-module", "app").to_str().unwrap(), &[]);
|
||||
let ending = "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n";
|
||||
if !&valgrind_out.stdout.ends_with(ending) {
|
||||
panic!(
|
||||
"expected output to end with {:?} but instead got {:?}",
|
||||
ending, &valgrind_out.stdout
|
||||
);
|
||||
}
|
||||
// let memory_errors = extract_valgrind_errors(&raw_xml);
|
||||
// if !memory_errors.is_empty() {
|
||||
// panic!("{:?}", memory_errors);
|
||||
// }
|
||||
assert!(valgrind_out.status.success());
|
||||
}
|
||||
#[test]
|
||||
#[serial(multi_module)]
|
||||
fn run_multi_module_optimized() {
|
||||
check_output(
|
||||
"multi-module",
|
||||
"Quicksort.roc",
|
||||
&["--optimize"],
|
||||
"[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Uncomment this once we are correctly freeing the RocList even when in dev build.
|
||||
/*
|
||||
check_muti_module_output(run_roc(&[
|
||||
"run",
|
||||
example_file("multi-module", "Quicksort.roc")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
]));
|
||||
*/
|
||||
check_muti_module_output(run_roc(&[
|
||||
"run",
|
||||
example_file("multi-module", "Quicksort.roc")
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"--optimize",
|
||||
]));
|
||||
#[test]
|
||||
#[serial(multi_module)]
|
||||
// TODO: Stop ignoring this test once we are correctly freeing the RocList even when in dev build.
|
||||
#[ignore]
|
||||
fn run_multi_module_valgrind() {
|
||||
check_output(
|
||||
"multi-module",
|
||||
"Quicksort.roc",
|
||||
&[],
|
||||
"[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(multi_module)]
|
||||
// TODO: Stop ignoring this test once valgrind supports AVX512.
|
||||
#[ignore]
|
||||
fn run_multi_module_optimized_valgrind() {
|
||||
check_output(
|
||||
"multi-module",
|
||||
"Quicksort.roc",
|
||||
&["--optimize"],
|
||||
"[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n",
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use std::path::PathBuf;
|
||||
use std::process::{Command, ExitStatus, Stdio};
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Out {
|
||||
pub stdout: String,
|
||||
pub stderr: String,
|
||||
@ -131,6 +132,9 @@ enum ValgrindField {
|
||||
Args(ValgrindDummyStruct),
|
||||
Error(ValgrindError),
|
||||
Status(ValgrindDummyStruct),
|
||||
Stack(ValgrindDummyStruct),
|
||||
#[serde(rename = "fatal_signal")]
|
||||
FatalSignal(ValgrindDummyStruct),
|
||||
ErrorCounts(ValgrindDummyStruct),
|
||||
SuppCounts(ValgrindDummyStruct),
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ pub fn target_machine(
|
||||
Target::from_name(arch).unwrap().create_target_machine(
|
||||
&TargetTriple::create(target_triple_str(target)),
|
||||
arch,
|
||||
"+avx2", // TODO this string was used uncritically from an example, and should be reexamined
|
||||
"", // TODO: this probably should be TargetMachine::get_host_cpu_features() to enable all features.
|
||||
opt,
|
||||
reloc,
|
||||
model,
|
||||
|
4
compiler/builtins/bitcode/.gitignore
vendored
4
compiler/builtins/bitcode/.gitignore
vendored
@ -1,4 +1,2 @@
|
||||
main.ll
|
||||
main.o
|
||||
src/zig-cache
|
||||
zig-cache
|
||||
src/zig-cache
|
||||
|
@ -5,31 +5,19 @@ When their implementations are simple enough (e.g. addition), they
|
||||
can be implemented directly in Inkwell.
|
||||
|
||||
When their implementations are complex enough, it's nicer to
|
||||
implement them in a higher-level language like C (or eventually Zig),
|
||||
compile the result to LLVM bitcode, and import that bitcode into the compiler.
|
||||
implement them in a higher-level language like Zig, then compile
|
||||
the result to LLVM bitcode, and import that bitcode into the compiler.
|
||||
|
||||
Compiling the bitcode happens automatically in a Rust build script at `compiler/gen/build.rs`.
|
||||
You can find the compiled bitcode in `target/debug/build/roc_gen-[some random characters]/out/builtins.bc`.
|
||||
Compiling the bitcode happens automatically in a Rust build script at `compiler/builtins/build.rs`.
|
||||
Then `builtins/src/bitcode/rs` staticlly imports the compiled bitcode for use in the compiler.
|
||||
|
||||
> If you want to take a look at the human-readable LLVM IR, cd into `compiler/builtins/bitcode` and
|
||||
> run the following command. It should create `compiler/builtins/bitcode/lib.ll`
|
||||
>
|
||||
> ```bash
|
||||
> zig build-obj src/main.zig -femit-llvm-ir=test.ll -fno-emit-bin --strip
|
||||
> ```
|
||||
>
|
||||
> NOTE: The full command that we use when generating the bitcode is:
|
||||
> ```bash
|
||||
> zig build-obj src/main.zig -femit-llvm-ir=test.ll -fno-emit-bin --strip -O ReleaseSafe
|
||||
> ```
|
||||
> This is probably less readable then the first command, because it does some mangling of
|
||||
> non-exported names, etc. But if you're hitting a bug, it may be helpful.
|
||||
You can find the compiled bitcode in `target/debug/build/roc_builtins-[some random characters]/out/builtins.bc`.
|
||||
There will be two directories like `roc_builtins-[some random characters]`, look for the one that has an
|
||||
`out` directory as a child.
|
||||
|
||||
The bitcode is a bunch of bytes that aren't particularly human-readable.
|
||||
Since Roc is designed to be distributed as a single binary, these bytes
|
||||
need to be included in the raw source somewhere.
|
||||
|
||||
The `llvm/src/build.rs` file statically imports these raw bytes.
|
||||
> The bitcode is a bunch of bytes that aren't particularly human-readable.
|
||||
> If you want to take a look at the human-readable LLVM IR, look at
|
||||
> `target/debug/build/roc_builtins-[some random characters]/out/builtins.ll`
|
||||
|
||||
## Calling bitcode functions
|
||||
|
||||
|
@ -1,19 +1,21 @@
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
const print = std.debug.print;
|
||||
|
||||
export fn is_finite_(f: f64) bool {
|
||||
return std.math.isFinite(f);
|
||||
export fn atan_(num: f64) f64 {
|
||||
return math.atan(num);
|
||||
}
|
||||
|
||||
export fn atan_(f: f64) f64 {
|
||||
return std.math.atan(f);
|
||||
export fn is_finite_(num: f64) bool {
|
||||
return math.isFinite(num);
|
||||
}
|
||||
|
||||
export fn pow_int_(base: i64, exp: i64) i64 {
|
||||
return std.math.pow(i64, base, exp);
|
||||
return math.pow(i64, base, exp);
|
||||
}
|
||||
|
||||
// Str.split
|
||||
|
||||
const RocStr = struct {
|
||||
str_bytes: [*]u8,
|
||||
str_len: usize,
|
||||
|
70
compiler/builtins/build.rs
Normal file
70
compiler/builtins/build.rs
Normal file
@ -0,0 +1,70 @@
|
||||
use std::convert::AsRef;
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
|
||||
fn run_command<S, I>(command: &str, args: I)
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
let output_result = Command::new(OsStr::new(&command)).args(args).output();
|
||||
match output_result {
|
||||
Ok(output) => match output.status.success() {
|
||||
true => (),
|
||||
false => {
|
||||
let error_str = match str::from_utf8(&output.stderr) {
|
||||
Ok(stderr) => stderr.to_string(),
|
||||
Err(_) => format!("Failed to run \"{}\"", command),
|
||||
};
|
||||
panic!("{} failed: {}", command, error_str);
|
||||
}
|
||||
},
|
||||
Err(reason) => panic!("{} failed: {}", command, reason),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
|
||||
// "." is relative to where "build.rs" is
|
||||
let src_path = Path::new(".").join("bitcode").join("src").join("main.zig");
|
||||
let src_path_str = src_path.to_str().expect("Invalid src path");
|
||||
println!("Building main.zig from: {}", src_path_str);
|
||||
|
||||
let zig_cache_dir = Path::new(&out_dir).join("zig-cache");
|
||||
let zig_cache_dir_str = zig_cache_dir.to_str().expect("Invalid zig cache dir");
|
||||
println!("Setting zig cache to: {}", zig_cache_dir_str);
|
||||
|
||||
let dest_ll_path = Path::new(&out_dir).join("builtins.ll");
|
||||
let dest_ll = dest_ll_path.to_str().expect("Invalid dest ir path");
|
||||
let emit_ir_arg = "-femit-llvm-ir=".to_owned() + dest_ll;
|
||||
println!("Compiling zig llvm-ir to: {}", dest_ll);
|
||||
|
||||
run_command(
|
||||
"zig",
|
||||
&[
|
||||
"build-obj",
|
||||
src_path_str,
|
||||
&emit_ir_arg,
|
||||
"-fno-emit-bin",
|
||||
"--strip",
|
||||
"-O",
|
||||
"ReleaseFast",
|
||||
"--cache-dir",
|
||||
zig_cache_dir_str,
|
||||
],
|
||||
);
|
||||
|
||||
let dest_bc_path = Path::new(&out_dir).join("builtins.bc");
|
||||
let dest_bc = dest_bc_path.to_str().expect("Invalid dest bc path");
|
||||
println!("Compiling bitcode to: {}", dest_bc);
|
||||
|
||||
run_command("llvm-as", &[dest_ll, "-o", dest_bc]);
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed={}", src_path_str);
|
||||
println!("cargo:rustc-env=BUILTINS_BC={}", dest_bc);
|
||||
}
|
18
compiler/builtins/src/bitcode.rs
Normal file
18
compiler/builtins/src/bitcode.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use std::fs::File;
|
||||
use std::io::prelude::Read;
|
||||
use std::vec::Vec;
|
||||
|
||||
pub fn get_bytes() -> Vec<u8> {
|
||||
// In the build script for the builtins module, we compile the builtins bitcode and set
|
||||
// BUILTINS_BC to the path to the compiled output.
|
||||
let path: &'static str = env!(
|
||||
"BUILTINS_BC",
|
||||
"Env var BUILTINS_BC not found. Is there a problem with the build script?"
|
||||
);
|
||||
let mut builtins_bitcode = File::open(path).expect("Unable to find builtins bitcode source");
|
||||
let mut buffer = Vec::new();
|
||||
builtins_bitcode
|
||||
.read_to_end(&mut buffer)
|
||||
.expect("Unable to read builtins bitcode");
|
||||
buffer
|
||||
}
|
@ -10,5 +10,6 @@
|
||||
// and encouraging shortcuts here creates bad incentives. I would rather temporarily
|
||||
// re-enable this when working on performance optimizations than have it block PRs.
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
pub mod bitcode;
|
||||
pub mod std;
|
||||
pub mod unique;
|
||||
|
@ -1,31 +0,0 @@
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
let src_path = fs::canonicalize("./../builtins/bitcode/src/main.zig")
|
||||
.expect("Failed to resolve bitcode source");
|
||||
let src = src_path.to_str().expect("Invalid src path");
|
||||
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
|
||||
let dest_ll_path = Path::new(&out_dir).join("builtins.ll");
|
||||
let dest_ll = dest_ll_path.to_str().expect("Invalid dest ir path");
|
||||
let emit_ir_arg = "-femit-llvm-ir=".to_owned() + dest_ll;
|
||||
Command::new("zig")
|
||||
.args(&["build-obj", src, &emit_ir_arg, "-fno-emit-bin", "--strip", "-O", "ReleaseFast"])
|
||||
.status()
|
||||
.unwrap();
|
||||
|
||||
let dest_bc_path = Path::new(&out_dir).join("builtins.bc");
|
||||
let dest_bc = dest_bc_path.to_str().expect("Invalid dest bc path");
|
||||
Command::new("llvm-as")
|
||||
.args(&[dest_ll, "-o", dest_bc])
|
||||
.status()
|
||||
.unwrap();
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed={}", src);
|
||||
println!("cargo:rustc-env=BUILTINS_BC={}", dest_bc);
|
||||
}
|
@ -29,13 +29,12 @@ use inkwell::values::{
|
||||
};
|
||||
use inkwell::OptimizationLevel;
|
||||
use inkwell::{AddressSpace, IntPredicate};
|
||||
use roc_builtins::bitcode;
|
||||
use roc_collections::all::{ImMap, MutSet};
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||
use roc_mono::ir::{JoinPointId, Wrapped};
|
||||
use roc_mono::layout::{Builtin, Layout, MemoryMode};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::Read;
|
||||
use target_lexicon::CallingConvention;
|
||||
|
||||
/// This is for Inkwell's FunctionValue::verify - we want to know the verification
|
||||
@ -183,19 +182,9 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
||||
}
|
||||
|
||||
pub fn module_from_builtins<'ctx>(ctx: &'ctx Context, module_name: &str) -> Module<'ctx> {
|
||||
// In the build script for the gen module, we compile the builtins bitcode and set
|
||||
// BUILTINS_BC to the path to the compiled output.
|
||||
let path: &'static str = env!(
|
||||
"BUILTINS_BC",
|
||||
"Env var BUILTINS_BC not found. Is there a problem with the build script?"
|
||||
);
|
||||
let mut builtins_bitcode = File::open(path).expect("Unable to find builtins bitcode source");
|
||||
let mut buffer = std::vec::Vec::new();
|
||||
builtins_bitcode
|
||||
.read_to_end(&mut buffer)
|
||||
.expect("Unable to read builtins bitcode");
|
||||
let bitcode_bytes = bitcode::get_bytes();
|
||||
|
||||
let memory_buffer = MemoryBuffer::create_from_memory_range(&buffer, module_name);
|
||||
let memory_buffer = MemoryBuffer::create_from_memory_range(&bitcode_bytes, module_name);
|
||||
|
||||
let module = Module::parse_bitcode_from_buffer(&memory_buffer, ctx)
|
||||
.unwrap_or_else(|err| panic!("Unable to import builtins bitcode. LLVM error: {:?}", err));
|
||||
|
63
nix/zig.nix
63
nix/zig.nix
@ -1,31 +1,36 @@
|
||||
{ pkgs, isMacOS }:
|
||||
|
||||
if isMacOS
|
||||
then
|
||||
# As of 2020-10-25, building Zig from source on MacOS fails
|
||||
# so we just download the binary from their release page
|
||||
let
|
||||
version = "0.6.0";
|
||||
archiveName = "zig-macos-x86_64-${version}+91a1c20e7";
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "zig";
|
||||
version = version;
|
||||
buildInputs = [ pkgs.gzip ];
|
||||
src = pkgs.fetchurl {
|
||||
name = "${archiveName}.tar.xz";
|
||||
url = "https://ziglang.org/builds/${archiveName}.tar.xz";
|
||||
sha256 = "0svwlk76w171ikr8wjzchm4svd4hvna8idv84pi7ar2fr4i8bkic";
|
||||
};
|
||||
phases = [ "installPhase" ];
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
tar -xf $src
|
||||
cp ${archiveName}/zig $out/zig
|
||||
cp -r ${archiveName}/lib $out/lib
|
||||
ln -s "$out/zig" "$out/bin/zig"
|
||||
chmod +x $out/bin/zig
|
||||
'';
|
||||
}
|
||||
else
|
||||
pkgs.zig
|
||||
# We require at least specific commit of Zig after the latest tagged
|
||||
# release (0.6.0), so we just download the binaries for that commit
|
||||
|
||||
let
|
||||
version = "0.6.0+0088efc4b";
|
||||
osName =
|
||||
if isMacOS
|
||||
then "macos"
|
||||
else "linux";
|
||||
archiveName = "zig-${osName}-x86_64-${version}";
|
||||
sha256 =
|
||||
if isMacOS
|
||||
then "665c1a7f472cfc5e0715f0ddf6ff8409fb749ac91cbbae68c443b4a37ebd058e"
|
||||
else "bab70ae3bd0af538022bc3ef50d8f34fa8dceac39ba7d9e5d528eee7e6d5a1cf";
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "zig";
|
||||
version = version;
|
||||
buildInputs = [ pkgs.gzip ];
|
||||
src = pkgs.fetchurl {
|
||||
inherit sha256;
|
||||
name = "${archiveName}.tar.xz";
|
||||
url = "https://ziglang.org/builds/${archiveName}.tar.xz";
|
||||
};
|
||||
phases = [ "installPhase" ];
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
tar -xf $src
|
||||
cp ${archiveName}/zig $out/zig
|
||||
cp -r ${archiveName}/lib $out/lib
|
||||
ln -s "$out/zig" "$out/bin/zig"
|
||||
chmod +x $out/bin/zig
|
||||
'';
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
{ pkgs, zig }:
|
||||
|
||||
# As of 2020-10-25, building zls is not available on Nix
|
||||
# For some reason, this hangs on `zig build`. I'll try
|
||||
# to figure it our later :(
|
||||
# As of 2020-10-25, building zls is not available on Nix. For some reason,
|
||||
# this hangs on `zig build`. I'll try to figure it our later.
|
||||
|
||||
let
|
||||
rev = "e8c20351d85da8eb4bf22480045b994007284d69";
|
||||
|
Loading…
Reference in New Issue
Block a user