mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Add intrinsics.sqrt for floating-point values
This commit is contained in:
@@ -409,11 +409,6 @@ string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int
|
|||||||
return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4;
|
return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@(default_calling_convention = "none")
|
|
||||||
foreign {
|
|
||||||
@(link_name="llvm.sqrt.f32") _sqrt_f32 :: proc(x: f32) -> f32 ---
|
|
||||||
@(link_name="llvm.sqrt.f64") _sqrt_f64 :: proc(x: f64) -> f64 ---
|
|
||||||
}
|
|
||||||
abs_f16 :: #force_inline proc "contextless" (x: f16) -> f16 {
|
abs_f16 :: #force_inline proc "contextless" (x: f16) -> f16 {
|
||||||
return -x if x < 0 else x;
|
return -x if x < 0 else x;
|
||||||
}
|
}
|
||||||
@@ -445,27 +440,27 @@ max_f64 :: proc(a, b: f64) -> f64 {
|
|||||||
|
|
||||||
abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 {
|
abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 {
|
||||||
r, i := real(x), imag(x);
|
r, i := real(x), imag(x);
|
||||||
return f16(_sqrt_f32(f32(r*r + i*i)));
|
return f16(intrinsics.sqrt(f32(r*r + i*i)));
|
||||||
}
|
}
|
||||||
abs_complex64 :: #force_inline proc "contextless" (x: complex64) -> f32 {
|
abs_complex64 :: #force_inline proc "contextless" (x: complex64) -> f32 {
|
||||||
r, i := real(x), imag(x);
|
r, i := real(x), imag(x);
|
||||||
return _sqrt_f32(r*r + i*i);
|
return intrinsics.sqrt(r*r + i*i);
|
||||||
}
|
}
|
||||||
abs_complex128 :: #force_inline proc "contextless" (x: complex128) -> f64 {
|
abs_complex128 :: #force_inline proc "contextless" (x: complex128) -> f64 {
|
||||||
r, i := real(x), imag(x);
|
r, i := real(x), imag(x);
|
||||||
return _sqrt_f64(r*r + i*i);
|
return intrinsics.sqrt(r*r + i*i);
|
||||||
}
|
}
|
||||||
abs_quaternion64 :: #force_inline proc "contextless" (x: quaternion64) -> f16 {
|
abs_quaternion64 :: #force_inline proc "contextless" (x: quaternion64) -> f16 {
|
||||||
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
||||||
return f16(_sqrt_f32(f32(r*r + i*i + j*j + k*k)));
|
return f16(intrinsics.sqrt(f32(r*r + i*i + j*j + k*k)));
|
||||||
}
|
}
|
||||||
abs_quaternion128 :: #force_inline proc "contextless" (x: quaternion128) -> f32 {
|
abs_quaternion128 :: #force_inline proc "contextless" (x: quaternion128) -> f32 {
|
||||||
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
||||||
return _sqrt_f32(r*r + i*i + j*j + k*k);
|
return intrinsics.sqrt(r*r + i*i + j*j + k*k);
|
||||||
}
|
}
|
||||||
abs_quaternion256 :: #force_inline proc "contextless" (x: quaternion256) -> f64 {
|
abs_quaternion256 :: #force_inline proc "contextless" (x: quaternion256) -> f64 {
|
||||||
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
r, i, j, k := real(x), imag(x), jmag(x), kmag(x);
|
||||||
return _sqrt_f64(r*r + i*i + j*j + k*k);
|
return intrinsics.sqrt(r*r + i*i + j*j + k*k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2026,6 +2026,34 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BuiltinProc_sqrt:
|
||||||
|
{
|
||||||
|
Operand x = {};
|
||||||
|
check_expr(c, &x, ce->args[0]);
|
||||||
|
if (x.mode == Addressing_Invalid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_type_float(x.type)) {
|
||||||
|
gbString xts = type_to_string(x.type);
|
||||||
|
error(x.expr, "Expected a floating point value for '%.*s', got %s", LIT(builtin_procs[id].name), xts);
|
||||||
|
gb_string_free(xts);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x.mode == Addressing_Constant) {
|
||||||
|
f64 v = exact_value_to_f64(x.value);
|
||||||
|
|
||||||
|
operand->mode = Addressing_Constant;
|
||||||
|
operand->type = x.type;
|
||||||
|
operand->value = exact_value_float(gb_sqrt(v));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
operand->type = default_type(x.type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case BuiltinProc_atomic_fence:
|
case BuiltinProc_atomic_fence:
|
||||||
case BuiltinProc_atomic_fence_acq:
|
case BuiltinProc_atomic_fence_acq:
|
||||||
case BuiltinProc_atomic_fence_rel:
|
case BuiltinProc_atomic_fence_rel:
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ enum BuiltinProcId {
|
|||||||
BuiltinProc_overflow_sub,
|
BuiltinProc_overflow_sub,
|
||||||
BuiltinProc_overflow_mul,
|
BuiltinProc_overflow_mul,
|
||||||
|
|
||||||
|
BuiltinProc_sqrt,
|
||||||
|
|
||||||
BuiltinProc_volatile_store,
|
BuiltinProc_volatile_store,
|
||||||
BuiltinProc_volatile_load,
|
BuiltinProc_volatile_load,
|
||||||
|
|
||||||
@@ -278,6 +280,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
|||||||
{STR_LIT("overflow_sub"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
{STR_LIT("overflow_sub"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
{STR_LIT("overflow_mul"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
{STR_LIT("overflow_mul"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
|
|
||||||
|
{STR_LIT("sqrt"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
|
|
||||||
{STR_LIT("volatile_store"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
{STR_LIT("volatile_store"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||||
{STR_LIT("volatile_load"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
{STR_LIT("volatile_load"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
|
|
||||||
|
|||||||
@@ -9429,6 +9429,28 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BuiltinProc_sqrt:
|
||||||
|
{
|
||||||
|
Type *type = tv.type;
|
||||||
|
|
||||||
|
lbValue x = lb_build_expr(p, ce->args[0]);
|
||||||
|
x = lb_emit_conv(p, x, type);
|
||||||
|
|
||||||
|
char const *name = "llvm.sqrt";
|
||||||
|
LLVMTypeRef types[1] = {lb_type(p->module, type)};
|
||||||
|
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
|
||||||
|
GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0]));
|
||||||
|
LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
|
||||||
|
|
||||||
|
LLVMValueRef args[1] = {};
|
||||||
|
args[0] = x.value;
|
||||||
|
|
||||||
|
lbValue res = {};
|
||||||
|
res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
|
||||||
|
res.type = type;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case BuiltinProc_atomic_fence:
|
case BuiltinProc_atomic_fence:
|
||||||
LLVMBuildFence(p->builder, LLVMAtomicOrderingSequentiallyConsistent, false, "");
|
LLVMBuildFence(p->builder, LLVMAtomicOrderingSequentiallyConsistent, false, "");
|
||||||
|
|||||||
Reference in New Issue
Block a user