Skip to content

Commit 0c065f9

Browse files
authored
Merge pull request #1089 from bjorn3/custom_driver
Add custom rustc driver that uses cg_clif
2 parents c046ad0 + 9a513be commit 0c065f9

File tree

14 files changed

+191
-50
lines changed

14 files changed

+191
-50
lines changed

Readme.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,24 @@ If you compiled cg_clif in debug mode (aka you didn't pass `--release` to `./tes
3636
> You should prefer using the Cargo method.
3737
3838
```bash
39-
$ rustc +$(cat $cg_clif_dir/rust-toolchain) -Cpanic=abort -Zcodegen-backend=$cg_clif_dir/target/release/librustc_codegen_cranelift.so --sysroot $cg_clif_dir/build_sysroot/sysroot my_crate.rs
39+
$ $cg_clif_dir/target/release/cg_clif my_crate.rs
40+
```
41+
42+
### Jit mode
43+
44+
In jit mode cg_clif will immediately execute your code without creating an executable file.
45+
46+
> This requires all dependencies to be available as dynamic library.
47+
> The jit mode will probably need cargo integration to make this possible.
48+
49+
```bash
50+
$ $cg_clif_dir/cargo.sh jit
51+
```
52+
53+
or
54+
55+
```bash
56+
$ $cg_clif_dir/target/release/cg_clif --jit my_crate.rs
4057
```
4158

4259
### Shell
@@ -45,7 +62,7 @@ These are a few functions that allow you to easily run rust code from the shell
4562

4663
```bash
4764
function jit_naked() {
48-
echo "$@" | CG_CLIF_JIT=1 rustc -Zcodegen-backend=$cg_clif_dir/target/release/librustc_codegen_cranelift.so --sysroot $cg_clif_dir/build_sysroot/sysroot - -Cprefer-dynamic
65+
echo "$@" | $cg_clif_dir/target/release/cg_clif - --jit
4966
}
5067

5168
function jit() {

build_sysroot/build_sysroot.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ popd >/dev/null
1414
rm -r target/*/{debug,release}/{build,deps,examples,libsysroot*,native} 2>/dev/null || true
1515
rm -r sysroot/ 2>/dev/null || true
1616

17+
# Use rustc with cg_clif as hotpluggable backend instead of the custom cg_clif driver so that
18+
# build scripts are still compiled using cg_llvm.
19+
export RUSTC=rustc
20+
export RUSTFLAGS=$RUSTFLAGS" -Ztrim-diagnostic-paths=no -Zcodegen-backend=$(pwd)/../target/"$CHANNEL"/librustc_codegen_cranelift."$dylib_ext" --sysroot $(pwd)/sysroot"
21+
1722
# Build libs
18-
export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked"
23+
export RUSTFLAGS="$RUSTFLAGS -Zforce-unstable-if-unmarked -Cpanic=abort"
1924
if [[ "$1" == "--release" ]]; then
2025
sysroot_channel='release'
2126
# FIXME Enable incremental again once rust-lang/rust#74946 is fixed

cargo.sh

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ TOOLCHAIN=$(cat rust-toolchain)
1212

1313
popd >/dev/null
1414

15-
if [[ $(rustc -V) != $(rustc +${TOOLCHAIN} -V) ]]; then
16-
echo "rustc_codegen_cranelift is build for $(rustc +${TOOLCHAIN} -V) but the default rustc version is $(rustc -V)."
17-
echo "Using $(rustc +${TOOLCHAIN} -V)."
18-
fi
19-
2015
cmd=$1
2116
shift
2217

18+
if [[ "$cmd" = "jit" ]]; then
19+
cargo +${TOOLCHAIN} rustc $@ -- --jit
20+
else
2321
cargo +${TOOLCHAIN} $cmd $@
22+
fi

docs/env_vars.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# List of env vars recognized by cg_clif
22

33
<dl>
4-
<dt>CG_CLIF_JIT</dt>
5-
<dd>Enable JIT mode to immediately run a program instead of writing an executable file.</dd>
64
<dt>CG_CLIF_JIT_ARGS</dt>
75
<dd>When JIT mode is enable pass these arguments to the program.</dd>
86
<dt>CG_CLIF_INCR_CACHE_DISABLED</dt>

scripts/config.sh

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,18 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
3232
fi
3333
fi
3434

35-
export RUSTFLAGS=$linker' -Ztrim-diagnostic-paths=no -Cpanic=abort -Cdebuginfo=2 -Zpanic-abort-tests -Zcodegen-backend='$(pwd)'/target/'$CHANNEL'/librustc_codegen_cranelift.'$dylib_ext' --sysroot '$(pwd)'/build_sysroot/sysroot'
36-
export RUSTDOCFLAGS=$RUSTFLAGS
35+
export RUSTC=$(pwd)/"target/"$CHANNEL"/cg_clif"
36+
export RUSTFLAGS=$linker
37+
export RUSTDOCFLAGS=$linker' -Ztrim-diagnostic-paths=no -Cpanic=abort -Zpanic-abort-tests '\
38+
'-Zcodegen-backend='$(pwd)'/target/'$CHANNEL'/librustc_codegen_cranelift.'$dylib_ext' --sysroot '$(pwd)'/build_sysroot/sysroot'
3739

3840
# FIXME remove once the atomic shim is gone
3941
if [[ `uname` == 'Darwin' ]]; then
4042
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
4143
fi
4244

43-
export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib"
45+
export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/"$TARGET_TRIPLE"/lib:\
46+
$(pwd)/target/"$CHANNEL":$(rustc --print sysroot)/lib"
4447
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
4548

4649
export CG_CLIF_DISPLAY_CG_TIME=1

scripts/filter_profile.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ CHANNEL="release"
55
pushd $(dirname "$0")/../
66
source scripts/config.sh
77
popd
8-
CG_CLIF_JIT=1 PROFILE=$1 OUTPUT=$2 exec rustc $RUSTFLAGS $0 --crate-type bin -Cprefer-dynamic
8+
PROFILE=$1 OUTPUT=$2 exec $RUSTC $RUSTFLAGS --jit $0
99
#*/
1010

1111
//! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse

src/atomic_shim.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ use crate::prelude::*;
1010
pub static mut __cg_clif_global_atomic_mutex: libc::pthread_mutex_t =
1111
libc::PTHREAD_MUTEX_INITIALIZER;
1212

13-
pub(crate) fn init_global_lock(module: &mut Module<impl Backend>, bcx: &mut FunctionBuilder<'_>) {
14-
if std::env::var("CG_CLIF_JIT").is_ok() {
13+
pub(crate) fn init_global_lock(
14+
module: &mut Module<impl Backend>,
15+
bcx: &mut FunctionBuilder<'_>,
16+
use_jit: bool,
17+
) {
18+
if use_jit {
1519
// When using JIT, dylibs won't find the __cg_clif_global_atomic_mutex data object defined here,
16-
// so instead define it in the cg_clif dylib.
20+
// so instead we define it in the cg_clif dylib.
1721

1822
return;
1923
}
@@ -80,7 +84,7 @@ pub(crate) fn init_global_lock_constructor(
8084
let block = bcx.create_block();
8185
bcx.switch_to_block(block);
8286

83-
crate::atomic_shim::init_global_lock(module, &mut bcx);
87+
crate::atomic_shim::init_global_lock(module, &mut bcx, false);
8488

8589
bcx.ins().return_(&[]);
8690
bcx.seal_all_blocks();

src/bin/cg_clif.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#![feature(rustc_private)]
2+
3+
extern crate rustc_data_structures;
4+
extern crate rustc_driver;
5+
extern crate rustc_interface;
6+
extern crate rustc_session;
7+
extern crate rustc_target;
8+
9+
use rustc_data_structures::profiling::print_time_passes_entry;
10+
use rustc_interface::interface;
11+
use rustc_session::config::ErrorOutputType;
12+
use rustc_session::early_error;
13+
use rustc_target::spec::PanicStrategy;
14+
15+
#[derive(Default)]
16+
pub struct TimePassesCallbacks {
17+
time_passes: bool,
18+
}
19+
20+
impl rustc_driver::Callbacks for TimePassesCallbacks {
21+
fn config(&mut self, config: &mut interface::Config) {
22+
// If a --prints=... option has been given, we don't print the "total"
23+
// time because it will mess up the --prints output. See #64339.
24+
self.time_passes = config.opts.prints.is_empty()
25+
&& (config.opts.debugging_opts.time_passes || config.opts.debugging_opts.time);
26+
27+
// FIXME workaround for an ICE
28+
config.opts.debugging_opts.trim_diagnostic_paths = false;
29+
30+
config.opts.cg.panic = Some(PanicStrategy::Abort);
31+
config.opts.debugging_opts.panic_abort_tests = true;
32+
config.opts.maybe_sysroot = Some(
33+
std::env::current_exe()
34+
.unwrap()
35+
.parent()
36+
.unwrap()
37+
.parent()
38+
.unwrap()
39+
.parent()
40+
.unwrap()
41+
.join("build_sysroot")
42+
.join("sysroot"),
43+
);
44+
}
45+
}
46+
47+
fn main() {
48+
let start = std::time::Instant::now();
49+
rustc_driver::init_rustc_env_logger();
50+
let mut callbacks = TimePassesCallbacks::default();
51+
rustc_driver::install_ice_hook();
52+
let exit_code = rustc_driver::catch_with_exit_code(|| {
53+
let mut use_jit = false;
54+
55+
let mut args = std::env::args_os()
56+
.enumerate()
57+
.map(|(i, arg)| {
58+
arg.into_string().unwrap_or_else(|arg| {
59+
early_error(
60+
ErrorOutputType::default(),
61+
&format!("Argument {} is not valid Unicode: {:?}", i, arg),
62+
)
63+
})
64+
})
65+
.filter(|arg| {
66+
if arg == "--jit" {
67+
use_jit = true;
68+
false
69+
} else {
70+
true
71+
}
72+
})
73+
.collect::<Vec<_>>();
74+
if use_jit {
75+
args.push("-Cprefer-dynamic".to_string());
76+
}
77+
rustc_driver::run_compiler(
78+
&args,
79+
&mut callbacks,
80+
None,
81+
None,
82+
Some(Box::new(move |_| {
83+
Box::new(rustc_codegen_cranelift::CraneliftCodegenBackend {
84+
config: rustc_codegen_cranelift::BackendConfig {
85+
use_jit,
86+
}
87+
})
88+
})),
89+
)
90+
});
91+
// The extra `\t` is necessary to align this label with the others.
92+
print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed());
93+
std::process::exit(exit_code)
94+
}

src/driver/aot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege
150150
super::codegen_mono_items(&mut cx, mono_items);
151151
let (mut module, global_asm, debug, mut unwind_context) =
152152
tcx.sess.time("finalize CodegenCx", || cx.finalize());
153-
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, &mut unwind_context);
153+
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, &mut unwind_context, false);
154154

155155
let codegen_result = emit_module(
156156
tcx,

src/driver/jit.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,23 @@ use crate::prelude::*;
1111
pub(super) fn run_jit(tcx: TyCtxt<'_>) -> ! {
1212
use cranelift_simplejit::{SimpleJITBackend, SimpleJITBuilder};
1313

14-
// Rustc opens us without the RTLD_GLOBAL flag, so __cg_clif_global_atomic_mutex will not be
15-
// exported. We fix this by opening ourself again as global.
16-
// FIXME remove once atomic_shim is gone
17-
let cg_dylib = std::ffi::OsString::from(
18-
&tcx.sess
19-
.opts
20-
.debugging_opts
21-
.codegen_backend
22-
.as_ref()
23-
.unwrap(),
24-
);
25-
std::mem::forget(
26-
libloading::os::unix::Library::open(Some(cg_dylib), libc::RTLD_NOW | libc::RTLD_GLOBAL)
27-
.unwrap(),
28-
);
14+
#[cfg(unix)]
15+
unsafe {
16+
// When not using our custom driver rustc will open us without the RTLD_GLOBAL flag, so
17+
// __cg_clif_global_atomic_mutex will not be exported. We fix this by opening ourself again
18+
// as global.
19+
// FIXME remove once atomic_shim is gone
20+
21+
let mut dl_info: libc::Dl_info = std::mem::zeroed();
22+
assert_ne!(
23+
libc::dladdr(run_jit as *const libc::c_void, &mut dl_info),
24+
0
25+
);
26+
assert_ne!(
27+
libc::dlopen(dl_info.dli_fname, libc::RTLD_NOW | libc::RTLD_GLOBAL),
28+
std::ptr::null_mut(),
29+
);
30+
}
2931

3032
let imported_symbols = load_imported_symbols_for_jit(tcx);
3133

@@ -74,7 +76,7 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>) -> ! {
7476
if !global_asm.is_empty() {
7577
tcx.sess.fatal("Global asm is not supported in JIT mode");
7678
}
77-
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, &mut unwind_context);
79+
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, &mut unwind_context, true);
7880
crate::allocator::codegen(tcx, &mut jit_module, &mut unwind_context);
7981

8082
jit_module.finalize_definitions();
@@ -85,7 +87,7 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>) -> ! {
8587

8688
let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id);
8789

88-
println!("Rustc codegen cranelift will JIT run the executable, because the CG_CLIF_JIT env var is set");
90+
println!("Rustc codegen cranelift will JIT run the executable, because --jit was passed");
8991

9092
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
9193
unsafe { ::std::mem::transmute(finalized_main) };

0 commit comments

Comments
 (0)