diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-11-22 00:13:52 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-11-22 00:13:52 +0000 |
| commit | 36ad9dae43cd21d8532994cd0d0e92a89af0ed04 (patch) | |
| tree | 2ab180093e4d5ac1e6ed39ed3b8ce5437255ffb5 /src | |
| parent | 24347ced45aabd3ce4f4a261b8140a976cadff2e (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.cpp | 14 | ||||
| -rw-r--r-- | src/checker/expr.cpp | 36 | ||||
| -rw-r--r-- | src/checker/types.cpp | 240 | ||||
| -rw-r--r-- | src/common.cpp | 51 | ||||
| -rw-r--r-- | src/main.cpp | 9 | ||||
| -rw-r--r-- | src/parser.cpp | 5 | ||||
| -rw-r--r-- | src/ssa.cpp | 64 | ||||
| -rw-r--r-- | src/ssa_print.cpp | 45 |
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) { |