Merge pull request #627 from bjorn3/wip_i128

Support 128bit numbers
This commit is contained in:
bjorn3 2019-07-26 12:19:24 +02:00 committed by GitHub
commit a302f88d23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 455 additions and 232 deletions

80
Cargo.lock generated
View File

@ -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"

View File

@ -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" }

View File

@ -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

View File

@ -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

View File

@ -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 = []

View File

@ -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"
)]

View File

@ -314,7 +314,7 @@ impl Neg for i16 {
type Output = i16;
fn neg(self) -> i16 {
-self
self
}
}

View File

@ -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;
}
}
}

View File

@ -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)]

View File

@ -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,

View File

@ -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
View 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)
}
}
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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));

View File

@ -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;

View File

@ -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 {