mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
Stop using llvm instrinsics that just call libc
In a future PR. I will change zig to insure that all of these instrinsics use musl directly and do not call out to the linked libc.
This commit is contained in:
parent
8cbd40a743
commit
7683c5ae53
6 changed files with 102 additions and 95 deletions
|
@ -7,11 +7,12 @@ use inkwell::{
|
|||
};
|
||||
use roc_builtins::{
|
||||
bitcode::{FloatWidth, IntWidth, IntrinsicName},
|
||||
float_intrinsic, llvm_int_intrinsic,
|
||||
llvm_int_intrinsic,
|
||||
};
|
||||
|
||||
use super::build::{add_func, FunctionSpec};
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn add_float_intrinsic<'ctx, F>(
|
||||
ctx: &'ctx Context,
|
||||
module: &Module<'ctx>,
|
||||
|
@ -111,18 +112,6 @@ pub(crate) fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
|
|||
i8_ptr_type.fn_type(&[], false),
|
||||
);
|
||||
|
||||
add_float_intrinsic(ctx, module, &LLVM_LOG, |t| t.fn_type(&[t.into()], false));
|
||||
add_float_intrinsic(ctx, module, &LLVM_POW, |t| {
|
||||
t.fn_type(&[t.into(), t.into()], false)
|
||||
});
|
||||
add_float_intrinsic(ctx, module, &LLVM_FABS, |t| t.fn_type(&[t.into()], false));
|
||||
add_float_intrinsic(ctx, module, &LLVM_SIN, |t| t.fn_type(&[t.into()], false));
|
||||
add_float_intrinsic(ctx, module, &LLVM_COS, |t| t.fn_type(&[t.into()], false));
|
||||
add_float_intrinsic(ctx, module, &LLVM_CEILING, |t| {
|
||||
t.fn_type(&[t.into()], false)
|
||||
});
|
||||
add_float_intrinsic(ctx, module, &LLVM_FLOOR, |t| t.fn_type(&[t.into()], false));
|
||||
|
||||
add_int_intrinsic(ctx, module, &LLVM_ADD_WITH_OVERFLOW, |t| {
|
||||
let fields = [t.into(), i1_type.into()];
|
||||
ctx.struct_type(&fields, false)
|
||||
|
@ -150,17 +139,6 @@ pub(crate) fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
|
|||
});
|
||||
}
|
||||
|
||||
pub const LLVM_POW: IntrinsicName = float_intrinsic!("llvm.pow");
|
||||
pub const LLVM_FABS: IntrinsicName = float_intrinsic!("llvm.fabs");
|
||||
pub static LLVM_SQRT: IntrinsicName = float_intrinsic!("llvm.sqrt");
|
||||
pub static LLVM_LOG: IntrinsicName = float_intrinsic!("llvm.log");
|
||||
|
||||
pub static LLVM_SIN: IntrinsicName = float_intrinsic!("llvm.sin");
|
||||
pub static LLVM_COS: IntrinsicName = float_intrinsic!("llvm.cos");
|
||||
pub static LLVM_CEILING: IntrinsicName = float_intrinsic!("llvm.ceil");
|
||||
pub static LLVM_FLOOR: IntrinsicName = float_intrinsic!("llvm.floor");
|
||||
pub static LLVM_ROUND: IntrinsicName = float_intrinsic!("llvm.round");
|
||||
|
||||
pub static LLVM_MEMSET_I64: &str = "llvm.memset.p0i8.i64";
|
||||
pub static LLVM_MEMSET_I32: &str = "llvm.memset.p0i8.i32";
|
||||
|
||||
|
|
|
@ -41,9 +41,13 @@ use crate::llvm::{
|
|||
self, basic_type_from_layout, zig_num_parse_result_type, zig_to_int_checked_result_type,
|
||||
},
|
||||
intrinsics::{
|
||||
LLVM_ADD_SATURATED, LLVM_ADD_WITH_OVERFLOW, LLVM_CEILING, LLVM_COS, LLVM_FABS, LLVM_FLOOR,
|
||||
LLVM_LOG, LLVM_MUL_WITH_OVERFLOW, LLVM_POW, LLVM_ROUND, LLVM_SIN, LLVM_SQRT,
|
||||
LLVM_SUB_SATURATED, LLVM_SUB_WITH_OVERFLOW,
|
||||
// These instrinsics do not generate calls to libc and are safe to keep.
|
||||
// If we find that any of them generate calls to libc on some platforms, we need to define them as zig bitcode.
|
||||
LLVM_ADD_SATURATED,
|
||||
LLVM_ADD_WITH_OVERFLOW,
|
||||
LLVM_MUL_WITH_OVERFLOW,
|
||||
LLVM_SUB_SATURATED,
|
||||
LLVM_SUB_WITH_OVERFLOW,
|
||||
},
|
||||
refcounting::PointerToRefcount,
|
||||
};
|
||||
|
@ -1704,7 +1708,11 @@ fn build_float_binop<'ctx>(
|
|||
NumLt => bd.build_float_compare(OLT, lhs, rhs, "float_lt").into(),
|
||||
NumLte => bd.build_float_compare(OLE, lhs, rhs, "float_lte").into(),
|
||||
NumDivFrac => bd.build_float_div(lhs, rhs, "div_float").into(),
|
||||
NumPow => env.call_intrinsic(&LLVM_POW[float_width], &[lhs.into(), rhs.into()]),
|
||||
NumPow => call_bitcode_fn(
|
||||
env,
|
||||
&[lhs.into(), rhs.into()],
|
||||
&bitcode::NUM_POW[float_width],
|
||||
),
|
||||
_ => {
|
||||
unreachable!("Unrecognized int binary operation: {:?}", op);
|
||||
}
|
||||
|
@ -2316,9 +2324,9 @@ fn build_float_unary_op<'a, 'ctx>(
|
|||
// TODO: Handle different sized floats
|
||||
match op {
|
||||
NumNeg => bd.build_float_neg(arg, "negate_float").into(),
|
||||
NumAbs => env.call_intrinsic(&LLVM_FABS[float_width], &[arg.into()]),
|
||||
NumSqrtUnchecked => env.call_intrinsic(&LLVM_SQRT[float_width], &[arg.into()]),
|
||||
NumLogUnchecked => env.call_intrinsic(&LLVM_LOG[float_width], &[arg.into()]),
|
||||
NumAbs => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_FABS[float_width]),
|
||||
NumSqrtUnchecked => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_SQRT[float_width]),
|
||||
NumLogUnchecked => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_LOG[float_width]),
|
||||
NumToFrac => {
|
||||
let return_width = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(Builtin::Float(return_width)) => return_width,
|
||||
|
@ -2342,64 +2350,46 @@ fn build_float_unary_op<'a, 'ctx>(
|
|||
}
|
||||
}
|
||||
NumCeiling => {
|
||||
let (return_signed, return_type) = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => (
|
||||
int_width.is_signed(),
|
||||
convert::int_type_from_int_width(env, int_width),
|
||||
),
|
||||
let int_width = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
|
||||
};
|
||||
let opcode = if return_signed {
|
||||
InstructionOpcode::FPToSI
|
||||
} else {
|
||||
InstructionOpcode::FPToUI
|
||||
};
|
||||
env.builder.build_cast(
|
||||
opcode,
|
||||
env.call_intrinsic(&LLVM_CEILING[float_width], &[arg.into()]),
|
||||
return_type,
|
||||
"num_ceiling",
|
||||
)
|
||||
match float_width {
|
||||
FloatWidth::F32 => {
|
||||
call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_CEILING_F32[int_width])
|
||||
}
|
||||
FloatWidth::F64 => {
|
||||
call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_CEILING_F64[int_width])
|
||||
}
|
||||
}
|
||||
}
|
||||
NumFloor => {
|
||||
let (return_signed, return_type) = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => (
|
||||
int_width.is_signed(),
|
||||
convert::int_type_from_int_width(env, int_width),
|
||||
),
|
||||
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
|
||||
let int_width = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
_ => internal_error!("Floor return layout is not int: {:?}", layout),
|
||||
};
|
||||
let opcode = if return_signed {
|
||||
InstructionOpcode::FPToSI
|
||||
} else {
|
||||
InstructionOpcode::FPToUI
|
||||
};
|
||||
env.builder.build_cast(
|
||||
opcode,
|
||||
env.call_intrinsic(&LLVM_FLOOR[float_width], &[arg.into()]),
|
||||
return_type,
|
||||
"num_floor",
|
||||
)
|
||||
match float_width {
|
||||
FloatWidth::F32 => {
|
||||
call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_FLOOR_F32[int_width])
|
||||
}
|
||||
FloatWidth::F64 => {
|
||||
call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_FLOOR_F64[int_width])
|
||||
}
|
||||
}
|
||||
}
|
||||
NumRound => {
|
||||
let (return_signed, return_type) = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => (
|
||||
int_width.is_signed(),
|
||||
convert::int_type_from_int_width(env, int_width),
|
||||
),
|
||||
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
|
||||
let int_width = match layout_interner.get(layout).repr {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
_ => internal_error!("Round return layout is not int: {:?}", layout),
|
||||
};
|
||||
let opcode = if return_signed {
|
||||
InstructionOpcode::FPToSI
|
||||
} else {
|
||||
InstructionOpcode::FPToUI
|
||||
};
|
||||
env.builder.build_cast(
|
||||
opcode,
|
||||
env.call_intrinsic(&LLVM_ROUND[float_width], &[arg.into()]),
|
||||
return_type,
|
||||
"num_round",
|
||||
)
|
||||
match float_width {
|
||||
FloatWidth::F32 => {
|
||||
call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_ROUND_F32[int_width])
|
||||
}
|
||||
FloatWidth::F64 => {
|
||||
call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_ROUND_F64[int_width])
|
||||
}
|
||||
}
|
||||
}
|
||||
NumIsNan => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_IS_NAN[float_width]),
|
||||
NumIsInfinite => {
|
||||
|
@ -2408,8 +2398,8 @@ fn build_float_unary_op<'a, 'ctx>(
|
|||
NumIsFinite => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_IS_FINITE[float_width]),
|
||||
|
||||
// trigonometry
|
||||
NumSin => env.call_intrinsic(&LLVM_SIN[float_width], &[arg.into()]),
|
||||
NumCos => env.call_intrinsic(&LLVM_COS[float_width], &[arg.into()]),
|
||||
NumSin => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_SIN[float_width]),
|
||||
NumCos => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_COS[float_width]),
|
||||
|
||||
NumAtan => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_ATAN[float_width]),
|
||||
NumAcos => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_ACOS[float_width]),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue