aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-11-22 00:13:52 +0000
committerGinger Bill <bill@gingerbill.org>2016-11-22 00:13:52 +0000
commit36ad9dae43cd21d8532994cd0d0e92a89af0ed04 (patch)
tree2ab180093e4d5ac1e6ed39ed3b8ce5437255ffb5 /src
parent24347ced45aabd3ce4f4a261b8140a976cadff2e (diff)
128 bit integers
Kind of works but may be buggy due to LLVM not actually sure
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.cpp14
-rw-r--r--src/checker/expr.cpp36
-rw-r--r--src/checker/types.cpp240
-rw-r--r--src/common.cpp51
-rw-r--r--src/main.cpp9
-rw-r--r--src/parser.cpp5
-rw-r--r--src/ssa.cpp64
-rw-r--r--src/ssa_print.cpp45
8 files changed, 307 insertions, 157 deletions
diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp
index 218cfbd4b..f8c35bcc3 100644
--- a/src/checker/checker.cpp
+++ b/src/checker/checker.cpp
@@ -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;
diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp
index 4afef5385..1b2353ac5 100644
--- a/src/checker/expr.cpp
+++ b/src/checker/expr.cpp
@@ -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:
diff --git a/src/checker/types.cpp b/src/checker/types.cpp
index 0fbcd84bb..965798be9 100644
--- a/src/checker/types.cpp
+++ b/src/checker/types.cpp
@@ -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;
diff --git a/src/common.cpp b/src/common.cpp
index d0703378c..e07ea362a 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -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_++)
diff --git a/src/main.cpp b/src/main.cpp
index 55b115a64..6fea6d583 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -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));
diff --git a/src/parser.cpp b/src/parser.cpp
index a50edb6c4..d263fa1dd 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -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];
diff --git a/src/ssa.cpp b/src/ssa.cpp
index a71465601..0563f0022 100644
--- a/src/ssa.cpp
+++ b/src/ssa.cpp
@@ -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));
- GB_PANIC("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);
- return NULL;
+ 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
+
+ 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);
diff --git a/src/ssa_print.cpp b/src/ssa_print.cpp
index e02c58513..2f074008d 100644
--- a/src/ssa_print.cpp
+++ b/src/ssa_print.cpp
@@ -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) {