Fix conversions
This commit is contained in:
@@ -25,6 +25,7 @@ either = "1.5"
|
|||||||
wabt = "0.7"
|
wabt = "0.7"
|
||||||
lazy_static = "1.2"
|
lazy_static = "1.2"
|
||||||
quickcheck = "0.7"
|
quickcheck = "0.7"
|
||||||
|
typemap = "0.3"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "experimental" }
|
maintenance = { status = "experimental" }
|
||||||
|
|||||||
750
src/backend.rs
750
src/backend.rs
@@ -1,20 +1,22 @@
|
|||||||
#![allow(dead_code)] // for now
|
#![allow(dead_code)] // for now
|
||||||
|
|
||||||
use crate::microwasm::{BrTarget, SignlessType, Type, F32, F64, I32, I64};
|
|
||||||
|
|
||||||
use self::registers::*;
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::microwasm::Value;
|
use crate::microwasm::{BrTarget, SignlessType, Type, Value, F32, F64, I32, I64};
|
||||||
use crate::module::{ModuleContext, RuntimeFunc};
|
use crate::module::{ModuleContext, RuntimeFunc};
|
||||||
use cranelift_codegen::{binemit, ir};
|
use cranelift_codegen::{binemit, ir};
|
||||||
use dynasmrt::x64::Assembler;
|
use dynasmrt::x64::Assembler;
|
||||||
use dynasmrt::{AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, ExecutableBuffer};
|
use dynasmrt::{AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, ExecutableBuffer};
|
||||||
|
use either::Either;
|
||||||
use std::{
|
use std::{
|
||||||
|
any::{Any, TypeId},
|
||||||
|
collections::HashMap,
|
||||||
iter::{self, FromIterator},
|
iter::{self, FromIterator},
|
||||||
mem,
|
mem,
|
||||||
ops::RangeInclusive,
|
ops::RangeInclusive,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use self::registers::*;
|
||||||
|
|
||||||
// TODO: Get rid of this! It's a total hack.
|
// TODO: Get rid of this! It's a total hack.
|
||||||
mod magic {
|
mod magic {
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir;
|
||||||
@@ -226,9 +228,9 @@ pub mod registers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SIGN_MASK_F64: u64 = 0b1000000000000000000000000000000000000000000000000000000000000000;
|
const SIGN_MASK_F64: u64 = 0b1000000000000000000000000000000000000000000000000000000000000000;
|
||||||
const REST_MASK_F64: u64 = 0b0111111111111111111111111111111111111111111111111111111111111111;
|
const REST_MASK_F64: u64 = !SIGN_MASK_F64;
|
||||||
const SIGN_MASK_F32: u32 = 0b10000000000000000000000000000000;
|
const SIGN_MASK_F32: u32 = 0b10000000000000000000000000000000;
|
||||||
const REST_MASK_F32: u32 = 0b01111111111111111111111111111111;
|
const REST_MASK_F32: u32 = !SIGN_MASK_F32;
|
||||||
|
|
||||||
extern "sysv64" fn println(len: u64, args: *const u8) {
|
extern "sysv64" fn println(len: u64, args: *const u8) {
|
||||||
println!("{}", unsafe {
|
println!("{}", unsafe {
|
||||||
@@ -499,15 +501,15 @@ pub struct FunctionEnd {
|
|||||||
should_generate_epilogue: bool,
|
should_generate_epilogue: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CodeGenSession<'a, M> {
|
pub struct CodeGenSession<'module, M> {
|
||||||
assembler: Assembler,
|
assembler: Assembler,
|
||||||
pub module_context: &'a M,
|
pub module_context: &'module M,
|
||||||
labels: Labels,
|
labels: Labels,
|
||||||
func_starts: Vec<(Option<AssemblyOffset>, DynamicLabel)>,
|
func_starts: Vec<(Option<AssemblyOffset>, DynamicLabel)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, M> CodeGenSession<'a, M> {
|
impl<'module, M> CodeGenSession<'module, M> {
|
||||||
pub fn new(func_count: u32, module_context: &'a M) -> Self {
|
pub fn new(func_count: u32, module_context: &'module M) -> Self {
|
||||||
let mut assembler = Assembler::new().unwrap();
|
let mut assembler = Assembler::new().unwrap();
|
||||||
let func_starts = iter::repeat_with(|| (None, assembler.new_dynamic_label()))
|
let func_starts = iter::repeat_with(|| (None, assembler.new_dynamic_label()))
|
||||||
.take(func_count as usize)
|
.take(func_count as usize)
|
||||||
@@ -538,7 +540,7 @@ impl<'a, M> CodeGenSession<'a, M> {
|
|||||||
Context {
|
Context {
|
||||||
asm: &mut self.assembler,
|
asm: &mut self.assembler,
|
||||||
current_function: func_idx,
|
current_function: func_idx,
|
||||||
reloc_sink: reloc_sink,
|
reloc_sink,
|
||||||
func_starts: &self.func_starts,
|
func_starts: &self.func_starts,
|
||||||
labels: &mut self.labels,
|
labels: &mut self.labels,
|
||||||
block_state: Default::default(),
|
block_state: Default::default(),
|
||||||
@@ -681,32 +683,28 @@ impl<T> From<T> for Pending<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
struct Labels {
|
enum LabelValue {
|
||||||
trap: Option<Pending<Label>>,
|
I8(i8),
|
||||||
ret: Option<Pending<Label>>,
|
I16(i16),
|
||||||
neg_const_f32: Option<Pending<Label>>,
|
I32(i32),
|
||||||
neg_const_f64: Option<Pending<Label>>,
|
I64(i64),
|
||||||
abs_const_f32: Option<Pending<Label>>,
|
|
||||||
abs_const_f64: Option<Pending<Label>>,
|
|
||||||
truncate_f32_const_u32: Option<Pending<Label>>,
|
|
||||||
truncate_f64_const_u32: Option<Pending<Label>>,
|
|
||||||
truncate_f32_const_u64: Option<Pending<Label>>,
|
|
||||||
truncate_f64_const_u64: Option<Pending<Label>>,
|
|
||||||
copysign_consts_f32: Option<Pending<(Label, Label)>>,
|
|
||||||
copysign_consts_f64: Option<Pending<(Label, Label)>>,
|
|
||||||
from_u64_consts_f64: Option<Pending<(Label, Label)>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Context<'a, M> {
|
type Labels = HashMap<
|
||||||
asm: &'a mut Assembler,
|
(u32, Either<TypeId, (LabelValue, Option<LabelValue>)>),
|
||||||
reloc_sink: &'a mut dyn binemit::RelocSink,
|
(Label, u32, Option<Box<FnMut(&mut Assembler)>>),
|
||||||
module_context: &'a M,
|
>;
|
||||||
|
|
||||||
|
pub struct Context<'this, M> {
|
||||||
|
asm: &'this mut Assembler,
|
||||||
|
reloc_sink: &'this mut dyn binemit::RelocSink,
|
||||||
|
module_context: &'this M,
|
||||||
current_function: u32,
|
current_function: u32,
|
||||||
func_starts: &'a Vec<(Option<AssemblyOffset>, DynamicLabel)>,
|
func_starts: &'this Vec<(Option<AssemblyOffset>, DynamicLabel)>,
|
||||||
/// Each push and pop on the value stack increments or decrements this value by 1 respectively.
|
/// Each push and pop on the value stack increments or decrements this value by 1 respectively.
|
||||||
pub block_state: BlockState,
|
pub block_state: BlockState,
|
||||||
labels: &'a mut Labels,
|
labels: &'this mut Labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Label in code.
|
/// Label in code.
|
||||||
@@ -2000,7 +1998,7 @@ pub struct VirtualCallingConvention {
|
|||||||
pub depth: StackDepth,
|
pub depth: StackDepth,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'module, M: ModuleContext> Context<'module, M> {
|
impl<'this, M: ModuleContext> Context<'this, M> {
|
||||||
pub fn debug(&mut self, d: std::fmt::Arguments) {
|
pub fn debug(&mut self, d: std::fmt::Arguments) {
|
||||||
asm_println!(self.asm, "{}", d);
|
asm_println!(self.asm, "{}", d);
|
||||||
}
|
}
|
||||||
@@ -2373,12 +2371,15 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_global(&mut self, global_idx: u32) {
|
pub fn get_global(&mut self, global_idx: u32) {
|
||||||
let (reg, offset) =
|
let (reg, offset) = self
|
||||||
self.module_context
|
.module_context
|
||||||
.defined_global_index(global_idx)
|
.defined_global_index(global_idx)
|
||||||
.map(|defined_global_index| {
|
.map(|defined_global_index| {
|
||||||
(None, self.module_context
|
(
|
||||||
.vmctx_vmglobal_definition(defined_global_index))
|
None,
|
||||||
|
self.module_context
|
||||||
|
.vmctx_vmglobal_definition(defined_global_index),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
let reg = self.block_state.regs.take(I64);
|
let reg = self.block_state.regs.take(I64);
|
||||||
@@ -2410,12 +2411,15 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
|
|
||||||
pub fn set_global(&mut self, global_idx: u32) {
|
pub fn set_global(&mut self, global_idx: u32) {
|
||||||
let val = self.pop();
|
let val = self.pop();
|
||||||
let (reg, offset) =
|
let (reg, offset) = self
|
||||||
self.module_context
|
.module_context
|
||||||
.defined_global_index(global_idx)
|
.defined_global_index(global_idx)
|
||||||
.map(|defined_global_index| {
|
.map(|defined_global_index| {
|
||||||
(None, self.module_context
|
(
|
||||||
.vmctx_vmglobal_definition(defined_global_index))
|
None,
|
||||||
|
self.module_context
|
||||||
|
.vmctx_vmglobal_definition(defined_global_index),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
let reg = self.block_state.regs.take(I64);
|
let reg = self.block_state.regs.take(I64);
|
||||||
@@ -2430,7 +2434,6 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
(Some(reg), 0)
|
(Some(reg), 0)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let val = self.into_reg(GPRType::Rq, val);
|
let val = self.into_reg(GPRType::Rq, val);
|
||||||
let vmctx = GPR::Rq(VMCTX);
|
let vmctx = GPR::Rq(VMCTX);
|
||||||
|
|
||||||
@@ -2572,7 +2575,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
}
|
}
|
||||||
(GPR::Rx(in_reg), GPR::Rx(out_reg)) => {
|
(GPR::Rx(in_reg), GPR::Rx(out_reg)) => {
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; movq Rx(out_reg), Rx(in_reg)
|
; movapd Rx(out_reg), Rx(in_reg)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2772,7 +2775,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
let const_label = self.neg_const_f32_label();
|
let const_label = self.aligned_label(16, LabelValue::I32(SIGN_MASK_F32 as i32));
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; xorps Rx(reg.rx().unwrap()), [=>const_label.0]
|
; xorps Rx(reg.rx().unwrap()), [=>const_label.0]
|
||||||
@@ -2793,7 +2796,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
let const_label = self.neg_const_f64_label();
|
let const_label = self.aligned_label(16, LabelValue::I64(SIGN_MASK_F64 as i64));
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; xorpd Rx(reg.rx().unwrap()), [=>const_label.0]
|
; xorpd Rx(reg.rx().unwrap()), [=>const_label.0]
|
||||||
@@ -2814,7 +2817,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
let const_label = self.abs_const_f32_label();
|
let const_label = self.aligned_label(16, LabelValue::I32(REST_MASK_F32 as i32));
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; andps Rx(reg.rx().unwrap()), [=>const_label.0]
|
; andps Rx(reg.rx().unwrap()), [=>const_label.0]
|
||||||
@@ -2835,7 +2838,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let reg = self.into_temp_reg(GPRType::Rx, val);
|
let reg = self.into_temp_reg(GPRType::Rx, val);
|
||||||
let const_label = self.abs_const_f64_label();
|
let const_label = self.aligned_label(16, LabelValue::I64(REST_MASK_F64 as i64));
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; andps Rx(reg.rx().unwrap()), [=>const_label.0]
|
; andps Rx(reg.rx().unwrap()), [=>const_label.0]
|
||||||
@@ -2899,7 +2902,8 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
} else {
|
} else {
|
||||||
let left = self.into_temp_reg(GPRType::Rx, left);
|
let left = self.into_temp_reg(GPRType::Rx, left);
|
||||||
let right = self.into_reg(GPRType::Rx, right);
|
let right = self.into_reg(GPRType::Rx, right);
|
||||||
let (sign_mask, rest_mask) = self.copysign_consts_f32_labels();
|
let sign_mask = self.aligned_label(16, LabelValue::I32(SIGN_MASK_F32 as i32));
|
||||||
|
let rest_mask = self.aligned_label(16, LabelValue::I32(REST_MASK_F32 as i32));
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; andps Rx(right.rx().unwrap()), [=>sign_mask.0]
|
; andps Rx(right.rx().unwrap()), [=>sign_mask.0]
|
||||||
@@ -2927,7 +2931,8 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
} else {
|
} else {
|
||||||
let left = self.into_temp_reg(GPRType::Rx, left);
|
let left = self.into_temp_reg(GPRType::Rx, left);
|
||||||
let right = self.into_reg(GPRType::Rx, right);
|
let right = self.into_reg(GPRType::Rx, right);
|
||||||
let (sign_mask, rest_mask) = self.copysign_consts_f64_labels();
|
let sign_mask = self.aligned_label(16, LabelValue::I64(SIGN_MASK_F64 as i64));
|
||||||
|
let rest_mask = self.aligned_label(16, LabelValue::I64(REST_MASK_F64 as i64));
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; andpd Rx(right.rx().unwrap()), [=>sign_mask.0]
|
; andpd Rx(right.rx().unwrap()), [=>sign_mask.0]
|
||||||
@@ -3048,54 +3053,169 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
as_f64,
|
as_f64,
|
||||||
|a: wasmparser::Ieee64| wasmparser::Ieee32((f64::from_bits(a.bits()) as f32).to_bits())
|
|a: wasmparser::Ieee64| wasmparser::Ieee32((f64::from_bits(a.bits()) as f32).to_bits())
|
||||||
);
|
);
|
||||||
conversion!(
|
pub fn i32_truncate_f32_s(&mut self) {
|
||||||
i32_truncate_f32_s,
|
let mut val = self.pop();
|
||||||
cvttss2si,
|
|
||||||
Rx,
|
let out_val = match val {
|
||||||
rx,
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
Rd,
|
(f32::from_bits(imm.as_f32().unwrap().bits()) as i32).into(),
|
||||||
rq,
|
),
|
||||||
f32,
|
other => {
|
||||||
i32,
|
let reg = self.into_reg(F32, other);
|
||||||
as_f32,
|
let temp = self.block_state.regs.take(I32);
|
||||||
|a: wasmparser::Ieee32| f32::from_bits(a.bits()) as i32
|
val = ValueLocation::Reg(reg);
|
||||||
|
|
||||||
|
let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32));
|
||||||
|
let float_cmp_mask = self.aligned_label(16, LabelValue::I32(0xcf000000u32 as i32));
|
||||||
|
let zero = self.aligned_label(16, LabelValue::I32(0));
|
||||||
|
let trap_mask = self.trap_label();
|
||||||
|
|
||||||
|
dynasm!(self.asm
|
||||||
|
; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; cmp Rd(temp.rq().unwrap()), [=>sign_mask.0]
|
||||||
|
; jne >ret
|
||||||
|
; ucomiss Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; jp =>trap_mask.0
|
||||||
|
; ucomiss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
|
||||||
|
; jnae =>trap_mask.0
|
||||||
|
; ucomiss Rx(reg.rx().unwrap()), [=>zero.0]
|
||||||
|
; jnb =>trap_mask.0
|
||||||
|
; ret:
|
||||||
);
|
);
|
||||||
conversion!(
|
|
||||||
i32_truncate_f32_u,
|
ValueLocation::Reg(temp)
|
||||||
cvttss2si,
|
}
|
||||||
Rx,
|
};
|
||||||
rx,
|
|
||||||
Rq,
|
self.free_value(val);
|
||||||
rq,
|
|
||||||
f32,
|
self.push(out_val);
|
||||||
i32,
|
}
|
||||||
as_f32,
|
pub fn i32_truncate_f32_u(&mut self) {
|
||||||
|a: wasmparser::Ieee32| f32::from_bits(a.bits()) as i32
|
let mut val = self.pop();
|
||||||
|
|
||||||
|
let out_val = match val {
|
||||||
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
|
(f32::from_bits(imm.as_f32().unwrap().bits()) as i32).into(),
|
||||||
|
),
|
||||||
|
other => {
|
||||||
|
let reg = self.into_temp_reg(F32, other);
|
||||||
|
val = ValueLocation::Reg(reg);
|
||||||
|
let temp = self.block_state.regs.take(I32);
|
||||||
|
|
||||||
|
let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32));
|
||||||
|
let float_cmp_mask = self.aligned_label(16, LabelValue::I32(0x4f000000u32 as i32));
|
||||||
|
let zero = self.aligned_label(16, LabelValue::I32(0));
|
||||||
|
let trap_mask = self.trap_label();
|
||||||
|
|
||||||
|
dynasm!(self.asm
|
||||||
|
; ucomiss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
|
||||||
|
; jae >else_
|
||||||
|
; jp =>trap_mask.0
|
||||||
|
; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; cmp Rd(temp.rq().unwrap()), 0
|
||||||
|
; jnge =>trap_mask.0
|
||||||
|
; jmp >ret
|
||||||
|
; else_:
|
||||||
|
; subss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
|
||||||
|
; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; cmp Rd(temp.rq().unwrap()), 0
|
||||||
|
; jnge =>trap_mask.0
|
||||||
|
; add Rq(temp.rq().unwrap()), [=>sign_mask.0]
|
||||||
|
; ret:
|
||||||
);
|
);
|
||||||
conversion!(
|
|
||||||
i32_truncate_f64_s,
|
ValueLocation::Reg(temp)
|
||||||
cvttsd2si,
|
}
|
||||||
Rx,
|
};
|
||||||
rx,
|
|
||||||
Rd,
|
self.free_value(val);
|
||||||
rq,
|
|
||||||
f64,
|
self.push(out_val);
|
||||||
i32,
|
}
|
||||||
as_f64,
|
|
||||||
|a: wasmparser::Ieee64| f64::from_bits(a.bits()) as i32
|
pub fn i32_truncate_f64_s(&mut self) {
|
||||||
|
let mut val = self.pop();
|
||||||
|
|
||||||
|
let out_val = match val {
|
||||||
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
|
(f64::from_bits(imm.as_f64().unwrap().bits()) as i32).into(),
|
||||||
|
),
|
||||||
|
other => {
|
||||||
|
let reg = self.into_reg(F32, other);
|
||||||
|
let temp = self.block_state.regs.take(I32);
|
||||||
|
val = ValueLocation::Reg(reg);
|
||||||
|
|
||||||
|
let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32));
|
||||||
|
let float_cmp_mask = self.aligned_label(16, LabelValue::I64(0xc1e0000000200000u64 as i64));
|
||||||
|
let zero = self.aligned_label(16, LabelValue::I64(0));
|
||||||
|
let trap_mask = self.trap_label();
|
||||||
|
|
||||||
|
dynasm!(self.asm
|
||||||
|
; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; cmp Rd(temp.rq().unwrap()), [=>sign_mask.0]
|
||||||
|
; jne >ret
|
||||||
|
; ucomisd Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; jp =>trap_mask.0
|
||||||
|
; ucomisd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
|
||||||
|
; jna =>trap_mask.0
|
||||||
|
; ucomisd Rx(reg.rx().unwrap()), [=>zero.0]
|
||||||
|
; jnb =>trap_mask.0
|
||||||
|
; ret:
|
||||||
);
|
);
|
||||||
conversion!(
|
|
||||||
i32_truncate_f64_u,
|
ValueLocation::Reg(temp)
|
||||||
cvttsd2si,
|
}
|
||||||
Rx,
|
};
|
||||||
rx,
|
|
||||||
Rq,
|
self.free_value(val);
|
||||||
rq,
|
|
||||||
f64,
|
self.push(out_val);
|
||||||
i32,
|
}
|
||||||
as_f64,
|
|
||||||
|a: wasmparser::Ieee64| f64::from_bits(a.bits()) as i32
|
pub fn i32_truncate_f64_u(&mut self) {
|
||||||
|
let mut val = self.pop();
|
||||||
|
|
||||||
|
let out_val = match val {
|
||||||
|
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
|
||||||
|
(f32::from_bits(imm.as_f32().unwrap().bits()) as i32).into(),
|
||||||
|
),
|
||||||
|
other => {
|
||||||
|
let reg = self.into_temp_reg(F32, other);
|
||||||
|
val = ValueLocation::Reg(reg);
|
||||||
|
let temp = self.block_state.regs.take(I32);
|
||||||
|
|
||||||
|
let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32));
|
||||||
|
let float_cmp_mask = self.aligned_label(16, LabelValue::I64(0x41e0000000000000u64 as i64));
|
||||||
|
let zero = self.aligned_label(16, LabelValue::I64(0));
|
||||||
|
let trap_mask = self.trap_label();
|
||||||
|
|
||||||
|
dynasm!(self.asm
|
||||||
|
; ucomisd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
|
||||||
|
; jae >else_
|
||||||
|
; jp =>trap_mask.0
|
||||||
|
; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; cmp Rd(temp.rq().unwrap()), 0
|
||||||
|
; jnge =>trap_mask.0
|
||||||
|
; jmp >ret
|
||||||
|
; else_:
|
||||||
|
; subsd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
|
||||||
|
; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; cmp Rd(temp.rq().unwrap()), 0
|
||||||
|
; jnge =>trap_mask.0
|
||||||
|
; add Rq(temp.rq().unwrap()), [=>sign_mask.0]
|
||||||
|
; ret:
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ValueLocation::Reg(temp)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.free_value(val);
|
||||||
|
|
||||||
|
self.push(out_val);
|
||||||
|
}
|
||||||
|
|
||||||
conversion!(
|
conversion!(
|
||||||
f32_convert_from_i32_s,
|
f32_convert_from_i32_s,
|
||||||
cvtsi2ss,
|
cvtsi2ss,
|
||||||
@@ -3171,6 +3291,8 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
pub fn i64_truncate_f32_u(&mut self) {
|
pub fn i64_truncate_f32_u(&mut self) {
|
||||||
|
struct Trunc;
|
||||||
|
|
||||||
let mut val = self.pop();
|
let mut val = self.pop();
|
||||||
|
|
||||||
let out_val = match val {
|
let out_val = match val {
|
||||||
@@ -3182,7 +3304,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
val = ValueLocation::Reg(reg);
|
val = ValueLocation::Reg(reg);
|
||||||
|
|
||||||
let temp = self.block_state.regs.take(I64);
|
let temp = self.block_state.regs.take(I64);
|
||||||
let u64_trunc_f32_const = self.truncate_f32_const_u64_label();
|
let u64_trunc_f32_const = self.aligned_label(16, LabelValue::I32(0x5F000000));
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; comiss Rx(reg.rx().unwrap()), [=>u64_trunc_f32_const.0]
|
; comiss Rx(reg.rx().unwrap()), [=>u64_trunc_f32_const.0]
|
||||||
@@ -3217,7 +3339,8 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
val = ValueLocation::Reg(reg);
|
val = ValueLocation::Reg(reg);
|
||||||
|
|
||||||
let temp = self.block_state.regs.take(I64);
|
let temp = self.block_state.regs.take(I64);
|
||||||
let u64_trunc_f64_const = self.truncate_f64_const_u64_label();
|
let u64_trunc_f64_const =
|
||||||
|
self.aligned_label(16, LabelValue::I64(0x43E0000000000000));
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; comisd Rx(reg.rx().unwrap()), [=>u64_trunc_f64_const.0]
|
; comisd Rx(reg.rx().unwrap()), [=>u64_trunc_f64_const.0]
|
||||||
@@ -3346,7 +3469,17 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
let out = self.block_state.regs.take(F64);
|
let out = self.block_state.regs.take(F64);
|
||||||
let temp = self.block_state.regs.take(F64);
|
let temp = self.block_state.regs.take(F64);
|
||||||
|
|
||||||
let (conv_const_0, conv_const_1) = self.from_u64_consts_f64_labels();
|
let conv_const_0 = self.aligned_label(
|
||||||
|
16,
|
||||||
|
(LabelValue::I32(0x43300000), LabelValue::I32(0x43300000)),
|
||||||
|
);
|
||||||
|
let conv_const_1 = self.aligned_label(
|
||||||
|
16,
|
||||||
|
(
|
||||||
|
LabelValue::I64(0x4330000000000000),
|
||||||
|
LabelValue::I64(0x4530000000000000),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; movq Rx(temp.rx().unwrap()), rdi
|
; movq Rx(temp.rx().unwrap()), rdi
|
||||||
@@ -3615,7 +3748,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
) -> (
|
) -> (
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
impl Iterator<Item = (GPR, GPR)> + Clone,
|
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
|
||||||
) {
|
) {
|
||||||
self.block_state.regs.mark_used(RAX);
|
self.block_state.regs.mark_used(RAX);
|
||||||
self.block_state.regs.mark_used(RDX);
|
self.block_state.regs.mark_used(RDX);
|
||||||
@@ -3687,7 +3820,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
) -> (
|
) -> (
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
impl Iterator<Item = (GPR, GPR)> + Clone + 'module,
|
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
|
||||||
) {
|
) {
|
||||||
self.full_div(divisor, quotient, |this, divisor| match divisor {
|
self.full_div(divisor, quotient, |this, divisor| match divisor {
|
||||||
ValueLocation::Stack(offset) => {
|
ValueLocation::Stack(offset) => {
|
||||||
@@ -3714,7 +3847,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
) -> (
|
) -> (
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
impl Iterator<Item = (GPR, GPR)> + Clone + 'module,
|
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
|
||||||
) {
|
) {
|
||||||
self.full_div(divisor, quotient, |this, divisor| match divisor {
|
self.full_div(divisor, quotient, |this, divisor| match divisor {
|
||||||
ValueLocation::Stack(offset) => {
|
ValueLocation::Stack(offset) => {
|
||||||
@@ -3741,7 +3874,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
) -> (
|
) -> (
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
impl Iterator<Item = (GPR, GPR)> + Clone + 'module,
|
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
|
||||||
) {
|
) {
|
||||||
self.full_div(divisor, quotient, |this, divisor| match divisor {
|
self.full_div(divisor, quotient, |this, divisor| match divisor {
|
||||||
ValueLocation::Stack(offset) => {
|
ValueLocation::Stack(offset) => {
|
||||||
@@ -3768,7 +3901,7 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
) -> (
|
) -> (
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
ValueLocation,
|
ValueLocation,
|
||||||
impl Iterator<Item = (GPR, GPR)> + Clone + 'module,
|
impl Iterator<Item = (GPR, GPR)> + Clone + 'this,
|
||||||
) {
|
) {
|
||||||
self.full_div(divisor, quotient, |this, divisor| match divisor {
|
self.full_div(divisor, quotient, |this, divisor| match divisor {
|
||||||
ValueLocation::Stack(offset) => {
|
ValueLocation::Stack(offset) => {
|
||||||
@@ -4484,179 +4617,68 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn align(&mut self, align_to: u32) {
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .align align_to as usize
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes the function epilogue (right now all this does is add the trap label that the
|
/// Writes the function epilogue (right now all this does is add the trap label that the
|
||||||
/// conditional traps in `call_indirect` use)
|
/// conditional traps in `call_indirect` use)
|
||||||
pub fn epilogue(&mut self) {
|
pub fn epilogue(&mut self) {
|
||||||
if let Some(l) = self.labels.trap.as_ref().and_then(Pending::as_undefined) {
|
let mut values = self.labels.values_mut().collect::<Vec<_>>();
|
||||||
self.define_label(l);
|
values.sort_unstable_by_key(|(_, align, _)| *align);
|
||||||
|
for (label, align, func) in values {
|
||||||
|
if let Some(mut func) = func.take() {
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
; ud2
|
; .align *align as usize
|
||||||
);
|
);
|
||||||
self.labels.trap = Some(Pending::defined(l));
|
self.asm.dynamic_label(label.0);
|
||||||
|
func(&mut self.asm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(l) = self.labels.ret.as_ref().and_then(Pending::as_undefined) {
|
|
||||||
self.define_label(l);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; ret
|
|
||||||
);
|
|
||||||
self.labels.ret = Some(Pending::defined(l));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(l) = self
|
|
||||||
.labels
|
|
||||||
.neg_const_f32
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(l);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .dword SIGN_MASK_F32 as i32
|
|
||||||
);
|
|
||||||
self.labels.neg_const_f32 = Some(Pending::defined(l));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(l) = self
|
|
||||||
.labels
|
|
||||||
.neg_const_f64
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(l);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .qword SIGN_MASK_F64 as i64
|
|
||||||
);
|
|
||||||
self.labels.neg_const_f64 = Some(Pending::defined(l));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(l) = self
|
|
||||||
.labels
|
|
||||||
.abs_const_f32
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(l);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .dword (!SIGN_MASK_F32) as i32
|
|
||||||
);
|
|
||||||
self.labels.abs_const_f32 = Some(Pending::defined(l));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(l) = self
|
|
||||||
.labels
|
|
||||||
.abs_const_f64
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(l);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .qword (!SIGN_MASK_F64) as i64
|
|
||||||
);
|
|
||||||
self.labels.abs_const_f64 = Some(Pending::defined(l));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(l) = self
|
|
||||||
.labels
|
|
||||||
.truncate_f32_const_u64
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(l);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .dword 0x5F000000
|
|
||||||
);
|
|
||||||
self.labels.truncate_f32_const_u64 = Some(Pending::defined(l));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(l) = self
|
|
||||||
.labels
|
|
||||||
.truncate_f64_const_u64
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(l);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .qword 0x43E0000000000000
|
|
||||||
);
|
|
||||||
self.labels.truncate_f64_const_u64 = Some(Pending::defined(l));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((sign_mask, rest_mask)) = self
|
|
||||||
.labels
|
|
||||||
.copysign_consts_f32
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(sign_mask);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .dword SIGN_MASK_F32 as i32
|
|
||||||
);
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(rest_mask);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .dword REST_MASK_F32 as i32
|
|
||||||
);
|
|
||||||
self.labels.copysign_consts_f32 = Some(Pending::defined((sign_mask, rest_mask)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((sign_mask, rest_mask)) = self
|
|
||||||
.labels
|
|
||||||
.copysign_consts_f64
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(sign_mask);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .qword SIGN_MASK_F64 as i64
|
|
||||||
);
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(rest_mask);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .qword REST_MASK_F64 as i64
|
|
||||||
);
|
|
||||||
self.labels.copysign_consts_f64 = Some(Pending::defined((sign_mask, rest_mask)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((conv_const_0, conv_const_1)) = self
|
|
||||||
.labels
|
|
||||||
.from_u64_consts_f64
|
|
||||||
.as_ref()
|
|
||||||
.and_then(Pending::as_undefined)
|
|
||||||
{
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(conv_const_0);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .dword 0x43300000
|
|
||||||
; .dword 0x43300000
|
|
||||||
);
|
|
||||||
self.align(16);
|
|
||||||
self.define_label(conv_const_1);
|
|
||||||
dynasm!(self.asm
|
|
||||||
; .qword 0x4330000000000000
|
|
||||||
; .qword 0x4530000000000000
|
|
||||||
);
|
|
||||||
self.labels.from_u64_consts_f64 = Some(Pending::defined((conv_const_0, conv_const_1)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trap(&mut self) {
|
pub fn trap(&mut self) {
|
||||||
|
let trap_label = self.trap_label();
|
||||||
dynasm!(self.asm
|
dynasm!(self.asm
|
||||||
|
; jmp =>trap_label.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trap_label(&mut self) -> Label {
|
||||||
|
self.label(|asm: &mut Assembler| {
|
||||||
|
dynasm!(asm
|
||||||
; ud2
|
; ud2
|
||||||
);
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ret_label(&mut self) -> Label {
|
||||||
|
self.label(|asm: &mut Assembler| {
|
||||||
|
dynasm!(asm
|
||||||
|
; ret
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn label<F>(&mut self, fun: F) -> Label
|
||||||
|
where
|
||||||
|
F: IntoLabel,
|
||||||
|
{
|
||||||
|
self.aligned_label(1, fun)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn aligned_label<F>(&mut self, align: u32, fun: F) -> Label
|
||||||
|
where
|
||||||
|
F: IntoLabel,
|
||||||
|
{
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
|
let key = fun.key();
|
||||||
|
if let Some((label, current_align, func)) = self.labels.get(&(align, key)) {
|
||||||
|
return *label;
|
||||||
|
}
|
||||||
|
|
||||||
|
let label = self.create_label();
|
||||||
|
self.labels
|
||||||
|
.insert((align, key), (label, align, Some(fun.callback())));
|
||||||
|
|
||||||
|
label
|
||||||
}
|
}
|
||||||
|
|
||||||
fn target_to_label(&mut self, target: BrTarget<Label>) -> Label {
|
fn target_to_label(&mut self, target: BrTarget<Label>) -> Label {
|
||||||
@@ -4665,132 +4687,92 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
BrTarget::Return => self.ret_label(),
|
BrTarget::Return => self.ret_label(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
trait IntoLabel {
|
||||||
fn trap_label(&mut self) -> Label {
|
fn key(&self) -> Either<TypeId, (LabelValue, Option<LabelValue>)>;
|
||||||
if let Some(l) = &self.labels.trap {
|
fn callback(self) -> Box<FnMut(&mut Assembler)>;
|
||||||
return l.label;
|
}
|
||||||
|
|
||||||
|
impl<F> IntoLabel for F
|
||||||
|
where
|
||||||
|
F: FnMut(&mut Assembler) + Any,
|
||||||
|
{
|
||||||
|
fn key(&self) -> Either<TypeId, (LabelValue, Option<LabelValue>)> {
|
||||||
|
Either::Left(TypeId::of::<Self>())
|
||||||
}
|
}
|
||||||
|
|
||||||
let label = self.create_label();
|
fn callback(self) -> Box<FnMut(&mut Assembler)> {
|
||||||
self.labels.trap = Some(label.into());
|
Box::new(self)
|
||||||
label
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
fn const_value(val: LabelValue) -> impl FnMut(&mut Assembler) {
|
||||||
fn ret_label(&mut self) -> Label {
|
move |asm| match val {
|
||||||
if let Some(l) = &self.labels.ret {
|
LabelValue::I8(val) => dynasm!(asm
|
||||||
return l.label;
|
; .byte val
|
||||||
}
|
),
|
||||||
|
LabelValue::I16(val) => dynasm!(asm
|
||||||
let label = self.create_label();
|
; .word val
|
||||||
self.labels.ret = Some(label.into());
|
),
|
||||||
label
|
LabelValue::I32(val) => dynasm!(asm
|
||||||
}
|
; .dword val
|
||||||
|
),
|
||||||
#[must_use]
|
LabelValue::I64(val) => dynasm!(asm
|
||||||
fn neg_const_f32_label(&mut self) -> Label {
|
; .qword val
|
||||||
if let Some(l) = &self.labels.neg_const_f32 {
|
),
|
||||||
return l.label;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let label = self.create_label();
|
fn const_values(a: LabelValue, b: LabelValue) -> impl FnMut(&mut Assembler) {
|
||||||
self.labels.neg_const_f32 = Some(label.into());
|
move |asm| {
|
||||||
label
|
match a {
|
||||||
}
|
LabelValue::I8(val) => dynasm!(asm
|
||||||
|
; .byte val
|
||||||
#[must_use]
|
),
|
||||||
fn neg_const_f64_label(&mut self) -> Label {
|
LabelValue::I16(val) => dynasm!(asm
|
||||||
if let Some(l) = &self.labels.neg_const_f64 {
|
; .word val
|
||||||
return l.label;
|
),
|
||||||
}
|
LabelValue::I32(val) => dynasm!(asm
|
||||||
|
; .dword val
|
||||||
let label = self.create_label();
|
),
|
||||||
self.labels.neg_const_f64 = Some(label.into());
|
LabelValue::I64(val) => dynasm!(asm
|
||||||
label
|
; .qword val
|
||||||
}
|
),
|
||||||
|
}
|
||||||
#[must_use]
|
|
||||||
fn abs_const_f32_label(&mut self) -> Label {
|
match b {
|
||||||
if let Some(l) = &self.labels.abs_const_f32 {
|
LabelValue::I8(val) => dynasm!(asm
|
||||||
return l.label;
|
; .byte val
|
||||||
}
|
),
|
||||||
|
LabelValue::I16(val) => dynasm!(asm
|
||||||
let label = self.create_label();
|
; .word val
|
||||||
self.labels.abs_const_f32 = Some(label.into());
|
),
|
||||||
label
|
LabelValue::I32(val) => dynasm!(asm
|
||||||
}
|
; .dword val
|
||||||
|
),
|
||||||
#[must_use]
|
LabelValue::I64(val) => dynasm!(asm
|
||||||
fn abs_const_f64_label(&mut self) -> Label {
|
; .qword val
|
||||||
if let Some(l) = &self.labels.abs_const_f64 {
|
),
|
||||||
return l.label;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let label = self.create_label();
|
|
||||||
self.labels.abs_const_f64 = Some(label.into());
|
impl IntoLabel for LabelValue {
|
||||||
label
|
fn key(&self) -> Either<TypeId, (LabelValue, Option<LabelValue>)> {
|
||||||
}
|
Either::Right((*self, None))
|
||||||
|
}
|
||||||
#[must_use]
|
fn callback(self) -> Box<FnMut(&mut Assembler)> {
|
||||||
fn truncate_f32_const_u64_label(&mut self) -> Label {
|
Box::new(const_value(self))
|
||||||
if let Some(l) = &self.labels.truncate_f32_const_u64 {
|
}
|
||||||
return l.label;
|
}
|
||||||
}
|
|
||||||
|
impl IntoLabel for (LabelValue, LabelValue) {
|
||||||
let label = self.create_label();
|
fn key(&self) -> Either<TypeId, (LabelValue, Option<LabelValue>)> {
|
||||||
self.labels.truncate_f32_const_u64 = Some(label.into());
|
Either::Right((self.0, Some(self.1)))
|
||||||
label
|
}
|
||||||
}
|
fn callback(self) -> Box<FnMut(&mut Assembler)> {
|
||||||
|
Box::new(const_values(self.0, self.1))
|
||||||
#[must_use]
|
|
||||||
fn truncate_f64_const_u64_label(&mut self) -> Label {
|
|
||||||
if let Some(l) = &self.labels.truncate_f64_const_u64 {
|
|
||||||
return l.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
let label = self.create_label();
|
|
||||||
self.labels.truncate_f64_const_u64 = Some(label.into());
|
|
||||||
label
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
fn copysign_consts_f32_labels(&mut self) -> (Label, Label) {
|
|
||||||
if let Some(l) = &self.labels.copysign_consts_f32 {
|
|
||||||
return l.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sign_mask = self.create_label();
|
|
||||||
let rest_mask = self.create_label();
|
|
||||||
let labels = (sign_mask, rest_mask);
|
|
||||||
self.labels.copysign_consts_f32 = Some(labels.into());
|
|
||||||
labels
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
fn copysign_consts_f64_labels(&mut self) -> (Label, Label) {
|
|
||||||
if let Some(l) = &self.labels.copysign_consts_f64 {
|
|
||||||
return l.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sign_mask = self.create_label();
|
|
||||||
let rest_mask = self.create_label();
|
|
||||||
let labels = (sign_mask, rest_mask);
|
|
||||||
self.labels.copysign_consts_f64 = Some(labels.into());
|
|
||||||
labels
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
fn from_u64_consts_f64_labels(&mut self) -> (Label, Label) {
|
|
||||||
if let Some(l) = &self.labels.from_u64_consts_f64 {
|
|
||||||
return l.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sign_mask = self.create_label();
|
|
||||||
let rest_mask = self.create_label();
|
|
||||||
let labels = (sign_mask, rest_mask);
|
|
||||||
self.labels.from_u64_consts_f64 = Some(labels.into());
|
|
||||||
labels
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
try_from,
|
try_from,
|
||||||
try_trait,
|
try_trait,
|
||||||
bind_by_move_pattern_guards,
|
bind_by_move_pattern_guards,
|
||||||
|
fnbox,
|
||||||
copysign
|
copysign
|
||||||
)]
|
)]
|
||||||
#![plugin(dynasm)]
|
#![plugin(dynasm)]
|
||||||
|
|||||||
Reference in New Issue
Block a user