[WIP] Basic i128 support

This commit is contained in:
bjorn3 2019-06-12 20:54:38 +02:00
parent bf3ec3be3e
commit de32ddad23
8 changed files with 144 additions and 249 deletions

60
Cargo.lock generated
View File

@ -117,28 +117,25 @@ dependencies = [
[[package]]
name = "cranelift"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
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",
"cranelift-frontend 0.36.0",
]
[[package]]
name = "cranelift-bforest"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
dependencies = [
"cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
"cranelift-entity 0.36.0",
]
[[package]]
name = "cranelift-codegen"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
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",
"cranelift-codegen-meta 0.36.0",
"cranelift-entity 0.36.0",
"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 +145,20 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
dependencies = [
"cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
"cranelift-entity 0.36.0",
]
[[package]]
name = "cranelift-entity"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
[[package]]
name = "cranelift-faerie"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
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",
"cranelift-module 0.36.0",
"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 +168,8 @@ dependencies = [
[[package]]
name = "cranelift-frontend"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
dependencies = [
"cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
"cranelift-codegen 0.36.0",
"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 +177,9 @@ dependencies = [
[[package]]
name = "cranelift-module"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
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",
"cranelift-entity 0.36.0",
"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 +187,8 @@ dependencies = [
[[package]]
name = "cranelift-native"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
dependencies = [
"cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
"cranelift-codegen 0.36.0",
"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 +196,10 @@ dependencies = [
[[package]]
name = "cranelift-simplejit"
version = "0.36.0"
source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
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",
"cranelift-module 0.36.0",
"cranelift-native 0.36.0",
"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 +601,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",
"cranelift-faerie 0.36.0",
"cranelift-module 0.36.0",
"cranelift-simplejit 0.36.0",
"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 +872,6 @@ 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 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

@ -28,11 +28,11 @@ indexmap = "1.0.2"
object = "0.12.0"
# Uncomment to use local checkout of cranelift
#[patch."https://github.com/CraneStation/cranelift.git"]
#cranelift = { path = "../cranelift/cranelift-umbrella" }
#cranelift-module = { path = "../cranelift/cranelift-module" }
#cranelift-simplejit = { path = "../cranelift/cranelift-simplejit" }
#cranelift-faerie = { path = "../cranelift/cranelift-faerie" }
[patch."https://github.com/CraneStation/cranelift.git"]
cranelift = { path = "../cranelift/cranelift-umbrella" }
cranelift-module = { path = "../cranelift/cranelift-module" }
cranelift-simplejit = { path = "../cranelift/cranelift-simplejit" }
cranelift-faerie = { path = "../cranelift/cranelift-faerie" }
#[patch."https://github.com/gimli-rs/gimli.git"]
#gimli = { path = "../" }

View File

@ -144,6 +144,14 @@ impl Add for usize {
}
}
impl Add for u128 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
#[lang = "sub"]
pub trait Sub<RHS = Self> {
type Output;

View File

@ -118,139 +118,5 @@ fn take_f32(_f: f32) {}
fn take_unique(_u: Unique<()>) {}
fn main() {
take_unique(Unique {
pointer: 0 as *const (),
_marker: PhantomData,
});
take_f32(0.1);
//return;
unsafe {
printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8);
let hello: &[u8] = b"Hello\0" as &[u8; 6];
let ptr: *const u8 = hello as *const [u8] as *const u8;
puts(ptr);
let world: Box<&str> = box "World!\0";
puts(*world as *const str as *const u8);
world as Box<SomeTrait>;
assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8);
assert_eq!(intrinsics::bswap(0xabu8), 0xabu8);
assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16);
assert_eq!(intrinsics::bswap(0xffee_ddccu32), 0xccdd_eeffu32);
assert_eq!(intrinsics::bswap(0x1234_5678_ffee_ddccu64), 0xccdd_eeff_7856_3412u64);
assert_eq!(intrinsics::size_of_val(hello) as u8, 6);
let chars = &['C', 'h', 'a', 'r', 's'];
let chars = chars as &[char];
assert_eq!(intrinsics::size_of_val(chars) as u8, 4 * 5);
let a: &dyn SomeTrait = &"abc\0";
a.object_safe();
assert_eq!(intrinsics::size_of_val(a) as u8, 16);
assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4);
assert_eq!(intrinsics::min_align_of::<u16>() as u8, 2);
assert_eq!(intrinsics::min_align_of_val(&a) as u8, intrinsics::min_align_of::<&str>() as u8);
assert!(!intrinsics::needs_drop::<u8>());
assert!(intrinsics::needs_drop::<NoisyDrop>());
Unique {
pointer: 0 as *const &str,
_marker: PhantomData,
} as Unique<dyn SomeTrait>;
struct MyDst<T: ?Sized>(T);
intrinsics::size_of_val(&MyDst([0u8; 4]) as &MyDst<[u8]>);
struct Foo {
x: u8,
y: !,
}
unsafe fn zeroed<T>() -> T {
intrinsics::init::<T>()
}
unsafe fn uninitialized<T>() -> T {
MaybeUninit { uninit: () }.value
}
zeroed::<(u8, u8)>();
#[allow(unreachable_code)]
{
if false {
zeroed::<!>();
zeroed::<Foo>();
uninitialized::<Foo>();
}
}
}
let _ = box NoisyDrop {
text: "Boxed outer got dropped!\0",
inner: NoisyDropInner,
} as Box<SomeTrait>;
const FUNC_REF: Option<fn()> = Some(main);
match FUNC_REF {
Some(_) => {},
None => assert!(false),
}
match Ordering::Less {
Ordering::Less => {},
_ => assert!(false),
}
[NoisyDropInner, NoisyDropInner];
let x = &[0u32, 42u32] as &[u32];
match x {
[] => assert_eq!(0u32, 1),
[_, ref y..] => assert_eq!(&x[1] as *const u32 as usize, &y[0] as *const u32 as usize),
}
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
extern {
#[linkage = "weak"]
static ABC: *const u8;
}
{
extern {
#[linkage = "weak"]
static ABC: *const u8;
}
}
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;
}
}
assert_eq!((1u128 + 2) as u16, 3);
}

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,

