mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
missing functions for dev backend for glue
This commit is contained in:
parent
e2dac4f022
commit
1e744dca7c
9 changed files with 113 additions and 17 deletions
|
@ -122,6 +122,9 @@ comptime {
|
|||
num.exportCeiling(f32, T, ROC_BUILTINS ++ "." ++ NUM ++ ".ceiling_f32.");
|
||||
num.exportCeiling(f64, T, ROC_BUILTINS ++ "." ++ NUM ++ ".ceiling_f64.");
|
||||
|
||||
num.exportNumToFloatCast(T, f32, ROC_BUILTINS ++ "." ++ NUM ++ ".num_to_float_cast_f32.");
|
||||
num.exportNumToFloatCast(T, f64, ROC_BUILTINS ++ "." ++ NUM ++ ".num_to_float_cast_f64.");
|
||||
|
||||
num.exportAddWithOverflow(T, ROC_BUILTINS ++ "." ++ NUM ++ ".add_with_overflow.");
|
||||
num.exportAddOrPanic(T, ROC_BUILTINS ++ "." ++ NUM ++ ".add_or_panic.");
|
||||
num.exportAddSaturatedInt(T, ROC_BUILTINS ++ "." ++ NUM ++ ".add_saturated.");
|
||||
|
|
|
@ -86,6 +86,15 @@ pub fn exportParseFloat(comptime T: type, comptime name: []const u8) void {
|
|||
@export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong });
|
||||
}
|
||||
|
||||
pub fn exportNumToFloatCast(comptime T: type, comptime F: type, comptime name: []const u8) void {
|
||||
comptime var f = struct {
|
||||
fn func(x: T) callconv(.C) F {
|
||||
return @floatFromInt(x);
|
||||
}
|
||||
}.func;
|
||||
@export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong });
|
||||
}
|
||||
|
||||
pub fn exportPow(comptime T: type, comptime name: []const u8) void {
|
||||
comptime var f = struct {
|
||||
fn func(base: T, exp: T) callconv(.C) T {
|
||||
|
|
|
@ -292,6 +292,10 @@ pub const NUM_FLOOR_F32: IntrinsicName = int_intrinsic!("roc_builtins.num.floor_
|
|||
pub const NUM_FLOOR_F64: IntrinsicName = int_intrinsic!("roc_builtins.num.floor_f64");
|
||||
pub const NUM_ROUND_F32: IntrinsicName = int_intrinsic!("roc_builtins.num.round_f32");
|
||||
pub const NUM_ROUND_F64: IntrinsicName = int_intrinsic!("roc_builtins.num.round_f64");
|
||||
pub const INT_TO_FLOAT_CAST_F32: IntrinsicName =
|
||||
int_intrinsic!("roc_builtins.num.num_to_float_cast_f32");
|
||||
pub const INT_TO_FLOAT_CAST_F64: IntrinsicName =
|
||||
int_intrinsic!("roc_builtins.num.num_to_float_cast_f64");
|
||||
|
||||
pub const NUM_ADD_OR_PANIC_INT: IntrinsicName = int_intrinsic!("roc_builtins.num.add_or_panic");
|
||||
pub const NUM_ADD_SATURATED_INT: IntrinsicName = int_intrinsic!("roc_builtins.num.add_saturated");
|
||||
|
|
|
@ -1668,6 +1668,11 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
Self::mov_freg64_mem64_offset32(buf, dst, AArch64GeneralReg::FP, offset)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn mov_freg32_base32(buf: &mut Vec<'_, u8>, dst: AArch64FloatReg, offset: i32) {
|
||||
Self::mov_freg32_mem32_offset32(buf, dst, AArch64GeneralReg::FP, offset)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn mov_reg_mem_offset32(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
|
|
|
@ -358,6 +358,7 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
|
||||
// base32 is similar to stack based instructions but they reference the base/frame pointer.
|
||||
fn mov_freg64_base32(buf: &mut Vec<'_, u8>, dst: FloatReg, offset: i32);
|
||||
fn mov_freg32_base32(buf: &mut Vec<'_, u8>, dst: FloatReg, offset: i32);
|
||||
|
||||
fn mov_reg_base32(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
|
@ -2154,6 +2155,30 @@ impl<
|
|||
);
|
||||
}
|
||||
|
||||
fn build_int_to_float_cast(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src: &Symbol,
|
||||
int_width: IntWidth,
|
||||
float_width: FloatWidth,
|
||||
) {
|
||||
use roc_builtins::bitcode::{INT_TO_FLOAT_CAST_F32, INT_TO_FLOAT_CAST_F64};
|
||||
|
||||
self.build_fn_call(
|
||||
dst,
|
||||
match float_width {
|
||||
FloatWidth::F32 => INT_TO_FLOAT_CAST_F32[int_width].to_string(),
|
||||
FloatWidth::F64 => INT_TO_FLOAT_CAST_F64[int_width].to_string(),
|
||||
},
|
||||
&[*src],
|
||||
&[Layout::from_int_width(int_width)],
|
||||
match float_width {
|
||||
FloatWidth::F32 => &Layout::F32,
|
||||
FloatWidth::F64 => &Layout::F64,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn build_num_cmp(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
|
|
|
@ -448,17 +448,26 @@ impl<
|
|||
}
|
||||
Stack(ReferencedPrimitive {
|
||||
base_offset, size, ..
|
||||
}) if base_offset % 8 == 0 && size == 8 => {
|
||||
// The primitive is aligned and the data is exactly 8 bytes, treat it like regular stack.
|
||||
let reg = self.get_float_reg(buf);
|
||||
ASM::mov_freg64_base32(buf, reg, base_offset);
|
||||
self.float_used_regs.push((reg, *sym));
|
||||
self.symbol_storage_map.insert(*sym, Reg(Float(reg)));
|
||||
self.free_reference(sym);
|
||||
reg
|
||||
}
|
||||
Stack(ReferencedPrimitive { .. }) => {
|
||||
todo!("loading referenced primitives")
|
||||
}) => {
|
||||
if base_offset % 8 == 0 && size == 8 {
|
||||
// The primitive is aligned and the data is exactly 8 bytes, treat it like regular stack.
|
||||
let reg = self.get_float_reg(buf);
|
||||
ASM::mov_freg64_base32(buf, reg, base_offset);
|
||||
self.float_used_regs.push((reg, *sym));
|
||||
self.symbol_storage_map.insert(*sym, Reg(Float(reg)));
|
||||
self.free_reference(sym);
|
||||
reg
|
||||
} else if base_offset % 4 == 0 && size == 4 {
|
||||
// The primitive is aligned and the data is exactly 8 bytes, treat it like regular stack.
|
||||
let reg = self.get_float_reg(buf);
|
||||
ASM::mov_freg32_base32(buf, reg, base_offset);
|
||||
self.float_used_regs.push((reg, *sym));
|
||||
self.symbol_storage_map.insert(*sym, Reg(Float(reg)));
|
||||
self.free_reference(sym);
|
||||
reg
|
||||
} else {
|
||||
todo!("loading referenced primitives")
|
||||
}
|
||||
}
|
||||
Stack(Complex { .. }) => {
|
||||
internal_error!("Cannot load large values into float registers: {}", sym)
|
||||
|
@ -570,12 +579,15 @@ impl<
|
|||
}
|
||||
Stack(ReferencedPrimitive {
|
||||
base_offset, size, ..
|
||||
}) if base_offset % 8 == 0 && *size == 8 => {
|
||||
// The primitive is aligned and the data is exactly 8 bytes, treat it like regular stack.
|
||||
ASM::mov_freg64_base32(buf, reg, *base_offset);
|
||||
}
|
||||
Stack(ReferencedPrimitive { .. }) => {
|
||||
todo!("loading referenced primitives")
|
||||
}) => {
|
||||
if base_offset % 8 == 0 && *size == 8 {
|
||||
// The primitive is aligned and the data is exactly 8 bytes, treat it like regular stack.
|
||||
ASM::mov_freg64_base32(buf, reg, *base_offset);
|
||||
} else if base_offset % 4 == 0 && *size == 4 {
|
||||
ASM::mov_freg32_base32(buf, reg, *base_offset);
|
||||
} else {
|
||||
todo!("loading referenced primitives")
|
||||
}
|
||||
}
|
||||
Stack(Complex { .. }) => {
|
||||
internal_error!("Cannot load large values into float registers: {}", sym)
|
||||
|
|
|
@ -2433,6 +2433,11 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
movsd_freg64_base64_offset32(buf, dst, X86_64GeneralReg::RBP, offset)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn mov_freg32_base32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, offset: i32) {
|
||||
movss_freg32_base32_offset32(buf, dst, X86_64GeneralReg::RBP, offset)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn mov_reg_base32(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
|
|
|
@ -2019,6 +2019,24 @@ trait Backend<'a> {
|
|||
self.build_num_cmp(sym, &args[0], &args[1], &arg_layouts[0]);
|
||||
}
|
||||
|
||||
LowLevel::NumToFloatCast => {
|
||||
let float_width = match *ret_layout {
|
||||
Layout::F64 => FloatWidth::F64,
|
||||
Layout::F32 => FloatWidth::F32,
|
||||
_ => unreachable!("invalid return layout for NumToFloatCast"),
|
||||
};
|
||||
|
||||
match arg_layouts[0].try_to_int_width() {
|
||||
Some(int_width) => {
|
||||
self.build_int_to_float_cast(sym, &args[0], int_width, float_width);
|
||||
}
|
||||
None => {
|
||||
//
|
||||
todo!("other NumToFloatCast cases");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x => todo!("low level, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
@ -2135,6 +2153,14 @@ trait Backend<'a> {
|
|||
target: IntWidth,
|
||||
);
|
||||
|
||||
fn build_int_to_float_cast(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src: &Symbol,
|
||||
int_width: IntWidth,
|
||||
float_width: FloatWidth,
|
||||
);
|
||||
|
||||
/// build_num_abs stores the absolute value of src into dst.
|
||||
fn build_num_abs(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>);
|
||||
|
||||
|
|
|
@ -103,6 +103,13 @@ macro_rules! impl_to_from_int_width {
|
|||
_ => roc_error_macros::internal_error!("not an integer layout!")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_to_int_width(&self) -> Option<IntWidth> {
|
||||
match self {
|
||||
$(&$layout => Some($int_width),)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue