diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e6d3375fb..e06a1fb88 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,13 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + include: + - os: ubuntu-latest + - os: macos-latest + # cross-compile from Linux to Windows using mingw + - os: ubuntu-latest + env: + TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - uses: actions/checkout@v2 @@ -36,6 +42,12 @@ jobs: path: target key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} + - name: Install MinGW toolchain and wine + if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' + run: | + sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable + rustup target add x86_64-pc-windows-gnu + - name: Prepare dependencies run: | git config --global user.email "user@example.com" @@ -43,6 +55,8 @@ jobs: ./prepare.sh - name: Test + env: + TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} run: | # Enable backtraces for easier debugging export RUST_BACKTRACE=1 @@ -57,6 +71,7 @@ jobs: run: tar cvfJ cg_clif.tar.xz build - name: Upload prebuilt cg_clif + if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' uses: actions/upload-artifact@v2 with: name: cg_clif-${{ runner.os }} diff --git a/Cargo.lock b/Cargo.lock index 76d9f0d27..1ed186032 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,16 +39,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" dependencies = [ "byteorder", "cranelift-bforest", @@ -65,8 +65,8 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -74,18 +74,18 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" [[package]] name = "cranelift-entity" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" [[package]] name = "cranelift-frontend" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" dependencies = [ "cranelift-codegen", "log", @@ -95,8 +95,8 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" dependencies = [ "anyhow", "cranelift-codegen", @@ -113,8 +113,8 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" dependencies = [ "anyhow", "cranelift-codegen", @@ -125,8 +125,8 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" dependencies = [ "cranelift-codegen", "target-lexicon", @@ -134,8 +134,8 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.70.0" -source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" +version = "0.71.0" +source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#e41d88214455987751997b9d6173c5dee93204da" dependencies = [ "anyhow", "cranelift-codegen", diff --git a/build.sh b/build.sh index 090349e54..76bc18843 100755 --- a/build.sh +++ b/build.sh @@ -55,6 +55,7 @@ ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir" mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" +mkdir -p "$target_dir/lib/rustlib/$HOST_TRIPLE/lib/" if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" fi @@ -64,12 +65,18 @@ case "$build_sysroot" in ;; "llvm") cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/" + if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then + cp -r $(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/lib "$target_dir/lib/rustlib/$HOST_TRIPLE/" + fi ;; "clif") echo "[BUILD] sysroot" dir=$(pwd) cd "$target_dir" time "$dir/build_sysroot/build_sysroot.sh" + if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then + time TARGET_TRIPLE="$HOST_TRIPLE" "$dir/build_sysroot/build_sysroot.sh" + fi cp lib/rustlib/*/lib/libstd-* lib/ ;; *) diff --git a/example/mini_core.rs b/example/mini_core.rs index 7c6d7fc10..c4834c804 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -621,6 +621,7 @@ struct PanicLocation { } #[no_mangle] +#[cfg(not(windows))] pub fn get_tls() -> u8 { #[thread_local] static A: u8 = 42; diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 237f4d11d..08ceaeb65 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -239,7 +239,7 @@ fn main() { assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42); - #[cfg(not(jit))] + #[cfg(not(any(jit, windows)))] { extern { #[linkage = "extern_weak"] @@ -292,7 +292,7 @@ fn main() { from_decimal_string(); - #[cfg(not(jit))] + #[cfg(not(any(jit, windows)))] test_tls(); #[cfg(all(not(jit), target_os = "linux"))] diff --git a/example/std_example.rs b/example/std_example.rs index 015bbdfed..221b512e3 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -16,7 +16,8 @@ fn main() { let mut stderr = stderr.lock(); // FIXME support lazy jit when multi threading - #[cfg(not(lazy_jit))] + // FIXME support TLS on windows + #[cfg(not(any(lazy_jit, windows)))] std::thread::spawn(move || { println!("Hello from another thread!"); }); diff --git a/scripts/tests.sh b/scripts/tests.sh index f9a9fb091..3afcea8f0 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -71,14 +71,20 @@ function base_sysroot_tests() { echo "[AOT] mod_bench" $MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE" $RUN_WRAPPER ./target/out/mod_bench +} +function extended_sysroot_tests() { pushd rand - rm -r ./target || true - ../build/cargo.sh test --workspace + cargo clean + if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then + echo "[TEST] rust-random/rand" + ../build/cargo.sh test --workspace + else + echo "[AOT] rust-random/rand" + ../build/cargo.sh build --workspace --target $TARGET_TRIPLE --tests + fi popd -} -function extended_sysroot_tests() { pushd simple-raytracer if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[BENCH COMPILE] ebobby/simple-raytracer" @@ -92,27 +98,40 @@ function extended_sysroot_tests() { else echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[COMPILE] ebobby/simple-raytracer" - ../cargo.sh build + ../build/cargo.sh build --target $TARGET_TRIPLE echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" fi popd pushd build_sysroot/sysroot_src/library/core/tests echo "[TEST] libcore" - rm -r ./target || true - ../../../../../build/cargo.sh test + cargo clean + if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then + ../../../../../build/cargo.sh test + else + ../../../../../build/cargo.sh build --target $TARGET_TRIPLE --tests + fi popd pushd regex echo "[TEST] rust-lang/regex example shootout-regex-dna" - ../build/cargo.sh clean + cargo clean # Make sure `[codegen mono items] start` doesn't poison the diff - ../build/cargo.sh build --example shootout-regex-dna - cat examples/regexdna-input.txt | ../build/cargo.sh run --example shootout-regex-dna | grep -v "Spawned thread" > res.txt - diff -u res.txt examples/regexdna-output.txt + ../build/cargo.sh build --example shootout-regex-dna --target $TARGET_TRIPLE + if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then + cat examples/regexdna-input.txt \ + | ../build/cargo.sh run --example shootout-regex-dna --target $TARGET_TRIPLE \ + | grep -v "Spawned thread" > res.txt + diff -u res.txt examples/regexdna-output.txt + fi - echo "[TEST] rust-lang/regex tests" - ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then + echo "[TEST] rust-lang/regex tests" + ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + else + echo "[AOT] rust-lang/regex tests" + ../build/cargo.sh build --tests --target $TARGET_TRIPLE + fi popd } diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs index ae75e6508..ffe1922ab 100644 --- a/src/codegen_i128.rs +++ b/src/codegen_i128.rs @@ -32,18 +32,56 @@ pub(crate) fn maybe_codegen<'tcx>( BinOp::Add | BinOp::Sub if !checked => None, BinOp::Mul if !checked => { let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; - Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) + if fx.tcx.sess.target.is_like_windows { + let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + let args = + [ret_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; + fx.lib_call( + "__multi3", + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(pointer_ty(fx.tcx)), + AbiParam::new(pointer_ty(fx.tcx)), + ], + vec![], + &args, + ); + Some(ret_place.to_cvalue(fx)) + } else { + Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) + } } BinOp::Add | BinOp::Sub | BinOp::Mul => { assert!(checked); let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); - let param_types = vec![ - AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), - AbiParam::new(types::I128), - AbiParam::new(types::I128), - ]; - let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let (param_types, args) = if fx.tcx.sess.target.is_like_windows { + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + ( + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(pointer_ty(fx.tcx)), + AbiParam::new(pointer_ty(fx.tcx)), + ], + [out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)], + ) + } else { + ( + vec![ + AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), + AbiParam::new(types::I128), + AbiParam::new(types::I128), + ], + [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)], + ) + }; let name = match (bin_op, is_signed) { (BinOp::Add, false) => "__rust_u128_addo", (BinOp::Add, true) => "__rust_i128_addo", @@ -57,20 +95,33 @@ pub(crate) fn maybe_codegen<'tcx>( Some(out_place.to_cvalue(fx)) } BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"), - BinOp::Div => { + BinOp::Div | BinOp::Rem => { assert!(!checked); - if is_signed { - Some(fx.easy_call("__divti3", &[lhs, rhs], fx.tcx.types.i128)) - } else { - Some(fx.easy_call("__udivti3", &[lhs, rhs], fx.tcx.types.u128)) - } - } - BinOp::Rem => { - assert!(!checked); - if is_signed { - Some(fx.easy_call("__modti3", &[lhs, rhs], fx.tcx.types.i128)) + let name = match (bin_op, is_signed) { + (BinOp::Div, false) => "__udivti3", + (BinOp::Div, true) => "__divti3", + (BinOp::Rem, false) => "__umodti3", + (BinOp::Rem, true) => "__modti3", + _ => unreachable!(), + }; + if fx.tcx.sess.target.is_like_windows { + let (lhs_ptr, lhs_extra) = lhs.force_stack(fx); + let (rhs_ptr, rhs_extra) = rhs.force_stack(fx); + assert!(lhs_extra.is_none()); + assert!(rhs_extra.is_none()); + let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)]; + let ret = fx.lib_call( + name, + vec![AbiParam::new(pointer_ty(fx.tcx)), AbiParam::new(pointer_ty(fx.tcx))], + vec![AbiParam::new(types::I64X2)], + &args, + )[0]; + // FIXME use bitcast instead of store to get from i64x2 to i128 + let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); + ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); + Some(ret_place.to_cvalue(fx)) } else { - Some(fx.easy_call("__umodti3", &[lhs, rhs], fx.tcx.types.u128)) + Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty)) } } BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => { diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 5b3df2bd3..33234f820 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -20,6 +20,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( if template.is_empty() { // Black box return; + } else if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { + let true_ = fx.bcx.ins().iconst(types::I32, 1); + fx.bcx.ins().trapnz(true_, TrapCode::User(1)); + return; } let mut slot_size = Size::from_bytes(0); diff --git a/src/lib.rs b/src/lib.rs index e1927ad3a..5db249970 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -313,6 +313,8 @@ fn build_isa(sess: &Session) -> Box { flags_builder.set("enable_simd", "true").unwrap(); + flags_builder.set("enable_llvm_abi_extensions", "true").unwrap(); + use rustc_session::config::OptLevel; match sess.opts.optimize { OptLevel::No => {