View File

@ -899,6 +899,19 @@ pub fn trans_int_binop<'a, 'tcx: 'a>(
"int binop requires lhs and rhs of same type"
);
}
if out_ty == fx.tcx.types.u128 || out_ty == fx.tcx.types.i128 {
return match (bin_op, signed) {
_ => {
let layout = fx.layout_of(out_ty);
let a = fx.bcx.ins().iconst(types::I64, 42);
let b = fx.bcx.ins().iconst(types::I64, 0);
let val = fx.bcx.ins().iconcat(a, b);
CValue::by_val(val, layout)
}
}
}
binop_match! {
fx, bin_op, signed, lhs, rhs, out_ty, "int/uint";
Add (_) iadd;
@ -948,69 +961,79 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
let lhs = in_lhs.load_scalar(fx);
let rhs = in_rhs.load_scalar(fx);
let (res, has_overflow) = match bin_op {
BinOp::Add => {
/*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs);
(val, c_out)*/
// FIXME(CraneStation/cranelift#849) legalize iadd_cout for i8 and i16
let val = fx.bcx.ins().iadd(lhs, rhs);
let has_overflow = if !signed {
fx.bcx.ins().icmp(IntCC::UnsignedLessThan, val, lhs)
} else {
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
let slt = fx.bcx.ins().icmp(IntCC::SignedLessThan, val, lhs);
fx.bcx.ins().bxor(rhs_is_negative, slt)
};
(val, has_overflow)
let (res, has_overflow) = if in_lhs.layout().ty == fx.tcx.types.u128 || in_lhs.layout().ty == fx.tcx.types.i128 {
match (bin_op, signed) {
_ => {
let a = fx.bcx.ins().iconst(types::I64, 42);
let b = fx.bcx.ins().iconst(types::I64, 0);
(fx.bcx.ins().iconcat(a, b), fx.bcx.ins().bconst(types::B1, false))
}
}
BinOp::Sub => {
/*let (val, b_out) = fx.bcx.ins().isub_bout(lhs, rhs);
(val, b_out)*/
// FIXME(CraneStation/cranelift#849) legalize isub_bout for i8 and i16
let val = fx.bcx.ins().isub(lhs, rhs);
let has_overflow = if !signed {
fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, val, lhs)
} else {
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
let sgt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, val, lhs);
fx.bcx.ins().bxor(rhs_is_negative, sgt)
};
(val, has_overflow)
} else {
match bin_op {
BinOp::Add => {
/*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs);
(val, c_out)*/
// FIXME(CraneStation/cranelift#849) legalize iadd_cout for i8 and i16
let val = fx.bcx.ins().iadd(lhs, rhs);
let has_overflow = if !signed {
fx.bcx.ins().icmp(IntCC::UnsignedLessThan, val, lhs)
} else {
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
let slt = fx.bcx.ins().icmp(IntCC::SignedLessThan, val, lhs);
fx.bcx.ins().bxor(rhs_is_negative, slt)
};
(val, has_overflow)
}
BinOp::Sub => {
/*let (val, b_out) = fx.bcx.ins().isub_bout(lhs, rhs);
(val, b_out)*/
// FIXME(CraneStation/cranelift#849) legalize isub_bout for i8 and i16
let val = fx.bcx.ins().isub(lhs, rhs);
let has_overflow = if !signed {
fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, val, lhs)
} else {
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
let sgt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, val, lhs);
fx.bcx.ins().bxor(rhs_is_negative, sgt)
};
(val, has_overflow)
}
BinOp::Mul => {
let val = fx.bcx.ins().imul(lhs, rhs);
/*let val_hi = if !signed {
fx.bcx.ins().umulhi(lhs, rhs)
} else {
fx.bcx.ins().smulhi(lhs, rhs)
};
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);*/
// TODO: check for overflow
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
(val, has_overflow)
}
BinOp::Shl => {
let val = fx.bcx.ins().ishl(lhs, rhs);
// TODO: check for overflow
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
(val, has_overflow)
}
BinOp::Shr => {
let val = if !signed {
fx.bcx.ins().ushr(lhs, rhs)
} else {
fx.bcx.ins().sshr(lhs, rhs)
};
// TODO: check for overflow
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
(val, has_overflow)
}
_ => bug!(
"binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
bin_op,
in_lhs,
in_rhs
),
}
BinOp::Mul => {
let val = fx.bcx.ins().imul(lhs, rhs);
/*let val_hi = if !signed {
fx.bcx.ins().umulhi(lhs, rhs)
} else {
fx.bcx.ins().smulhi(lhs, rhs)
};
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);*/
// TODO: check for overflow
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
(val, has_overflow)
}
BinOp::Shl => {
let val = fx.bcx.ins().ishl(lhs, rhs);
// TODO: check for overflow
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
(val, has_overflow)
}
BinOp::Shr => {
let val = if !signed {
fx.bcx.ins().ushr(lhs, rhs)
} else {
fx.bcx.ins().sshr(lhs, rhs)
};
// TODO: check for overflow
let has_overflow = fx.bcx.ins().bconst(types::B1, false);
(val, has_overflow)
}
_ => bug!(
"binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
bin_op,
in_lhs,
in_rhs
),
};
let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);

