From 48f8aad18043c5929da9eedce4d9d8af33fa4651 Mon Sep 17 00:00:00 2001 From: Jared Ramirez Date: Sun, 25 Oct 2020 14:09:53 -0700 Subject: [PATCH] Compile bitcode as part of build script --- compiler/builtins/bitcode/.gitignore | 2 +- compiler/builtins/bitcode/Makefile | 7 ---- compiler/builtins/bitcode/README.md | 44 +++++--------------------- compiler/builtins/bitcode/generate.sh | 13 -------- compiler/gen/build.rs | 23 ++++++++++++++ compiler/gen/src/llvm/build.rs | 17 ++++++++-- compiler/gen/src/llvm/builtins.bc | Bin 3856 -> 0 bytes 7 files changed, 47 insertions(+), 59 deletions(-) delete mode 100644 compiler/builtins/bitcode/Makefile delete mode 100755 compiler/builtins/bitcode/generate.sh create mode 100644 compiler/gen/build.rs delete mode 100644 compiler/gen/src/llvm/builtins.bc diff --git a/compiler/builtins/bitcode/.gitignore b/compiler/builtins/bitcode/.gitignore index 1fcb1529f8..c7f8e4f525 100644 --- a/compiler/builtins/bitcode/.gitignore +++ b/compiler/builtins/bitcode/.gitignore @@ -1 +1 @@ -out +lib.ll diff --git a/compiler/builtins/bitcode/Makefile b/compiler/builtins/bitcode/Makefile deleted file mode 100644 index 421d5bfb60..0000000000 --- a/compiler/builtins/bitcode/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -.PHONY: build clean - -build: - ./generate.sh ../../gen/src/llvm/builtins.bc - -clean: - rm -rf ./out diff --git a/compiler/builtins/bitcode/README.md b/compiler/builtins/bitcode/README.md index 823c734851..17ab42e2e5 100644 --- a/compiler/builtins/bitcode/README.md +++ b/compiler/builtins/bitcode/README.md @@ -5,52 +5,24 @@ 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 Rust, compile the -result to LLVM bitcode, and import that bitcode into the compiler. +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. -Here is the process for doing that. +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`. -## Building the bitcode - -The source we'll use to generate the bitcode is in `src/lib.rs` in this directory. - -To generate the bitcode, `cd` into `compiler/builtins/bitcode/` and run: - -```bash -$ ./regenerate.sh -``` - -> If you want to take a look at the human-readable LLVM IR rather than the -> bitcode, run this instead and look for a `.ll` file instead of a `.bc` file: +> 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 -> $ cargo rustc --release --lib -- --emit=llvm-ir +> clang -S -emit-llvm src/lib.c > ``` -> -> Then look in the root `roc` source directory under `target/release/deps/` for a file -> with a name like `roc_builtins_bitcode-8da0901c58a73ebf.bc` - except -> probably with a different hash before the `.bc`. If there's more than one -> `*.bc` file in that directory, delete the whole `deps/` directory and re-run -> the `cargo rustc` command above to regenerate it. - -**Note**: In order to be able to address the bitcode functions by name, they need to be defined with the `#[no_mangle]` attribute. 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 -using the [`include_bytes!` macro](https://doc.rust-lang.org/std/macro.include_bytes.html). -The current `.bc` file is located at: - -``` -compiler/gen/src/llvm/builtins.bc -``` - -The script will automatically replace this `.bc` file with the new one. - -Once that's done, `git status` should show that the `builtins.bc` file -has been changed. Commit that change and you're done! +The `llvm/src/build.rs` file statically imports these raw bytes. ## Calling bitcode functions diff --git a/compiler/builtins/bitcode/generate.sh b/compiler/builtins/bitcode/generate.sh deleted file mode 100755 index e1d12b6f74..0000000000 --- a/compiler/builtins/bitcode/generate.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -euxo pipefail - -# Clear out any existing output files -rm -rf ./out -mkdir ./out - -# Regenerate the .bc file -clang -emit-llvm -o out/lib.bc -c src/lib.c - -# Copy bc file for it to be used -cp ./out/lib.bc "$1" diff --git a/compiler/gen/build.rs b/compiler/gen/build.rs new file mode 100644 index 0000000000..bf76f2cfcc --- /dev/null +++ b/compiler/gen/build.rs @@ -0,0 +1,23 @@ +use std::env; +use std::fs; +use std::path::Path; +use std::process::Command; + +fn main() { + let src_path = fs::canonicalize("./../builtins/bitcode/src/lib.c") + .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_path = Path::new(&out_dir).join("builtins.bc"); + let dest = dest_path.to_str().expect("Invalid dest path"); + + Command::new("clang") + .args(&["-emit-llvm", "-o", dest, "-c", src]) + .status() + .unwrap(); + + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed={}", src); + println!("cargo:rustc-env=BUILTINS_BC={}", dest); +} diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index abde3b5437..a6e22b3a1d 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -34,6 +34,8 @@ 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 @@ -181,8 +183,19 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { } pub fn module_from_builtins<'ctx>(ctx: &'ctx Context, module_name: &str) -> Module<'ctx> { - let memory_buffer = - MemoryBuffer::create_from_memory_range(include_bytes!("builtins.bc"), module_name); + // 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 memory_buffer = MemoryBuffer::create_from_memory_range(&buffer, 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)); diff --git a/compiler/gen/src/llvm/builtins.bc b/compiler/gen/src/llvm/builtins.bc deleted file mode 100644 index e8adb3a3e7d68053d383dc360953408498a8a5da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3856 zcmeHKeM}qY8Gny6zT?B^OJJ+1@7!}pGf!>EK~k`>scbGEPKPwJMq0LY!iGXkM~Jbh zF;2SK*vZkBKQ3MVu+(a@rB2JVY@-UAvZ+$dTc%SFF8|lZY5VTt8_ZWmIgot)2ed8IJD2KW3YH{!JAN+ak z&flKhf0$^(Q^;72(DzA%s>+P048}Fksc8KLM^1HI%{E!yB;wUimeX|x)f?Rr_DEU# zn^o;`wyD-k>%LRj)IRQ1Y6a=&_%BgiQ@iRoqwLx<<8pLHCyKGv*Hy-&>P{U(n*>7o zAAakz&!G_ts$7nU!fcUWaTw-2+E21 zVOUJ^(@{f#5M`fR9yL)BK^{)XK9&la1|Uu!{0VZoy-iBZP$%x8^Y{ zBEw3Gn>F%lz%$J)r+^iQ0F{*oYHLXMB8`RNQ`ex&&Lcx==u2Yj+$kedq_@JIp+67t4^G!?c} zX>K}-MMl#YIY=>07?zFvQjzN$7x2tPv4^Z1 zx%nu+=*Ct6Z+wV~1~(f8OM$9E&rWdWZL7&X;UTtdlYNb|p|B!{O_aOjMFBw7Wl6alN|1ZlsTwN5!&uf{C-N8>LtcMIxU zF70ik#rR8td|4ZiCE$!9Jio2 zMh;TMNn2WKy_&UrMVXD-dn|Kv5{tjJ$=q`>H|^THpaFsT)Xl89n5}{u{_CHhb{?tP z;xXIXk_GHCLE5g7NV~esY$*_#SYWc{13VbUDqwJFw_IS3%Ng^s#4Ql|%Tdd6)|Mmn zmmStA^4ZDE<9W%Pj9D;&?WMn*u>s&5>?{%a2Sg#NpV_8iTb6_U%cNn6u!GM4hs2Iq z^-~hKQ|lL&{S@pA$Tyj_5~PhyrfAnbREu8u2>T>uFEb^XW_A`2w2`Td`QJeN4DF4S z9fv%Q3x=AwJ;ADK#ysuz4*KL9C8XU9piFJ@NAmPky~3$9sU!r-Y26SPC9riKgZwFm`~cu1f^1@)Z>6^3-0qyoau z>J^sqN2te*9n8=Fc=mqxuipRN$83d5g-R6<6ekFscRuGp2;@LC9*T#jiIl9<@XiPb@EOi|O-Z zTTW`5Alvex35fG&Alo`+9|U|KiBp>(*X4KNds-B=gQE84CbQ{c4ze@+4Je0<{Iti= zC%%R+CS27i()J#{1=jp#ZO~1f@lq`~gHSCI*$3Ig4eFTO4ZgMtZ4DO`BW8@Z*Z zVQHDe6(eEj({-9BrPjB>`CWT=1aZqFAu5#U?6{|Bu?7q;m+DL-F3)~S;8HMeo^Rv6Yp2z1U&+HpoW3$pNPJ&9Zpx_3XAobd52-8_}D^` zzd;zV{YM3ao`QF`!6``N)peG-y~+jqY%b^BQlM z`UgD&-$wQHbB$w3T|GSqFX3SIVOL(%O*cwn&gmX&>h8JnlR*EO`rq_C6=>|Kvc9E1 zVpdKpENm>kFrS-ST0dH`8?gQwd=Y;vR8>MvGXgi}q%R@0fvF}ToMp$>xY_NJ5f@ne zdP#TaFK_{{e^YrI1pK$bppb?jb4g|;i*J!fKu81c8kGZX0zz=XP;EWxQ3>=I{^dTW zP*xN3P3UTm(qqI0Hmk`jUt_(Pr$^Y{U!%&5JBH$dj&&*zc$#3nMkSSa;`{gFlVX_* z4rMhnZuOPwC|iBP^j$kaeq**qOxw?WtYTf$Dd0`0TTC4-_NXgkd__F@fibJ8sNdPI z>qczGe$J>yyW#L45;MM-5Y6nW{HrFq?}R;9zOODm1AkQt2UWD4PL{vV()M?g>=<$K zn=B!is?H2sw!*L#P+Nv7UkVZt~(KEEDcnCLB)> z?~GmW#tpymd=3ww?T7w2^kdK~puY^KA`b`;BP>BXCCu84K#dCB0Y3$-_ri4fq?d7kgXoxAltw2xIfSZ zUfMt0+vOSd43-|g(<5E|gTq||1Hn@beV*<>Ltpcul8cAT&0Woh_IrH3f!_V6JUyoa lp+>Qxv8h1}_