From e0225c3579147557ad4fe2241d8fbe61851a6389 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 19 May 2021 10:32:41 +0100 Subject: [PATCH] Add `intrinsics.sqrt` for floating-point values --- core/runtime/internal.odin | 17 ++++++----------- src/check_builtin.cpp | 28 ++++++++++++++++++++++++++++ src/checker_builtin_procs.hpp | 4 ++++ src/llvm_backend.cpp | 22 ++++++++++++++++++++++ 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 0e128567a..b95f3e64d 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -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; } -@(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 { 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 { 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 { 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 { 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 { 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 { 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 { 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); } diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 8932ac914..54cd21582 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2026,6 +2026,34 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } 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_acq: case BuiltinProc_atomic_fence_rel: diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 5b1aecd68..cb864f37d 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -56,6 +56,8 @@ enum BuiltinProcId { BuiltinProc_overflow_sub, BuiltinProc_overflow_mul, + BuiltinProc_sqrt, + BuiltinProc_volatile_store, 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_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_load"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index a15b6a172..9dfa123a2 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -9429,6 +9429,28 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, 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: LLVMBuildFence(p->builder, LLVMAtomicOrderingSequentiallyConsistent, false, "");