mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-22 12:43:36 +00:00
commit
a302f88d23
80
Cargo.lock
generated
80
Cargo.lock
generated
@ -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)" = "<none>"
|
||||
"checksum cranelift-bforest 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift-codegen-meta 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift-faerie 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift-frontend 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift-native 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift-simplejit 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
|
||||
"checksum cranelift 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-bforest 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-codegen 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-codegen-meta 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-entity 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-faerie 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-frontend 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-module 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-native 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"checksum cranelift-simplejit 0.36.0 (git+https://github.com/bjorn3/cretonne.git?branch=do_not_remove_cg_clif_i128)" = "<none>"
|
||||
"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"
|
||||
|
@ -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" }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <bjorn3@users.noreply.github.com>"]
|
||||
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 = []
|
@ -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"
|
||||
)]
|
@ -314,7 +314,7 @@ impl Neg for i16 {
|
||||
type Output = i16;
|
||||
|
||||
fn neg(self) -> i16 {
|
||||
-self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,21 +236,4 @@ fn main() {
|
||||
unsafe { assert_eq!(ABC as usize, 0); }
|
||||
|
||||
&mut (|| Some(0 as *const ())) as &mut FnMut() -> Option<*const ()>;
|
||||
|
||||
// checked binops
|
||||
let zeroi8 = 0i8;
|
||||
let oneu8 = 1u8;
|
||||
let onei8 = 1i8;
|
||||
zeroi8 - 1;
|
||||
oneu8 - 1;
|
||||
zeroi8 - -2i8;
|
||||
#[allow(unreachable_code)]
|
||||
{
|
||||
if false {
|
||||
let minustwoi8 = -2i8;
|
||||
oneu8 + 255;
|
||||
onei8 + 127;
|
||||
minustwoi8 - 127;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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::<Vec<_>>();
|
||||
@ -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)]
|
||||
|
45
src/abi.rs
45
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<types::Type>,
|
||||
output_ty: Option<types::Type>,
|
||||
output_tys: Vec<types::Type>,
|
||||
args: &[Value],
|
||||
) -> Option<Value> {
|
||||
) -> &[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( (...) -> <non empty tuple> ) 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<impl Backend>) {
|
||||
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,
|
||||
|
123
src/base.rs
123
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 at {:?}.", msg, bb_data.terminator().source_info.span));
|
||||
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<Name>
|
||||
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,6 +888,11 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
|
||||
|
||||
let lhs = in_lhs.load_scalar(fx);
|
||||
let rhs = in_rhs.load_scalar(fx);
|
||||
|
||||
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);
|
||||
|
195
src/codegen_i128.rs
Normal file
195
src/codegen_i128.rs
Normal file
@ -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<CValue<'tcx>> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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<i64> {
|
||||
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<u128> {
|
||||
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<u128> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, <T> () {
|
||||
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, <T> (c ptr) {
|
||||
@ -169,7 +169,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
|
||||
};
|
||||
min_align_of, <T> () {
|
||||
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, <T> (c ptr) {
|
||||
@ -188,14 +188,14 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
|
||||
};
|
||||
pref_align_of, <T> () {
|
||||
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, <T> () {
|
||||
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, <T> () {
|
||||
@ -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, <T> (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, <T> (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, <T> (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));
|
||||
|
@ -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<dyn isa::TargetIsa + 'static> {
|
||||
"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;
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user