Skip to content

Commit

Permalink
Update instructions for building LLVM intrinsics
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicholas Rodrigues Lordello committed Aug 29, 2023
1 parent 211f35a commit 10bbd4c
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
1 change: 1 addition & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
cargo test --release
- name: Test LLVM Intrinsics
run: |
sudo apt update && sudo apt install clang-16
cargo clippy --features llvm-intrinsics --all-targets -- -D warnings
cargo test --features llvm-intrinsics
cargo test --features llvm-intrinsics --release
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,24 @@ in order to actually take advantage of the the optimized assembly:
RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build
```

Note that **the `clang` version must match the `rustc` LLVM version**. If not,
it is possible to encounter errors when running the `ethnum-intrinsics` build
script. You can verify the LLVM version used by `rustc` with:

```sh
rustc --version --verbose | grep LLVM
```

In particular, this affects macOS which ships its own `clang` binary. The
`ethnum-intrinsics` build script accepts a `CLANG` environment variable to
specity a specific `clang` executable path to use. Using the major LLVM
version from the command above:

```
brew install llvm@${LLVM_VERSION}
CLANG=/opt/homebrew/opt/llvm@${LLVM_VERSION}/bin/clang cargo build
```

### API Stability

The instinsics are exported under `ethnum::intrinsics`. That being said, be
Expand Down
20 changes: 8 additions & 12 deletions intrinsics/build/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ use cc::Build;
use std::{env, error::Error, fs, path::PathBuf, process::Command};

fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rerun-if-env-changed=CLANG");
let clang = env::var("CLANG")
.map(PathBuf::from)
.unwrap_or_else(|_| "clang".into());

let out_dir = PathBuf::from(env::var("OUT_DIR")?);

let template = {
Expand All @@ -35,24 +40,15 @@ fn main() -> Result<(), Box<dyn Error>> {
let source = template
.replace("i128", "i256")
.replace(" 127", " 255")
.replace("dereferenceable(16)", "dereferenceable(32)")
// TODO(nlordell): Figure out why Clang doesn't like these
.replace("mustprogress ", "")
.replace("noundef ", "")
.replace("memory(argmem: readwrite) ", "")
.replace("memory(argmem: read) ", "")
.replace("memory(none) ", "")
.replace(", !!1", "");
.replace("dereferenceable(16)", "dereferenceable(32)");

let path = out_dir.join("intrinsics.ll");
fs::write(&path, source)?;
path
};

let mut build = Build::new();
build
.compiler("clang")
.file(intrinsics_ir_path)
.opt_level(3);
build.compiler(&clang).file(intrinsics_ir_path).opt_level(3);

let linker_plugin_lto =
matches!(env::var("RUSTFLAGS"), Ok(flags) if flags.contains("-Clinker-plugin-lto"));
Expand Down

0 comments on commit 10bbd4c

Please sign in to comment.