View File

@ -28,7 +28,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 +36,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,

View File

@ -34,6 +34,16 @@ enum CValueInner {
ByValPair(Value, Value),
}
fn store_scalar<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, value: Value, addr: Value, offset: i32) {
if fx.bcx.func.dfg.value_type(value) == types::I128 {
let (a, b) = fx.bcx.ins().isplit(value);
fx.bcx.ins().store(MemFlags::new(), a, addr, offset);
fx.bcx.ins().store(MemFlags::new(), b, addr, offset + 8);
} else {
fx.bcx.ins().store(MemFlags::new(), value, addr, offset);
}
}
impl<'tcx> CValue<'tcx> {
pub fn by_ref(value: Value, layout: TyLayout<'tcx>) -> CValue<'tcx> {
CValue(CValueInner::ByRef(value), layout)
@ -147,7 +157,15 @@ impl<'tcx> CValue<'tcx> {
{
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 = if clif_ty == types::I128 {
// FIXME don't assume little-endian arch
let lsb = fx.bcx.ins().iconst(types::I64, const_val);
let msb = fx.bcx.ins().iconst(types::I64, 0);
fx.bcx.ins().iconcat(lsb, msb)
} else {
fx.bcx.ins().iconst(clif_ty, const_val)
};
CValue::by_val(val, layout)
}
pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
@ -343,15 +361,15 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
match from.0 {
CValueInner::ByVal(val) => {
fx.bcx.ins().store(MemFlags::new(), val, addr, 0);
store_scalar(fx, val, addr, 0);
}
CValueInner::ByValPair(value, extra) => {
match dst_layout.abi {
Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
fx.bcx.ins().store(MemFlags::new(), value, addr, 0);
fx.bcx.ins().store(
MemFlags::new(),
store_scalar(fx, value, addr, 0);
store_scalar(
fx,
extra,
addr,
b_offset,