mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-28 17:04:34 +00:00
Replace many foreign llvm calls with intrinsics
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package math_bits
|
||||
|
||||
import "intrinsics"
|
||||
import "core:runtime"
|
||||
|
||||
U8_MIN :: 0;
|
||||
@@ -22,32 +23,10 @@ I16_MAX :: 1 << 15 - 1;
|
||||
I32_MAX :: 1 << 31 - 1;
|
||||
I64_MAX :: 1 << 63 - 1;
|
||||
|
||||
@(default_calling_convention="none")
|
||||
foreign {
|
||||
@(link_name="llvm.ctpop.i8") count_ones8 :: proc(i: u8) -> u8 ---
|
||||
@(link_name="llvm.ctpop.i16") count_ones16 :: proc(i: u16) -> u16 ---
|
||||
@(link_name="llvm.ctpop.i32") count_ones32 :: proc(i: u32) -> u32 ---
|
||||
@(link_name="llvm.ctpop.i64") count_ones64 :: proc(i: u64) -> u64 ---
|
||||
|
||||
@(link_name="llvm.cttz.i8") trailing_zeros8 :: proc(i: u8, is_zero_undef := false) -> u8 ---
|
||||
@(link_name="llvm.cttz.i16") trailing_zeros16 :: proc(i: u16, is_zero_undef := false) -> u16 ---
|
||||
@(link_name="llvm.cttz.i32") trailing_zeros32 :: proc(i: u32, is_zero_undef := false) -> u32 ---
|
||||
@(link_name="llvm.cttz.i64") trailing_zeros64 :: proc(i: u64, is_zero_undef := false) -> u64 ---
|
||||
|
||||
@(link_name="llvm.bitreverse.i8") reverse_bits8 :: proc(i: u8) -> u8 ---
|
||||
@(link_name="llvm.bitreverse.i16") reverse_bits16 :: proc(i: u16) -> u16 ---
|
||||
@(link_name="llvm.bitreverse.i32") reverse_bits32 :: proc(i: u32) -> u32 ---
|
||||
@(link_name="llvm.bitreverse.i64") reverse_bits64 :: proc(i: u64) -> u64 ---
|
||||
}
|
||||
|
||||
|
||||
trailing_zeros_uint :: proc(i: uint) -> uint {
|
||||
when size_of(uint) == size_of(u64) {
|
||||
return uint(trailing_zeros64(u64(i)));
|
||||
} else {
|
||||
return uint(trailing_zeros32(u32(i)));
|
||||
}
|
||||
}
|
||||
count_ones :: intrinsics.count_ones;
|
||||
trailing_zeros :: intrinsics.trailing_zeros;
|
||||
reverse_bits :: intrinsics.reverse_bits;
|
||||
|
||||
|
||||
leading_zeros_u8 :: proc(i: u8) -> int {
|
||||
@@ -117,10 +96,17 @@ byte_swap :: proc{
|
||||
byte_swap_int,
|
||||
};
|
||||
|
||||
count_zeros8 :: proc(i: u8) -> u8 { return 8 - count_ones8(i); }
|
||||
count_zeros16 :: proc(i: u16) -> u16 { return 16 - count_ones16(i); }
|
||||
count_zeros32 :: proc(i: u32) -> u32 { return 32 - count_ones32(i); }
|
||||
count_zeros64 :: proc(i: u64) -> u64 { return 64 - count_ones64(i); }
|
||||
count_zeros8 :: proc(i: u8) -> u8 { return 8 - count_ones(i); }
|
||||
count_zeros16 :: proc(i: u16) -> u16 { return 16 - count_ones(i); }
|
||||
count_zeros32 :: proc(i: u32) -> u32 { return 32 - count_ones(i); }
|
||||
count_zeros64 :: proc(i: u64) -> u64 { return 64 - count_ones(i); }
|
||||
|
||||
count_zeros :: proc{
|
||||
count_zeros8,
|
||||
count_zeros16,
|
||||
count_zeros32,
|
||||
count_zeros64,
|
||||
};
|
||||
|
||||
|
||||
rotate_left8 :: proc(x: u8, k: int) -> u8 {
|
||||
@@ -176,120 +162,10 @@ to_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; }
|
||||
to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
|
||||
|
||||
@(default_calling_convention="none")
|
||||
foreign {
|
||||
@(link_name="llvm.uadd.with.overflow.i8") overflowing_add_u8 :: proc(lhs, rhs: u8) -> (u8, bool) ---
|
||||
@(link_name="llvm.sadd.with.overflow.i8") overflowing_add_i8 :: proc(lhs, rhs: i8) -> (i8, bool) ---
|
||||
@(link_name="llvm.uadd.with.overflow.i16") overflowing_add_u16 :: proc(lhs, rhs: u16) -> (u16, bool) ---
|
||||
@(link_name="llvm.sadd.with.overflow.i16") overflowing_add_i16 :: proc(lhs, rhs: i16) -> (i16, bool) ---
|
||||
@(link_name="llvm.uadd.with.overflow.i32") overflowing_add_u32 :: proc(lhs, rhs: u32) -> (u32, bool) ---
|
||||
@(link_name="llvm.sadd.with.overflow.i32") overflowing_add_i32 :: proc(lhs, rhs: i32) -> (i32, bool) ---
|
||||
@(link_name="llvm.uadd.with.overflow.i64") overflowing_add_u64 :: proc(lhs, rhs: u64) -> (u64, bool) ---
|
||||
@(link_name="llvm.sadd.with.overflow.i64") overflowing_add_i64 :: proc(lhs, rhs: i64) -> (i64, bool) ---
|
||||
}
|
||||
|
||||
overflowing_add_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
when size_of(uint) == size_of(u32) {
|
||||
x, ok := overflowing_add_u32(u32(lhs), u32(rhs));
|
||||
return uint(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_add_u64(u64(lhs), u64(rhs));
|
||||
return uint(x), ok;
|
||||
}
|
||||
}
|
||||
overflowing_add_int :: proc(lhs, rhs: int) -> (int, bool) {
|
||||
when size_of(int) == size_of(i32) {
|
||||
x, ok := overflowing_add_i32(i32(lhs), i32(rhs));
|
||||
return int(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_add_i64(i64(lhs), i64(rhs));
|
||||
return int(x), ok;
|
||||
}
|
||||
}
|
||||
|
||||
overflowing_add :: proc{
|
||||
overflowing_add_u8, overflowing_add_i8,
|
||||
overflowing_add_u16, overflowing_add_i16,
|
||||
overflowing_add_u32, overflowing_add_i32,
|
||||
overflowing_add_u64, overflowing_add_i64,
|
||||
overflowing_add_uint, overflowing_add_int,
|
||||
};
|
||||
|
||||
@(default_calling_convention="none")
|
||||
foreign {
|
||||
@(link_name="llvm.usub.with.overflow.i8") overflowing_sub_u8 :: proc(lhs, rhs: u8) -> (u8, bool) ---
|
||||
@(link_name="llvm.ssub.with.overflow.i8") overflowing_sub_i8 :: proc(lhs, rhs: i8) -> (i8, bool) ---
|
||||
@(link_name="llvm.usub.with.overflow.i16") overflowing_sub_u16 :: proc(lhs, rhs: u16) -> (u16, bool) ---
|
||||
@(link_name="llvm.ssub.with.overflow.i16") overflowing_sub_i16 :: proc(lhs, rhs: i16) -> (i16, bool) ---
|
||||
@(link_name="llvm.usub.with.overflow.i32") overflowing_sub_u32 :: proc(lhs, rhs: u32) -> (u32, bool) ---
|
||||
@(link_name="llvm.ssub.with.overflow.i32") overflowing_sub_i32 :: proc(lhs, rhs: i32) -> (i32, bool) ---
|
||||
@(link_name="llvm.usub.with.overflow.i64") overflowing_sub_u64 :: proc(lhs, rhs: u64) -> (u64, bool) ---
|
||||
@(link_name="llvm.ssub.with.overflow.i64") overflowing_sub_i64 :: proc(lhs, rhs: i64) -> (i64, bool) ---
|
||||
}
|
||||
overflowing_sub_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
when size_of(uint) == size_of(u32) {
|
||||
x, ok := overflowing_sub_u32(u32(lhs), u32(rhs));
|
||||
return uint(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_sub_u64(u64(lhs), u64(rhs));
|
||||
return uint(x), ok;
|
||||
}
|
||||
}
|
||||
overflowing_sub_int :: proc(lhs, rhs: int) -> (int, bool) {
|
||||
when size_of(int) == size_of(i32) {
|
||||
x, ok := overflowing_sub_i32(i32(lhs), i32(rhs));
|
||||
return int(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_sub_i64(i64(lhs), i64(rhs));
|
||||
return int(x), ok;
|
||||
}
|
||||
}
|
||||
|
||||
overflowing_sub :: proc{
|
||||
overflowing_sub_u8, overflowing_sub_i8,
|
||||
overflowing_sub_u16, overflowing_sub_i16,
|
||||
overflowing_sub_u32, overflowing_sub_i32,
|
||||
overflowing_sub_u64, overflowing_sub_i64,
|
||||
overflowing_sub_uint, overflowing_sub_int,
|
||||
};
|
||||
|
||||
@(default_calling_convention="none")
|
||||
foreign {
|
||||
@(link_name="llvm.umul.with.overflow.i8") overflowing_mul_u8 :: proc(lhs, rhs: u8) -> (u8, bool) ---
|
||||
@(link_name="llvm.smul.with.overflow.i8") overflowing_mul_i8 :: proc(lhs, rhs: i8) -> (i8, bool) ---
|
||||
@(link_name="llvm.umul.with.overflow.i16") overflowing_mul_u16 :: proc(lhs, rhs: u16) -> (u16, bool) ---
|
||||
@(link_name="llvm.smul.with.overflow.i16") overflowing_mul_i16 :: proc(lhs, rhs: i16) -> (i16, bool) ---
|
||||
@(link_name="llvm.umul.with.overflow.i32") overflowing_mul_u32 :: proc(lhs, rhs: u32) -> (u32, bool) ---
|
||||
@(link_name="llvm.smul.with.overflow.i32") overflowing_mul_i32 :: proc(lhs, rhs: i32) -> (i32, bool) ---
|
||||
@(link_name="llvm.umul.with.overflow.i64") overflowing_mul_u64 :: proc(lhs, rhs: u64) -> (u64, bool) ---
|
||||
@(link_name="llvm.smul.with.overflow.i64") overflowing_mul_i64 :: proc(lhs, rhs: i64) -> (i64, bool) ---
|
||||
}
|
||||
overflowing_mul_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
when size_of(uint) == size_of(u32) {
|
||||
x, ok := overflowing_mul_u32(u32(lhs), u32(rhs));
|
||||
return uint(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_mul_u64(u64(lhs), u64(rhs));
|
||||
return uint(x), ok;
|
||||
}
|
||||
}
|
||||
overflowing_mul_int :: proc(lhs, rhs: int) -> (int, bool) {
|
||||
when size_of(int) == size_of(i32) {
|
||||
x, ok := overflowing_mul_i32(i32(lhs), i32(rhs));
|
||||
return int(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_mul_i64(i64(lhs), i64(rhs));
|
||||
return int(x), ok;
|
||||
}
|
||||
}
|
||||
|
||||
overflowing_mul :: proc{
|
||||
overflowing_mul_u8, overflowing_mul_i8,
|
||||
overflowing_mul_u16, overflowing_mul_i16,
|
||||
overflowing_mul_u32, overflowing_mul_i32,
|
||||
overflowing_mul_u64, overflowing_mul_i64,
|
||||
overflowing_mul_uint, overflowing_mul_int,
|
||||
};
|
||||
overflowing_add :: intrinsics.overflow_add;
|
||||
overflowing_sub :: intrinsics.overflow_sub;
|
||||
overflowing_mul :: intrinsics.overflow_mul;
|
||||
|
||||
|
||||
len_u8 :: proc(x: u8) -> int {
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
//
|
||||
package runtime
|
||||
|
||||
import "intrinsics"
|
||||
|
||||
// NOTE(bill): This must match the compiler's
|
||||
Calling_Convention :: enum u8 {
|
||||
Invalid = 0,
|
||||
@@ -430,17 +432,9 @@ typeid_base_without_enum :: typeid_core;
|
||||
|
||||
|
||||
|
||||
@(default_calling_convention = "none")
|
||||
foreign {
|
||||
@(link_name="llvm.debugtrap")
|
||||
debug_trap :: proc() ---;
|
||||
|
||||
@(link_name="llvm.trap")
|
||||
trap :: proc() -> ! ---;
|
||||
|
||||
@(link_name="llvm.readcyclecounter")
|
||||
read_cycle_counter :: proc() -> u64 ---;
|
||||
}
|
||||
debug_trap :: intrinsics.debug_trap;
|
||||
trap :: intrinsics.trap;
|
||||
read_cycle_counter :: intrinsics.read_cycle_counter;
|
||||
|
||||
|
||||
|
||||
@@ -488,7 +482,6 @@ __init_context :: proc "contextless" (c: ^Context) {
|
||||
c.logger.data = nil;
|
||||
}
|
||||
|
||||
|
||||
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) {
|
||||
print_caller_location(loc);
|
||||
print_string(" ");
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package runtime
|
||||
|
||||
import "intrinsics"
|
||||
|
||||
@builtin
|
||||
Maybe :: union(T: typeid) #maybe {T};
|
||||
|
||||
@@ -539,20 +541,15 @@ excl_bit_set :: proc(s: ^$S/bit_set[$E; $U], other: S) {
|
||||
@builtin
|
||||
card :: proc(s: $S/bit_set[$E; $U]) -> int {
|
||||
when size_of(S) == 1 {
|
||||
foreign { @(link_name="llvm.ctpop.i8") count_ones :: proc(i: u8) -> u8 --- }
|
||||
return int(count_ones(transmute(u8)s));
|
||||
return int(intrinsics.count_ones(transmute(u8)s));
|
||||
} else when size_of(S) == 2 {
|
||||
foreign { @(link_name="llvm.ctpop.i16") count_ones :: proc(i: u16) -> u16 --- }
|
||||
return int(count_ones(transmute(u16)s));
|
||||
return int(intrinsics.count_ones(transmute(u16)s));
|
||||
} else when size_of(S) == 4 {
|
||||
foreign { @(link_name="llvm.ctpop.i32") count_ones :: proc(i: u32) -> u32 --- }
|
||||
return int(count_ones(transmute(u32)s));
|
||||
return int(intrinsics.count_ones(transmute(u32)s));
|
||||
} else when size_of(S) == 8 {
|
||||
foreign { @(link_name="llvm.ctpop.i64") count_ones :: proc(i: u64) -> u64 --- }
|
||||
return int(count_ones(transmute(u64)s));
|
||||
return int(intrinsics.count_ones(transmute(u64)s));
|
||||
} else when size_of(S) == 16 {
|
||||
foreign { @(link_name="llvm.ctpop.i128") count_ones :: proc(i: u128) -> u128 --- }
|
||||
return int(count_ones(transmute(u128)s));
|
||||
return int(intrinsics.count_ones(transmute(u128)s));
|
||||
} else {
|
||||
#panic("Unhandled card bit_set size");
|
||||
}
|
||||
|
||||
@@ -415,59 +415,32 @@ foreign {
|
||||
@(link_name="llvm.sqrt.f64") _sqrt_f64 :: proc(x: f64) -> f64 ---
|
||||
}
|
||||
abs_f16 :: #force_inline proc "contextless" (x: f16) -> f16 {
|
||||
foreign {
|
||||
@(link_name="llvm.fabs.f16") _abs :: proc "none" (x: f16) -> f16 ---
|
||||
}
|
||||
return _abs(x);
|
||||
return -x if x < 0 else x;
|
||||
}
|
||||
abs_f32 :: #force_inline proc "contextless" (x: f32) -> f32 {
|
||||
foreign {
|
||||
@(link_name="llvm.fabs.f32") _abs :: proc "none" (x: f32) -> f32 ---
|
||||
}
|
||||
return _abs(x);
|
||||
return -x if x < 0 else x;
|
||||
}
|
||||
abs_f64 :: #force_inline proc "contextless" (x: f64) -> f64 {
|
||||
foreign {
|
||||
@(link_name="llvm.fabs.f64") _abs :: proc "none" (x: f64) -> f64 ---
|
||||
}
|
||||
return _abs(x);
|
||||
return -x if x < 0 else x;
|
||||
}
|
||||
|
||||
min_f16 :: proc(a, b: f16) -> f16 {
|
||||
foreign {
|
||||
@(link_name="llvm.minnum.f16") _min :: proc "none" (a, b: f16) -> f16 ---
|
||||
}
|
||||
return _min(a, b);
|
||||
return a if a < b else b;
|
||||
}
|
||||
min_f32 :: proc(a, b: f32) -> f32 {
|
||||
foreign {
|
||||
@(link_name="llvm.minnum.f32") _min :: proc "none" (a, b: f32) -> f32 ---
|
||||
}
|
||||
return _min(a, b);
|
||||
return a if a < b else b;
|
||||
}
|
||||
min_f64 :: proc(a, b: f64) -> f64 {
|
||||
foreign {
|
||||
@(link_name="llvm.minnum.f64") _min :: proc "none" (a, b: f64) -> f64 ---
|
||||
}
|
||||
return _min(a, b);
|
||||
return a if a < b else b;
|
||||
}
|
||||
max_f16 :: proc(a, b: f16) -> f16 {
|
||||
foreign {
|
||||
@(link_name="llvm.maxnum.f16") _max :: proc "none" (a, b: f16) -> f16 ---
|
||||
}
|
||||
return _max(a, b);
|
||||
return a if a > b else b;
|
||||
}
|
||||
max_f32 :: proc(a, b: f32) -> f32 {
|
||||
foreign {
|
||||
@(link_name="llvm.maxnum.f32") _max :: proc "none" (a, b: f32) -> f32 ---
|
||||
}
|
||||
return _max(a, b);
|
||||
return a if a > b else b;
|
||||
}
|
||||
max_f64 :: proc(a, b: f64) -> f64 {
|
||||
foreign {
|
||||
@(link_name="llvm.maxnum.f64") _max :: proc "none" (a, b: f64) -> f64 ---
|
||||
}
|
||||
return _max(a, b);
|
||||
return a if a > b else b;
|
||||
}
|
||||
|
||||
abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package runtime
|
||||
|
||||
import "intrinsics"
|
||||
|
||||
@(link_name="__umodti3")
|
||||
umodti3 :: proc "c" (a, b: u128) -> u128 {
|
||||
r: u128 = ---;
|
||||
@@ -86,12 +88,6 @@ fixdfti :: proc(a: u64) -> i128 {
|
||||
|
||||
}
|
||||
|
||||
@(default_calling_convention = "none")
|
||||
foreign {
|
||||
@(link_name="llvm.ctlz.i128") _clz_i128 :: proc(x: i128, is_zero_undef := false) -> i128 ---
|
||||
}
|
||||
|
||||
|
||||
@(link_name="__floattidf")
|
||||
floattidf :: proc(a: i128) -> f64 {
|
||||
DBL_MANT_DIG :: 53;
|
||||
@@ -102,7 +98,7 @@ floattidf :: proc(a: i128) -> f64 {
|
||||
N :: size_of(i128) * 8;
|
||||
s := a >> (N-1);
|
||||
a = (a ~ s) - s;
|
||||
sd: = N - _clz_i128(a); // number of significant digits
|
||||
sd: = N - intrinsics.leading_zeros(a); // number of significant digits
|
||||
e := u32(sd - 1); // exponent
|
||||
if sd > DBL_MANT_DIG {
|
||||
switch sd {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package runtime
|
||||
|
||||
import "intrinsics"
|
||||
|
||||
@(link_name="__umodti3")
|
||||
umodti3 :: proc "c" (a, b: u128) -> u128 {
|
||||
r: u128 = ---;
|
||||
@@ -86,12 +88,6 @@ fixdfti :: proc(a: u64) -> i128 {
|
||||
|
||||
}
|
||||
|
||||
@(default_calling_convention = "none")
|
||||
foreign {
|
||||
@(link_name="llvm.ctlz.i128") _clz_i128 :: proc(x: i128, is_zero_undef := false) -> i128 ---
|
||||
}
|
||||
|
||||
|
||||
@(link_name="__floattidf")
|
||||
floattidf :: proc(a: i128) -> f64 {
|
||||
DBL_MANT_DIG :: 53;
|
||||
@@ -102,7 +98,7 @@ floattidf :: proc(a: i128) -> f64 {
|
||||
N :: size_of(i128) * 8;
|
||||
s := a >> (N-1);
|
||||
a = (a ~ s) - s;
|
||||
sd: = N - _clz_i128(a); // number of significant digits
|
||||
sd: = N - intrinsics.leading_zeros((a); // number of significant digits
|
||||
e := u32(sd - 1); // exponent
|
||||
if sd > DBL_MANT_DIG {
|
||||
switch sd {
|
||||
|
||||
@@ -1,35 +1,11 @@
|
||||
package runtime
|
||||
|
||||
@(default_calling_convention="none")
|
||||
foreign {
|
||||
@(link_name="llvm.cttz.i8") _ctz_u8 :: proc(i: u8, is_zero_undef := false) -> u8 ---
|
||||
@(link_name="llvm.cttz.i16") _ctz_u16 :: proc(i: u16, is_zero_undef := false) -> u16 ---
|
||||
@(link_name="llvm.cttz.i32") _ctz_u32 :: proc(i: u32, is_zero_undef := false) -> u32 ---
|
||||
@(link_name="llvm.cttz.i64") _ctz_u64 :: proc(i: u64, is_zero_undef := false) -> u64 ---
|
||||
}
|
||||
_ctz :: proc{
|
||||
_ctz_u8,
|
||||
_ctz_u16,
|
||||
_ctz_u32,
|
||||
_ctz_u64,
|
||||
};
|
||||
|
||||
@(default_calling_convention="none")
|
||||
foreign {
|
||||
@(link_name="llvm.ctlz.i8") _clz_u8 :: proc(i: u8, is_zero_undef := false) -> u8 ---
|
||||
@(link_name="llvm.ctlz.i16") _clz_u16 :: proc(i: u16, is_zero_undef := false) -> u16 ---
|
||||
@(link_name="llvm.ctlz.i32") _clz_u32 :: proc(i: u32, is_zero_undef := false) -> u32 ---
|
||||
@(link_name="llvm.ctlz.i64") _clz_u64 :: proc(i: u64, is_zero_undef := false) -> u64 ---
|
||||
}
|
||||
_clz :: proc{
|
||||
_clz_u8,
|
||||
_clz_u16,
|
||||
_clz_u32,
|
||||
_clz_u64,
|
||||
};
|
||||
|
||||
import "intrinsics"
|
||||
|
||||
udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
|
||||
_ctz :: intrinsics.trailing_zeros;
|
||||
_clz :: intrinsics.leading_zeros;
|
||||
|
||||
n := transmute([2]u64)a;
|
||||
d := transmute([2]u64)b;
|
||||
q, r: [2]u64 = ---, ---;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package time
|
||||
|
||||
import "intrinsics"
|
||||
|
||||
Duration :: distinct i64;
|
||||
|
||||
Nanosecond :: Duration(1);
|
||||
@@ -137,11 +139,7 @@ clock :: proc(t: Time) -> (hour, min, sec: int) {
|
||||
|
||||
|
||||
read_cycle_counter :: proc() -> u64 {
|
||||
foreign _ {
|
||||
@(link_name="llvm.readcyclecounter")
|
||||
llvm_readcyclecounter :: proc "none" () -> u64 ---
|
||||
}
|
||||
return llvm_readcyclecounter();
|
||||
return u64(intrinsics.read_cycle_counter());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1924,6 +1924,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
|
||||
case BuiltinProc_count_ones:
|
||||
case BuiltinProc_trailing_zeros:
|
||||
case BuiltinProc_leading_zeros:
|
||||
case BuiltinProc_reverse_bits:
|
||||
{
|
||||
Operand x = {};
|
||||
|
||||
@@ -47,6 +47,7 @@ enum BuiltinProcId {
|
||||
|
||||
BuiltinProc_count_ones,
|
||||
BuiltinProc_trailing_zeros,
|
||||
BuiltinProc_leading_zeros,
|
||||
BuiltinProc_reverse_bits,
|
||||
BuiltinProc_byte_swap,
|
||||
|
||||
@@ -265,6 +266,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
|
||||
{STR_LIT("count_ones"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("trailing_zeros"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("leading_zeros"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("reverse_bits"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("byte_swap"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
|
||||
@@ -9108,6 +9108,8 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
|
||||
|
||||
case BuiltinProc_trailing_zeros:
|
||||
return lb_emit_trailing_zeros(p, lb_build_expr(p, ce->args[0]), tv.type);
|
||||
case BuiltinProc_leading_zeros:
|
||||
return lb_emit_leading_zeros(p, lb_build_expr(p, ce->args[0]), tv.type);
|
||||
|
||||
case BuiltinProc_count_ones:
|
||||
return lb_emit_count_ones(p, lb_build_expr(p, ce->args[0]), tv.type);
|
||||
@@ -9989,6 +9991,26 @@ lbValue lb_emit_trailing_zeros(lbProcedure *p, lbValue x, Type *type) {
|
||||
return res;
|
||||
}
|
||||
|
||||
lbValue lb_emit_leading_zeros(lbProcedure *p, lbValue x, Type *type) {
|
||||
x = lb_emit_conv(p, x, type);
|
||||
|
||||
char const *name = "llvm.ctlz";
|
||||
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[2] = {};
|
||||
args[0] = x.value;
|
||||
args[1] = LLVMConstNull(LLVMInt1TypeInContext(p->module->ctx));
|
||||
|
||||
lbValue res = {};
|
||||
res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
|
||||
res.type = type;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
lbValue lb_emit_reverse_bits(lbProcedure *p, lbValue x, Type *type) {
|
||||
x = lb_emit_conv(p, x, type);
|
||||
|
||||
@@ -396,6 +396,7 @@ LLVMMetadataRef lb_debug_type(lbModule *m, Type *type);
|
||||
|
||||
lbValue lb_emit_count_ones(lbProcedure *p, lbValue x, Type *type);
|
||||
lbValue lb_emit_trailing_zeros(lbProcedure *p, lbValue x, Type *type);
|
||||
lbValue lb_emit_leading_zeros(lbProcedure *p, lbValue x, Type *type);
|
||||
lbValue lb_emit_reverse_bits(lbProcedure *p, lbValue x, Type *type);
|
||||
|
||||
lbValue lb_emit_bit_set_card(lbProcedure *p, lbValue x);
|
||||
|
||||
Reference in New Issue
Block a user