authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-21 03:02:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-21 03:02:25-07:00
log32e2196257b2650e41b683d16bf00ba77ccfbb13
tree1eb681e2443aa31c4d5fea8ab798f12faaf7b3d2
parent5e212db29cf9e2c06aba363736ffb965e631aa2d

number literal rework


11 files changed, 772 insertions(+), 616 deletions(-)

CMakeLists.txt+1
...@@ -25,6 +25,7 @@ include_directories(...@@ -25,6 +25,7 @@ include_directories(
25)25)
2626
27set(ZIG_SOURCES27set(ZIG_SOURCES
28 "${CMAKE_SOURCE_DIR}/src/bignum.cpp"
28 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"29 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
29 "${CMAKE_SOURCE_DIR}/src/parser.cpp"30 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
30 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"31 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
src/all_types.hpp+20-41
...@@ -13,6 +13,7 @@...@@ -13,6 +13,7 @@
13#include "zig_llvm.hpp"13#include "zig_llvm.hpp"
14#include "hash_map.hpp"14#include "hash_map.hpp"
15#include "errmsg.hpp"15#include "errmsg.hpp"
16#include "bignum.hpp"
1617
17struct AstNode;18struct AstNode;
18struct ImportTableEntry;19struct ImportTableEntry;
...@@ -49,15 +50,6 @@ enum CastOp {...@@ -49,15 +50,6 @@ enum CastOp {
49 CastOpPointerReinterpret,50 CastOpPointerReinterpret,
50};51};
5152
52struct Cast {
53 CastOp op;
54 // if op is CastOpArrayToString, this will be a pointer to
55 // the string struct on the stack
56 LLVMValueRef ptr;
57 TypeTableEntry *after_type;
58 AstNode *source_node;
59};
60
61struct ConstEnumValue {53struct ConstEnumValue {
62 uint64_t tag;54 uint64_t tag;
63 ConstExprValue *payload;55 ConstExprValue *payload;
...@@ -68,9 +60,7 @@ struct ConstExprValue {...@@ -68,9 +60,7 @@ struct ConstExprValue {
68 bool depends_on_compile_var;60 bool depends_on_compile_var;
6961
70 union {62 union {
71 uint64_t x_uint;63 BigNum x_bignum;
72 int64_t x_int;
73 double x_float;
74 bool x_bool;64 bool x_bool;
75 FnTableEntry *x_fn;65 FnTableEntry *x_fn;
76 TypeTableEntry *x_type;66 TypeTableEntry *x_type;
...@@ -79,8 +69,19 @@ struct ConstExprValue {...@@ -79,8 +69,19 @@ struct ConstExprValue {
79 } data;69 } data;
80};70};
8171
72struct Cast {
73 CastOp op;
74 // if op is CastOpArrayToString, this will be a pointer to
75 // the string struct on the stack
76 LLVMValueRef ptr;
77 TypeTableEntry *after_type;
78 AstNode *source_node;
79 ConstExprValue const_val;
80};
81
82struct Expr {82struct Expr {
83 TypeTableEntry *type_entry;83 TypeTableEntry *type_entry;
84 TypeTableEntry *resolved_type;
84 // the context in which this expression is evaluated.85 // the context in which this expression is evaluated.
85 // for blocks, this points to the containing scope, not the block's own scope for its children.86 // for blocks, this points to the containing scope, not the block's own scope for its children.
86 BlockContext *block_context;87 BlockContext *block_context;
...@@ -92,10 +93,6 @@ struct Expr {...@@ -92,10 +93,6 @@ struct Expr {
92 ConstExprValue const_val;93 ConstExprValue const_val;
93};94};
9495
95struct NumLitCodeGen {
96 TypeTableEntry *resolved_type;
97};
98
99struct StructValExprCodeGen {96struct StructValExprCodeGen {
100 TypeTableEntry *type_entry;97 TypeTableEntry *type_entry;
101 LLVMValueRef ptr;98 LLVMValueRef ptr;
...@@ -315,7 +312,6 @@ struct AstNodeFnCallExpr {...@@ -315,7 +312,6 @@ struct AstNodeFnCallExpr {
315 // populated by semantic analyzer:312 // populated by semantic analyzer:
316 BuiltinFnEntry *builtin_fn;313 BuiltinFnEntry *builtin_fn;
317 Expr resolved_expr;314 Expr resolved_expr;
318 NumLitCodeGen resolved_num_lit;
319 Cast cast;315 Cast cast;
320 FnTableEntry *fn_entry;316 FnTableEntry *fn_entry;
321};317};
...@@ -550,26 +546,15 @@ struct AstNodeCharLiteral {...@@ -550,26 +546,15 @@ struct AstNodeCharLiteral {
550};546};
551547
552enum NumLit {548enum NumLit {
553 NumLitF32,549 NumLitFloat,
554 NumLitF64,550 NumLitUInt,
555 NumLitF128,
556 NumLitU8,
557 NumLitU16,
558 NumLitU32,
559 NumLitU64,
560 NumLitI8,
561 NumLitI16,
562 NumLitI32,
563 NumLitI64,
564
565 NumLitCount
566};551};
567552
568struct AstNodeNumberLiteral {553struct AstNodeNumberLiteral {
569 NumLit kind;554 NumLit kind;
570555
571 // overflow is true if when parsing the number, we discovered it would not556 // overflow is true if when parsing the number, we discovered it would not
572 // fit without losing data in a uint64_t, int64_t, or double557 // fit without losing data in a uint64_t or double
573 bool overflow;558 bool overflow;
574559
575 union {560 union {
...@@ -578,7 +563,6 @@ struct AstNodeNumberLiteral {...@@ -578,7 +563,6 @@ struct AstNodeNumberLiteral {
578 } data;563 } data;
579564
580 // populated by semantic analyzer565 // populated by semantic analyzer
581 NumLitCodeGen codegen;
582 Expr resolved_expr;566 Expr resolved_expr;
583};567};
584568
...@@ -586,7 +570,6 @@ struct AstNodeErrorLiteral {...@@ -586,7 +570,6 @@ struct AstNodeErrorLiteral {
586 Buf symbol;570 Buf symbol;
587571
588 // populated by semantic analyzer572 // populated by semantic analyzer
589 NumLitCodeGen codegen;
590 Expr resolved_expr;573 Expr resolved_expr;
591};574};
592575
...@@ -758,10 +741,6 @@ struct TypeTableEntryStruct {...@@ -758,10 +741,6 @@ struct TypeTableEntryStruct {
758 bool reported_infinite_err;741 bool reported_infinite_err;
759};742};
760743
761struct TypeTableEntryNumLit {
762 NumLit kind;
763};
764
765struct TypeTableEntryMaybe {744struct TypeTableEntryMaybe {
766 TypeTableEntry *child_type;745 TypeTableEntry *child_type;
767};746};
...@@ -808,7 +787,8 @@ enum TypeTableEntryId {...@@ -808,7 +787,8 @@ enum TypeTableEntryId {
808 TypeTableEntryIdPointer,787 TypeTableEntryIdPointer,
809 TypeTableEntryIdArray,788 TypeTableEntryIdArray,
810 TypeTableEntryIdStruct,789 TypeTableEntryIdStruct,
811 TypeTableEntryIdNumberLiteral,790 TypeTableEntryIdNumLitFloat,
791 TypeTableEntryIdNumLitInt,
812 TypeTableEntryIdMaybe,792 TypeTableEntryIdMaybe,
813 TypeTableEntryIdError,793 TypeTableEntryIdError,
814 TypeTableEntryIdEnum,794 TypeTableEntryIdEnum,
...@@ -830,7 +810,6 @@ struct TypeTableEntry {...@@ -830,7 +810,6 @@ struct TypeTableEntry {
830 TypeTableEntryInt integral;810 TypeTableEntryInt integral;
831 TypeTableEntryArray array;811 TypeTableEntryArray array;
832 TypeTableEntryStruct structure;812 TypeTableEntryStruct structure;
833 TypeTableEntryNumLit num_lit;
834 TypeTableEntryMaybe maybe;813 TypeTableEntryMaybe maybe;
835 TypeTableEntryError error;814 TypeTableEntryError error;
836 TypeTableEntryEnum enumeration;815 TypeTableEntryEnum enumeration;
...@@ -951,10 +930,10 @@ struct CodeGen {...@@ -951,10 +930,10 @@ struct CodeGen {
951 TypeTableEntry *entry_unreachable;930 TypeTableEntry *entry_unreachable;
952 TypeTableEntry *entry_type;931 TypeTableEntry *entry_type;
953 TypeTableEntry *entry_invalid;932 TypeTableEntry *entry_invalid;
933 TypeTableEntry *entry_num_lit_int;
934 TypeTableEntry *entry_num_lit_float;
954 } builtin_types;935 } builtin_types;
955936
956 TypeTableEntry *num_lit_types[NumLitCount];
957
958 LLVMTargetDataRef target_data_ref;937 LLVMTargetDataRef target_data_ref;
959 unsigned pointer_size_bytes;938 unsigned pointer_size_bytes;
960 bool is_static;939 bool is_static;
src/analyze.cpp+331-333
...@@ -103,7 +103,8 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {...@@ -103,7 +103,8 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
103 case TypeTableEntryIdFloat:103 case TypeTableEntryIdFloat:
104 case TypeTableEntryIdPointer:104 case TypeTableEntryIdPointer:
105 case TypeTableEntryIdArray:105 case TypeTableEntryIdArray:
106 case TypeTableEntryIdNumberLiteral:106 case TypeTableEntryIdNumLitFloat:
107 case TypeTableEntryIdNumLitInt:
107 case TypeTableEntryIdMaybe:108 case TypeTableEntryIdMaybe:
108 case TypeTableEntryIdFn:109 case TypeTableEntryIdFn:
109 case TypeTableEntryIdError:110 case TypeTableEntryIdError:
...@@ -121,24 +122,20 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {...@@ -121,24 +122,20 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
121 return entry;122 return entry;
122}123}
123124
124static NumLit get_number_literal_kind_unsigned(uint64_t x) {125static int bits_needed_for_unsigned(uint64_t x) {
125 if (x <= UINT8_MAX) {126 if (x <= UINT8_MAX) {
126 return NumLitU8;127 return 8;
127 } else if (x <= UINT16_MAX) {128 } else if (x <= UINT16_MAX) {
128 return NumLitU16;129 return 16;
129 } else if (x <= UINT32_MAX) {130 } else if (x <= UINT32_MAX) {
130 return NumLitU32;131 return 32;
131 } else {132 } else {
132 return NumLitU64;133 return 64;
133 }134 }
134}135}
135136
136static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) {137static TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
137 return g->num_lit_types[get_number_literal_kind_unsigned(x)];138 return get_int_type(g, false, bits_needed_for_unsigned(x));
138}
139
140static TypeTableEntry *get_int_type_unsigned(CodeGen *g, uint64_t x) {
141 return get_int_type(g, false, num_lit_bit_count(get_number_literal_kind_unsigned(x)));
142}139}
143140
144TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {141TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
...@@ -660,10 +657,9 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt...@@ -660,10 +657,9 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
660 if (!enum_type->data.enumeration.is_invalid) {657 if (!enum_type->data.enumeration.is_invalid) {
661 enum_type->data.enumeration.gen_field_count = gen_field_index;658 enum_type->data.enumeration.gen_field_count = gen_field_index;
662659
663 uint64_t tag_size_in_bits = num_lit_bit_count(get_number_literal_kind_unsigned(field_count));660 TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
664 enum_type->align_in_bits = tag_size_in_bits;661 enum_type->align_in_bits = tag_type_entry->size_in_bits;
665 enum_type->size_in_bits = tag_size_in_bits + biggest_union_member_size_in_bits;662 enum_type->size_in_bits = tag_type_entry->size_in_bits + biggest_union_member_size_in_bits;
666 TypeTableEntry *tag_type_entry = get_int_type_unsigned(g, field_count);
667 enum_type->data.enumeration.tag_type = tag_type_entry;663 enum_type->data.enumeration.tag_type = tag_type_entry;
668664
669 if (biggest_union_member) {665 if (biggest_union_member) {
...@@ -1048,136 +1044,105 @@ static TypeTableEntry *get_return_type(BlockContext *context) {...@@ -1048,136 +1044,105 @@ static TypeTableEntry *get_return_type(BlockContext *context) {
1048 return unwrapped_node_type(return_type_node);1044 return unwrapped_node_type(return_type_node);
1049}1045}
10501046
1051static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) {1047static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTableEntry *other_type) {
1052 NumLit num_lit = literal_type->data.num_lit.kind;1048 Expr *expr = get_resolved_expr(literal_node);
1053 uint64_t lit_size_in_bits = num_lit_bit_count(num_lit);1049 ConstExprValue *const_val = &expr->const_val;
10541050 assert(const_val->ok);
1055 switch (other_type->id) {1051 if (other_type->id == TypeTableEntryIdFloat) {
1056 case TypeTableEntryIdInvalid:1052 expr->resolved_type = other_type;
1057 case TypeTableEntryIdNumberLiteral:1053 return true;
1058 zig_unreachable();1054 } else if (other_type->id == TypeTableEntryIdInt &&
1059 case TypeTableEntryIdVoid:1055 const_val->data.x_bignum.kind == BigNumKindInt)
1060 case TypeTableEntryIdBool:1056 {
1061 case TypeTableEntryIdUnreachable:1057 if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type->size_in_bits,
1062 case TypeTableEntryIdPointer:1058 other_type->data.integral.is_signed))
1063 case TypeTableEntryIdArray:1059 {
1064 case TypeTableEntryIdStruct:1060 expr->resolved_type = other_type;
1065 case TypeTableEntryIdEnum:1061 return true;
1066 case TypeTableEntryIdMetaType:1062 }
1067 case TypeTableEntryIdFn:1063 } else if (other_type->id == TypeTableEntryIdNumLitFloat ||
1068 case TypeTableEntryIdError:1064 other_type->id == TypeTableEntryIdNumLitInt)
1069 return false;1065 {
1070 case TypeTableEntryIdInt:1066 return true;
1071 if (is_num_lit_unsigned(num_lit)) {
1072 return lit_size_in_bits <= other_type->size_in_bits;
1073 } else {
1074 return false;
1075 }
1076 case TypeTableEntryIdFloat:
1077 if (is_num_lit_float(num_lit)) {
1078 return lit_size_in_bits <= other_type->size_in_bits;
1079 } else if (other_type->size_in_bits == 32) {
1080 return lit_size_in_bits < 24;
1081 } else if (other_type->size_in_bits == 64) {
1082 return lit_size_in_bits < 53;
1083 } else {
1084 return false;
1085 }
1086 case TypeTableEntryIdMaybe:
1087 return false;
1088 }1067 }
1089 zig_unreachable();
1090}
1091
1092static TypeTableEntry *resolve_rhs_number_literal(CodeGen *g, AstNode *non_literal_node,
1093 TypeTableEntry *non_literal_type, AstNode *literal_node, TypeTableEntry *literal_type)
1094{
1095 NumLitCodeGen *num_lit_codegen = get_resolved_num_lit(literal_node);
10961068
1097 if (non_literal_type && num_lit_fits_in_other_type(g, literal_type, non_literal_type)) {1069 add_node_error(g, literal_node,
1098 assert(!num_lit_codegen->resolved_type);1070 buf_sprintf("value %s cannot be represented in type '%s'",
1099 num_lit_codegen->resolved_type = non_literal_type;1071 buf_ptr(bignum_to_buf(&const_val->data.x_bignum)),
1100 return non_literal_type;1072 buf_ptr(&other_type->name)));
1101 } else {1073 return false;
1102 return nullptr;
1103 }
1104}1074}
11051075
1106static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstNode *node2,1076static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *parent_source_node,
1107 TypeTableEntry *type1, TypeTableEntry *type2)1077 AstNode **child_nodes, TypeTableEntry **child_types, int child_count)
1108{1078{
1109 if (type1->id == TypeTableEntryIdNumberLiteral &&1079 TypeTableEntry *prev_type = child_types[0];
1110 type2->id == TypeTableEntryIdNumberLiteral)1080 AstNode *prev_node = child_nodes[0];
1111 {1081 if (prev_type->id == TypeTableEntryIdInvalid) {
1112 NumLitCodeGen *codegen_num_lit_1 = get_resolved_num_lit(node1);1082 return prev_type;
1113 NumLitCodeGen *codegen_num_lit_2 = get_resolved_num_lit(node2);1083 }
11141084 for (int i = 1; i < child_count; i += 1) {
1115 assert(!codegen_num_lit_1->resolved_type);1085 TypeTableEntry *cur_type = child_types[i];
1116 assert(!codegen_num_lit_2->resolved_type);1086 AstNode *cur_node = child_nodes[i];
11171087 if (cur_type->id == TypeTableEntryIdInvalid) {
1118 if (is_num_lit_float(type1->data.num_lit.kind) &&1088 return cur_type;
1119 is_num_lit_float(type2->data.num_lit.kind))1089 } else if (prev_type->id == TypeTableEntryIdUnreachable) {
1090 prev_type = cur_type;
1091 prev_node = cur_node;
1092 } else if (cur_type->id == TypeTableEntryIdUnreachable) {
1093 continue;
1094 } else if (prev_type->id == TypeTableEntryIdInt &&
1095 cur_type->id == TypeTableEntryIdInt &&
1096 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
1097 {
1098 if (cur_type->size_in_bits > prev_type->size_in_bits) {
1099 prev_type = cur_type;
1100 prev_node = cur_node;
1101 }
1102 } else if (prev_type->id == TypeTableEntryIdFloat &&
1103 cur_type->id == TypeTableEntryIdFloat)
1104 {
1105 if (cur_type->size_in_bits > prev_type->size_in_bits) {
1106 prev_type = cur_type;
1107 prev_node = cur_node;
1108 }
1109 } else if (prev_type->id == TypeTableEntryIdNumLitFloat &&
1110 cur_type->id == TypeTableEntryIdNumLitFloat)
1111 {
1112 continue;
1113 } else if (prev_type->id == TypeTableEntryIdNumLitInt &&
1114 cur_type->id == TypeTableEntryIdNumLitInt)
1120 {1115 {
1121 codegen_num_lit_1->resolved_type = g->builtin_types.entry_f64;1116 continue;
1122 codegen_num_lit_2->resolved_type = g->builtin_types.entry_f64;1117 } else if (prev_type->id == TypeTableEntryIdNumLitInt ||
1123 return g->builtin_types.entry_f64;1118 prev_type->id == TypeTableEntryIdNumLitFloat)
1124 } else if (is_num_lit_unsigned(type1->data.num_lit.kind) &&1119 {
1125 is_num_lit_unsigned(type2->data.num_lit.kind))1120 if (num_lit_fits_in_other_type(g, prev_node, cur_type)) {
1121 prev_type = cur_type;
1122 prev_node = cur_node;
1123 continue;
1124 } else {
1125 return g->builtin_types.entry_invalid;
1126 }
1127 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||
1128 cur_type->id == TypeTableEntryIdNumLitFloat)
1126 {1129 {
1127 codegen_num_lit_1->resolved_type = g->builtin_types.entry_u64;1130 if (num_lit_fits_in_other_type(g, cur_node, prev_type)) {
1128 codegen_num_lit_2->resolved_type = g->builtin_types.entry_u64;1131 continue;
1129 return g->builtin_types.entry_u64;1132 } else {
1133 return g->builtin_types.entry_invalid;
1134 }
1135 } else if (prev_type == cur_type) {
1136 continue;
1130 } else {1137 } else {
1131 return nullptr;1138 add_node_error(g, parent_source_node,
1132 }1139 buf_sprintf("incompatible types: '%s' and '%s'",
1133 } else if (type1->id == TypeTableEntryIdNumberLiteral) {1140 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
1134 return resolve_rhs_number_literal(g, node2, type2, node1, type1);
1135 } else {
1136 assert(type2->id == TypeTableEntryIdNumberLiteral);
1137 return resolve_rhs_number_literal(g, node1, type1, node2, type2);
1138 }
1139}
11401141
1141static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *node,1142 return g->builtin_types.entry_invalid;
1142 TypeTableEntry *type1, TypeTableEntry *type2, AstNode *node1, AstNode *node2)1143 }
1143{
1144 if (type1->id == TypeTableEntryIdInvalid ||
1145 type2->id == TypeTableEntryIdInvalid)
1146 {
1147 return type1;
1148 } else if (type1->id == TypeTableEntryIdUnreachable) {
1149 return type2;
1150 } else if (type2->id == TypeTableEntryIdUnreachable) {
1151 return type1;
1152 } else if (type1->id == TypeTableEntryIdInt &&
1153 type2->id == TypeTableEntryIdInt &&
1154 type1->data.integral.is_signed == type2->data.integral.is_signed)
1155 {
1156 return (type1->size_in_bits > type2->size_in_bits) ? type1 : type2;
1157 } else if (type1->id == TypeTableEntryIdFloat &&
1158 type2->id == TypeTableEntryIdFloat)
1159 {
1160 return (type1->size_in_bits > type2->size_in_bits) ? type1 : type2;
1161 } else if (type1->id == TypeTableEntryIdArray &&
1162 type2->id == TypeTableEntryIdArray &&
1163 type1 == type2)
1164 {
1165 return type1;
1166 } else if (type1->id == TypeTableEntryIdNumberLiteral ||
1167 type2->id == TypeTableEntryIdNumberLiteral)
1168 {
1169 TypeTableEntry *resolved_type = resolve_number_literals(g, node1, node2, type1, type2);
1170 if (resolved_type)
1171 return resolved_type;
1172 } else if (type1 == type2) {
1173 return type1;
1174 }1144 }
11751145 return prev_type;
1176 add_node_error(g, node,
1177 buf_sprintf("incompatible types: '%s' and '%s'",
1178 buf_ptr(&type1->name), buf_ptr(&type2->name)));
1179
1180 return g->builtin_types.entry_invalid;
1181}1146}
11821147
1183static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *context, AstNode *node,1148static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *context, AstNode *node,
...@@ -1192,16 +1157,6 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont...@@ -1192,16 +1157,6 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
1192 if (actual_type->id == TypeTableEntryIdUnreachable)1157 if (actual_type->id == TypeTableEntryIdUnreachable)
1193 return actual_type; // sorry toots; gotta run. good luck with that expected type.1158 return actual_type; // sorry toots; gotta run. good luck with that expected type.
11941159
1195 if (actual_type->id == TypeTableEntryIdNumberLiteral &&
1196 num_lit_fits_in_other_type(g, actual_type, expected_type))
1197 {
1198 NumLitCodeGen *num_lit_code_gen = get_resolved_num_lit(node);
1199 assert(!num_lit_code_gen->resolved_type ||
1200 num_lit_code_gen->resolved_type == expected_type);
1201 num_lit_code_gen->resolved_type = expected_type;
1202 return expected_type;
1203 }
1204
1205 if (expected_type->id == TypeTableEntryIdMaybe &&1160 if (expected_type->id == TypeTableEntryIdMaybe &&
1206 actual_type->id == TypeTableEntryIdMaybe)1161 actual_type->id == TypeTableEntryIdMaybe)
1207 {1162 {
...@@ -1283,6 +1238,16 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont...@@ -1283,6 +1238,16 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
1283 return expected_type;1238 return expected_type;
1284 }1239 }
12851240
1241 if ((actual_type->id == TypeTableEntryIdNumLitFloat ||
1242 actual_type->id == TypeTableEntryIdNumLitInt))
1243 {
1244 if (num_lit_fits_in_other_type(g, node, expected_type)) {
1245 return expected_type;
1246 } else {
1247 return g->builtin_types.entry_invalid;
1248 }
1249 }
1250
1286 add_node_error(g, first_executing_node(node),1251 add_node_error(g, first_executing_node(node),
1287 buf_sprintf("expected type '%s', got '%s'",1252 buf_sprintf("expected type '%s', got '%s'",
1288 buf_ptr(&expected_type->name),1253 buf_ptr(&expected_type->name),
...@@ -1292,23 +1257,23 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont...@@ -1292,23 +1257,23 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
1292}1257}
12931258
1294static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, BlockContext *block_context,1259static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, BlockContext *block_context,
1295 AstNode *parent_node,1260 AstNode *parent_source_node,
1296 AstNode *child1, AstNode *child2,1261 AstNode **child_nodes, TypeTableEntry **child_types, int child_count)
1297 TypeTableEntry *type1, TypeTableEntry *type2)
1298{1262{
1299 assert(type1);1263 assert(child_count > 0);
1300 assert(type2);
13011264
1302 TypeTableEntry *parent_type = determine_peer_type_compatibility(g, parent_node, type1, type2, child1, child2);1265 TypeTableEntry *expected_type = determine_peer_type_compatibility(g, parent_source_node,
1266 child_nodes, child_types, child_count);
13031267
1304 if (parent_type->id == TypeTableEntryIdInvalid) {1268 if (expected_type->id == TypeTableEntryIdInvalid) {
1305 return parent_type;1269 return expected_type;
1306 }1270 }
13071271
1308 resolve_type_compatibility(g, block_context, child1, parent_type, type1);1272 for (int i = 0; i < child_count; i += 1) {
1309 resolve_type_compatibility(g, block_context, child2, parent_type, type2);1273 resolve_type_compatibility(g, block_context, child_nodes[i], expected_type, child_types[i]);
1274 }
13101275
1311 return parent_type;1276 return expected_type;
1312}1277}
13131278
1314BlockContext *new_block_context(AstNode *node, BlockContext *parent) {1279BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
...@@ -1732,12 +1697,58 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As...@@ -1732,12 +1697,58 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As
1732{1697{
1733 Expr *expr = get_resolved_expr(node);1698 Expr *expr = get_resolved_expr(node);
1734 expr->const_val.ok = true;1699 expr->const_val.ok = true;
1735 expr->const_val.data.x_uint = x;1700
1736 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, x);1701 bignum_init_unsigned(&expr->const_val.data.x_bignum, x);
1737 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);1702
1738 return resolved_type ? resolved_type : num_lit_type;1703 if (expected_type) {
1704 if (expected_type->id == TypeTableEntryIdMaybe) {
1705 return g->builtin_types.entry_num_lit_int;
1706 } else {
1707 num_lit_fits_in_other_type(g, node, expected_type);
1708 return expected_type;
1709 }
1710 } else {
1711 return g->builtin_types.entry_num_lit_int;
1712 }
1713}
1714
1715static TypeTableEntry *resolve_expr_const_val_as_float_num_lit(CodeGen *g, AstNode *node,
1716 TypeTableEntry *expected_type, double x)
1717{
1718 Expr *expr = get_resolved_expr(node);
1719 expr->const_val.ok = true;
1720
1721 bignum_init_float(&expr->const_val.data.x_bignum, x);
1722
1723 if (expected_type) {
1724 num_lit_fits_in_other_type(g, node, expected_type);
1725 return expected_type;
1726 } else {
1727 return g->builtin_types.entry_num_lit_float;
1728 }
1729}
1730
1731static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *node,
1732 bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), AstNode *op1, AstNode *op2,
1733 TypeTableEntry *resolved_type)
1734{
1735 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
1736 ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
1737 ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
1738
1739 const_val->ok = true;
1740
1741 if (bignum_fn(&const_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum)) {
1742 add_node_error(g, node,
1743 buf_sprintf("value cannot be represented in any integer type"));
1744 } else {
1745 num_lit_fits_in_other_type(g, node, resolved_type);
1746 }
1747
1748 return resolved_type;
1739}1749}
17401750
1751
1741static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1752static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1742 TypeTableEntry *expected_type, AstNode *node)1753 TypeTableEntry *expected_type, AstNode *node)
1743{1754{
...@@ -1918,60 +1929,6 @@ static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {...@@ -1918,60 +1929,6 @@ static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
1918 }1929 }
1919}1930}
19201931
1921static bool eval_bool_bin_op_signed(int64_t a, BinOpType bin_op, int64_t b) {
1922 if (bin_op == BinOpTypeCmpEq) {
1923 return a == b;
1924 } else if (bin_op == BinOpTypeCmpNotEq) {
1925 return a != b;
1926 } else if (bin_op == BinOpTypeCmpLessThan) {
1927 return a < b;
1928 } else if (bin_op == BinOpTypeCmpGreaterThan) {
1929 return a > b;
1930 } else if (bin_op == BinOpTypeCmpLessOrEq) {
1931 return a <= b;
1932 } else if (bin_op == BinOpTypeCmpGreaterOrEq) {
1933 return a >= b;
1934 } else {
1935 zig_unreachable();
1936 }
1937}
1938
1939static bool eval_bool_bin_op_unsigned(uint64_t a, BinOpType bin_op, uint64_t b) {
1940 if (bin_op == BinOpTypeCmpEq) {
1941 return a == b;
1942 } else if (bin_op == BinOpTypeCmpNotEq) {
1943 return a != b;
1944 } else if (bin_op == BinOpTypeCmpLessThan) {
1945 return a < b;
1946 } else if (bin_op == BinOpTypeCmpGreaterThan) {
1947 return a > b;
1948 } else if (bin_op == BinOpTypeCmpLessOrEq) {
1949 return a <= b;
1950 } else if (bin_op == BinOpTypeCmpGreaterOrEq) {
1951 return a >= b;
1952 } else {
1953 zig_unreachable();
1954 }
1955}
1956
1957static bool eval_bool_bin_op_float(double a, BinOpType bin_op, double b) {
1958 if (bin_op == BinOpTypeCmpEq) {
1959 return a == b;
1960 } else if (bin_op == BinOpTypeCmpNotEq) {
1961 return a != b;
1962 } else if (bin_op == BinOpTypeCmpLessThan) {
1963 return a < b;
1964 } else if (bin_op == BinOpTypeCmpGreaterThan) {
1965 return a > b;
1966 } else if (bin_op == BinOpTypeCmpLessOrEq) {
1967 return a <= b;
1968 } else if (bin_op == BinOpTypeCmpGreaterOrEq) {
1969 return a >= b;
1970 } else {
1971 zig_unreachable();
1972 }
1973}
1974
1975static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1932static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1976 AstNode *node)1933 AstNode *node)
1977{1934{
...@@ -1983,8 +1940,11 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im...@@ -1983,8 +1940,11 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
1983 TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, op1);1940 TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, op1);
1984 TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, op2);1941 TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, op2);
19851942
1943 AstNode *op_nodes[] = {op1, op2};
1944 TypeTableEntry *op_types[] = {op1_type, op2_type};
1945
1986 TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, context, node,1946 TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, context, node,
1987 op1, op2, op1_type, op2_type);1947 op_nodes, op_types, 2);
19881948
1989 if (resolved_type->id == TypeTableEntryIdInvalid) {1949 if (resolved_type->id == TypeTableEntryIdInvalid) {
1990 return g->builtin_types.entry_invalid;1950 return g->builtin_types.entry_invalid;
...@@ -1997,20 +1957,30 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im...@@ -1997,20 +1957,30 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
1997 }1957 }
19981958
1999 bool answer;1959 bool answer;
2000 if (resolved_type->id == TypeTableEntryIdInt) {1960 if (resolved_type->id == TypeTableEntryIdNumLitFloat ||
2001 if (op1_type->data.integral.is_signed &&1961 resolved_type->id == TypeTableEntryIdNumLitInt ||
2002 op2_type->data.integral.is_signed)1962 resolved_type->id == TypeTableEntryIdFloat ||
2003 {1963 resolved_type->id == TypeTableEntryIdInt)
2004 answer = eval_bool_bin_op_signed(op1_val->data.x_int, bin_op_type, op2_val->data.x_int);1964 {
2005 } else if (!op1_type->data.integral.is_signed &&1965 bool (*bignum_cmp)(BigNum *, BigNum *);
2006 !op2_type->data.integral.is_signed)1966 if (bin_op_type == BinOpTypeCmpEq) {
2007 {1967 bignum_cmp = bignum_cmp_eq;
2008 answer = eval_bool_bin_op_unsigned(op1_val->data.x_uint, bin_op_type, op2_val->data.x_uint);1968 } else if (bin_op_type == BinOpTypeCmpNotEq) {
1969 bignum_cmp = bignum_cmp_neq;
1970 } else if (bin_op_type == BinOpTypeCmpLessThan) {
1971 bignum_cmp = bignum_cmp_lt;
1972 } else if (bin_op_type == BinOpTypeCmpGreaterThan) {
1973 bignum_cmp = bignum_cmp_gt;
1974 } else if (bin_op_type == BinOpTypeCmpLessOrEq) {
1975 bignum_cmp = bignum_cmp_lte;
1976 } else if (bin_op_type == BinOpTypeCmpGreaterOrEq) {
1977 bignum_cmp = bignum_cmp_gte;
2009 } else {1978 } else {
2010 zig_unreachable();1979 zig_unreachable();
2011 }1980 }
2012 } else if (resolved_type->id == TypeTableEntryIdFloat) {1981
2013 answer = eval_bool_bin_op_float(op1_val->data.x_float, bin_op_type, op2_val->data.x_float);1982 answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum);
1983
2014 } else if (resolved_type->id == TypeTableEntryIdEnum) {1984 } else if (resolved_type->id == TypeTableEntryIdEnum) {
2015 ConstEnumValue *enum1 = &op1_val->data.x_enum;1985 ConstEnumValue *enum1 = &op1_val->data.x_enum;
2016 ConstEnumValue *enum2 = &op2_val->data.x_enum;1986 ConstEnumValue *enum2 = &op2_val->data.x_enum;
...@@ -2124,7 +2094,45 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -2124,7 +2094,45 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
2124 TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1);2094 TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1);
2125 TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2);2095 TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2);
21262096
2127 return resolve_peer_type_compatibility(g, context, node, op1, op2, lhs_type, rhs_type);2097 AstNode *op_nodes[] = {op1, op2};
2098 TypeTableEntry *op_types[] = {lhs_type, rhs_type};
2099
2100 TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, context, node,
2101 op_nodes, op_types, 2);
2102
2103 if (resolved_type->id == TypeTableEntryIdInvalid) {
2104 return resolved_type;
2105 }
2106
2107 ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
2108 ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
2109 if (!op1_val->ok || !op2_val->ok) {
2110 return resolved_type;
2111 }
2112
2113 if (bin_op_type == BinOpTypeAdd) {
2114 return resolve_expr_const_val_as_bignum_op(g, node, bignum_add, op1, op2, resolved_type);
2115 } else if (bin_op_type == BinOpTypeSub) {
2116 return resolve_expr_const_val_as_bignum_op(g, node, bignum_sub, op1, op2, resolved_type);
2117 } else if (bin_op_type == BinOpTypeMult) {
2118 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mul, op1, op2, resolved_type);
2119 } else if (bin_op_type == BinOpTypeDiv) {
2120 return resolve_expr_const_val_as_bignum_op(g, node, bignum_div, op1, op2, resolved_type);
2121 } else if (bin_op_type == BinOpTypeMod) {
2122 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mod, op1, op2, resolved_type);
2123 } else if (bin_op_type == BinOpTypeBinOr) {
2124 return resolve_expr_const_val_as_bignum_op(g, node, bignum_or, op1, op2, resolved_type);
2125 } else if (bin_op_type == BinOpTypeBinAnd) {
2126 return resolve_expr_const_val_as_bignum_op(g, node, bignum_and, op1, op2, resolved_type);
2127 } else if (bin_op_type == BinOpTypeBinXor) {
2128 return resolve_expr_const_val_as_bignum_op(g, node, bignum_xor, op1, op2, resolved_type);
2129 } else if (bin_op_type == BinOpTypeBitShiftLeft) {
2130 return resolve_expr_const_val_as_bignum_op(g, node, bignum_shl, op1, op2, resolved_type);
2131 } else if (bin_op_type == BinOpTypeBitShiftRight) {
2132 return resolve_expr_const_val_as_bignum_op(g, node, bignum_shr, op1, op2, resolved_type);
2133 } else {
2134 zig_unreachable();
2135 }
2128 }2136 }
2129 case BinOpTypeUnwrapMaybe:2137 case BinOpTypeUnwrapMaybe:
2130 {2138 {
...@@ -2197,6 +2205,8 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -2197,6 +2205,8 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
2197 AstNodeVariableDeclaration *variable_declaration,2205 AstNodeVariableDeclaration *variable_declaration,
2198 bool expr_is_maybe)2206 bool expr_is_maybe)
2199{2207{
2208 bool is_const = variable_declaration->is_const;
2209
2200 TypeTableEntry *explicit_type = nullptr;2210 TypeTableEntry *explicit_type = nullptr;
2201 if (variable_declaration->type != nullptr) {2211 if (variable_declaration->type != nullptr) {
2202 explicit_type = analyze_type_expr(g, import, context, variable_declaration->type);2212 explicit_type = analyze_type_expr(g, import, context, variable_declaration->type);
...@@ -2223,19 +2233,19 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -2223,19 +2233,19 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
2223 add_node_error(g, source_node,2233 add_node_error(g, source_node,
2224 buf_sprintf("variable initialization is unreachable"));2234 buf_sprintf("variable initialization is unreachable"));
2225 implicit_type = g->builtin_types.entry_invalid;2235 implicit_type = g->builtin_types.entry_invalid;
2226 } else if (implicit_type->id == TypeTableEntryIdNumberLiteral) {2236 } else if (!is_const &&
2227 add_node_error(g, source_node,2237 (implicit_type->id == TypeTableEntryIdNumLitFloat ||
2228 buf_sprintf("unable to infer variable type"));2238 implicit_type->id == TypeTableEntryIdNumLitInt))
2229 implicit_type = g->builtin_types.entry_invalid;
2230 } else if (implicit_type->id == TypeTableEntryIdMetaType &&
2231 !variable_declaration->is_const)
2232 {2239 {
2240 add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
2241 implicit_type = g->builtin_types.entry_invalid;
2242 } else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) {
2233 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));2243 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
2234 implicit_type = g->builtin_types.entry_invalid;2244 implicit_type = g->builtin_types.entry_invalid;
2235 }2245 }
2236 }2246 }
22372247
2238 if (implicit_type == nullptr && variable_declaration->is_const) {2248 if (implicit_type == nullptr && is_const) {
2239 add_node_error(g, source_node, buf_sprintf("const variable missing initialization"));2249 add_node_error(g, source_node, buf_sprintf("const variable missing initialization"));
2240 implicit_type = g->builtin_types.entry_invalid;2250 implicit_type = g->builtin_types.entry_invalid;
2241 }2251 }
...@@ -2244,7 +2254,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -2244,7 +2254,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
2244 assert(type != nullptr); // should have been caught by the parser2254 assert(type != nullptr); // should have been caught by the parser
22452255
2246 VariableTableEntry *var = add_local_var(g, source_node, context,2256 VariableTableEntry *var = add_local_var(g, source_node, context,
2247 &variable_declaration->symbol, type, variable_declaration->is_const);2257 &variable_declaration->symbol, type, is_const);
22482258
22492259
2250 bool is_pub = (variable_declaration->visib_mod != VisibModPrivate);2260 bool is_pub = (variable_declaration->visib_mod != VisibModPrivate);
...@@ -2300,28 +2310,15 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry...@@ -2300,28 +2310,15 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry
2300 return g->builtin_types.entry_invalid;2310 return g->builtin_types.entry_invalid;
2301 }2311 }
23022312
2303 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;2313 if (node->data.number_literal.kind == NumLitUInt) {
2304 const_val->ok = true;2314 return resolve_expr_const_val_as_unsigned_num_lit(g, node,
2305 if (is_num_lit_unsigned(node->data.number_literal.kind)) {2315 expected_type, node->data.number_literal.data.x_uint);
2306 const_val->data.x_uint = node->data.number_literal.data.x_uint;2316 } else if (node->data.number_literal.kind == NumLitFloat) {
2307 } else if (is_num_lit_float(node->data.number_literal.kind)) {2317 return resolve_expr_const_val_as_float_num_lit(g, node,
2308 const_val->data.x_float = node->data.number_literal.data.x_float;2318 expected_type, node->data.number_literal.data.x_float);
2309 } else {2319 } else {
2310 zig_unreachable();2320 zig_unreachable();
2311 }2321 }
2312
2313 TypeTableEntry *num_lit_type = g->num_lit_types[node->data.number_literal.kind];
2314 if (expected_type) {
2315 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
2316 assert(!codegen_num_lit->resolved_type);
2317 TypeTableEntry *after_implicit_cast_resolved_type =
2318 resolve_type_compatibility(g, block_context, node, expected_type, num_lit_type);
2319 assert(codegen_num_lit->resolved_type ||
2320 after_implicit_cast_resolved_type->id == TypeTableEntryIdInvalid);
2321 return after_implicit_cast_resolved_type;
2322 } else {
2323 return num_lit_type;
2324 }
2325}2322}
23262323
2327static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,2324static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
...@@ -2353,8 +2350,15 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,...@@ -2353,8 +2350,15 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
23532350
2354 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;2351 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
2355 if (const_val->ok) {2352 if (const_val->ok) {
2356 return resolve_expr_const_val_as_type(g, node,2353 if (const_val->data.x_bignum.is_negative) {
2357 get_array_type(g, child_type, const_val->data.x_uint));2354 add_node_error(g, size_node,
2355 buf_sprintf("array size %s is negative",
2356 buf_ptr(bignum_to_buf(&const_val->data.x_bignum))));
2357 return g->builtin_types.entry_invalid;
2358 } else {
2359 return resolve_expr_const_val_as_type(g, node,
2360 get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint));
2361 }
2358 } else {2362 } else {
2359 return resolve_expr_const_val_as_type(g, node,2363 return resolve_expr_const_val_as_type(g, node,
2360 get_unknown_size_array_type(g, child_type, node->data.array_type.is_const));2364 get_unknown_size_array_type(g, child_type, node->data.array_type.is_const));
...@@ -2493,9 +2497,9 @@ static TypeTableEntry *analyze_if_then_else(CodeGen *g, ImportTableEntry *import...@@ -2493,9 +2497,9 @@ static TypeTableEntry *analyze_if_then_else(CodeGen *g, ImportTableEntry *import
2493 if (expected_type) {2497 if (expected_type) {
2494 return (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type;2498 return (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type;
2495 } else {2499 } else {
2496 return resolve_peer_type_compatibility(g, context, parent_node,2500 AstNode *op_nodes[] = {then_block, else_node};
2497 then_block, else_node,2501 TypeTableEntry *op_types[] = {then_type, else_type};
2498 then_type, else_type);2502 return resolve_peer_type_compatibility(g, context, parent_node, op_nodes, op_types, 2);
2499 }2503 }
2500}2504}
25012505
...@@ -2535,10 +2539,60 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor...@@ -2535,10 +2539,60 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
2535 if (type_entry->id == TypeTableEntryIdInvalid) {2539 if (type_entry->id == TypeTableEntryIdInvalid) {
2536 return g->builtin_types.entry_invalid;2540 return g->builtin_types.entry_invalid;
2537 } else if (type_entry->id == TypeTableEntryIdInt) {2541 } else if (type_entry->id == TypeTableEntryIdInt) {
2538 // TODO const expr eval for min/max int2542 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2543 const_val->ok = true;
2544 if (is_max) {
2545 if (type_entry->data.integral.is_signed) {
2546 int64_t val;
2547 if (type_entry->size_in_bits == 64) {
2548 val = INT64_MAX;
2549 } else if (type_entry->size_in_bits == 32) {
2550 val = INT32_MAX;
2551 } else if (type_entry->size_in_bits == 16) {
2552 val = INT16_MAX;
2553 } else if (type_entry->size_in_bits == 8) {
2554 val = INT8_MAX;
2555 } else {
2556 zig_unreachable();
2557 }
2558 bignum_init_signed(&const_val->data.x_bignum, val);
2559 } else {
2560 uint64_t val;
2561 if (type_entry->size_in_bits == 64) {
2562 val = UINT64_MAX;
2563 } else if (type_entry->size_in_bits == 32) {
2564 val = UINT32_MAX;
2565 } else if (type_entry->size_in_bits == 16) {
2566 val = UINT16_MAX;
2567 } else if (type_entry->size_in_bits == 8) {
2568 val = UINT8_MAX;
2569 } else {
2570 zig_unreachable();
2571 }
2572 bignum_init_unsigned(&const_val->data.x_bignum, val);
2573 }
2574 } else {
2575 if (type_entry->data.integral.is_signed) {
2576 int64_t val;
2577 if (type_entry->size_in_bits == 64) {
2578 val = INT64_MIN;
2579 } else if (type_entry->size_in_bits == 32) {
2580 val = INT32_MIN;
2581 } else if (type_entry->size_in_bits == 16) {
2582 val = INT16_MIN;
2583 } else if (type_entry->size_in_bits == 8) {
2584 val = INT8_MIN;
2585 } else {
2586 zig_unreachable();
2587 }
2588 bignum_init_signed(&const_val->data.x_bignum, val);
2589 } else {
2590 bignum_init_unsigned(&const_val->data.x_bignum, 0);
2591 }
2592 }
2539 return type_entry;2593 return type_entry;
2540 } else if (type_entry->id == TypeTableEntryIdFloat) {2594 } else if (type_entry->id == TypeTableEntryIdFloat) {
2541 // TODO const expr eval for min/max float2595 zig_panic("TODO analyze_min_max_value float");
2542 return type_entry;2596 return type_entry;
2543 } else if (type_entry->id == TypeTableEntryIdBool) {2597 } else if (type_entry->id == TypeTableEntryIdBool) {
2544 return resolve_expr_const_val_as_bool(g, node, is_max);2598 return resolve_expr_const_val_as_bool(g, node, is_max);
...@@ -2559,10 +2613,9 @@ static void eval_const_expr_implicit_cast(CodeGen *g, ImportTableEntry *import,...@@ -2559,10 +2613,9 @@ static void eval_const_expr_implicit_cast(CodeGen *g, ImportTableEntry *import,
2559 case CastOpPointerReinterpret:2613 case CastOpPointerReinterpret:
2560 {2614 {
2561 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;2615 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;
2562 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;2616 ConstExprValue *const_val = &cast->const_val;
2563 if (other_val != const_val) {2617 assert(const_val != other_val);
2564 *const_val = *other_val;2618 *const_val = *other_val;
2565 }
2566 break;2619 break;
2567 }2620 }
2568 case CastOpToUnknownSizeArray:2621 case CastOpToUnknownSizeArray:
...@@ -2571,14 +2624,11 @@ static void eval_const_expr_implicit_cast(CodeGen *g, ImportTableEntry *import,...@@ -2571,14 +2624,11 @@ static void eval_const_expr_implicit_cast(CodeGen *g, ImportTableEntry *import,
2571 case CastOpMaybeWrap:2624 case CastOpMaybeWrap:
2572 {2625 {
2573 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;2626 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;
2574 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;2627 ConstExprValue *const_val = &cast->const_val;
2575 if (!other_val->ok) {2628 if (!other_val->ok) {
2576 break;2629 break;
2577 } else if (const_val == other_val) {
2578 ConstExprValue *new_val = allocate<ConstExprValue>(1);
2579 memcpy(new_val, other_val, sizeof(ConstExprValue));
2580 other_val = new_val;
2581 }2630 }
2631 assert(const_val != other_val);
25822632
2583 const_val->data.x_maybe = other_val;2633 const_val->data.x_maybe = other_val;
2584 const_val->ok = true;2634 const_val->ok = true;
...@@ -2635,12 +2685,10 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -2635,12 +2685,10 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
2635 context->cast_expr_alloca_list.append(cast);2685 context->cast_expr_alloca_list.append(cast);
2636 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);2686 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
2637 return wanted_type;2687 return wanted_type;
2638 } else if (actual_type->id == TypeTableEntryIdNumberLiteral &&2688 } else if (actual_type->id == TypeTableEntryIdNumLitFloat ||
2639 num_lit_fits_in_other_type(g, actual_type, wanted_type))2689 actual_type->id == TypeTableEntryIdNumLitInt)
2640 {2690 {
2641 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(expr_node);2691 num_lit_fits_in_other_type(g, expr_node, wanted_type);
2642 assert(!codegen_num_lit->resolved_type);
2643 codegen_num_lit->resolved_type = wanted_type;
2644 cast->op = CastOpNothing;2692 cast->op = CastOpNothing;
2645 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);2693 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
2646 return wanted_type;2694 return wanted_type;
...@@ -2998,7 +3046,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -2998,7 +3046,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
2998 return g->builtin_types.entry_bool;3046 return g->builtin_types.entry_bool;
2999 }3047 }
30003048
3001 bool answer = target_const_val->data.x_bool;3049 bool answer = !target_const_val->data.x_bool;
3002 return resolve_expr_const_val_as_bool(g, node, answer);3050 return resolve_expr_const_val_as_bool(g, node, answer);
3003 }3051 }
3004 case PrefixOpBinNot:3052 case PrefixOpBinNot:
...@@ -3008,8 +3056,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -3008,8 +3056,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
3008 if (expr_type->id == TypeTableEntryIdInvalid) {3056 if (expr_type->id == TypeTableEntryIdInvalid) {
3009 return expr_type;3057 return expr_type;
3010 } else if (expr_type->id == TypeTableEntryIdInt ||3058 } else if (expr_type->id == TypeTableEntryIdInt ||
3011 (expr_type->id == TypeTableEntryIdNumberLiteral &&3059 expr_type->id == TypeTableEntryIdNumLitInt)
3012 !is_num_lit_float(expr_type->data.num_lit.kind)))
3013 {3060 {
3014 return expr_type;3061 return expr_type;
3015 } else {3062 } else {
...@@ -3017,6 +3064,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -3017,6 +3064,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
3017 buf_ptr(&expr_type->name)));3064 buf_ptr(&expr_type->name)));
3018 return g->builtin_types.entry_invalid;3065 return g->builtin_types.entry_invalid;
3019 }3066 }
3067 // TODO const expr eval
3020 }3068 }
3021 case PrefixOpNegation:3069 case PrefixOpNegation:
3022 {3070 {
...@@ -3030,13 +3078,16 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -3030,13 +3078,16 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
3030 return expr_type;3078 return expr_type;
3031 } else if (expr_type->id == TypeTableEntryIdFloat) {3079 } else if (expr_type->id == TypeTableEntryIdFloat) {
3032 return expr_type;3080 return expr_type;
3033 } else if (expr_type->id == TypeTableEntryIdNumberLiteral) {3081 } else if (expr_type->id == TypeTableEntryIdNumLitInt) {
3082 return expr_type;
3083 } else if (expr_type->id == TypeTableEntryIdNumLitFloat) {
3034 return expr_type;3084 return expr_type;
3035 } else {3085 } else {
3036 add_node_error(g, node, buf_sprintf("invalid negation type: '%s'",3086 add_node_error(g, node, buf_sprintf("invalid negation type: '%s'",
3037 buf_ptr(&expr_type->name)));3087 buf_ptr(&expr_type->name)));
3038 return g->builtin_types.entry_invalid;3088 return g->builtin_types.entry_invalid;
3039 }3089 }
3090 // TODO const expr eval
3040 }3091 }
3041 case PrefixOpAddressOf:3092 case PrefixOpAddressOf:
3042 case PrefixOpConstAddressOf:3093 case PrefixOpConstAddressOf:
...@@ -4129,59 +4180,6 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -4129,59 +4180,6 @@ Expr *get_resolved_expr(AstNode *node) {
4129 zig_unreachable();4180 zig_unreachable();
4130}4181}
41314182
4132NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
4133 switch (node->type) {
4134 case NodeTypeNumberLiteral:
4135 return &node->data.number_literal.codegen;
4136 case NodeTypeErrorLiteral:
4137 return &node->data.error_literal.codegen;
4138 case NodeTypeFnCallExpr:
4139 return &node->data.fn_call_expr.resolved_num_lit;
4140 case NodeTypeReturnExpr:
4141 case NodeTypeBinOpExpr:
4142 case NodeTypePrefixOpExpr:
4143 case NodeTypeArrayAccessExpr:
4144 case NodeTypeSliceExpr:
4145 case NodeTypeFieldAccessExpr:
4146 case NodeTypeIfBoolExpr:
4147 case NodeTypeIfVarExpr:
4148 case NodeTypeWhileExpr:
4149 case NodeTypeForExpr:
4150 case NodeTypeSwitchExpr:
4151 case NodeTypeSwitchProng:
4152 case NodeTypeSwitchRange:
4153 case NodeTypeAsmExpr:
4154 case NodeTypeContainerInitExpr:
4155 case NodeTypeRoot:
4156 case NodeTypeRootExportDecl:
4157 case NodeTypeFnProto:
4158 case NodeTypeFnDef:
4159 case NodeTypeFnDecl:
4160 case NodeTypeParamDecl:
4161 case NodeTypeBlock:
4162 case NodeTypeExternBlock:
4163 case NodeTypeDirective:
4164 case NodeTypeVariableDeclaration:
4165 case NodeTypeStringLiteral:
4166 case NodeTypeCharLiteral:
4167 case NodeTypeSymbol:
4168 case NodeTypeUse:
4169 case NodeTypeBoolLiteral:
4170 case NodeTypeNullLiteral:
4171 case NodeTypeLabel:
4172 case NodeTypeGoto:
4173 case NodeTypeBreak:
4174 case NodeTypeContinue:
4175 case NodeTypeStructDecl:
4176 case NodeTypeStructField:
4177 case NodeTypeStructValueField:
4178 case NodeTypeArrayType:
4179 case NodeTypeErrorValueDecl:
4180 zig_unreachable();
4181 }
4182 zig_unreachable();
4183}
4184
4185TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {4183TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
4186 switch (node->type) {4184 switch (node->type) {
4187 case NodeTypeVariableDeclaration:4185 case NodeTypeVariableDeclaration:
src/analyze.hpp-1
...@@ -18,7 +18,6 @@ VariableTableEntry *find_variable(BlockContext *context, Buf *name);...@@ -18,7 +18,6 @@ VariableTableEntry *find_variable(BlockContext *context, Buf *name);
18TypeTableEntry *find_container(BlockContext *context, Buf *name);18TypeTableEntry *find_container(BlockContext *context, Buf *name);
19BlockContext *new_block_context(AstNode *node, BlockContext *parent);19BlockContext *new_block_context(AstNode *node, BlockContext *parent);
20Expr *get_resolved_expr(AstNode *node);20Expr *get_resolved_expr(AstNode *node);
21NumLitCodeGen *get_resolved_num_lit(AstNode *node);
22TopLevelDecl *get_resolved_top_level_decl(AstNode *node);21TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
23bool is_node_void_expr(AstNode *node);22bool is_node_void_expr(AstNode *node);
24TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);23TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
src/bignum.cpp created+305
...@@ -0,0 +1,305 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "bignum.hpp"
9
10#include <assert.h>
11#include <math.h>
12
13static void bignum_normalize(BigNum *bn) {
14 assert(bn->kind == BigNumKindInt);
15 if (bn->data.x_uint == 0) {
16 bn->is_negative = false;
17 }
18}
19
20void bignum_init_float(BigNum *dest, double x) {
21 dest->kind = BigNumKindFloat;
22 dest->is_negative = false;
23 dest->data.x_float = x;
24}
25
26void bignum_init_unsigned(BigNum *dest, uint64_t x) {
27 dest->kind = BigNumKindInt;
28 dest->is_negative = false;
29 dest->data.x_uint = x;
30}
31
32void bignum_init_signed(BigNum *dest, int64_t x) {
33 dest->kind = BigNumKindInt;
34 if (x < 0) {
35 dest->is_negative = true;
36 dest->data.x_uint = ((uint64_t)(-(x + 1))) + 1;
37 } else {
38 dest->is_negative = false;
39 dest->data.x_uint = x;
40 }
41}
42
43bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) {
44 assert(bn->kind == BigNumKindInt);
45
46 if (is_signed) {
47 if (bn->data.x_uint <= ((uint64_t)(INT8_MAX)) + 1) {
48 return bit_count >= 8;
49 } else if (bn->data.x_uint <= ((uint64_t)(INT16_MAX)) + 1) {
50 return bit_count >= 16;
51 } else if (bn->data.x_uint <= ((uint64_t)(INT32_MAX)) + 1) {
52 return bit_count >= 32;
53 } else {
54 return bit_count >= 64;
55 }
56 } else {
57 if (bn->is_negative) {
58 return bn->data.x_uint == 0;
59 } else {
60 if (bn->data.x_uint <= UINT8_MAX) {
61 return bit_count >= 8;
62 } else if (bn->data.x_uint <= UINT16_MAX) {
63 return bit_count >= 16;
64 } else if (bn->data.x_uint <= UINT32_MAX) {
65 return bit_count >= 32;
66 } else {
67 return bit_count >= 64;
68 }
69 }
70 }
71}
72
73uint64_t bignum_to_twos_complement(BigNum *bn) {
74 assert(bn->kind == BigNumKindInt);
75
76 if (bn->is_negative) {
77 int64_t x = bn->data.x_uint;
78 return -x;
79 } else {
80 return bn->data.x_uint;
81 }
82}
83
84// returns true if overflow happened
85bool bignum_add(BigNum *dest, BigNum *op1, BigNum *op2) {
86 assert(op1->kind == op2->kind);
87 dest->kind = op1->kind;
88
89 if (dest->kind == BigNumKindFloat) {
90 dest->data.x_float = op1->data.x_float + op2->data.x_float;
91 return false;
92 }
93
94 if (op1->is_negative == op2->is_negative) {
95 return __builtin_uaddll_overflow(op1->data.x_uint, op2->data.x_uint, &dest->data.x_uint);
96 } else if (!op1->is_negative && op2->is_negative) {
97 if (__builtin_usubll_overflow(op1->data.x_uint, op2->data.x_uint, &dest->data.x_uint)) {
98 dest->data.x_uint = (UINT64_MAX - dest->data.x_uint) + 1;
99 dest->is_negative = true;
100 bignum_normalize(dest);
101 return false;
102 } else {
103 bignum_normalize(dest);
104 return false;
105 }
106 } else {
107 return bignum_add(dest, op2, op1);
108 }
109}
110
111void bignum_negate(BigNum *dest, BigNum *op) {
112 dest->kind = op->kind;
113
114 if (dest->kind == BigNumKindFloat) {
115 dest->data.x_float = -dest->data.x_float;
116 } else {
117 dest->data.x_uint = op->data.x_uint;
118 dest->is_negative = !op->is_negative;
119 bignum_normalize(dest);
120 }
121}
122
123bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2) {
124 BigNum op2_negated;
125 bignum_negate(&op2_negated, op2);
126 return bignum_add(dest, op1, &op2_negated);
127}
128
129bool bignum_mul(BigNum *dest, BigNum *op1, BigNum *op2) {
130 assert(op1->kind == op2->kind);
131 dest->kind = op1->kind;
132
133 if (dest->kind == BigNumKindFloat) {
134 dest->data.x_float = op1->data.x_float * op2->data.x_float;
135 bignum_normalize(dest);
136 return false;
137 }
138
139 if (__builtin_umulll_overflow(op1->data.x_uint, op2->data.x_uint, &dest->data.x_uint)) {
140 return true;
141 }
142
143 dest->is_negative = op1->is_negative != op2->is_negative;
144 bignum_normalize(dest);
145 return false;
146}
147
148bool bignum_div(BigNum *dest, BigNum *op1, BigNum *op2) {
149 assert(op1->kind == op2->kind);
150 dest->kind = op1->kind;
151
152 if (dest->kind == BigNumKindFloat) {
153 dest->data.x_float = op1->data.x_float / op2->data.x_float;
154 } else {
155 dest->data.x_uint = op1->data.x_uint / op2->data.x_uint;
156 dest->is_negative = op1->is_negative != op2->is_negative;
157 bignum_normalize(dest);
158 }
159 return false;
160}
161
162bool bignum_mod(BigNum *dest, BigNum *op1, BigNum *op2) {
163 assert(op1->kind == op2->kind);
164 dest->kind = op1->kind;
165
166 if (dest->kind == BigNumKindFloat) {
167 dest->data.x_float = fmod(op1->data.x_float, op2->data.x_float);
168 } else {
169 if (op1->is_negative || op2->is_negative) {
170 zig_panic("TODO handle mod with negative numbers");
171 }
172 dest->data.x_uint = op1->data.x_uint % op2->data.x_uint;
173 bignum_normalize(dest);
174 }
175 return false;
176}
177
178bool bignum_or(BigNum *dest, BigNum *op1, BigNum *op2) {
179 assert(op1->kind == BigNumKindInt);
180 assert(op2->kind == BigNumKindInt);
181
182 assert(!op1->is_negative);
183 assert(!op2->is_negative);
184
185 dest->kind = BigNumKindInt;
186 dest->data.x_uint = op1->data.x_uint | op2->data.x_uint;
187 return false;
188}
189
190bool bignum_and(BigNum *dest, BigNum *op1, BigNum *op2) {
191 assert(op1->kind == BigNumKindInt);
192 assert(op2->kind == BigNumKindInt);
193
194 assert(!op1->is_negative);
195 assert(!op2->is_negative);
196
197 dest->kind = BigNumKindInt;
198 dest->data.x_uint = op1->data.x_uint & op2->data.x_uint;
199 return false;
200}
201
202bool bignum_xor(BigNum *dest, BigNum *op1, BigNum *op2) {
203 assert(op1->kind == BigNumKindInt);
204 assert(op2->kind == BigNumKindInt);
205
206 assert(!op1->is_negative);
207 assert(!op2->is_negative);
208
209 dest->kind = BigNumKindInt;
210 dest->data.x_uint = op1->data.x_uint ^ op2->data.x_uint;
211 return false;
212}
213
214bool bignum_shl(BigNum *dest, BigNum *op1, BigNum *op2) {
215 assert(op1->kind == BigNumKindInt);
216 assert(op2->kind == BigNumKindInt);
217
218 assert(!op1->is_negative);
219 assert(!op2->is_negative);
220
221 dest->kind = BigNumKindInt;
222 dest->data.x_uint = op1->data.x_uint << op2->data.x_uint;
223 return false;
224}
225
226bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2) {
227 assert(op1->kind == BigNumKindInt);
228 assert(op2->kind == BigNumKindInt);
229
230 assert(!op1->is_negative);
231 assert(!op2->is_negative);
232
233 dest->kind = BigNumKindInt;
234 dest->data.x_uint = op1->data.x_uint >> op2->data.x_uint;
235 return false;
236}
237
238
239Buf *bignum_to_buf(BigNum *bn) {
240 if (bn->kind == BigNumKindFloat) {
241 return buf_sprintf("%f", bn->data.x_float);
242 } else {
243 const char *neg = bn->is_negative ? "-" : "";
244 return buf_sprintf("%s%llu", neg, bn->data.x_uint);
245 }
246}
247
248bool bignum_cmp_eq(BigNum *op1, BigNum *op2) {
249 assert(op1->kind == op2->kind);
250 if (op1->kind == BigNumKindFloat) {
251 return op1->data.x_float == op2->data.x_float;
252 } else {
253 return op1->data.x_uint == op2->data.x_uint &&
254 (op1->is_negative == op2->is_negative || op1->data.x_uint == 0);
255 }
256}
257
258bool bignum_cmp_neq(BigNum *op1, BigNum *op2) {
259 return !bignum_cmp_eq(op1, op2);
260}
261
262bool bignum_cmp_lt(BigNum *op1, BigNum *op2) {
263 return !bignum_cmp_gte(op1, op2);
264}
265
266bool bignum_cmp_gt(BigNum *op1, BigNum *op2) {
267 return !bignum_cmp_lte(op1, op2);
268}
269
270bool bignum_cmp_lte(BigNum *op1, BigNum *op2) {
271 assert(op1->kind == op2->kind);
272 if (op1->kind == BigNumKindFloat) {
273 return (op1->data.x_float <= op2->data.x_float);
274 }
275
276 // assume normalized is_negative
277 if (!op1->is_negative && !op2->is_negative) {
278 return op1->data.x_uint <= op2->data.x_uint;
279 } else if (op1->is_negative && op2->is_negative) {
280 return op1->data.x_uint >= op2->data.x_uint;
281 } else if (op1->is_negative && !op2->is_negative) {
282 return true;
283 } else {
284 return false;
285 }
286}
287
288bool bignum_cmp_gte(BigNum *op1, BigNum *op2) {
289 assert(op1->kind == op2->kind);
290
291 if (op1->kind == BigNumKindFloat) {
292 return (op1->data.x_float >= op2->data.x_float);
293 }
294
295 // assume normalized is_negative
296 if (!op1->is_negative && !op2->is_negative) {
297 return op1->data.x_uint >= op2->data.x_uint;
298 } else if (op1->is_negative && op2->is_negative) {
299 return op1->data.x_uint <= op2->data.x_uint;
300 } else if (op1->is_negative && !op2->is_negative) {
301 return false;
302 } else {
303 return true;
304 }
305}
src/bignum.hpp created+56
...@@ -0,0 +1,56 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "buffer.hpp"
9
10#include <stdint.h>
11
12enum BigNumKind {
13 BigNumKindInt,
14 BigNumKindFloat,
15};
16
17struct BigNum {
18 BigNumKind kind;
19 bool is_negative;
20 union {
21 unsigned long long x_uint;
22 double x_float;
23 } data;
24};
25
26void bignum_init_float(BigNum *dest, double x);
27void bignum_init_unsigned(BigNum *dest, uint64_t x);
28void bignum_init_signed(BigNum *dest, int64_t x);
29
30bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed);
31uint64_t bignum_to_twos_complement(BigNum *bn);
32
33// returns true if overflow happened
34bool bignum_add(BigNum *dest, BigNum *op1, BigNum *op2);
35bool bignum_sub(BigNum *dest, BigNum *op1, BigNum *op2);
36bool bignum_mul(BigNum *dest, BigNum *op1, BigNum *op2);
37bool bignum_div(BigNum *dest, BigNum *op1, BigNum *op2);
38bool bignum_mod(BigNum *dest, BigNum *op1, BigNum *op2);
39
40bool bignum_or(BigNum *dest, BigNum *op1, BigNum *op2);
41bool bignum_and(BigNum *dest, BigNum *op1, BigNum *op2);
42bool bignum_xor(BigNum *dest, BigNum *op1, BigNum *op2);
43bool bignum_shl(BigNum *dest, BigNum *op1, BigNum *op2);
44bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2);
45
46void bignum_negate(BigNum *dest, BigNum *op);
47
48// returns the result of the comparison
49bool bignum_cmp_eq(BigNum *op1, BigNum *op2);
50bool bignum_cmp_neq(BigNum *op1, BigNum *op2);
51bool bignum_cmp_lt(BigNum *op1, BigNum *op2);
52bool bignum_cmp_gt(BigNum *op1, BigNum *op2);
53bool bignum_cmp_lte(BigNum *op1, BigNum *op2);
54bool bignum_cmp_gte(BigNum *op1, BigNum *op2);
55
56Buf *bignum_to_buf(BigNum *bn);
src/codegen.cpp+50-119
...@@ -118,6 +118,9 @@ static TypeTableEntry *get_expr_type(AstNode *node) {...@@ -118,6 +118,9 @@ static TypeTableEntry *get_expr_type(AstNode *node) {
118 if (expr->implicit_cast.after_type) {118 if (expr->implicit_cast.after_type) {
119 return expr->implicit_cast.after_type;119 return expr->implicit_cast.after_type;
120 }120 }
121 if (expr->resolved_type) {
122 return expr->resolved_type;
123 }
121 return expr->type_entry;124 return expr->type_entry;
122}125}
123126
...@@ -131,29 +134,35 @@ static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_no...@@ -131,29 +134,35 @@ static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_no
131 }134 }
132}135}
133136
134static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,137static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *expr_node) {
135 NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)138 Expr *expr = get_resolved_expr(expr_node);
136{139 TypeTableEntry *type_entry = expr->resolved_type;
137 TypeTableEntry *type_entry = codegen_num_lit->resolved_type;140 if (!type_entry) {
141 type_entry = expr->type_entry;
142 }
138 assert(type_entry);143 assert(type_entry);
139144
140 // override the expression type for number literals145 ConstExprValue *const_val = &expr->const_val;
141 get_resolved_expr(source_node)->type_entry = type_entry;
142146
143 if (type_entry->id == TypeTableEntryIdInt) {147 assert(const_val->ok);
144 // here the union has int64_t and uint64_t and we purposefully read
145 // the uint64_t value in either case, because we want the twos
146 // complement representation
147148
149 if (type_entry->id == TypeTableEntryIdInt) {
150 assert(const_val->data.x_bignum.kind == BigNumKindInt);
148 return LLVMConstInt(type_entry->type_ref,151 return LLVMConstInt(type_entry->type_ref,
149 num_lit_node->data.x_uint,152 bignum_to_twos_complement(&const_val->data.x_bignum),
150 type_entry->data.integral.is_signed);153 type_entry->data.integral.is_signed);
151 } else if (type_entry->id == TypeTableEntryIdFloat) {154 } else if (type_entry->id == TypeTableEntryIdFloat) {
152155 if (const_val->data.x_bignum.kind == BigNumKindFloat) {
153 return LLVMConstReal(type_entry->type_ref,156 return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);
154 num_lit_node->data.x_float);157 } else {
158 int64_t x = const_val->data.x_bignum.data.x_uint;
159 if (const_val->data.x_bignum.is_negative) {
160 x = -x;
161 }
162 return LLVMConstReal(type_entry->type_ref, x);
163 }
155 } else {164 } else {
156 zig_panic("bad number literal type");165 zig_unreachable();
157 }166 }
158}167}
159168
...@@ -265,73 +274,10 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -265,73 +274,10 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
265 return nullptr;274 return nullptr;
266 }275 }
267 case BuiltinFnIdSizeof:276 case BuiltinFnIdSizeof:
268 {
269 assert(node->data.fn_call_expr.params.length == 1);
270 AstNode *type_node = node->data.fn_call_expr.params.at(0);
271 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
272
273 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
274 AstNodeNumberLiteral num_lit_node;
275 num_lit_node.kind = NumLitU64; // this field isn't even read
276 num_lit_node.overflow = false;
277 num_lit_node.data.x_uint = type_entry->size_in_bits / 8;
278 return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);
279 }
280 case BuiltinFnIdMinValue:277 case BuiltinFnIdMinValue:
281 {
282 assert(node->data.fn_call_expr.params.length == 1);
283 AstNode *type_node = node->data.fn_call_expr.params.at(0);
284 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
285
286
287 if (type_entry->id == TypeTableEntryIdInt) {
288 if (type_entry->data.integral.is_signed) {
289 return LLVMConstInt(type_entry->type_ref, 1ULL << (type_entry->size_in_bits - 1), false);
290 } else {
291 return LLVMConstNull(type_entry->type_ref);
292 }
293 } else if (type_entry->id == TypeTableEntryIdFloat) {
294 zig_panic("TODO codegen min_value float");
295 } else {
296 zig_unreachable();
297 }
298 }
299 case BuiltinFnIdMaxValue:278 case BuiltinFnIdMaxValue:
300 {
301 assert(node->data.fn_call_expr.params.length == 1);
302 AstNode *type_node = node->data.fn_call_expr.params.at(0);
303 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
304
305
306 if (type_entry->id == TypeTableEntryIdInt) {
307 if (type_entry->data.integral.is_signed) {
308 return LLVMConstInt(type_entry->type_ref, (1ULL << (type_entry->size_in_bits - 1)) - 1, false);
309 } else {
310 return LLVMConstAllOnes(type_entry->type_ref);
311 }
312 } else if (type_entry->id == TypeTableEntryIdFloat) {
313 zig_panic("TODO codegen max_value float");
314 } else {
315 zig_unreachable();
316 }
317 }
318 case BuiltinFnIdMemberCount:279 case BuiltinFnIdMemberCount:
319 {280 return gen_number_literal(g, node);
320 assert(node->data.fn_call_expr.params.length == 1);
321 AstNode *type_node = node->data.fn_call_expr.params.at(0);
322 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
323
324 if (type_entry->id == TypeTableEntryIdEnum) {
325 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
326 AstNodeNumberLiteral num_lit_node;
327 num_lit_node.kind = NumLitU64; // field ignored
328 num_lit_node.overflow = false;
329 num_lit_node.data.x_uint = type_entry->data.enumeration.field_count;
330 return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);
331 } else {
332 zig_unreachable();
333 }
334 }
335 }281 }
336 zig_unreachable();282 zig_unreachable();
337}283}
...@@ -1407,11 +1353,22 @@ static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) {...@@ -1407,11 +1353,22 @@ static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) {
1407 assert(node->data.if_bool_expr.condition);1353 assert(node->data.if_bool_expr.condition);
1408 assert(node->data.if_bool_expr.then_block);1354 assert(node->data.if_bool_expr.then_block);
14091355
1410 LLVMValueRef cond_value = gen_expr(g, node->data.if_bool_expr.condition);1356 ConstExprValue *const_val = &get_resolved_expr(node->data.if_bool_expr.condition)->const_val;
1357 if (const_val->ok) {
1358 if (const_val->data.x_bool) {
1359 return gen_expr(g, node->data.if_bool_expr.then_block);
1360 } else if (node->data.if_bool_expr.else_node) {
1361 return gen_expr(g, node->data.if_bool_expr.else_node);
1362 } else {
1363 return nullptr;
1364 }
1365 } else {
1366 LLVMValueRef cond_value = gen_expr(g, node->data.if_bool_expr.condition);
14111367
1412 return gen_if_bool_expr_raw(g, node, cond_value,1368 return gen_if_bool_expr_raw(g, node, cond_value,
1413 node->data.if_bool_expr.then_block,1369 node->data.if_bool_expr.then_block,
1414 node->data.if_bool_expr.else_node);1370 node->data.if_bool_expr.else_node);
1371 }
1415}1372}
14161373
1417static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {1374static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
...@@ -1932,15 +1889,6 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {...@@ -1932,15 +1889,6 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
1932 get_resolved_expr(node)->block_context, false, &init_val);1889 get_resolved_expr(node)->block_context, false, &init_val);
1933}1890}
19341891
1935static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *node) {
1936 assert(node->type == NodeTypeNumberLiteral);
1937
1938 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
1939 assert(codegen_num_lit);
1940
1941 return gen_number_literal_raw(g, node, codegen_num_lit, &node->data.number_literal);
1942}
1943
1944static LLVMValueRef gen_error_literal(CodeGen *g, AstNode *node) {1892static LLVMValueRef gen_error_literal(CodeGen *g, AstNode *node) {
1945 assert(node->type == NodeTypeErrorLiteral);1893 assert(node->type == NodeTypeErrorLiteral);
19461894
...@@ -2383,20 +2331,6 @@ static void add_int_overflow_fns(CodeGen *g, TypeTableEntry *type_entry) {...@@ -2383,20 +2331,6 @@ static void add_int_overflow_fns(CodeGen *g, TypeTableEntry *type_entry) {
2383 type_entry->data.integral.mul_with_overflow_fn = get_arithmetic_overflow_fn(g, type_entry, "smul", "umul");2331 type_entry->data.integral.mul_with_overflow_fn = get_arithmetic_overflow_fn(g, type_entry, "smul", "umul");
2384}2332}
23852333
2386static const NumLit num_lit_kinds[] = {
2387 NumLitF32,
2388 NumLitF64,
2389 NumLitF128,
2390 NumLitU8,
2391 NumLitU16,
2392 NumLitU32,
2393 NumLitU64,
2394 NumLitI8,
2395 NumLitI16,
2396 NumLitI32,
2397 NumLitI64,
2398};
2399
2400static const int int_sizes_in_bits[] = {2334static const int int_sizes_in_bits[] = {
2401 8,2335 8,
2402 16,2336 16,
...@@ -2411,18 +2345,15 @@ static void define_builtin_types(CodeGen *g) {...@@ -2411,18 +2345,15 @@ static void define_builtin_types(CodeGen *g) {
2411 buf_init_from_str(&entry->name, "(invalid)");2345 buf_init_from_str(&entry->name, "(invalid)");
2412 g->builtin_types.entry_invalid = entry;2346 g->builtin_types.entry_invalid = entry;
2413 }2347 }
24142348 {
2415 assert(NumLitCount == array_length(num_lit_kinds));2349 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
2416 for (int i = 0; i < NumLitCount; i += 1) {2350 buf_init_from_str(&entry->name, "(float literal)");
2417 NumLit num_lit_kind = num_lit_kinds[i];2351 g->builtin_types.entry_num_lit_float = entry;
2418 // This type should just create a constant with whatever actual number2352 }
2419 // type is expected at the time.2353 {
2420 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumberLiteral);2354 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitInt);
2421 buf_resize(&entry->name, 0);2355 buf_init_from_str(&entry->name, "(integer literal)");
2422 buf_appendf(&entry->name, "(%s literal)", num_lit_str(num_lit_kind));2356 g->builtin_types.entry_num_lit_int = entry;
2423 entry->data.num_lit.kind = num_lit_kind;
2424 entry->size_in_bits = num_lit_bit_count(num_lit_kind);
2425 g->num_lit_types[i] = entry;
2426 }2357 }
24272358
2428 for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) {2359 for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) {
src/parser.cpp+7-114
...@@ -301,13 +301,12 @@ void ast_print(AstNode *node, int indent) {...@@ -301,13 +301,12 @@ void ast_print(AstNode *node, int indent) {
301 break;301 break;
302 case NodeTypeNumberLiteral:302 case NodeTypeNumberLiteral:
303 {303 {
304 NumLit num_lit = node->data.number_literal.kind;304 NumLit kind = node->data.number_literal.kind;
305 const char *name = node_type_str(node->type);305 const char *name = node_type_str(node->type);
306 const char *kind_str = num_lit_str(num_lit);306 if (kind == NumLitUInt) {
307 if (is_num_lit_unsigned(num_lit)) {307 fprintf(stderr, "%s uint %" PRIu64 "\n", name, node->data.number_literal.data.x_uint);
308 fprintf(stderr, "%s %s %" PRIu64 "\n", name, kind_str, node->data.number_literal.data.x_uint);
309 } else {308 } else {
310 fprintf(stderr, "%s %s %f\n", name, kind_str, node->data.number_literal.data.x_float);309 fprintf(stderr, "%s float %f\n", name, node->data.number_literal.data.x_float);
311 }310 }
312 break;311 break;
313 }312 }
...@@ -808,16 +807,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -808,16 +807,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
808 if (num_lit->overflow) return;807 if (num_lit->overflow) return;
809808
810 num_lit->data.x_uint = whole_number;809 num_lit->data.x_uint = whole_number;
811810 num_lit->kind = NumLitUInt;
812 if (whole_number <= UINT8_MAX) {
813 num_lit->kind = NumLitU8;
814 } else if (whole_number <= UINT16_MAX) {
815 num_lit->kind = NumLitU16;
816 } else if (whole_number <= UINT32_MAX) {
817 num_lit->kind = NumLitU32;
818 } else {
819 num_lit->kind = NumLitU64;
820 }
821 } else {811 } else {
822 // float812 // float
823813
...@@ -834,7 +824,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -834,7 +824,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
834 }824 }
835 assert(str_end == buf_ptr(pc->buf) + token->end_pos);825 assert(str_end == buf_ptr(pc->buf) + token->end_pos);
836 num_lit->data.x_float = x;826 num_lit->data.x_float = x;
837 num_lit->kind = NumLitF64;827 num_lit->kind = NumLitFloat;
838 return;828 return;
839 }829 }
840830
...@@ -954,8 +944,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi...@@ -954,8 +944,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi
954 double x = *(double *)&double_bits;944 double x = *(double *)&double_bits;
955945
956 num_lit->data.x_float = x;946 num_lit->data.x_float = x;
957 // TODO: see if we can store it in f32947 num_lit->kind = NumLitFloat;
958 num_lit->kind = NumLitF64;
959 }948 }
960}949}
961950
...@@ -3053,99 +3042,3 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner,...@@ -3053,99 +3042,3 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner,
3053 pc.root = ast_parse_root(&pc, &token_index);3042 pc.root = ast_parse_root(&pc, &token_index);
3054 return pc.root;3043 return pc.root;
3055}3044}
3056
3057const char *num_lit_str(NumLit num_lit) {
3058 switch (num_lit) {
3059 case NumLitF32:
3060 return "f32";
3061 case NumLitF64:
3062 return "f64";
3063 case NumLitF128:
3064 return "f128";
3065 case NumLitU8:
3066 return "u8";
3067 case NumLitU16:
3068 return "u16";
3069 case NumLitU32:
3070 return "u32";
3071 case NumLitU64:
3072 return "u64";
3073 case NumLitI8:
3074 return "i8";
3075 case NumLitI16:
3076 return "i16";
3077 case NumLitI32:
3078 return "i32";
3079 case NumLitI64:
3080 return "i64";
3081 case NumLitCount:
3082 zig_unreachable();
3083 }
3084 zig_unreachable();
3085}
3086
3087bool is_num_lit_unsigned(NumLit num_lit) {
3088 switch (num_lit) {
3089 case NumLitF32:
3090 case NumLitF64:
3091 case NumLitF128:
3092 case NumLitI8:
3093 case NumLitI16:
3094 case NumLitI32:
3095 case NumLitI64:
3096 return false;
3097 case NumLitU8:
3098 case NumLitU16:
3099 case NumLitU32:
3100 case NumLitU64:
3101 return true;
3102 case NumLitCount:
3103 zig_unreachable();
3104 }
3105 zig_unreachable();
3106}
3107
3108bool is_num_lit_float(NumLit num_lit) {
3109 switch (num_lit) {
3110 case NumLitF32:
3111 case NumLitF64:
3112 case NumLitF128:
3113 return true;
3114 case NumLitU8:
3115 case NumLitU16:
3116 case NumLitU32:
3117 case NumLitU64:
3118 case NumLitI8:
3119 case NumLitI16:
3120 case NumLitI32:
3121 case NumLitI64:
3122 return false;
3123 case NumLitCount:
3124 zig_unreachable();
3125 }
3126 zig_unreachable();
3127}
3128
3129uint64_t num_lit_bit_count(NumLit num_lit) {
3130 switch (num_lit) {
3131 case NumLitU8:
3132 case NumLitI8:
3133 return 8;
3134 case NumLitU16:
3135 case NumLitI16:
3136 return 16;
3137 case NumLitU32:
3138 case NumLitI32:
3139 case NumLitF32:
3140 return 32;
3141 case NumLitU64:
3142 case NumLitI64:
3143 case NumLitF64:
3144 return 64;
3145 case NumLitF128:
3146 return 128;
3147 case NumLitCount:
3148 zig_unreachable();
3149 }
3150 zig_unreachable();
3151}
src/parser.hpp-6
...@@ -24,10 +24,4 @@ const char *node_type_str(NodeType node_type);...@@ -24,10 +24,4 @@ const char *node_type_str(NodeType node_type);
2424
25void ast_print(AstNode *node, int indent);25void ast_print(AstNode *node, int indent);
2626
27const char *num_lit_str(NumLit num_lit);
28bool is_num_lit_unsigned(NumLit num_lit);
29bool is_num_lit_float(NumLit num_lit);
30uint64_t num_lit_bit_count(NumLit num_lit);
31
32
33#endif27#endif
std/std.zig+1-1
...@@ -34,7 +34,7 @@ pub %.BadPerm;...@@ -34,7 +34,7 @@ pub %.BadPerm;
34pub %.PipeFail;34pub %.PipeFail;
35*/35*/
3636
37const buffer_size: u16 = 4 * 1024;37//const buffer_size: u16 = 4 * 1024;
38const max_u64_base10_digits: isize = 20;38const max_u64_base10_digits: isize = 20;
3939
40/*40/*
test/run_tests.cpp+1-1
...@@ -1323,7 +1323,7 @@ fn f() i32 => {...@@ -1323,7 +1323,7 @@ fn f() i32 => {
1323fn f() => {1323fn f() => {
1324 if (0) {}1324 if (0) {}
1325}1325}
1326 )SOURCE", 1, ".tmp_source.zig:3:9: error: expected type 'bool', got '(u8 literal)'");1326 )SOURCE", 1, ".tmp_source.zig:3:9: error: value 0 cannot be represented in type 'bool'");
13271327
1328 add_compile_fail_case("assign unreachable", R"SOURCE(1328 add_compile_fail_case("assign unreachable", R"SOURCE(
1329fn f() => {1329fn f() => {