| ... | @@ -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 | } |
| 123 | | 124 | |
| 124 | static NumLit get_number_literal_kind_unsigned(uint64_t x) { | 125 | static 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 | } |
| 135 | | 136 | |
| 136 | static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) { | 137 | static 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 | | | |
| 140 | static 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 | } |
| 143 | | 140 | |
| 144 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { | 141 | TypeTableEntry *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; |
| 662 | | 659 | |
| 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; |
| 668 | | 664 | |
| 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 | } |
| 1050 | | 1046 | |
| 1051 | static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) { | 1047 | static 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; |
| 1054 | | 1050 | 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 | | | |
| 1092 | static 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); | | |
| 1096 | | 1068 | |
| 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 | } |
| 1105 | | 1075 | |
| 1106 | static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstNode *node2, | 1076 | static 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 | } |
| 1114 | | 1084 | 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]; |
| 1117 | | 1087 | 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 | } | | |
| 1140 | | 1141 | |
| 1141 | static 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 | } |
| 1175 | | 1145 | 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 | } |
| 1182 | | 1147 | |
| 1183 | static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *context, AstNode *node, | 1148 | static 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. |
| 1194 | | 1159 | |
| 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 | } |
| 1285 | | 1240 | |
| | 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 | } |
| 1293 | | 1258 | |
| 1294 | static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, BlockContext *block_context, | 1259 | static 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); | | |
| 1301 | | 1264 | |
| 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); |
| 1303 | | 1267 | |
| 1304 | if (parent_type->id == TypeTableEntryIdInvalid) { | 1268 | if (expected_type->id == TypeTableEntryIdInvalid) { |
| 1305 | return parent_type; | 1269 | return expected_type; |
| 1306 | } | 1270 | } |
| 1307 | | 1271 | |
| 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 | } |
| 1310 | | 1275 | |
| 1311 | return parent_type; | 1276 | return expected_type; |
| 1312 | } | 1277 | } |
| 1313 | | 1278 | |
| 1314 | BlockContext *new_block_context(AstNode *node, BlockContext *parent) { | 1279 | BlockContext *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 | |
| | 1715 | static 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 | |
| | 1731 | static 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 | } |
| 1740 | | 1750 | |
| | 1751 | |
| 1741 | static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1752 | static 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 | } |
| 1920 | | 1931 | |
| 1921 | static 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 | | | |
| 1939 | static 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 | | | |
| 1957 | static 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 | | | |
| 1975 | static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1932 | static 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); |
| 1985 | | 1942 | |
| | 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); |
| 1988 | | 1948 | |
| 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 | } |
| 1998 | | 1958 | |
| 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); |
| 2126 | | 2096 | |
| 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 | } |
| 2237 | | 2247 | |
| 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 parser | 2254 | assert(type != nullptr); // should have been caught by the parser |
| 2245 | | 2255 | |
| 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); |
| 2248 | | 2258 | |
| 2249 | | 2259 | |
| 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 | } |
| 2302 | | 2312 | |
| 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 | } |
| 2326 | | 2323 | |
| 2327 | static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import, | 2324 | static 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, |
| 2353 | | 2350 | |
| 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 | } |
| 2501 | | 2505 | |
| ... | @@ -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 int | 2542 | 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 float | 2595 | 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); |
| 2582 | | 2632 | |
| 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 | } |
| 3000 | | 3048 | |
| 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 | } |
| 4131 | | 4182 | |
| 4132 | NumLitCodeGen *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 | | | |
| 4185 | TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { | 4183 | TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { |
| 4186 | switch (node->type) { | 4184 | switch (node->type) { |
| 4187 | case NodeTypeVariableDeclaration: | 4185 | case NodeTypeVariableDeclaration: |