mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
128 bit integers
Kind of works but may be buggy due to LLVM not actually sure
This commit is contained in:
+37
-5
@@ -4,16 +4,48 @@
|
||||
variadic :: proc(args: ..any) {
|
||||
for i := 0; i < args.count; i++ {
|
||||
match type a : args[i] {
|
||||
case int: fmt.println("int", a)
|
||||
case f32: fmt.println("f32", a)
|
||||
case f64: fmt.println("f64", a)
|
||||
case string: fmt.println("string", a)
|
||||
case u128: fmt.println("u128", a)
|
||||
case i128: fmt.println("i128", a)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.println(..args)
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
fmt.println("Hellope, everybody!")
|
||||
|
||||
variadic(1, 1.0 as f32, 1.0 as f64, "Hellope")
|
||||
|
||||
|
||||
variadic(1 as u128,
|
||||
1 as i128,
|
||||
)
|
||||
|
||||
x: i128 = 321312321
|
||||
y: i128 = 123123123
|
||||
z: i128
|
||||
x *= x; x *= x
|
||||
y *= y; y *= y
|
||||
fmt.println("x =", x)
|
||||
fmt.println("y =", y)
|
||||
z = x + y; fmt.println("x + y", z)
|
||||
z = x - y; fmt.println("x - y", z)
|
||||
z = x * y; fmt.println("x * y", z)
|
||||
z = x / y; fmt.println("x / y", z)
|
||||
z = x % y; fmt.println("x % y", z)
|
||||
z = x & y; fmt.println("x & y", z)
|
||||
z = x ~ y; fmt.println("x ~ y", z)
|
||||
z = x | y; fmt.println("x | y", z)
|
||||
z = x &~ y; fmt.println("x &~ y", z)
|
||||
|
||||
z = -x
|
||||
z = ~x
|
||||
|
||||
b: bool
|
||||
b = x == y; fmt.println("x == y", b)
|
||||
b = x != y; fmt.println("x != y", b)
|
||||
b = x < y; fmt.println("x < y", b)
|
||||
b = x <= y; fmt.println("x <= y", b)
|
||||
b = x > y; fmt.println("x > y", b)
|
||||
b = x >= y; fmt.println("x >= y", b)
|
||||
}
|
||||
|
||||
+2
-1
@@ -131,7 +131,6 @@ fmuladd64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
|
||||
|
||||
|
||||
|
||||
|
||||
Allocator :: struct #ordered {
|
||||
Mode :: enum {
|
||||
ALLOC,
|
||||
@@ -364,3 +363,5 @@ __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
#shared_global_scope
|
||||
|
||||
#import "fmt.odin"
|
||||
|
||||
|
||||
__u128_mod :: proc(a, b: u128) -> u128 #link_name "__umodti3" {
|
||||
_, r := __u128_quo_mod(a, b)
|
||||
return r
|
||||
}
|
||||
|
||||
__u128_quo :: proc(a, b: u128) -> u128 #link_name "__udivti3" {
|
||||
n, _ := __u128_quo_mod(a, b)
|
||||
return n
|
||||
}
|
||||
|
||||
__i128_mod :: proc(a, b: i128) -> i128 #link_name "__modti3" {
|
||||
_, r := __i128_quo_mod(a, b)
|
||||
return r
|
||||
}
|
||||
|
||||
__i128_quo :: proc(a, b: i128) -> i128 #link_name "__divti3" {
|
||||
n, _ := __i128_quo_mod(a, b)
|
||||
return n
|
||||
}
|
||||
|
||||
__i128_quo_mod :: proc(a, b: i128) -> (i128, i128) #link_name "__divmodti4" {
|
||||
s := b >> 127
|
||||
b = (b ~ s) - s
|
||||
s = a >> 127
|
||||
a = (a ~ s) - s
|
||||
|
||||
n, r := __u128_quo_mod(a as u128, b as u128)
|
||||
return (n as i128 ~ s) - s, (r as i128 ~ s) - s
|
||||
}
|
||||
|
||||
|
||||
__u128_quo_mod :: proc(a, b: u128) -> (u128, u128) #link_name "__udivmodti4" {
|
||||
clz :: proc(x: u64) -> u64 {
|
||||
clz_u64 :: proc(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.ctlz.i64"
|
||||
return clz_u64(x, false)
|
||||
}
|
||||
ctz :: proc(x: u64) -> u64 {
|
||||
ctz_u64 :: proc(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.cttz.i64"
|
||||
return ctz_u64(x, false)
|
||||
}
|
||||
|
||||
|
||||
u128_lo_hi :: raw_union {
|
||||
all: u128
|
||||
using _lohi: struct {lo, hi: u64}
|
||||
}
|
||||
|
||||
n, d, q, r: u128_lo_hi
|
||||
sr: u64
|
||||
|
||||
n.all = a
|
||||
d.all = b
|
||||
|
||||
if n.hi == 0 {
|
||||
if d.hi == 0 {
|
||||
return (n.lo / d.lo) as u128, (n.lo % d.lo) as u128
|
||||
}
|
||||
return 0, n.lo as u128
|
||||
}
|
||||
if d.lo == 0 {
|
||||
if d.hi == 0 {
|
||||
return (n.hi / d.lo) as u128, (n.hi % d.lo) as u128
|
||||
}
|
||||
if n.lo == 0 {
|
||||
r.hi = n.hi % d.hi
|
||||
r.lo = 0
|
||||
return (n.hi / d.hi) as u128, r.all
|
||||
}
|
||||
if (d.hi & (d.hi-1)) == 0 {
|
||||
r.lo = n.lo
|
||||
r.hi = n.hi & (d.hi-1)
|
||||
return (n.hi >> ctz(d.hi)) as u128, r.all
|
||||
}
|
||||
|
||||
sr = clz(d.hi) - clz(n.hi)
|
||||
if sr > 64 - 2 {
|
||||
return 0, n.all
|
||||
}
|
||||
sr++
|
||||
q.lo = 0
|
||||
q.hi = n.lo << (64-sr)
|
||||
r.hi = n.hi >> sr
|
||||
r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
} else {
|
||||
if d.hi == 0 {
|
||||
if (d.lo & (d.lo - 1)) == 0 {
|
||||
rem := (n.lo % (d.lo - 1)) as u128
|
||||
if d.lo == 1 {
|
||||
return n.all, rem
|
||||
}
|
||||
sr = ctz(d.lo)
|
||||
q.hi = n.hi >> sr
|
||||
q.lo = (n.hi << (64-sr)) | (n.lo >> sr);
|
||||
return q.all, rem
|
||||
}
|
||||
|
||||
sr = 1 + 64 + clz(d.lo) - clz(n.hi)
|
||||
|
||||
q.all = n.all << (128-sr)
|
||||
r.all = n.all >> sr
|
||||
if sr == 64 {
|
||||
q.lo = 0
|
||||
q.hi = n.lo
|
||||
r.hi = 0
|
||||
r.lo = n.hi
|
||||
} else if sr < 64 {
|
||||
q.lo = 0
|
||||
q.hi = n.lo << (64-sr)
|
||||
r.hi = n.hi >> sr
|
||||
r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
} else {
|
||||
q.lo = n.lo << (128-sr)
|
||||
q.hi = (n.hi << (128-sr)) | (n.lo >> (sr-64))
|
||||
r.hi = 0
|
||||
r.lo = n.hi >> (sr-64)
|
||||
}
|
||||
} else {
|
||||
sr = clz(d.hi) - clz(n.hi)
|
||||
if sr > 64-1 {
|
||||
return 0, n.all
|
||||
}
|
||||
sr++
|
||||
q.lo = 0
|
||||
q.hi = n.lo << (64-sr)
|
||||
r.all = n.all >> sr
|
||||
if sr < 64 {
|
||||
r.hi = n.hi >> sr
|
||||
r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
} else {
|
||||
r.hi = 0
|
||||
r.lo = n.hi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
carry: u64
|
||||
for ; sr > 0; sr-- {
|
||||
r.hi = (r.hi << 1) | (r.lo >> (64-1))
|
||||
r.lo = (r.lo << 1) | (r.hi >> (64-1))
|
||||
q.hi = (q.hi << 1) | (q.lo >> (64-1))
|
||||
q.lo = (q.lo << 1) | carry
|
||||
|
||||
carry = 0
|
||||
if r.all >= d.all {
|
||||
r.all -= d.all
|
||||
carry = 1
|
||||
}
|
||||
}
|
||||
|
||||
q.all = (q.all << 1) | (carry as u128)
|
||||
return q.all, r.all
|
||||
}
|
||||
+65
-58
@@ -91,11 +91,12 @@ print_pointer_to_buffer :: proc(buffer: ^[]byte, p: rawptr) #inline {
|
||||
print_u64_to_buffer(buffer, p as uint as u64)
|
||||
}
|
||||
|
||||
print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) }
|
||||
print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f, 10) }
|
||||
print_f16_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 4) }
|
||||
print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) }
|
||||
print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f as f64, 16) }
|
||||
print_u64_to_buffer :: proc(buffer: ^[]byte, value: u64) {
|
||||
i := value
|
||||
buf: [22]byte
|
||||
buf: [20]byte
|
||||
len := 0
|
||||
if i == 0 {
|
||||
buf[len] = #rune "0"
|
||||
@@ -119,6 +120,25 @@ print_i64_to_buffer :: proc(buffer: ^[]byte, value: i64) {
|
||||
print_u64_to_buffer(buffer, i as u64)
|
||||
}
|
||||
|
||||
print_u128_to_buffer :: proc(buffer: ^[]byte, value: u128) {
|
||||
a := value transmute [2]u64
|
||||
if a[1] != 0 {
|
||||
print_u64_to_buffer(buffer, a[1])
|
||||
}
|
||||
print_u64_to_buffer(buffer, a[0])
|
||||
}
|
||||
print_i128_to_buffer :: proc(buffer: ^[]byte, value: i128) {
|
||||
i := value
|
||||
neg := i < 0
|
||||
if neg {
|
||||
i = -i
|
||||
print_rune_to_buffer(buffer, #rune "-")
|
||||
}
|
||||
print_u128_to_buffer(buffer, i as u128)
|
||||
}
|
||||
|
||||
|
||||
|
||||
print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
||||
f := value
|
||||
if f == 0 {
|
||||
@@ -136,8 +156,8 @@ print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
||||
|
||||
print_rune_to_buffer(buffer, #rune ".")
|
||||
|
||||
mult := 10.0
|
||||
for decimal_places := 6; decimal_places >= 0; decimal_places-- {
|
||||
mult: f64 = 10.0
|
||||
for ; decimal_places >= 0; decimal_places-- {
|
||||
i = (f * mult) as u64
|
||||
print_u64_to_buffer(buffer, i as u64)
|
||||
f -= i as f64 / mult
|
||||
@@ -289,6 +309,11 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
return
|
||||
}
|
||||
|
||||
if arg.data == nil {
|
||||
print_string_to_buffer(buf, "<nil>")
|
||||
return
|
||||
}
|
||||
|
||||
using Type_Info
|
||||
match type info : arg.type_info {
|
||||
case Named:
|
||||
@@ -315,63 +340,50 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
}
|
||||
|
||||
case Integer:
|
||||
if arg.data != nil {
|
||||
match type i : arg {
|
||||
case i8: print_i64_to_buffer(buf, i as i64)
|
||||
case i16: print_i64_to_buffer(buf, i as i64)
|
||||
case i32: print_i64_to_buffer(buf, i as i64)
|
||||
case i64: print_i64_to_buffer(buf, i as i64)
|
||||
case u8: print_u64_to_buffer(buf, i as u64)
|
||||
case u16: print_u64_to_buffer(buf, i as u64)
|
||||
case u32: print_u64_to_buffer(buf, i as u64)
|
||||
case u64: print_u64_to_buffer(buf, i as u64)
|
||||
}
|
||||
} else {
|
||||
print_u64_to_buffer(buf, 0)
|
||||
match type i : arg {
|
||||
case i8: print_i64_to_buffer(buf, i as i64)
|
||||
case u8: print_u64_to_buffer(buf, i as u64)
|
||||
case i16: print_i64_to_buffer(buf, i as i64)
|
||||
case u16: print_u64_to_buffer(buf, i as u64)
|
||||
case i32: print_i64_to_buffer(buf, i as i64)
|
||||
case u32: print_u64_to_buffer(buf, i as u64)
|
||||
case i64: print_i64_to_buffer(buf, i as i64)
|
||||
case u64: print_u64_to_buffer(buf, i as u64)
|
||||
case i128: print_i128_to_buffer(buf, i)
|
||||
case u128: print_u128_to_buffer(buf, i)
|
||||
|
||||
case int: print_u64_to_buffer(buf, i as u64)
|
||||
case uint: print_u64_to_buffer(buf, i as u64)
|
||||
}
|
||||
|
||||
case Float:
|
||||
if arg.data != nil {
|
||||
match type f : arg {
|
||||
case f32: print_f64_to_buffer(buf, f as f64)
|
||||
case f64: print_f64_to_buffer(buf, f as f64)
|
||||
}
|
||||
} else {
|
||||
print_f64_to_buffer(buf, 0)
|
||||
match type f : arg {
|
||||
// case f16: print_f64_to_buffer(buf, f as f64)
|
||||
case f32: print_f64_to_buffer(buf, f as f64)
|
||||
case f64: print_f64_to_buffer(buf, f as f64)
|
||||
// case f128: print_f64_to_buffer(buf, f as f64)
|
||||
}
|
||||
|
||||
case String:
|
||||
if arg.data != nil {
|
||||
match type s : arg {
|
||||
case string: print_string_to_buffer(buf, s)
|
||||
}
|
||||
} else {
|
||||
print_string_to_buffer(buf, "")
|
||||
match type s : arg {
|
||||
case string: print_string_to_buffer(buf, s)
|
||||
}
|
||||
|
||||
case Boolean:
|
||||
if arg.data != nil {
|
||||
match type b : arg {
|
||||
case bool: print_bool_to_buffer(buf, b)
|
||||
}
|
||||
} else {
|
||||
print_bool_to_buffer(buf, false)
|
||||
match type b : arg {
|
||||
case bool: print_bool_to_buffer(buf, b)
|
||||
}
|
||||
|
||||
case Pointer:
|
||||
if arg.data != nil {
|
||||
match type p : arg {
|
||||
case ^Type_Info: print_type_to_buffer(buf, p)
|
||||
default: print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
|
||||
}
|
||||
} else {
|
||||
print_pointer_to_buffer(buf, nil)
|
||||
match type p : arg {
|
||||
case ^Type_Info: print_type_to_buffer(buf, p)
|
||||
default: print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
|
||||
}
|
||||
|
||||
case Maybe:
|
||||
size := mem.size_of_type_info(info.elem)
|
||||
data := slice_ptr(arg.data as ^byte, size+1)
|
||||
if data[size] != 0 && arg.data != nil {
|
||||
if data[size] != 0 {
|
||||
print_any_to_buffer(buf, make_any(info.elem, arg.data))
|
||||
} else {
|
||||
print_string_to_buffer(buf, "nil")
|
||||
@@ -381,14 +393,14 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
value: i64 = 0
|
||||
|
||||
match type i : make_any(info.base, arg.data) {
|
||||
case i8: value = i as i64
|
||||
case i16: value = i as i64
|
||||
case i32: value = i as i64
|
||||
case i64: value = i as i64
|
||||
case u8: value = i as i64
|
||||
case u16: value = i as i64
|
||||
case u32: value = i as i64
|
||||
case u64: value = i as i64
|
||||
case i8: value = i as i64
|
||||
case i16: value = i as i64
|
||||
case i32: value = i as i64
|
||||
case i64: value = i as i64
|
||||
case u8: value = i as i64
|
||||
case u16: value = i as i64
|
||||
case u32: value = i as i64
|
||||
case u64: value = i as i64
|
||||
}
|
||||
print_string_to_buffer(buf, __enum_to_string(arg.type_info, value))
|
||||
|
||||
@@ -448,11 +460,6 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
|
||||
|
||||
case Struct:
|
||||
if arg.data == nil {
|
||||
print_string_to_buffer(buf, "nil")
|
||||
return
|
||||
}
|
||||
|
||||
bprintf(buf, "%{", arg.type_info)
|
||||
defer print_string_to_buffer(buf, "}")
|
||||
|
||||
|
||||
@@ -1328,6 +1328,20 @@ void check_parsed_files(Checker *c) {
|
||||
}
|
||||
}
|
||||
|
||||
for (isize i = 0; i < gb_count_of(basic_types)-1; i++) {
|
||||
Type *t = &basic_types[i];
|
||||
if (t->Basic.size > 0) {
|
||||
add_type_info_type(c, t);
|
||||
}
|
||||
}
|
||||
|
||||
for (isize i = 0; i < gb_count_of(basic_type_aliases)-1; i++) {
|
||||
Type *t = &basic_type_aliases[i];
|
||||
if (t->Basic.size > 0) {
|
||||
add_type_info_type(c, t);
|
||||
}
|
||||
}
|
||||
|
||||
// for_array(i, c->info.type_info_map.entries) {
|
||||
// auto *e = &c->info.type_info_map.entries[i];
|
||||
// Type *prev_type = cast(Type *)e->key.ptr;
|
||||
|
||||
+20
-16
@@ -1347,6 +1347,9 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac
|
||||
u64 umax = ~0ull;
|
||||
if (s < 64) {
|
||||
umax = (1ull << s) - 1ull;
|
||||
} else {
|
||||
// TODO(bill): I NEED A PROPER BIG NUMBER LIBRARY THAT CAN SUPPORT 128 bit integers and floats
|
||||
s = 64;
|
||||
}
|
||||
i64 imax = (1ll << (s-1ll));
|
||||
|
||||
@@ -1356,6 +1359,7 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac
|
||||
case Basic_i16:
|
||||
case Basic_i32:
|
||||
case Basic_i64:
|
||||
case Basic_i128:
|
||||
case Basic_int:
|
||||
return gb_is_between(i, -imax, imax-1);
|
||||
|
||||
@@ -1363,6 +1367,7 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac
|
||||
case Basic_u16:
|
||||
case Basic_u32:
|
||||
case Basic_u64:
|
||||
case Basic_u128:
|
||||
case Basic_uint:
|
||||
return !(u < 0 || u > umax);
|
||||
|
||||
@@ -1378,11 +1383,10 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac
|
||||
}
|
||||
|
||||
switch (type->Basic.kind) {
|
||||
// case Basic_f16:
|
||||
case Basic_f32:
|
||||
if (out_value) *out_value = v;
|
||||
return true;
|
||||
|
||||
case Basic_f64:
|
||||
// case Basic_f128:
|
||||
if (out_value) *out_value = v;
|
||||
return true;
|
||||
|
||||
@@ -2091,7 +2095,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (op.kind == Token_Add || op.kind == Token_Sub) {
|
||||
if (op.kind == Token_Add || op.kind == Token_Sub) {
|
||||
if (is_type_pointer(x->type) && is_type_integer(y->type)) {
|
||||
*x = check_ptr_addition(c, op.kind, x, y, node);
|
||||
return;
|
||||
@@ -2668,7 +2672,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
} break;
|
||||
|
||||
case BuiltinProc_size_of: {
|
||||
// size_of :: proc(Type) -> int
|
||||
// size_of :: proc(Type) -> untyped int
|
||||
Type *type = check_type(c, ce->args[0]);
|
||||
if (type == NULL || type == t_invalid) {
|
||||
error(ast_node_token(ce->args[0]), "Expected a type for `size_of`");
|
||||
@@ -2677,12 +2681,12 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->value = make_exact_value_integer(type_size_of(c->sizes, c->allocator, type));
|
||||
operand->type = t_int;
|
||||
operand->type = t_untyped_integer;
|
||||
|
||||
} break;
|
||||
|
||||
case BuiltinProc_size_of_val:
|
||||
// size_of_val :: proc(val: Type) -> int
|
||||
// size_of_val :: proc(val: Type) -> untyped int
|
||||
check_assignment(c, operand, NULL, make_string("argument of `size_of_val`"));
|
||||
if (operand->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
@@ -2690,11 +2694,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->value = make_exact_value_integer(type_size_of(c->sizes, c->allocator, operand->type));
|
||||
operand->type = t_int;
|
||||
operand->type = t_untyped_integer;
|
||||
break;
|
||||
|
||||
case BuiltinProc_align_of: {
|
||||
// align_of :: proc(Type) -> int
|
||||
// align_of :: proc(Type) -> untyped int
|
||||
Type *type = check_type(c, ce->args[0]);
|
||||
if (type == NULL || type == t_invalid) {
|
||||
error(ast_node_token(ce->args[0]), "Expected a type for `align_of`");
|
||||
@@ -2702,11 +2706,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
}
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->value = make_exact_value_integer(type_align_of(c->sizes, c->allocator, type));
|
||||
operand->type = t_int;
|
||||
operand->type = t_untyped_integer;
|
||||
} break;
|
||||
|
||||
case BuiltinProc_align_of_val:
|
||||
// align_of_val :: proc(val: Type) -> int
|
||||
// align_of_val :: proc(val: Type) -> untyped int
|
||||
check_assignment(c, operand, NULL, make_string("argument of `align_of_val`"));
|
||||
if (operand->mode == Addressing_Invalid) {
|
||||
return false;
|
||||
@@ -2714,11 +2718,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->value = make_exact_value_integer(type_align_of(c->sizes, c->allocator, operand->type));
|
||||
operand->type = t_int;
|
||||
operand->type = t_untyped_integer;
|
||||
break;
|
||||
|
||||
case BuiltinProc_offset_of: {
|
||||
// offset_of :: proc(Type, field) -> int
|
||||
// offset_of :: proc(Type, field) -> untyped int
|
||||
Operand op = {};
|
||||
Type *bt = check_type(c, ce->args[0]);
|
||||
Type *type = base_type(bt);
|
||||
@@ -2758,11 +2762,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->value = make_exact_value_integer(type_offset_of_from_selection(c->sizes, c->allocator, type, sel));
|
||||
operand->type = t_int;
|
||||
operand->type = t_untyped_integer;
|
||||
} break;
|
||||
|
||||
case BuiltinProc_offset_of_val: {
|
||||
// offset_of_val :: proc(val: expression) -> int
|
||||
// offset_of_val :: proc(val: expression) -> untyped int
|
||||
AstNode *arg = unparen_expr(ce->args[0]);
|
||||
if (arg->kind != AstNode_SelectorExpr) {
|
||||
gbString str = expr_to_string(arg);
|
||||
@@ -2808,7 +2812,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
operand->mode = Addressing_Constant;
|
||||
// IMPORTANT TODO(bill): Fix for anonymous fields
|
||||
operand->value = make_exact_value_integer(type_offset_of_from_selection(c->sizes, c->allocator, type, sel));
|
||||
operand->type = t_int;
|
||||
operand->type = t_untyped_integer;
|
||||
} break;
|
||||
|
||||
case BuiltinProc_type_of_val:
|
||||
|
||||
+121
-119
@@ -11,8 +11,12 @@ enum BasicKind {
|
||||
Basic_u32,
|
||||
Basic_i64,
|
||||
Basic_u64,
|
||||
Basic_i128,
|
||||
Basic_u128,
|
||||
// Basic_f16,
|
||||
Basic_f32,
|
||||
Basic_f64,
|
||||
// Basic_f128,
|
||||
Basic_int,
|
||||
Basic_uint,
|
||||
Basic_rawptr,
|
||||
@@ -50,6 +54,7 @@ enum BasicFlag : u32 {
|
||||
struct BasicType {
|
||||
BasicKind kind;
|
||||
u32 flags;
|
||||
i64 size; // -1 if arch. dep.
|
||||
String name;
|
||||
};
|
||||
|
||||
@@ -164,6 +169,111 @@ struct Type {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
|
||||
gb_global Type basic_types[] = {
|
||||
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
|
||||
{Type_Basic, {Basic_bool, BasicFlag_Boolean, 1, STR_LIT("bool")}},
|
||||
{Type_Basic, {Basic_i8, BasicFlag_Integer, 1, STR_LIT("i8")}},
|
||||
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, 1, STR_LIT("u8")}},
|
||||
{Type_Basic, {Basic_i16, BasicFlag_Integer, 2, STR_LIT("i16")}},
|
||||
{Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, 2, STR_LIT("u16")}},
|
||||
{Type_Basic, {Basic_i32, BasicFlag_Integer, 4, STR_LIT("i32")}},
|
||||
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}},
|
||||
{Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}},
|
||||
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}},
|
||||
{Type_Basic, {Basic_i128, BasicFlag_Integer, 16, STR_LIT("i128")}},
|
||||
{Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}},
|
||||
// {Type_Basic, {Basic_f16, BasicFlag_Float, 2, STR_LIT("f16")}},
|
||||
{Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
|
||||
{Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
|
||||
// {Type_Basic, {Basic_f128, BasicFlag_Float, 16, STR_LIT("f128")}},
|
||||
{Type_Basic, {Basic_int, BasicFlag_Integer, -1, STR_LIT("int")}},
|
||||
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uint")}},
|
||||
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
|
||||
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
|
||||
{Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
|
||||
{Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, 0, STR_LIT("untyped bool")}},
|
||||
{Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped integer")}},
|
||||
{Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, 0, STR_LIT("untyped float")}},
|
||||
{Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, 0, STR_LIT("untyped string")}},
|
||||
{Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, 0, STR_LIT("untyped rune")}},
|
||||
{Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, 0, STR_LIT("untyped nil")}},
|
||||
};
|
||||
|
||||
gb_global Type basic_type_aliases[] = {
|
||||
{Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, 1, STR_LIT("byte")}},
|
||||
{Type_Basic, {Basic_rune, BasicFlag_Integer, 4, STR_LIT("rune")}},
|
||||
};
|
||||
|
||||
gb_global Type *t_invalid = &basic_types[Basic_Invalid];
|
||||
gb_global Type *t_bool = &basic_types[Basic_bool];
|
||||
gb_global Type *t_i8 = &basic_types[Basic_i8];
|
||||
gb_global Type *t_u8 = &basic_types[Basic_u8];
|
||||
gb_global Type *t_i16 = &basic_types[Basic_i16];
|
||||
gb_global Type *t_u16 = &basic_types[Basic_u16];
|
||||
gb_global Type *t_i32 = &basic_types[Basic_i32];
|
||||
gb_global Type *t_u32 = &basic_types[Basic_u32];
|
||||
gb_global Type *t_i64 = &basic_types[Basic_i64];
|
||||
gb_global Type *t_u64 = &basic_types[Basic_u64];
|
||||
gb_global Type *t_i128 = &basic_types[Basic_i128];
|
||||
gb_global Type *t_u128 = &basic_types[Basic_u128];
|
||||
// gb_global Type *t_f16 = &basic_types[Basic_f16];
|
||||
gb_global Type *t_f32 = &basic_types[Basic_f32];
|
||||
gb_global Type *t_f64 = &basic_types[Basic_f64];
|
||||
// gb_global Type *t_f128 = &basic_types[Basic_f128];
|
||||
gb_global Type *t_int = &basic_types[Basic_int];
|
||||
gb_global Type *t_uint = &basic_types[Basic_uint];
|
||||
gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
|
||||
gb_global Type *t_string = &basic_types[Basic_string];
|
||||
gb_global Type *t_any = &basic_types[Basic_any];
|
||||
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
||||
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
||||
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
||||
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
||||
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
||||
gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
|
||||
gb_global Type *t_byte = &basic_type_aliases[0];
|
||||
gb_global Type *t_rune = &basic_type_aliases[1];
|
||||
|
||||
|
||||
gb_global Type *t_u8_ptr = NULL;
|
||||
gb_global Type *t_int_ptr = NULL;
|
||||
|
||||
gb_global Type *t_type_info = NULL;
|
||||
gb_global Type *t_type_info_ptr = NULL;
|
||||
gb_global Type *t_type_info_member = NULL;
|
||||
gb_global Type *t_type_info_member_ptr = NULL;
|
||||
|
||||
gb_global Type *t_type_info_named = NULL;
|
||||
gb_global Type *t_type_info_integer = NULL;
|
||||
gb_global Type *t_type_info_float = NULL;
|
||||
gb_global Type *t_type_info_any = NULL;
|
||||
gb_global Type *t_type_info_string = NULL;
|
||||
gb_global Type *t_type_info_boolean = NULL;
|
||||
gb_global Type *t_type_info_pointer = NULL;
|
||||
gb_global Type *t_type_info_maybe = NULL;
|
||||
gb_global Type *t_type_info_procedure = NULL;
|
||||
gb_global Type *t_type_info_array = NULL;
|
||||
gb_global Type *t_type_info_slice = NULL;
|
||||
gb_global Type *t_type_info_vector = NULL;
|
||||
gb_global Type *t_type_info_tuple = NULL;
|
||||
gb_global Type *t_type_info_struct = NULL;
|
||||
gb_global Type *t_type_info_union = NULL;
|
||||
gb_global Type *t_type_info_raw_union = NULL;
|
||||
gb_global Type *t_type_info_enum = NULL;
|
||||
|
||||
gb_global Type *t_allocator = NULL;
|
||||
gb_global Type *t_allocator_ptr = NULL;
|
||||
gb_global Type *t_context = NULL;
|
||||
gb_global Type *t_context_ptr = NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
gbString type_to_string(Type *type, gbAllocator a = heap_allocator());
|
||||
|
||||
Type *base_type(Type *t) {
|
||||
@@ -304,98 +414,6 @@ Type *type_deref(Type *t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
|
||||
gb_global Type basic_types[] = {
|
||||
{Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}},
|
||||
{Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
|
||||
{Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
|
||||
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
|
||||
{Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
||||
{Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
|
||||
{Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
||||
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
|
||||
{Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
||||
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
||||
{Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
||||
{Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
||||
{Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
|
||||
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
|
||||
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}},
|
||||
{Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}},
|
||||
{Type_Basic, {Basic_any, 0, STR_LIT("any")}},
|
||||
{Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}},
|
||||
{Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}},
|
||||
{Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}},
|
||||
{Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}},
|
||||
{Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}},
|
||||
{Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, STR_LIT("untyped nil")}},
|
||||
};
|
||||
|
||||
gb_global Type basic_type_aliases[] = {
|
||||
{Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}},
|
||||
{Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}},
|
||||
};
|
||||
|
||||
gb_global Type *t_invalid = &basic_types[Basic_Invalid];
|
||||
gb_global Type *t_bool = &basic_types[Basic_bool];
|
||||
gb_global Type *t_i8 = &basic_types[Basic_i8];
|
||||
gb_global Type *t_i16 = &basic_types[Basic_i16];
|
||||
gb_global Type *t_i32 = &basic_types[Basic_i32];
|
||||
gb_global Type *t_i64 = &basic_types[Basic_i64];
|
||||
gb_global Type *t_u8 = &basic_types[Basic_u8];
|
||||
gb_global Type *t_u16 = &basic_types[Basic_u16];
|
||||
gb_global Type *t_u32 = &basic_types[Basic_u32];
|
||||
gb_global Type *t_u64 = &basic_types[Basic_u64];
|
||||
gb_global Type *t_f32 = &basic_types[Basic_f32];
|
||||
gb_global Type *t_f64 = &basic_types[Basic_f64];
|
||||
gb_global Type *t_int = &basic_types[Basic_int];
|
||||
gb_global Type *t_uint = &basic_types[Basic_uint];
|
||||
gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
|
||||
gb_global Type *t_string = &basic_types[Basic_string];
|
||||
gb_global Type *t_any = &basic_types[Basic_any];
|
||||
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
|
||||
gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
|
||||
gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
|
||||
gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
|
||||
gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
|
||||
gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil];
|
||||
gb_global Type *t_byte = &basic_type_aliases[0];
|
||||
gb_global Type *t_rune = &basic_type_aliases[1];
|
||||
|
||||
|
||||
gb_global Type *t_u8_ptr = NULL;
|
||||
gb_global Type *t_int_ptr = NULL;
|
||||
|
||||
gb_global Type *t_type_info = NULL;
|
||||
gb_global Type *t_type_info_ptr = NULL;
|
||||
gb_global Type *t_type_info_member = NULL;
|
||||
gb_global Type *t_type_info_member_ptr = NULL;
|
||||
|
||||
gb_global Type *t_type_info_named = NULL;
|
||||
gb_global Type *t_type_info_integer = NULL;
|
||||
gb_global Type *t_type_info_float = NULL;
|
||||
gb_global Type *t_type_info_any = NULL;
|
||||
gb_global Type *t_type_info_string = NULL;
|
||||
gb_global Type *t_type_info_boolean = NULL;
|
||||
gb_global Type *t_type_info_pointer = NULL;
|
||||
gb_global Type *t_type_info_maybe = NULL;
|
||||
gb_global Type *t_type_info_procedure = NULL;
|
||||
gb_global Type *t_type_info_array = NULL;
|
||||
gb_global Type *t_type_info_slice = NULL;
|
||||
gb_global Type *t_type_info_vector = NULL;
|
||||
gb_global Type *t_type_info_tuple = NULL;
|
||||
gb_global Type *t_type_info_struct = NULL;
|
||||
gb_global Type *t_type_info_union = NULL;
|
||||
gb_global Type *t_type_info_raw_union = NULL;
|
||||
gb_global Type *t_type_info_enum = NULL;
|
||||
|
||||
gb_global Type *t_allocator = NULL;
|
||||
gb_global Type *t_allocator_ptr = NULL;
|
||||
gb_global Type *t_context = NULL;
|
||||
gb_global Type *t_context_ptr = NULL;
|
||||
|
||||
|
||||
Type *get_enum_base_type(Type *t) {
|
||||
Type *bt = base_type(t);
|
||||
if (bt->kind == Type_Record && bt->Record.kind == TypeRecord_Enum) {
|
||||
@@ -787,24 +805,6 @@ struct BaseTypeSizes {
|
||||
i64 max_align;
|
||||
};
|
||||
|
||||
// TODO(bill): Change
|
||||
gb_global i64 basic_type_sizes[] = {
|
||||
0, // Basic_Invalid
|
||||
1, // Basic_bool
|
||||
1, // Basic_i8
|
||||
1, // Basic_u8
|
||||
2, // Basic_i16
|
||||
2, // Basic_u16
|
||||
4, // Basic_i32
|
||||
4, // Basic_u32
|
||||
8, // Basic_i64
|
||||
8, // Basic_u64
|
||||
4, // Basic_f32
|
||||
8, // Basic_f64
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct Selection {
|
||||
Entity *entity;
|
||||
Array<isize> index;
|
||||
@@ -1124,6 +1124,8 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
}
|
||||
|
||||
// return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
|
||||
// NOTE(bill): Things that are bigger than s.word_size, are actually comprised of smaller types
|
||||
// TODO(bill): Is this correct for 128-bit types (integers)?
|
||||
return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.word_size);
|
||||
}
|
||||
|
||||
@@ -1173,16 +1175,16 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
case Type_Basic: {
|
||||
GB_ASSERT(is_type_typed(t));
|
||||
BasicKind kind = t->Basic.kind;
|
||||
if (kind < gb_count_of(basic_type_sizes)) {
|
||||
i64 size = basic_type_sizes[kind];
|
||||
if (size > 0) {
|
||||
return size;
|
||||
}
|
||||
i64 size = t->Basic.size;
|
||||
if (size > 0) {
|
||||
return size;
|
||||
}
|
||||
if (kind == Basic_string) {
|
||||
return 2 * s.word_size;
|
||||
} else if (kind == Basic_any) {
|
||||
return 2 * s.word_size;
|
||||
switch (kind) {
|
||||
case Basic_string: return 2*s.word_size;
|
||||
case Basic_any: return 2*s.word_size;
|
||||
|
||||
case Basic_int: case Basic_uint: case Basic_rawptr:
|
||||
return s.word_size;
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
@@ -167,6 +167,57 @@ i64 prev_pow2(i64 n) {
|
||||
return n - (n >> 1);
|
||||
}
|
||||
|
||||
i16 f32_to_f16(f32 value) {
|
||||
union { u32 i; f32 f; } v;
|
||||
i32 i, s, e, m;
|
||||
|
||||
v.f = value;
|
||||
i = (i32)v.i;
|
||||
|
||||
s = (i >> 16) & 0x00008000;
|
||||
e = ((i >> 23) & 0x000000ff) - (127 - 15);
|
||||
m = i & 0x007fffff;
|
||||
|
||||
|
||||
if (e <= 0) {
|
||||
if (e < -10) return cast(i16)s;
|
||||
m = (m | 0x00800000) >> (1 - e);
|
||||
|
||||
if (m & 0x00001000)
|
||||
m += 0x00002000;
|
||||
|
||||
return cast(i16)(s | (m >> 13));
|
||||
} else if (e == 0xff - (127 - 15)) {
|
||||
if (m == 0) {
|
||||
return cast(i16)(s | 0x7c00); /* NOTE(bill): infinity */
|
||||
} else {
|
||||
/* NOTE(bill): NAN */
|
||||
m >>= 13;
|
||||
return cast(i16)(s | 0x7c00 | m | (m == 0));
|
||||
}
|
||||
} else {
|
||||
if (m & 0x00001000) {
|
||||
m += 0x00002000;
|
||||
if (m & 0x00800000) {
|
||||
m = 0;
|
||||
e += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (e > 30) {
|
||||
float volatile f = 1e12f;
|
||||
int j;
|
||||
for (j = 0; j < 10; j++)
|
||||
f *= f; /* NOTE(bill): Cause overflow */
|
||||
|
||||
return cast(i16)(s | 0x7c00);
|
||||
}
|
||||
|
||||
return cast(i16)(s | (e << 10) | (m >> 13));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define for_array(index_, array_) for (isize index_ = 0; index_ < (array_).count; index_++)
|
||||
|
||||
|
||||
+4
-5
@@ -58,8 +58,6 @@ i32 win32_exec_command_line_app(char *name, char *fmt, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum ArchKind {
|
||||
ArchKind_x64,
|
||||
ArchKind_x86,
|
||||
@@ -139,11 +137,12 @@ int main(int argc, char **argv) {
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
Parser parser = {0};
|
||||
|
||||
// TODO(bill): prevent compiling without a linker
|
||||
|
||||
timings_start_section(&timings, make_string("parse files"));
|
||||
|
||||
Parser parser = {0};
|
||||
if (!init_parser(&parser)) {
|
||||
return 1;
|
||||
}
|
||||
@@ -244,8 +243,8 @@ int main(int argc, char **argv) {
|
||||
exit_code = win32_exec_command_line_app("msvc-link",
|
||||
"link %.*s.obj -OUT:%.*s.exe %s "
|
||||
"/defaultlib:libcmt "
|
||||
"/nologo /incremental:no /opt:ref /subsystem:console "
|
||||
"%.*s "
|
||||
"/nologo /incremental:no /opt:ref /subsystem:console /debug "
|
||||
" %.*s "
|
||||
"",
|
||||
LIT(output), LIT(output),
|
||||
lib_str, LIT(arch_data.link_flags));
|
||||
|
||||
@@ -3177,6 +3177,11 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
|
||||
ImportedFile runtime_file = {s, s, init_pos};
|
||||
array_add(&p->imports, runtime_file);
|
||||
}
|
||||
{
|
||||
String s = get_fullpath_core(heap_allocator(), make_string("_soft_numbers.odin"));
|
||||
ImportedFile runtime_file = {s, s, init_pos};
|
||||
array_add(&p->imports, runtime_file);
|
||||
}
|
||||
|
||||
for_array(i, p->imports) {
|
||||
ImportedFile imported_file = p->imports[i];
|
||||
|
||||
+53
-11
@@ -1526,6 +1526,8 @@ ssaValue *ssa_emit_arith(ssaProcedure *proc, TokenKind op, ssaValue *left, ssaVa
|
||||
case Token_And:
|
||||
case Token_Or:
|
||||
case Token_Xor:
|
||||
case Token_Shl:
|
||||
case Token_Shr:
|
||||
left = ssa_emit_conv(proc, left, type);
|
||||
right = ssa_emit_conv(proc, right, type);
|
||||
break;
|
||||
@@ -2160,6 +2162,34 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b32 ssa_is_type_aggregate(Type *t) {
|
||||
t = base_type(get_enum_base_type(t));
|
||||
switch (t->kind) {
|
||||
case Type_Basic:
|
||||
switch (t->Basic.kind) {
|
||||
case Basic_string:
|
||||
case Basic_any:
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Pointer:
|
||||
case Type_Vector:
|
||||
return false;
|
||||
|
||||
case Type_Array:
|
||||
case Type_Slice:
|
||||
case Type_Maybe:
|
||||
case Type_Record:
|
||||
case Type_Tuple:
|
||||
return true;
|
||||
|
||||
case Type_Named:
|
||||
return ssa_is_type_aggregate(t->Named.base);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
Type *src_type = ssa_type(value);
|
||||
@@ -2173,17 +2203,24 @@ ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
return value;
|
||||
}
|
||||
|
||||
i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
|
||||
i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
|
||||
ssaModule *m = proc->module;
|
||||
|
||||
if (sz == dz) {
|
||||
return ssa_emit_bitcast(proc, value, dst);
|
||||
i64 sz = type_size_of(m->sizes, m->allocator, src);
|
||||
i64 dz = type_size_of(m->sizes, m->allocator, dst);
|
||||
|
||||
GB_ASSERT_MSG(sz == dz, "Invalid transmute conversion: `%s` to `%s`", type_to_string(src_type), type_to_string(t));
|
||||
|
||||
if (ssa_is_type_aggregate(src) || ssa_is_type_aggregate(dst)) {
|
||||
ssaValue *s = ssa_add_local_generated(proc, src);
|
||||
ssa_emit_store(proc, s, value);
|
||||
|
||||
ssaValue *d = ssa_emit_bitcast(proc, s, make_type_pointer(m->allocator, dst));
|
||||
return ssa_emit_load(proc, d);
|
||||
}
|
||||
|
||||
// TODO(bill): Actually figure out what the conversion needs to be correctly 'cause LLVM
|
||||
|
||||
GB_PANIC("Invalid transmute conversion: `%s` to `%s`", type_to_string(src_type), type_to_string(t));
|
||||
|
||||
return NULL;
|
||||
return ssa_emit_bitcast(proc, value, dst);
|
||||
}
|
||||
|
||||
ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
@@ -5035,13 +5072,15 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_boolean);
|
||||
break;
|
||||
case Basic_i8:
|
||||
case Basic_i16:
|
||||
case Basic_i32:
|
||||
case Basic_i64:
|
||||
case Basic_u8:
|
||||
case Basic_i16:
|
||||
case Basic_u16:
|
||||
case Basic_i32:
|
||||
case Basic_u32:
|
||||
case Basic_i64:
|
||||
case Basic_u64:
|
||||
case Basic_i128:
|
||||
case Basic_u128:
|
||||
case Basic_int:
|
||||
case Basic_uint: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_integer);
|
||||
@@ -5052,8 +5091,11 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), is_signed);
|
||||
} break;
|
||||
|
||||
// case Basic_f16:
|
||||
case Basic_f32:
|
||||
case Basic_f64: {
|
||||
case Basic_f64:
|
||||
// case Basic_f128:
|
||||
{
|
||||
tag = ssa_add_local_generated(proc, t_type_info_float);
|
||||
ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), bits);
|
||||
|
||||
+39
-6
@@ -146,15 +146,19 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
||||
switch (t->Basic.kind) {
|
||||
case Basic_bool: ssa_fprintf(f, "i1"); break;
|
||||
case Basic_i8: ssa_fprintf(f, "i8"); break;
|
||||
case Basic_i16: ssa_fprintf(f, "i16"); break;
|
||||
case Basic_i32: ssa_fprintf(f, "i32"); break;
|
||||
case Basic_i64: ssa_fprintf(f, "i64"); break;
|
||||
case Basic_u8: ssa_fprintf(f, "i8"); break;
|
||||
case Basic_i16: ssa_fprintf(f, "i16"); break;
|
||||
case Basic_u16: ssa_fprintf(f, "i16"); break;
|
||||
case Basic_i32: ssa_fprintf(f, "i32"); break;
|
||||
case Basic_u32: ssa_fprintf(f, "i32"); break;
|
||||
case Basic_i64: ssa_fprintf(f, "i64"); break;
|
||||
case Basic_u64: ssa_fprintf(f, "i64"); break;
|
||||
case Basic_i128: ssa_fprintf(f, "i128"); break;
|
||||
case Basic_u128: ssa_fprintf(f, "i128"); break;
|
||||
// case Basic_f16: ssa_fprintf(f, "half"); break;
|
||||
case Basic_f32: ssa_fprintf(f, "float"); break;
|
||||
case Basic_f64: ssa_fprintf(f, "double"); break;
|
||||
// case Basic_f128: ssa_fprintf(f, "fp128"); break;
|
||||
case Basic_rawptr: ssa_fprintf(f, "%%..rawptr"); break;
|
||||
case Basic_string: ssa_fprintf(f, "%%..string"); break;
|
||||
case Basic_uint: ssa_fprintf(f, "i%lld", word_bits); break;
|
||||
@@ -361,16 +365,45 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
|
||||
}
|
||||
} break;
|
||||
case ExactValue_Float: {
|
||||
GB_ASSERT(is_type_float(type));
|
||||
type = base_type(type);
|
||||
u64 u = *cast(u64*)&value.value_float;
|
||||
if (is_type_float(type) && type->Basic.kind == Basic_f32) {
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_f32:
|
||||
// IMPORTANT NOTE(bill): LLVM requires all floating point constants to be
|
||||
// a 64 bit number if bits_of(float type) <= 64.
|
||||
// For some bizarre reason, you need to clear the bottom 29 bits
|
||||
// https://groups.google.com/forum/#!topic/llvm-dev/IlqV3TbSk6M
|
||||
// 64 bit mantissa: 52 bits
|
||||
// 32 bit mantissa: 23 bits
|
||||
// 29 == 52-23
|
||||
u >>= 29;
|
||||
u <<= 29;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type->Basic.kind) {
|
||||
case 0: break;
|
||||
#if 0
|
||||
case Basic_f16:
|
||||
ssa_fprintf(f, "bitcast (");
|
||||
ssa_print_type(f, m, t_u16);
|
||||
ssa_fprintf(f, " %u to ", cast(u16)f32_to_f16(cast(f32)value.value_float));
|
||||
ssa_print_type(f, m, t_f16);
|
||||
ssa_fprintf(f, ")");
|
||||
break;
|
||||
case Basic_f128:
|
||||
ssa_fprintf(f, "bitcast (");
|
||||
ssa_fprintf(f, "i128");
|
||||
// TODO(bill): Actually support f128
|
||||
ssa_fprintf(f, " %llu to ", u);
|
||||
ssa_print_type(f, m, t_f128);
|
||||
ssa_fprintf(f, ")");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ssa_fprintf(f, "0x%016llx", u);
|
||||
break;
|
||||
}
|
||||
ssa_fprintf(f, "0x%016llx", u);
|
||||
} break;
|
||||
case ExactValue_Pointer:
|
||||
if (value.value_pointer == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user