mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 06:38:47 +00:00
Add runtime.bswap_* required for -llvm-api
This commit is contained in:
+42
-25
@@ -1,6 +1,6 @@
|
|||||||
package math_bits
|
package math_bits
|
||||||
|
|
||||||
import "core:os"
|
import "core:runtime"
|
||||||
|
|
||||||
U8_MIN :: 0;
|
U8_MIN :: 0;
|
||||||
U16_MIN :: 0;
|
U16_MIN :: 0;
|
||||||
@@ -43,15 +43,32 @@ foreign {
|
|||||||
@(link_name="llvm.bitreverse.i16") reverse_bits16 :: proc(i: u16) -> u16 ---
|
@(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.i32") reverse_bits32 :: proc(i: u32) -> u32 ---
|
||||||
@(link_name="llvm.bitreverse.i64") reverse_bits64 :: proc(i: u64) -> u64 ---
|
@(link_name="llvm.bitreverse.i64") reverse_bits64 :: proc(i: u64) -> u64 ---
|
||||||
|
}
|
||||||
|
|
||||||
@(link_name="llvm.bswap.i16") byte_swap_u16 :: proc(u16) -> u16 ---
|
|
||||||
@(link_name="llvm.bswap.i32") byte_swap_u32 :: proc(u32) -> u32 ---
|
byte_swap_u16 :: proc(x: u16) -> u16 {
|
||||||
@(link_name="llvm.bswap.i64") byte_swap_u64 :: proc(u64) -> u64 ---
|
return u16(runtime.bswap_16(u16(x)));
|
||||||
@(link_name="llvm.bswap.i16") byte_swap_i16 :: proc(i16) -> i16 ---
|
}
|
||||||
@(link_name="llvm.bswap.i32") byte_swap_i32 :: proc(i32) -> i32 ---
|
byte_swap_u32 :: proc(x: u32) -> u32 {
|
||||||
@(link_name="llvm.bswap.i64") byte_swap_i64 :: proc(i64) -> i64 ---
|
return u32(runtime.bswap_32(u32(x)));
|
||||||
@(link_name="llvm.bswap.i128") byte_swap_u128 :: proc(u128) -> u128 ---
|
}
|
||||||
@(link_name="llvm.bswap.i128") byte_swap_i128 :: proc(i128) -> i128 ---
|
byte_swap_u64 :: proc(x: u64) -> u64 {
|
||||||
|
return u64(runtime.bswap_64(u64(x)));
|
||||||
|
}
|
||||||
|
byte_swap_i16 :: proc(x: i16) -> i16 {
|
||||||
|
return i16(runtime.bswap_16(u16(x)));
|
||||||
|
}
|
||||||
|
byte_swap_i32 :: proc(x: i32) -> i32 {
|
||||||
|
return i32(runtime.bswap_32(u32(x)));
|
||||||
|
}
|
||||||
|
byte_swap_i64 :: proc(x: i64) -> i64 {
|
||||||
|
return i64(runtime.bswap_64(u64(x)));
|
||||||
|
}
|
||||||
|
byte_swap_u128 :: proc(x: u128) -> u128 {
|
||||||
|
return u128(runtime.bswap_128(u128(x)));
|
||||||
|
}
|
||||||
|
byte_swap_i128 :: proc(x: i128) -> i128 {
|
||||||
|
return i128(runtime.bswap_128(u128(x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_swap_uint :: proc(i: uint) -> uint {
|
byte_swap_uint :: proc(i: uint) -> uint {
|
||||||
@@ -100,29 +117,29 @@ rotate_right32 :: proc(i: u32, s: uint) -> u32 { return (i >> s)|(i << (8*siz
|
|||||||
rotate_right64 :: proc(i: u64, s: uint) -> u64 { return (i >> s)|(i << (8*size_of(u64) - s)); }
|
rotate_right64 :: proc(i: u64, s: uint) -> u64 { return (i >> s)|(i << (8*size_of(u64) - s)); }
|
||||||
|
|
||||||
from_be_u8 :: proc(i: u8) -> u8 { return i; }
|
from_be_u8 :: proc(i: u8) -> u8 { return i; }
|
||||||
from_be_u16 :: proc(i: u16) -> u16 { when os.ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
from_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||||
from_be_u32 :: proc(i: u32) -> u32 { when os.ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
from_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||||
from_be_u64 :: proc(i: u64) -> u64 { when os.ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
from_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||||
from_be_uint :: proc(i: uint) -> uint { when os.ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
from_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||||
|
|
||||||
from_le_u8 :: proc(i: u8) -> u8 { return i; }
|
from_le_u8 :: proc(i: u8) -> u8 { return i; }
|
||||||
from_le_u16 :: proc(i: u16) -> u16 { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
from_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||||
from_le_u32 :: proc(i: u32) -> u32 { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
from_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||||
from_le_u64 :: proc(i: u64) -> u64 { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
from_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||||
from_le_uint :: proc(i: uint) -> uint { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
from_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||||
|
|
||||||
to_be_u8 :: proc(i: u8) -> u8 { return i; }
|
to_be_u8 :: proc(i: u8) -> u8 { return i; }
|
||||||
to_be_u16 :: proc(i: u16) -> u16 { when os.ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
to_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||||
to_be_u32 :: proc(i: u32) -> u32 { when os.ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
to_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||||
to_be_u64 :: proc(i: u64) -> u64 { when os.ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
to_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||||
to_be_uint :: proc(i: uint) -> uint { when os.ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
to_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||||
|
|
||||||
|
|
||||||
to_le_u8 :: proc(i: u8) -> u8 { return i; }
|
to_le_u8 :: proc(i: u8) -> u8 { return i; }
|
||||||
to_le_u16 :: proc(i: u16) -> u16 { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
to_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||||
to_le_u32 :: proc(i: u32) -> u32 { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
to_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||||
to_le_u64 :: proc(i: u64) -> u64 { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
to_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||||
to_le_uint :: proc(i: uint) -> uint { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||||
|
|
||||||
|
|
||||||
@(default_calling_convention="none")
|
@(default_calling_convention="none")
|
||||||
|
|||||||
@@ -2,15 +2,6 @@ package mem
|
|||||||
|
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
|
|
||||||
foreign _ {
|
|
||||||
@(link_name = "llvm.bswap.i16") swap16 :: proc(b: u16) -> u16 ---;
|
|
||||||
@(link_name = "llvm.bswap.i32") swap32 :: proc(b: u32) -> u32 ---;
|
|
||||||
@(link_name = "llvm.bswap.i64") swap64 :: proc(b: u64) -> u64 ---;
|
|
||||||
}
|
|
||||||
swap :: proc{swap16, swap32, swap64};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
set :: proc "contextless" (data: rawptr, value: byte, len: int) -> rawptr {
|
set :: proc "contextless" (data: rawptr, value: byte, len: int) -> rawptr {
|
||||||
foreign _ {
|
foreign _ {
|
||||||
when ODIN_USE_LLVM_API {
|
when ODIN_USE_LLVM_API {
|
||||||
|
|||||||
@@ -2,6 +2,22 @@ package runtime
|
|||||||
|
|
||||||
import "core:os"
|
import "core:os"
|
||||||
|
|
||||||
|
bswap_16 :: proc "none" (x: u16) -> u16 {
|
||||||
|
return x>>8 | x<<16;
|
||||||
|
}
|
||||||
|
|
||||||
|
bswap_32 :: proc "none" (x: u32) -> u32 {
|
||||||
|
return x>>24 | (x>>8)&0xff00 | (x<<8)&0xff0000 | x<<24;
|
||||||
|
}
|
||||||
|
|
||||||
|
bswap_64 :: proc "none" (x: u64) -> u64 {
|
||||||
|
return u64(bswap_32(u32(x))) | u64(bswap_32(u32(x>>32)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bswap_128 :: proc "none" (x: u128) -> u128 {
|
||||||
|
return u128(bswap_64(u64(x))) | u128(bswap_64(u64(x>>64)));
|
||||||
|
}
|
||||||
|
|
||||||
ptr_offset :: inline proc "contextless" (ptr: $P/^$T, n: int) -> P {
|
ptr_offset :: inline proc "contextless" (ptr: $P/^$T, n: int) -> P {
|
||||||
new := int(uintptr(ptr)) + size_of(T)*n;
|
new := int(uintptr(ptr)) + size_of(T)*n;
|
||||||
return P(uintptr(new));
|
return P(uintptr(new));
|
||||||
|
|||||||
@@ -1703,6 +1703,11 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
|||||||
|
|
||||||
str_lit("memory_compare"),
|
str_lit("memory_compare"),
|
||||||
str_lit("memory_compare_zero"),
|
str_lit("memory_compare_zero"),
|
||||||
|
|
||||||
|
str_lit("bswap_16"),
|
||||||
|
str_lit("bswap_32"),
|
||||||
|
str_lit("bswap_64"),
|
||||||
|
str_lit("bswap_128"),
|
||||||
};
|
};
|
||||||
for (isize i = 0; i < gb_count_of(required_runtime_entities); i++) {
|
for (isize i = 0; i < gb_count_of(required_runtime_entities); i++) {
|
||||||
add_dependency_to_set(c, scope_lookup(c->info.runtime_package->scope, required_runtime_entities[i]));
|
add_dependency_to_set(c, scope_lookup(c->info.runtime_package->scope, required_runtime_entities[i]));
|
||||||
|
|||||||
+43
-24
@@ -7783,6 +7783,23 @@ void lb_emit_increment(lbProcedure *p, lbValue addr) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLVMValueRef lb_lookup_runtime_procedure(lbModule *m, String const &name) {
|
||||||
|
AstPackage *pkg = m->info->runtime_package;
|
||||||
|
Entity *e = scope_lookup_current(pkg->scope, name);
|
||||||
|
|
||||||
|
lbValue *found = nullptr;
|
||||||
|
if (m != e->code_gen_module) {
|
||||||
|
gb_mutex_lock(&m->mutex);
|
||||||
|
}
|
||||||
|
found = map_get(&e->code_gen_module->values, hash_entity(e));
|
||||||
|
if (m != e->code_gen_module) {
|
||||||
|
gb_mutex_unlock(&m->mutex);
|
||||||
|
}
|
||||||
|
GB_ASSERT(found != nullptr);
|
||||||
|
|
||||||
|
return found->value;
|
||||||
|
}
|
||||||
|
|
||||||
lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) {
|
lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) {
|
||||||
Type *vt = core_type(value.type);
|
Type *vt = core_type(value.type);
|
||||||
GB_ASSERT(type_size_of(vt) == type_size_of(platform_type));
|
GB_ASSERT(type_size_of(vt) == type_size_of(platform_type));
|
||||||
@@ -7793,21 +7810,20 @@ lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) {
|
|||||||
res.type = platform_type;
|
res.type = platform_type;
|
||||||
res.value = value.value;
|
res.value = value.value;
|
||||||
|
|
||||||
// int sz = cast(int)type_size_of(vt);
|
int sz = cast(int)type_size_of(vt);
|
||||||
// if (sz > 1) {
|
if (sz > 1) {
|
||||||
// char buf[32] = {};
|
String name = {};
|
||||||
// gb_snprintf(buf, gb_count_of(buf), "llvm.bswap.i%d", sz*8);
|
switch (sz) {
|
||||||
// unsigned id = LLVMLookupIntrinsicID(buf, gb_strlen(buf));
|
case 2: name = str_lit("bswap_16"); break;
|
||||||
// gb_printf(">>> %s %u\n", buf, id);
|
case 4: name = str_lit("bswap_32"); break;
|
||||||
|
case 8: name = str_lit("bswap_64"); break;
|
||||||
|
case 16: name = str_lit("bswap_128"); break;
|
||||||
|
default: GB_PANIC("unhandled byteswap size"); break;
|
||||||
|
}
|
||||||
|
LLVMValueRef fn = lb_lookup_runtime_procedure(p->module, name);
|
||||||
|
|
||||||
// LLVMTypeRef types[2] = {};
|
res.value = LLVMBuildCall(p->builder, fn, &value.value, 1, "");
|
||||||
// types[0] = lb_type(p->module, value.type);
|
}
|
||||||
// types[1] = lb_type(p->module, value.type);
|
|
||||||
|
|
||||||
// LLVMValueRef fn = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
|
|
||||||
|
|
||||||
// res.value = LLVMBuildCall(p->builder, fn, &value.value, 1, "");
|
|
||||||
// }
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -7972,8 +7988,8 @@ lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x) {
|
|||||||
|
|
||||||
|
|
||||||
lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right) {
|
lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right) {
|
||||||
Type *a = base_type(left.type);
|
Type *a = core_type(left.type);
|
||||||
Type *b = base_type(right.type);
|
Type *b = core_type(right.type);
|
||||||
|
|
||||||
GB_ASSERT(gb_is_between(op_kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1));
|
GB_ASSERT(gb_is_between(op_kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1));
|
||||||
|
|
||||||
@@ -8235,14 +8251,17 @@ lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue ri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a = core_type(left.type);
|
||||||
|
b = core_type(right.type);
|
||||||
|
|
||||||
|
|
||||||
lbValue res = {};
|
lbValue res = {};
|
||||||
res.type = t_llvm_bool;
|
res.type = t_llvm_bool;
|
||||||
if (is_type_integer(left.type) ||
|
if (is_type_integer(a) ||
|
||||||
is_type_boolean(left.type) ||
|
is_type_boolean(a) ||
|
||||||
is_type_pointer(left.type) ||
|
is_type_pointer(a) ||
|
||||||
is_type_proc(left.type) ||
|
is_type_proc(a) ||
|
||||||
is_type_enum(left.type)) {
|
is_type_enum(a)) {
|
||||||
LLVMIntPredicate pred = {};
|
LLVMIntPredicate pred = {};
|
||||||
if (is_type_unsigned(left.type)) {
|
if (is_type_unsigned(left.type)) {
|
||||||
switch (op_kind) {
|
switch (op_kind) {
|
||||||
@@ -8264,7 +8283,7 @@ lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue ri
|
|||||||
case Token_NotEq: pred = LLVMIntNE; break;
|
case Token_NotEq: pred = LLVMIntNE; break;
|
||||||
}
|
}
|
||||||
res.value = LLVMBuildICmp(p->builder, pred, left.value, right.value, "");
|
res.value = LLVMBuildICmp(p->builder, pred, left.value, right.value, "");
|
||||||
} else if (is_type_float(left.type)) {
|
} else if (is_type_float(a)) {
|
||||||
LLVMRealPredicate pred = {};
|
LLVMRealPredicate pred = {};
|
||||||
switch (op_kind) {
|
switch (op_kind) {
|
||||||
case Token_CmpEq: pred = LLVMRealOEQ; break;
|
case Token_CmpEq: pred = LLVMRealOEQ; break;
|
||||||
@@ -8275,7 +8294,7 @@ lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue ri
|
|||||||
case Token_NotEq: pred = LLVMRealONE; break;
|
case Token_NotEq: pred = LLVMRealONE; break;
|
||||||
}
|
}
|
||||||
res.value = LLVMBuildFCmp(p->builder, pred, left.value, right.value, "");
|
res.value = LLVMBuildFCmp(p->builder, pred, left.value, right.value, "");
|
||||||
} else if (is_type_typeid(left.type)) {
|
} else if (is_type_typeid(a)) {
|
||||||
LLVMIntPredicate pred = {};
|
LLVMIntPredicate pred = {};
|
||||||
switch (op_kind) {
|
switch (op_kind) {
|
||||||
case Token_Gt: pred = LLVMIntUGT; break;
|
case Token_Gt: pred = LLVMIntUGT; break;
|
||||||
@@ -8287,7 +8306,7 @@ lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue ri
|
|||||||
}
|
}
|
||||||
res.value = LLVMBuildICmp(p->builder, pred, left.value, right.value, "");
|
res.value = LLVMBuildICmp(p->builder, pred, left.value, right.value, "");
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("Unhandled comparison kind %s %.*s %s", type_to_string(left.type), LIT(token_strings[op_kind]), type_to_string(right.type));
|
GB_PANIC("Unhandled comparison kind %s (%s) %.*s %s (%s)", type_to_string(left.type), type_to_string(base_type(left.type)), LIT(token_strings[op_kind]), type_to_string(right.type), type_to_string(base_type(right.type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
Reference in New Issue
Block a user