diff --git a/Cargo.lock b/Cargo.lock index 6e9f0955a..139fb70fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,28 +117,28 @@ dependencies = [ [[package]] name = "cranelift" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-frontend 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-codegen 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-frontend 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", ] [[package]] name = "cranelift-bforest" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-entity 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", ] [[package]] name = "cranelift-codegen" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-bforest 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-codegen-meta 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-bforest 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-codegen-meta 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-entity 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -148,23 +148,23 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-entity 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", ] [[package]] name = "cranelift-entity" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" [[package]] name = "cranelift-faerie" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-codegen 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-module 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", "faerie 0.10.1 (git+https://github.com/m4b/faerie.git)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "goblin 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -174,9 +174,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-codegen 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -184,10 +184,10 @@ dependencies = [ [[package]] name = "cranelift-module" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-codegen 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-entity 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "cranelift-native" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-codegen 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -205,11 +205,11 @@ dependencies = [ [[package]] name = "cranelift-simplejit" version = "0.36.0" -source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3" +source = "git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128#ca836a8e0d0b62e2ddecb5902cd5091b468a4db3" dependencies = [ - "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-native 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift-codegen 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-module 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-native 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -611,10 +611,10 @@ dependencies = [ "ar 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-faerie 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", - "cranelift-simplejit 0.36.0 (git+https://github.com/CraneStation/cranelift.git)", + "cranelift 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-faerie 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-module 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", + "cranelift-simplejit 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)", "faerie 0.10.1 (git+https://github.com/m4b/faerie.git)", "gimli 0.19.0 (git+https://github.com/gimli-rs/gimli.git)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -882,16 +882,16 @@ dependencies = [ "checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum cranelift 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-bforest 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-codegen-meta 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-faerie 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-frontend 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-native 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" -"checksum cranelift-simplejit 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "" +"checksum cranelift 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-bforest 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-codegen 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-codegen-meta 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-entity 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-faerie 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-frontend 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-module 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-native 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" +"checksum cranelift-simplejit 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" diff --git a/Cargo.toml b/Cargo.toml index 59d66d07f..414423d72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,12 @@ gimli = { git = "https://github.com/gimli-rs/gimli.git" } indexmap = "1.0.2" object = "0.12.0" +[patch."https://github.com/CraneStation/cranelift.git"] +cranelift = { git = "https://github.com/bjorn3/cretonne.git", branch = "do_not_remove_cg_clif_i128" } +cranelift-module = { git = "https://github.com/bjorn3/cretonne.git", branch = "do_not_remove_cg_clif_i128" } +cranelift-simplejit = { git = "https://github.com/bjorn3/cretonne.git", branch = "do_not_remove_cg_clif_i128" } +cranelift-faerie = { git = "https://github.com/bjorn3/cretonne.git", branch = "do_not_remove_cg_clif_i128" } + # Uncomment to use local checkout of cranelift #[patch."https://github.com/CraneStation/cranelift.git"] #cranelift = { path = "../cranelift/cranelift-umbrella" } diff --git a/Readme.md b/Readme.md index 5fc18c82e..56b65cf3e 100644 --- a/Readme.md +++ b/Readme.md @@ -29,10 +29,9 @@ $ RUSTFLAGS="-Cpanic=abort -Zcodegen-backend=$cg_clif_dir/target/debug/librustc_ ## Not yet supported -* Good non-rust abi support ([scalar pair and vector are passed by-ref](https://github.com/bjorn3/rustc_codegen_cranelift/issues/10)) +* Good non-rust abi support ([vectors are passed by-ref](https://github.com/bjorn3/rustc_codegen_cranelift/issues/10)) * Checked binops ([some missing instructions in cranelift](https://github.com/CraneStation/cranelift/issues/460)) * Inline assembly ([no cranelift support](https://github.com/CraneStation/cranelift/issues/444)) -* u128 and i128 ([no cranelift support](https://github.com/CraneStation/cranelift/issues/354)) * SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171)) ## Troubleshooting diff --git a/build_sysroot/Cargo.toml b/build_sysroot/Cargo.toml index 45484027e..90d245522 100644 --- a/build_sysroot/Cargo.toml +++ b/build_sysroot/Cargo.toml @@ -14,7 +14,6 @@ alloc_system = { path = "./alloc_system" } [patch.crates-io] rustc-std-workspace-core = { path = "./sysroot_src/src/tools/rustc-std-workspace-core" } rustc-std-workspace-alloc = { path = "./rustc-std-workspace-alloc" } -compiler_builtins = { path = "./compiler_builtins" } [profile.release] debug = true diff --git a/build_sysroot/compiler_builtins/Cargo.toml b/build_sysroot/compiler_builtins/Cargo.toml deleted file mode 100644 index 724a637a2..000000000 --- a/build_sysroot/compiler_builtins/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "compiler_builtins" -# Make sure the `compiler_builtins` from crates.io doesn't take precedence over this -# replacement by specifying a higher version than the one on crates.io. -version = "0.1.100" -authors = ["bjorn3 "] -edition = "2018" - -[lib] -name = "compiler_builtins" -path = "lib.rs" -test = false -doc = false - -[dependencies] -core = { path = "../sysroot_src/src/libcore" } - -[features] -rustc-dep-of-std = [] -c = [] diff --git a/build_sysroot/compiler_builtins/lib.rs b/build_sysroot/compiler_builtins/lib.rs deleted file mode 100644 index 79a54a3a4..000000000 --- a/build_sysroot/compiler_builtins/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(compiler_builtins, staged_api)] -#![compiler_builtins] -#![no_std] - -#![unstable( - feature = "compiler_builtins_lib", - reason = "Compiler builtins. Will never become stable.", - issue = "0" -)] diff --git a/example/mini_core.rs b/example/mini_core.rs index d900776c5..069a930e0 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -128,6 +128,14 @@ impl Add for u8 { } } +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + impl Add for usize { type Output = Self; @@ -151,6 +159,30 @@ impl Sub for usize { } } +impl Sub for u8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i16 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + #[lang = "bitor"] pub trait BitOr { type Output; @@ -270,6 +302,22 @@ pub trait Neg { fn neg(self) -> Self::Output; } +impl Neg for i8 { + type Output = i8; + + fn neg(self) -> i8 { + -self + } +} + +impl Neg for i16 { + type Output = i16; + + fn neg(self) -> i16 { + self + } +} + impl Neg for isize { type Output = isize; diff --git a/example/std_example.rs b/example/std_example.rs index 98d9ed17b..a09e050ce 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -1,6 +1,7 @@ #![feature(core_intrinsics)] use std::io::Write; +use std::intrinsics; fn main() { let _ = ::std::iter::repeat('a' as u8).take(10).collect::>(); @@ -29,6 +30,18 @@ fn main() { println!("{}", 2.3f32.ceil()); println!("{}", 2.3f32.min(1.0)); println!("{}", 2.3f32.max(1.0)); + + assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26); + assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); + + 0i128.checked_div(2i128); + 0u128.checked_div(2u128); + assert_eq!(1u128 + 2, 3); + + assert_eq!(0b100010000000000000000000000000000u128 >> 10, 0b10001000000000000000000u128); + assert_eq!(0xFEDCBA987654321123456789ABCDEFu128 >> 64, 0xFEDCBA98765432u128); + assert_eq!(0xFEDCBA987654321123456789ABCDEFu128 as i128 >> 64, 0xFEDCBA98765432i128); + assert_eq!(353985398u128 * 932490u128, 330087843781020u128); } #[derive(PartialEq)] diff --git a/src/abi.rs b/src/abi.rs index 2397da9be..5e041e6c6 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -87,7 +87,7 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type { Integer::I16 => types::I16, Integer::I32 => types::I32, Integer::I64 => types::I64, - Integer::I128 => unimpl!("u/i128"), + Integer::I128 => types::I128, }, Primitive::Float(flt) => match flt { FloatTy::F32 => types::F32, @@ -252,14 +252,12 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> { &mut self, name: &str, input_tys: Vec, - output_ty: Option, + output_tys: Vec, args: &[Value], - ) -> Option { + ) -> &[Value] { let sig = Signature { params: input_tys.iter().cloned().map(AbiParam::new).collect(), - returns: output_ty - .map(|output_ty| vec![AbiParam::new(output_ty)]) - .unwrap_or(Vec::new()), + returns: output_tys.iter().cloned().map(AbiParam::new).collect(), call_conv: CallConv::SystemV, }; let func_id = self @@ -270,12 +268,10 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> { .module .declare_func_in_func(func_id, &mut self.bcx.func); let call_inst = self.bcx.ins().call(func_ref, args); - if output_ty.is_none() { - return None; - } + self.add_comment(call_inst, format!("easy_call {}", name)); let results = self.bcx.inst_results(call_inst); - assert_eq!(results.len(), 1); - Some(results[0]) + assert!(results.len() <= 2, "{}", results.len()); + results } pub fn easy_call( @@ -294,23 +290,22 @@ impl<'a, 'tcx: 'a, B: Backend + 'a> FunctionCx<'a, 'tcx, B> { }) .unzip(); let return_layout = self.layout_of(return_ty); - let return_ty = if let ty::Tuple(tup) = return_ty.sty { - if !tup.is_empty() { - bug!("easy_call( (...) -> ) is not allowed"); - } - None + let return_tys = if let ty::Tuple(tup) = return_ty.sty { + tup.types().map(|ty| self.clif_type(ty).unwrap()).collect() } else { - Some(self.clif_type(return_ty).unwrap()) + vec![self.clif_type(return_ty).unwrap()] }; - if let Some(val) = self.lib_call(name, input_tys, return_ty, &args) { - CValue::by_val(val, return_layout) - } else { - CValue::by_ref( + let ret_vals = self.lib_call(name, input_tys, return_tys, &args); + match *ret_vals { + [] => CValue::by_ref( self.bcx .ins() .iconst(self.pointer_type, self.pointer_type.bytes() as i64), return_layout, - ) + ), + [val] => CValue::by_val(val, return_layout), + [val, extra] => CValue::by_val_pair(val, extra, return_layout), + _ => unreachable!(), } } @@ -346,7 +341,7 @@ fn add_arg_comment<'a, 'tcx: 'a>( }; let pass_mode = format!("{:?}", pass_mode); fx.add_global_comment(format!( - "{msg:5} {local:>3}{local_field:<5} {params:10} {pass_mode:20} {ssa:10} {ty:?}", + "{msg:5} {local:>3}{local_field:<5} {params:10} {pass_mode:36} {ssa:10} {ty:?}", msg = msg, local = format!("{:?}", local), local_field = local_field, @@ -360,7 +355,7 @@ fn add_arg_comment<'a, 'tcx: 'a>( #[cfg(debug_assertions)] fn add_local_header_comment(fx: &mut FunctionCx) { fx.add_global_comment(format!( - "msg loc.idx param pass mode ssa flags ty" + "msg loc.idx param pass mode ssa flags ty" )); } @@ -846,7 +841,7 @@ pub fn codegen_drop<'a, 'tcx: 'a>( ); drop_place.write_place_ref(fx, arg_place); let arg_value = arg_place.to_cvalue(fx); - crate::abi::codegen_call_inner( + codegen_call_inner( fx, None, drop_fn_ty, diff --git a/src/base.rs b/src/base.rs index 1adcec046..3d09b7cef 100644 --- a/src/base.rs +++ b/src/base.rs @@ -11,83 +11,6 @@ pub fn trans_fn<'a, 'clif, 'tcx: 'a, B: Backend + 'static>( let mir = tcx.instance_mir(instance.def); - // Check fn sig for u128 and i128 and replace those functions with a trap. - { - // FIXME implement u128 and i128 support - - // Check sig for u128 and i128 - let fn_sig = tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &instance.fn_sig(tcx)); - - struct UI128Visitor<'tcx>(TyCtxt<'tcx>, bool); - - impl<'tcx> rustc::ty::fold::TypeVisitor<'tcx> for UI128Visitor<'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { - if t.sty == self.0.types.u128.sty || t.sty == self.0.types.i128.sty { - self.1 = true; - return false; // stop visiting - } - - t.super_visit_with(self) - } - } - - let mut visitor = UI128Visitor(tcx, false); - fn_sig.visit_with(&mut visitor); - - //If found replace function with a trap. - if visitor.1 { - tcx.sess.warn("u128 and i128 are not yet supported. \ - Functions using these as args will be replaced with a trap."); - - // Declare function with fake signature - let sig = Signature { - params: vec![AbiParam::new(types::INVALID)], - returns: vec![], - call_conv: CallConv::Fast, - }; - let name = tcx.symbol_name(instance).as_str(); - let func_id = cx.module.declare_function(&*name, linkage, &sig).unwrap(); - - // Create trapping function - let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); - let mut func_ctx = FunctionBuilderContext::new(); - let mut bcx = FunctionBuilder::new(&mut func, &mut func_ctx); - let start_ebb = bcx.create_ebb(); - bcx.append_ebb_params_for_function_params(start_ebb); - bcx.switch_to_block(start_ebb); - - let mut fx = FunctionCx { - tcx, - module: cx.module, - pointer_type: pointer_ty(tcx), - - instance, - mir, - - bcx, - ebb_map: HashMap::new(), - local_map: HashMap::new(), - - clif_comments: crate::pretty_clif::CommentWriter::new(tcx, instance), - constants: &mut cx.ccx, - caches: &mut cx.caches, - source_info_set: indexmap::IndexSet::new(), - }; - - crate::trap::trap_unreachable(&mut fx, "[unimplemented] Called function with u128 or i128 as argument."); - fx.bcx.seal_all_blocks(); - fx.bcx.finalize(); - - // Define function - cx.caches.context.func = func; - cx.module - .define_function(func_id, &mut cx.caches.context) - .unwrap(); - cx.caches.context.clear(); - return; - } - } - // Declare function let (name, sig) = get_function_name_and_sig(tcx, instance, false); let func_id = cx.module.declare_function(&name, linkage, &sig).unwrap(); @@ -241,7 +164,7 @@ fn codegen_fn_content<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>) } else { fx.bcx.ins().brz(cond, target, &[]); }; - trap_panic(fx, format!("[panic] Assert {:?} failed.", msg)); + trap_panic(fx, format!("[panic] Assert {:?} at {:?} failed.", msg, bb_data.terminator().source_info.span)); } TerminatorKind::SwitchInt { @@ -343,7 +266,7 @@ fn trans_stmt<'a, 'tcx: 'a>( .discriminant_for_variant(fx.tcx, *variant_index) .unwrap() .val; - let discr = CValue::const_val(fx, ptr.layout().ty, to as u64 as i64); + let discr = CValue::const_val(fx, ptr.layout().ty, to); ptr.write_cvalue(fx, discr); } layout::Variants::Multiple { @@ -366,7 +289,7 @@ fn trans_stmt<'a, 'tcx: 'a>( let niche_llval = if niche_value == 0 { CValue::const_val(fx, niche.layout().ty, 0) } else { - CValue::const_val(fx, niche.layout().ty, niche_value as u64 as i64) + CValue::const_val(fx, niche.layout().ty, niche_value) }; niche.write_cvalue(fx, niche_llval); } @@ -391,7 +314,7 @@ fn trans_stmt<'a, 'tcx: 'a>( let rhs = trans_operand(fx, rhs); let res = match ty.sty { - ty::Bool => trans_bool_binop(fx, *bin_op, lhs, rhs, lval.layout().ty), + ty::Bool => trans_bool_binop(fx, *bin_op, lhs, rhs), ty::Uint(_) => { trans_int_binop(fx, *bin_op, lhs, rhs, lval.layout().ty, false) } @@ -434,15 +357,21 @@ fn trans_stmt<'a, 'tcx: 'a>( let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0); fx.bcx.ins().bint(types::I8, res) } - ty::Uint(_) | ty::Int(_) => fx.bcx.ins().bnot(val), + ty::Uint(_) | ty::Int(_) => { + fx.bcx.ins().bnot(val) + } _ => unimplemented!("un op Not for {:?}", layout.ty), } } UnOp::Neg => match layout.ty.sty { ty::Int(_) => { let clif_ty = fx.clif_type(layout.ty).unwrap(); - let zero = fx.bcx.ins().iconst(clif_ty, 0); - fx.bcx.ins().isub(zero, val) + if clif_ty == types::I128 { + crate::trap::trap_unreachable_ret_value(fx, layout, "i128 neg is not yet supported").load_scalar(fx) + } else { + let zero = fx.bcx.ins().iconst(clif_ty, 0); + fx.bcx.ins().isub(zero, val) + } } ty::Float(_) => fx.bcx.ins().fneg(val), _ => unimplemented!("un op Neg for {:?}", layout.ty), @@ -633,7 +562,7 @@ fn trans_stmt<'a, 'tcx: 'a>( .ty .is_sized(fx.tcx.at(DUMMY_SP), ParamEnv::reveal_all())); let ty_size = fx.layout_of(ty).size.bytes(); - let val = CValue::const_val(fx, fx.tcx.types.usize, ty_size as i64); + let val = CValue::const_val(fx, fx.tcx.types.usize, ty_size.into()); lval.write_cvalue(fx, val); } Rvalue::Aggregate(kind, operands) => match **kind { @@ -666,7 +595,7 @@ fn trans_stmt<'a, 'tcx: 'a>( clobbers, // Vec volatile, // bool alignstack, // bool - dialect, // syntax::ast::AsmDialect + dialect: _, // syntax::ast::AsmDialect asm_str_style: _, ctxt: _, } = asm; @@ -705,6 +634,9 @@ fn trans_stmt<'a, 'tcx: 'a>( crate::trap::trap_unimplemented(fx, "_xgetbv arch intrinsic is not supported"); } + _ if fx.tcx.symbol_name(fx.instance).as_str() == "__rust_probestack" => { + crate::trap::trap_unimplemented(fx, "__rust_probestack is not supported"); + } _ => unimpl!("Inline assembly is not supported"), } } @@ -747,7 +679,7 @@ pub fn trans_get_discriminant<'a, 'tcx: 'a>( .map_or(index.as_u32() as u128, |def| { def.discriminant_for_variant(fx.tcx, *index).val }); - return CValue::const_val(fx, dest_layout.ty, discr_val as u64 as i64); + return CValue::const_val(fx, dest_layout.ty, discr_val); } layout::Variants::Multiple { discr, discr_index, discr_kind, variants: _ } => { (discr, *discr_index, discr_kind) @@ -856,10 +788,9 @@ fn trans_bool_binop<'a, 'tcx: 'a>( bin_op: BinOp, lhs: CValue<'tcx>, rhs: CValue<'tcx>, - ty: Ty<'tcx>, ) -> CValue<'tcx> { let res = binop_match! { - fx, bin_op, false, lhs, rhs, ty, "bool"; + fx, bin_op, false, lhs, rhs, fx.tcx.types.bool, "bool"; Add (_) bug; Sub (_) bug; Mul (_) bug; @@ -899,6 +830,11 @@ pub fn trans_int_binop<'a, 'tcx: 'a>( "int binop requires lhs and rhs of same type" ); } + + if let Some(res) = crate::codegen_i128::maybe_codegen(fx, bin_op, false, signed, lhs, rhs, out_ty) { + return res; + } + binop_match! { fx, bin_op, signed, lhs, rhs, out_ty, "int/uint"; Add (_) iadd; @@ -938,6 +874,10 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>( out_ty: Ty<'tcx>, signed: bool, ) -> CValue<'tcx> { + if !fx.tcx.sess.overflow_checks() { + return trans_int_binop(fx, bin_op, in_lhs, in_rhs, out_ty, signed); + } + if bin_op != BinOp::Shl && bin_op != BinOp::Shr { assert_eq!( in_lhs.layout().ty, @@ -948,17 +888,67 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>( let lhs = in_lhs.load_scalar(fx); let rhs = in_rhs.load_scalar(fx); - let res = match bin_op { - BinOp::Add => fx.bcx.ins().iadd(lhs, rhs), - BinOp::Sub => fx.bcx.ins().isub(lhs, rhs), - BinOp::Mul => fx.bcx.ins().imul(lhs, rhs), - BinOp::Shl => fx.bcx.ins().ishl(lhs, rhs), + + if let Some(res) = crate::codegen_i128::maybe_codegen(fx, bin_op, true, signed, in_lhs, in_rhs, out_ty) { + return res; + } + + let (res, has_overflow) = match bin_op { + BinOp::Add => { + /*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs); + (val, c_out)*/ + // FIXME(CraneStation/cranelift#849) legalize iadd_cout for i8 and i16 + let val = fx.bcx.ins().iadd(lhs, rhs); + let has_overflow = if !signed { + fx.bcx.ins().icmp(IntCC::UnsignedLessThan, val, lhs) + } else { + let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0); + let slt = fx.bcx.ins().icmp(IntCC::SignedLessThan, val, lhs); + fx.bcx.ins().bxor(rhs_is_negative, slt) + }; + (val, has_overflow) + } + BinOp::Sub => { + /*let (val, b_out) = fx.bcx.ins().isub_bout(lhs, rhs); + (val, b_out)*/ + // FIXME(CraneStation/cranelift#849) legalize isub_bout for i8 and i16 + let val = fx.bcx.ins().isub(lhs, rhs); + let has_overflow = if !signed { + fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, val, lhs) + } else { + let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0); + let sgt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, val, lhs); + fx.bcx.ins().bxor(rhs_is_negative, sgt) + }; + (val, has_overflow) + } + BinOp::Mul => { + let val = fx.bcx.ins().imul(lhs, rhs); + /*let val_hi = if !signed { + fx.bcx.ins().umulhi(lhs, rhs) + } else { + fx.bcx.ins().smulhi(lhs, rhs) + }; + let has_overflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);*/ + // TODO: check for overflow + let has_overflow = fx.bcx.ins().bconst(types::B1, false); + (val, has_overflow) + } + BinOp::Shl => { + let val = fx.bcx.ins().ishl(lhs, rhs); + // TODO: check for overflow + let has_overflow = fx.bcx.ins().bconst(types::B1, false); + (val, has_overflow) + } BinOp::Shr => { - if !signed { + let val = if !signed { fx.bcx.ins().ushr(lhs, rhs) } else { fx.bcx.ins().sshr(lhs, rhs) - } + }; + // TODO: check for overflow + let has_overflow = fx.bcx.ins().bconst(types::B1, false); + (val, has_overflow) } _ => bug!( "binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", @@ -968,9 +958,7 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>( ), }; - // TODO: check for overflow - let has_overflow = fx.bcx.ins().iconst(types::I8, 0); - + let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow); let out_place = CPlace::new_stack_slot(fx, out_ty); let out_layout = out_place.layout(); out_place.write_cvalue(fx, CValue::by_val_pair(res, has_overflow, out_layout)); diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs new file mode 100644 index 000000000..9cd6bc8c7 --- /dev/null +++ b/src/codegen_i128.rs @@ -0,0 +1,195 @@ +//! Replaces 128-bit operators with lang item calls + +use crate::prelude::*; + +pub fn maybe_codegen<'a, 'tcx>( + fx: &mut FunctionCx<'a, 'tcx, impl Backend>, + bin_op: BinOp, + checked: bool, + is_signed: bool, + lhs: CValue<'tcx>, + rhs: CValue<'tcx>, + out_ty: Ty<'tcx>, +) -> Option> { + if lhs.layout().ty != fx.tcx.types.u128 && lhs.layout().ty != fx.tcx.types.i128 { + return None; + } + + let lhs_val = lhs.load_scalar(fx); + let rhs_val = rhs.load_scalar(fx); + + match bin_op { + BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => { + assert!(!checked); + return None; + } + BinOp::Add | BinOp::Sub if !checked => return None, + BinOp::Add => { + return Some(if is_signed { + fx.easy_call("__rust_i128_addo", &[lhs, rhs], out_ty) + } else { + fx.easy_call("__rust_u128_addo", &[lhs, rhs], out_ty) + }) + } + BinOp::Sub => { + return Some(if is_signed { + fx.easy_call("__rust_i128_subo", &[lhs, rhs], out_ty) + } else { + fx.easy_call("__rust_u128_subo", &[lhs, rhs], out_ty) + }) + } + BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"), + BinOp::Mul => { + let res = if checked { + if is_signed { + fx.easy_call("__rust_i128_mulo", &[lhs, rhs], out_ty) + } else { + fx.easy_call("__rust_u128_mulo", &[lhs, rhs], out_ty) + } + } else { + let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; + fx.easy_call("__multi3", &[lhs, rhs], val_ty) + }; + return Some(res); + } + BinOp::Div => { + 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)) + } else { + Some(fx.easy_call("__umodti3", &[lhs, rhs], fx.tcx.types.u128)) + } + } + BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => { + assert!(!checked); + let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs_val); + let (rhs_lsb, rhs_msb) = fx.bcx.ins().isplit(rhs_val); + + let res = match bin_op { + BinOp::Eq => { + let lsb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_lsb, rhs_lsb); + let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb); + fx.bcx.ins().band(lsb_eq, msb_eq) + } + BinOp::Ne => { + let lsb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_lsb, rhs_lsb); + let msb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_msb, rhs_msb); + fx.bcx.ins().bor(lsb_ne, msb_ne) + } + _ => { + // if msb_eq { + // lhs_cc + // } else { + // msb_cc + // } + let cc = match (bin_op, is_signed) { + (BinOp::Ge, false) => IntCC::UnsignedGreaterThanOrEqual, + (BinOp::Gt, false) => IntCC::UnsignedGreaterThan, + (BinOp::Lt, false) => IntCC::UnsignedLessThan, + (BinOp::Le, false) => IntCC::UnsignedLessThanOrEqual, + + (BinOp::Ge, true) => IntCC::SignedGreaterThanOrEqual, + (BinOp::Gt, true) => IntCC::SignedGreaterThan, + (BinOp::Lt, true) => IntCC::SignedLessThan, + (BinOp::Le, true) => IntCC::SignedLessThanOrEqual, + _ => unreachable!(), + }; + + let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb); + let lsb_cc = fx.bcx.ins().icmp(cc, lhs_lsb, rhs_lsb); + let msb_cc = fx.bcx.ins().icmp(cc, lhs_msb, rhs_msb); + + fx.bcx.ins().select(msb_eq, lsb_cc, msb_cc) + } + }; + + let res = fx.bcx.ins().bint(types::I8, res); + let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.bool)); + return Some(res); + } + BinOp::Shl | BinOp::Shr => { + let is_overflow = if checked { + // rhs >= 128 + + // FIXME support non 128bit rhs + /*let (rhs_lsb, rhs_msb) = fx.bcx.ins().isplit(rhs_val); + let rhs_msb_gt_0 = fx.bcx.ins().icmp_imm(IntCC::NotEqual, rhs_msb, 0); + let rhs_lsb_ge_128 = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThan, rhs_lsb, 127); + let is_overflow = fx.bcx.ins().bor(rhs_msb_gt_0, rhs_lsb_ge_128);*/ + let is_overflow = fx.bcx.ins().bconst(types::B1, false); + + Some(fx.bcx.ins().bint(types::I8, is_overflow)) + } else { + None + }; + + // Optimize `val >> 64`, because compiler_builtins uses it to deconstruct an 128bit + // integer into its lsb and msb. + // https://github.com/rust-lang-nursery/compiler-builtins/blob/79a6a1603d5672cbb9187ff41ff4d9b5048ac1cb/src/int/mod.rs#L217 + if let Some(64) = resolve_value_imm(fx.bcx.func, rhs_val) { + let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs_val); + let all_zeros = fx.bcx.ins().iconst(types::I64, 0); + let val = match (bin_op, is_signed) { + (BinOp::Shr, false) => { + let val = fx.bcx.ins().iconcat(lhs_msb, all_zeros); + Some(CValue::by_val(val, fx.layout_of(fx.tcx.types.u128))) + } + (BinOp::Shr, true) => { + let sign = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, lhs_msb, 0); + let all_ones = fx.bcx.ins().iconst(types::I64, u64::max_value() as i64); + let all_sign_bits = fx.bcx.ins().select(sign, all_zeros, all_ones); + + let val = fx.bcx.ins().iconcat(lhs_msb, all_sign_bits); + Some(CValue::by_val(val, fx.layout_of(fx.tcx.types.i128))) + } + (BinOp::Shl, _) => { + let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; + let val = fx.bcx.ins().iconcat(all_zeros, lhs_lsb); + Some(CValue::by_val(val, fx.layout_of(val_ty))) + } + _ => None + }; + if let Some(val) = val { + if let Some(is_overflow) = is_overflow { + let val = val.load_scalar(fx); + return Some(CValue::by_val_pair(val, is_overflow, fx.layout_of(out_ty))) + } else { + return Some(val); + } + } + } + + let truncated_rhs = clif_intcast(fx, rhs_val, types::I32, false); + let truncated_rhs = CValue::by_val(truncated_rhs, fx.layout_of(fx.tcx.types.u32)); + let val = match (bin_op, is_signed) { + (BinOp::Shl, false) => { + fx.easy_call("__ashlti3", &[lhs, truncated_rhs], fx.tcx.types.u128) + } + (BinOp::Shl, true) => { + fx.easy_call("__ashlti3", &[lhs, truncated_rhs], fx.tcx.types.i128) + } + (BinOp::Shr, false) => { + fx.easy_call("__lshrti3", &[lhs, truncated_rhs], fx.tcx.types.u128) + } + (BinOp::Shr, true) => { + fx.easy_call("__ashrti3", &[lhs, truncated_rhs], fx.tcx.types.i128) + } + (_, _) => unreachable!(), + }; + if let Some(is_overflow) = is_overflow { + let val = val.load_scalar(fx); + Some(CValue::by_val_pair(val, is_overflow, fx.layout_of(out_ty))) + } else { + Some(val) + } + } + } +} diff --git a/src/common.rs b/src/common.rs index bffa526c8..6a00d1341 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,5 +1,6 @@ use rustc_target::spec::{HasTargetSpec, Target}; +use cranelift::codegen::ir::{Opcode, InstructionData, ValueDef}; use cranelift_module::Module; use crate::prelude::*; @@ -28,7 +29,7 @@ pub fn clif_type_from_ty<'tcx>( UintTy::U16 => types::I16, UintTy::U32 => types::I32, UintTy::U64 => types::I64, - UintTy::U128 => unimpl!("u128"), + UintTy::U128 => types::I128, UintTy::Usize => pointer_ty(tcx), }, ty::Int(size) => match size { @@ -36,7 +37,7 @@ pub fn clif_type_from_ty<'tcx>( IntTy::I16 => types::I16, IntTy::I32 => types::I32, IntTy::I64 => types::I64, - IntTy::I128 => unimpl!("i128"), + IntTy::I128 => types::I128, IntTy::Isize => pointer_ty(tcx), }, ty::Char => types::I32, @@ -62,7 +63,7 @@ pub fn codegen_select(bcx: &mut FunctionBuilder, cond: Value, lhs: Value, rhs: V let rhs_ty = bcx.func.dfg.value_type(rhs); assert_eq!(lhs_ty, rhs_ty); if lhs_ty == types::I8 || lhs_ty == types::I16 { - // FIXME workaround for missing enocding for select.i8 + // FIXME workaround for missing encoding for select.i8 let lhs = bcx.ins().uextend(types::I32, lhs); let rhs = bcx.ins().uextend(types::I32, rhs); let res = bcx.ins().select(cond, lhs, rhs); @@ -79,17 +80,85 @@ pub fn clif_intcast<'a, 'tcx: 'a>( signed: bool, ) -> Value { let from = fx.bcx.func.dfg.value_type(val); - if from == to { - return val; + match (from, to) { + // equal + (_, _) if from == to => val, + + // extend + (_, types::I128) => { + let wider = if from == types::I64 { + val + } else if signed { + fx.bcx.ins().sextend(types::I64, val) + } else { + fx.bcx.ins().uextend(types::I64, val) + }; + let zero = fx.bcx.ins().iconst(types::I64, 0); + fx.bcx.ins().iconcat(wider, zero) + } + (_, _) if to.wider_or_equal(from) => { + if signed { + fx.bcx.ins().sextend(to, val) + } else { + fx.bcx.ins().uextend(to, val) + } + } + + // reduce + (types::I128, _) => { + let (lsb, _msb) = fx.bcx.ins().isplit(val); + if to == types::I64 { + lsb + } else { + fx.bcx.ins().ireduce(to, lsb) + } + } + (_, _) => { + fx.bcx.ins().ireduce(to, val) + } } - if to.wider_or_equal(from) { - if signed { - fx.bcx.ins().sextend(to, val) +} + +fn resolve_normal_value_imm(func: &Function, val: Value) -> Option { + if let ValueDef::Result(inst, 0 /*param*/) = func.dfg.value_def(val) { + if let InstructionData::UnaryImm { + opcode: Opcode::Iconst, + imm, + } = func.dfg[inst] { + Some(imm.into()) } else { - fx.bcx.ins().uextend(to, val) + None } } else { - fx.bcx.ins().ireduce(to, val) + None + } +} + +fn resolve_128bit_value_imm(func: &Function, val: Value) -> Option { + let (lsb, msb) = if let ValueDef::Result(inst, 0 /*param*/) = func.dfg.value_def(val) { + if let InstructionData::Binary { + opcode: Opcode::Iconcat, + args: [lsb, msb], + } = func.dfg[inst] { + (lsb, msb) + } else { + return None; + } + } else { + return None; + }; + + let lsb = resolve_normal_value_imm(func, lsb)? as u64 as u128; + let msb = resolve_normal_value_imm(func, msb)? as u64 as u128; + + Some(msb << 64 | lsb) +} + +pub fn resolve_value_imm(func: &Function, val: Value) -> Option { + if func.dfg.value_type(val) == types::I128 { + resolve_128bit_value_imm(func, val) + } else { + resolve_normal_value_imm(func, val).map(|imm| imm as u64 as u128) } } diff --git a/src/constant.rs b/src/constant.rs index 9a2b0cf36..10f757ffc 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -113,17 +113,13 @@ pub fn trans_const_value<'a, 'tcx: 'a>( let ty = fx.monomorphize(&const_.ty); let layout = fx.layout_of(ty); match ty.sty { - ty::Bool => { + ty::Bool | ty::Uint(_) => { let bits = const_.val.try_to_bits(layout.size).unwrap(); - CValue::const_val(fx, ty, bits as u64 as i64) - } - ty::Uint(_) => { - let bits = const_.val.try_to_bits(layout.size).unwrap(); - CValue::const_val(fx, ty, bits as u64 as i64) + CValue::const_val(fx, ty, bits) } ty::Int(_) => { let bits = const_.val.try_to_bits(layout.size).unwrap(); - CValue::const_val(fx, ty, rustc::mir::interpret::sign_extend(bits, layout.size) as i128 as i64) + CValue::const_val(fx, ty, rustc::mir::interpret::sign_extend(bits, layout.size)) } ty::FnDef(_def_id, _substs) => CValue::by_ref( fx.bcx diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 08a829ff1..ee00924ad 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -103,7 +103,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( // Insert non returning intrinsics here match intrinsic { "abort" => { - trap_panic(fx, "Called intrinisc::abort."); + trap_panic(fx, "Called intrinsic::abort."); } "unreachable" => { trap_unreachable(fx, "[corruption] Called intrinsic::unreachable."); @@ -150,7 +150,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( }; size_of, () { let size_of = fx.layout_of(T).size.bytes(); - let size_of = CValue::const_val(fx, usize_layout.ty, size_of as i64); + let size_of = CValue::const_val(fx, usize_layout.ty, size_of.into()); ret.write_cvalue(fx, size_of); }; size_of_val, (c ptr) { @@ -169,7 +169,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( }; min_align_of, () { let min_align = fx.layout_of(T).align.abi.bytes(); - let min_align = CValue::const_val(fx, usize_layout.ty, min_align as i64); + let min_align = CValue::const_val(fx, usize_layout.ty, min_align.into()); ret.write_cvalue(fx, min_align); }; min_align_of_val, (c ptr) { @@ -188,14 +188,14 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( }; pref_align_of, () { let pref_align = fx.layout_of(T).align.pref.bytes(); - let pref_align = CValue::const_val(fx, usize_layout.ty, pref_align as i64); + let pref_align = CValue::const_val(fx, usize_layout.ty, pref_align.into()); ret.write_cvalue(fx, pref_align); }; type_id, () { let type_id = fx.tcx.type_id_hash(T); - let type_id = CValue::const_val(fx, u64_layout.ty, type_id as i64); + let type_id = CValue::const_val(fx, u64_layout.ty, type_id.into()); ret.write_cvalue(fx, type_id); }; type_name, () { @@ -390,11 +390,33 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( fx.bcx.call_memset(fx.module.target_config(), dst_ptr, val, count); }; ctlz | ctlz_nonzero, (v arg) { - let res = CValue::by_val(fx.bcx.ins().clz(arg), fx.layout_of(T)); + let res = if T == fx.tcx.types.u128 || T == fx.tcx.types.i128 { + // FIXME verify this algorithm is correct + let (lsb, msb) = fx.bcx.ins().isplit(arg); + let lsb_lz = fx.bcx.ins().clz(lsb); + let msb_lz = fx.bcx.ins().clz(msb); + let msb_is_zero = fx.bcx.ins().icmp_imm(IntCC::Equal, msb, 0); + let lsb_lz_plus_64 = fx.bcx.ins().iadd_imm(lsb_lz, 64); + fx.bcx.ins().select(msb_is_zero, lsb_lz_plus_64, msb_lz) + } else { + fx.bcx.ins().clz(arg) + }; + let res = CValue::by_val(res, fx.layout_of(T)); ret.write_cvalue(fx, res); }; cttz | cttz_nonzero, (v arg) { - let res = CValue::by_val(fx.bcx.ins().ctz(arg), fx.layout_of(T)); + let res = if T == fx.tcx.types.u128 || T == fx.tcx.types.i128 { + // FIXME verify this algorithm is correct + let (lsb, msb) = fx.bcx.ins().isplit(arg); + let lsb_tz = fx.bcx.ins().ctz(lsb); + let msb_tz = fx.bcx.ins().ctz(msb); + let lsb_is_zero = fx.bcx.ins().icmp_imm(IntCC::Equal, lsb, 0); + let msb_tz_plus_64 = fx.bcx.ins().iadd_imm(msb_tz, 64); + fx.bcx.ins().select(lsb_is_zero, msb_tz_plus_64, lsb_tz) + } else { + fx.bcx.ins().ctz(arg) + }; + let res = CValue::by_val(res, fx.layout_of(T)); ret.write_cvalue(fx, res); }; ctpop, (v arg) { @@ -472,7 +494,13 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( let or_tmp6 = bcx.ins().bor(or_tmp3, or_tmp4); bcx.ins().bor(or_tmp5, or_tmp6) } - ty => unimplemented!("bwap {}", ty), + types::I128 => { + let (lo, hi) = bcx.ins().isplit(v); + let lo = swap(bcx, lo); + let hi = swap(bcx, hi); + bcx.ins().iconcat(hi, lo) + } + ty => unimplemented!("bswap {}", ty), } }; let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T)); diff --git a/src/lib.rs b/src/lib.rs index c6f77954a..8a4e79d54 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ mod allocator; mod analyze; mod archive; mod base; +mod codegen_i128; mod common; mod constant; mod debuginfo; @@ -53,7 +54,7 @@ mod vtable; mod prelude { pub use std::any::Any; pub use std::collections::{HashMap, HashSet}; - pub use std::convert::TryInto; + pub use std::convert::{TryFrom, TryInto}; pub use syntax::ast::{FloatTy, IntTy, UintTy}; pub use syntax::source_map::{Pos, Span, DUMMY_SP}; @@ -242,6 +243,8 @@ fn build_isa(sess: &Session) -> Box { "false" }).unwrap(); + flags_builder.set("opt_level", "best").unwrap(); + // FIXME enable again when https://github.com/CraneStation/cranelift/issues/664 is fixed /* use rustc::session::config::OptLevel; diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 716a81c5d..a8b3a2954 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -137,17 +137,38 @@ impl<'tcx> CValue<'tcx> { crate::unsize::coerce_unsized_into(fx, self, dest); } + /// If `ty` is signed, `const_val` must already be sign extended. pub fn const_val<'a>( fx: &mut FunctionCx<'a, 'tcx, impl Backend>, ty: Ty<'tcx>, - const_val: i64, + const_val: u128, ) -> CValue<'tcx> where 'tcx: 'a, { let clif_ty = fx.clif_type(ty).unwrap(); let layout = fx.layout_of(ty); - CValue::by_val(fx.bcx.ins().iconst(clif_ty, const_val), layout) + + let val = match ty.sty { + ty::TyKind::Uint(UintTy::U128) | ty::TyKind::Int(IntTy::I128) => { + let lsb = fx.bcx.ins().iconst(types::I64, const_val as u64 as i64); + let msb = fx.bcx.ins().iconst(types::I64, (const_val >> 64) as u64 as i64); + fx.bcx.ins().iconcat(lsb, msb) + } + ty::TyKind::Bool => { + assert!(const_val == 0 || const_val == 1, "Invalid bool 0x{:032X}", const_val); + fx.bcx.ins().iconst(types::I8, const_val as i64) + } + ty::TyKind::Uint(_) | ty::TyKind::Ref(..) | ty::TyKind::RawPtr(.. )=> { + fx.bcx.ins().iconst(clif_ty, u64::try_from(const_val).expect("uint") as i64) + } + ty::TyKind::Int(_) => { + fx.bcx.ins().iconst(clif_ty, const_val as i128 as i64) + } + _ => panic!("CValue::const_val for non bool/integer/pointer type {:?} is not allowed", ty), + }; + + CValue::by_val(val, layout) } pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {