Skip to content

Commit 33966cc

Browse files
committed
Add a workaround for 128 bit switches
1 parent cfe88fa commit 33966cc

File tree

3 files changed

+96
-20
lines changed

3 files changed

+96
-20
lines changed

example/mini_core.rs

+38-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
#![feature(
2-
no_core, lang_items, intrinsics, unboxed_closures, extern_types,
3-
decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls,
2+
no_core,
3+
lang_items,
4+
intrinsics,
5+
unboxed_closures,
6+
extern_types,
7+
decl_macro,
8+
rustc_attrs,
9+
transparent_unions,
10+
auto_traits,
11+
freeze_impls,
412
thread_local
513
)]
614
#![no_core]
@@ -35,13 +43,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
3543
pub trait DispatchFromDyn<T> {}
3644

3745
// &T -> &U
38-
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
46+
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
3947
// &mut T -> &mut U
40-
impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
48+
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
4149
// *const T -> *const U
42-
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
50+
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
4351
// *mut T -> *mut U
44-
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
52+
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
4553
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U, ()>> for Box<T, ()> {}
4654

4755
#[lang = "legacy_receiver"]
@@ -52,8 +60,7 @@ impl<T: ?Sized> LegacyReceiver for &mut T {}
5260
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
5361

5462
#[lang = "receiver"]
55-
trait Receiver {
56-
}
63+
trait Receiver {}
5764

5865
#[lang = "copy"]
5966
pub trait Copy {}
@@ -67,10 +74,13 @@ impl Copy for u16 {}
6774
impl Copy for u32 {}
6875
impl Copy for u64 {}
6976
impl Copy for usize {}
77+
impl Copy for u128 {}
7078
impl Copy for i8 {}
7179
impl Copy for i16 {}
7280
impl Copy for i32 {}
81+
impl Copy for i64 {}
7382
impl Copy for isize {}
83+
impl Copy for i128 {}
7484
impl Copy for f32 {}
7585
impl Copy for f64 {}
7686
impl Copy for char {}
@@ -336,7 +346,6 @@ impl PartialEq for u32 {
336346
}
337347
}
338348

339-
340349
impl PartialEq for u64 {
341350
fn eq(&self, other: &u64) -> bool {
342351
(*self) == (*other)
@@ -523,7 +532,11 @@ fn panic_in_cleanup() -> ! {
523532
#[track_caller]
524533
fn panic_bounds_check(index: usize, len: usize) -> ! {
525534
unsafe {
526-
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
535+
libc::printf(
536+
"index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8,
537+
len,
538+
index,
539+
);
527540
intrinsics::abort();
528541
}
529542
}
@@ -551,8 +564,7 @@ pub trait Deref {
551564
fn deref(&self) -> &Self::Target;
552565
}
553566

554-
pub trait Allocator {
555-
}
567+
pub trait Allocator {}
556568

557569
impl Allocator for () {}
558570

@@ -634,6 +646,8 @@ pub union MaybeUninit<T> {
634646
}
635647

636648
pub mod intrinsics {
649+
#[rustc_intrinsic]
650+
pub const fn black_box<T>(_dummy: T) -> T;
637651
#[rustc_intrinsic]
638652
pub fn abort() -> !;
639653
#[rustc_intrinsic]
@@ -711,19 +725,27 @@ pub struct VaList<'a>(&'a mut VaListImpl);
711725

712726
#[rustc_builtin_macro]
713727
#[rustc_macro_transparency = "semitransparent"]
714-
pub macro stringify($($t:tt)*) { /* compiler built-in */ }
728+
pub macro stringify($($t:tt)*) {
729+
/* compiler built-in */
730+
}
715731

716732
#[rustc_builtin_macro]
717733
#[rustc_macro_transparency = "semitransparent"]
718-
pub macro file() { /* compiler built-in */ }
734+
pub macro file() {
735+
/* compiler built-in */
736+
}
719737

720738
#[rustc_builtin_macro]
721739
#[rustc_macro_transparency = "semitransparent"]
722-
pub macro line() { /* compiler built-in */ }
740+
pub macro line() {
741+
/* compiler built-in */
742+
}
723743

724744
#[rustc_builtin_macro]
725745
#[rustc_macro_transparency = "semitransparent"]
726-
pub macro cfg() { /* compiler built-in */ }
746+
pub macro cfg() {
747+
/* compiler built-in */
748+
}
727749

728750
pub static A_STATIC: u8 = 42;
729751

src/builder.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -568,11 +568,28 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
568568
) {
569569
let mut gcc_cases = vec![];
570570
let typ = self.val_ty(value);
571-
for (on_val, dest) in cases {
572-
let on_val = self.const_uint_big(typ, on_val);
573-
gcc_cases.push(self.context.new_case(on_val, on_val, dest));
571+
// FIXME(FractalFir): This is a workaround for a libgccjit limitation.
572+
// Currently, libgccjit can't directly create 128 bit integers.
573+
// Since switch cases must be values, and casts are not constant, we can't use 128 bit switch cases.
574+
// In such a case, we will simply fall back to an if-ladder.
575+
// This *may* be slower than a native switch, but a slow working solution is better than none at all.
576+
if typ.is_i128(self) || typ.is_u128(self) {
577+
for (on_val, dest) in cases {
578+
let on_val = self.const_uint_big(typ, on_val);
579+
let is_case =
580+
self.context.new_comparison(self.location, ComparisonOp::Equals, value, on_val);
581+
let next_block = self.current_func().new_block("case");
582+
self.block.end_with_conditional(self.location, is_case, dest, next_block);
583+
self.block = next_block;
584+
}
585+
self.block.end_with_jump(self.location, default_block);
586+
} else {
587+
for (on_val, dest) in cases {
588+
let on_val = self.const_uint_big(typ, on_val);
589+
gcc_cases.push(self.context.new_case(on_val, on_val, dest));
590+
}
591+
self.block.end_with_switch(self.location, value, default_block, &gcc_cases);
574592
}
575-
self.block.end_with_switch(self.location, value, default_block, &gcc_cases);
576593
}
577594

578595
#[cfg(feature = "master")]

tests/run/switchint_128bit.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Compiler:
2+
//
3+
// Run-time:
4+
// status: 0
5+
6+
#![feature(no_core)]
7+
#![no_std]
8+
#![no_core]
9+
#![no_main]
10+
11+
extern crate mini_core;
12+
use intrinsics::black_box;
13+
use mini_core::*;
14+
15+
#[no_mangle]
16+
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
17+
// 1st. Check that small 128 bit values work.
18+
let val = black_box(64_u128);
19+
match val {
20+
0 => return 1,
21+
1 => return 2,
22+
64 => (),
23+
_ => return 3,
24+
}
25+
// 2nd check that *large* values work.
26+
const BIG: u128 = 0xDEAD_C0FE_BEEF_DECAF_BADD_DECAF_BEEF_u128;
27+
let val = black_box(BIG);
28+
match val {
29+
0 => return 4,
30+
1 => return 5,
31+
// Check that we will not match on the lower u64, if the upper qword is different!
32+
0xcafbadddecafbeef => return 6,
33+
0xDEAD_C0FE_BEEF_DECAF_BADD_DECAF_BEEF_u128 => (),
34+
_ => return 7,
35+
}
36+
0
37+
}

0 commit comments

Comments
 (0)