| author | |
| committer | |
| log | 8552d7fd19836f3350b7303f9bd897708b966805 |
| tree | 0189be7c4bc284bfb693db3eb007844bd168b213 |
| parent | 3eb5afd245d8e2059a8cf4b8aa4e201ec0613535 |
instead of wrapping integer types
closes #15915 files changed, 370 insertions(+), 261 deletions(-)
doc/langref.md+15-27| ... | @@ -69,7 +69,7 @@ UnwrapError = "%%" option("|" "Symbol" "|") Expression | ... | @@ -69,7 +69,7 @@ UnwrapError = "%%" option("|" "Symbol" "|") Expression |
| 69 | 69 | ||
| 70 | AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression | 70 | AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression |
| 71 | 71 | ||
| 72 | AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | 72 | AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%=" |
| 73 | 73 | ||
| 74 | BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | 74 | BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression |
| 75 | 75 | ||
| ... | @@ -111,17 +111,17 @@ BinaryAndExpression = BitShiftExpression "&" BinaryAndExpression | BitShiftExpre | ... | @@ -111,17 +111,17 @@ BinaryAndExpression = BitShiftExpression "&" BinaryAndExpression | BitShiftExpre |
| 111 | 111 | ||
| 112 | BitShiftExpression = AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression | 112 | BitShiftExpression = AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression |
| 113 | 113 | ||
| 114 | BitShiftOperator = "<<" | ">>" | 114 | BitShiftOperator = "<<" | ">>" | "<<%" |
| 115 | 115 | ||
| 116 | AdditionExpression = MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression | 116 | AdditionExpression = MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression |
| 117 | 117 | ||
| 118 | AdditionOperator = "+" | "-" | "++" | 118 | AdditionOperator = "+" | "-" | "++" | "+%" | "-%" |
| 119 | 119 | ||
| 120 | MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression | 120 | MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression |
| 121 | 121 | ||
| 122 | CurlySuffixExpression = TypeExpr option(ContainerInitExpression) | 122 | CurlySuffixExpression = TypeExpr option(ContainerInitExpression) |
| 123 | 123 | ||
| 124 | MultiplyOperator = "*" | "/" | "%" | "**" | 124 | MultiplyOperator = "*" | "/" | "%" | "**" | "*%" |
| 125 | 125 | ||
| 126 | PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression | 126 | PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression |
| 127 | 127 | ||
| ... | @@ -141,7 +141,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") | ... | @@ -141,7 +141,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") |
| 141 | 141 | ||
| 142 | StructLiteralField = "." "Symbol" "=" Expression | 142 | StructLiteralField = "." "Symbol" "=" Expression |
| 143 | 143 | ||
| 144 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | 144 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%" |
| 145 | 145 | ||
| 146 | PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol") | 146 | PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol") |
| 147 | 147 | ||
| ... | @@ -181,26 +181,15 @@ x{} | ... | @@ -181,26 +181,15 @@ x{} |
| 181 | Type name C equivalent Description | 181 | Type name C equivalent Description |
| 182 | 182 | ||
| 183 | i8 int8_t signed 8-bit integer | 183 | i8 int8_t signed 8-bit integer |
| 184 | u8 (none) unsigned 8-bit integer | 184 | u8 uint8_t unsigned 8-bit integer |
| 185 | i16 int16_t signed 16-bit integer | 185 | i16 int16_t signed 16-bit integer |
| 186 | u16 (none) unsigned 16-bit integer | 186 | u16 uint16_t unsigned 16-bit integer |
| 187 | i32 int32_t signed 32-bit integer | 187 | i32 int32_t signed 32-bit integer |
| 188 | u32 (none) unsigned 32-bit integer | 188 | u32 uint32_t unsigned 32-bit integer |
| 189 | i64 int64_t signed 64-bit integer | 189 | i64 int64_t signed 64-bit integer |
| 190 | u64 (none) unsigned 64-bit integer | 190 | u64 uint64_t unsigned 64-bit integer |
| 191 | isize intptr_t signed pointer sized integer | 191 | isize intptr_t signed pointer sized integer |
| 192 | usize (none) unsigned pointer sized integer | 192 | usize uintptr_t unsigned pointer sized integer |
| 193 | |||
| 194 | i8w (none) wrapping signed 8-bit integer | ||
| 195 | u8w uint8_t wrapping unsigned 8-bit integer | ||
| 196 | i16w (none) wrapping signed 16-bit integer | ||
| 197 | u16w uint16_t wrapping unsigned 16-bit integer | ||
| 198 | i32w (none) wrapping signed 32-bit integer | ||
| 199 | u32w uint32_t wrapping unsigned 32-bit integer | ||
| 200 | i64w (none) wrapping signed 64-bit integer | ||
| 201 | u64w uint64_t wrapping unsigned 64-bit integer | ||
| 202 | isizew (none) wrapping signed pointer sized integer | ||
| 203 | usizew uintptr_t wrapping unsigned pointer sized integer | ||
| 204 | 193 | ||
| 205 | c_short short for ABI compatibility with C | 194 | c_short short for ABI compatibility with C |
| 206 | c_ushort unsigned short for ABI compatibility with C | 195 | c_ushort unsigned short for ABI compatibility with C |
| ... | @@ -213,8 +202,8 @@ c_ulonglong unsigned long long for ABI compatibility with C | ... | @@ -213,8 +202,8 @@ c_ulonglong unsigned long long for ABI compatibility with C |
| 213 | c_long_double long double for ABI compatibility with C | 202 | c_long_double long double for ABI compatibility with C |
| 214 | c_void void for ABI compatibility with C | 203 | c_void void for ABI compatibility with C |
| 215 | 204 | ||
| 216 | f32 float 32-bit IEE754 floating point | 205 | f32 float 32-bit floating point |
| 217 | f64 double 64-bit IEE754 floating point | 206 | f64 double 64-bit floating point |
| 218 | ``` | 207 | ``` |
| 219 | 208 | ||
| 220 | ### Boolean Type | 209 | ### Boolean Type |
| ... | @@ -595,9 +584,8 @@ const b: u8 = @truncate(u8, a); | ... | @@ -595,9 +584,8 @@ const b: u8 = @truncate(u8, a); |
| 595 | This function, when semantically analyzed, causes a compile error with the message `msg`. | 584 | This function, when semantically analyzed, causes a compile error with the message `msg`. |
| 596 | 585 | ||
| 597 | There are several ways that code avoids being semantically checked, such as using `if` | 586 | There are several ways that code avoids being semantically checked, such as using `if` |
| 598 | or `switch` with compile variables, and inline functions. | 587 | or `switch` with compile time constants, and inline functions. |
| 599 | 588 | ||
| 600 | ### @int_type(inline is_signed: bool, inline bit_count: u8, inline is_wrapping: bool) -> type | 589 | ### @int_type(inline is_signed: bool, inline bit_count: u8) -> type |
| 601 | 590 | ||
| 602 | This function returns an integer type with the given signness, bit count, and | 591 | This function returns an integer type with the given signness and bit count. |
| 603 | wrapping behavior. |
doc/vim/syntax/zig.vim-1| ... | @@ -17,7 +17,6 @@ syn keyword zigConstant null undefined | ... | @@ -17,7 +17,6 @@ syn keyword zigConstant null undefined |
| 17 | syn keyword zigKeyword fn use | 17 | syn keyword zigKeyword fn use |
| 18 | syn keyword zigType bool f32 f64 void unreachable type error | 18 | syn keyword zigType bool f32 f64 void unreachable type error |
| 19 | syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize | 19 | syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize |
| 20 | syn keyword zigType i8w u8w i16w u16w i32w u32w i64w u64w isizew usizew | ||
| 21 | syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong | 20 | syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong |
| 22 | 21 | ||
| 23 | syn keyword zigBoolean true false | 22 | syn keyword zigBoolean true false |
src/all_types.hpp+10-2| ... | @@ -315,11 +315,15 @@ enum BinOpType { | ... | @@ -315,11 +315,15 @@ enum BinOpType { |
| 315 | BinOpTypeInvalid, | 315 | BinOpTypeInvalid, |
| 316 | BinOpTypeAssign, | 316 | BinOpTypeAssign, |
| 317 | BinOpTypeAssignTimes, | 317 | BinOpTypeAssignTimes, |
| 318 | BinOpTypeAssignTimesWrap, | ||
| 318 | BinOpTypeAssignDiv, | 319 | BinOpTypeAssignDiv, |
| 319 | BinOpTypeAssignMod, | 320 | BinOpTypeAssignMod, |
| 320 | BinOpTypeAssignPlus, | 321 | BinOpTypeAssignPlus, |
| 322 | BinOpTypeAssignPlusWrap, | ||
| 321 | BinOpTypeAssignMinus, | 323 | BinOpTypeAssignMinus, |
| 324 | BinOpTypeAssignMinusWrap, | ||
| 322 | BinOpTypeAssignBitShiftLeft, | 325 | BinOpTypeAssignBitShiftLeft, |
| 326 | BinOpTypeAssignBitShiftLeftWrap, | ||
| 323 | BinOpTypeAssignBitShiftRight, | 327 | BinOpTypeAssignBitShiftRight, |
| 324 | BinOpTypeAssignBitAnd, | 328 | BinOpTypeAssignBitAnd, |
| 325 | BinOpTypeAssignBitXor, | 329 | BinOpTypeAssignBitXor, |
| ... | @@ -338,10 +342,14 @@ enum BinOpType { | ... | @@ -338,10 +342,14 @@ enum BinOpType { |
| 338 | BinOpTypeBinXor, | 342 | BinOpTypeBinXor, |
| 339 | BinOpTypeBinAnd, | 343 | BinOpTypeBinAnd, |
| 340 | BinOpTypeBitShiftLeft, | 344 | BinOpTypeBitShiftLeft, |
| 345 | BinOpTypeBitShiftLeftWrap, | ||
| 341 | BinOpTypeBitShiftRight, | 346 | BinOpTypeBitShiftRight, |
| 342 | BinOpTypeAdd, | 347 | BinOpTypeAdd, |
| 348 | BinOpTypeAddWrap, | ||
| 343 | BinOpTypeSub, | 349 | BinOpTypeSub, |
| 350 | BinOpTypeSubWrap, | ||
| 344 | BinOpTypeMult, | 351 | BinOpTypeMult, |
| 352 | BinOpTypeMultWrap, | ||
| 345 | BinOpTypeDiv, | 353 | BinOpTypeDiv, |
| 346 | BinOpTypeMod, | 354 | BinOpTypeMod, |
| 347 | BinOpTypeUnwrapMaybe, | 355 | BinOpTypeUnwrapMaybe, |
| ... | @@ -449,6 +457,7 @@ enum PrefixOp { | ... | @@ -449,6 +457,7 @@ enum PrefixOp { |
| 449 | PrefixOpBoolNot, | 457 | PrefixOpBoolNot, |
| 450 | PrefixOpBinNot, | 458 | PrefixOpBinNot, |
| 451 | PrefixOpNegation, | 459 | PrefixOpNegation, |
| 460 | PrefixOpNegationWrap, | ||
| 452 | PrefixOpAddressOf, | 461 | PrefixOpAddressOf, |
| 453 | PrefixOpConstAddressOf, | 462 | PrefixOpConstAddressOf, |
| 454 | PrefixOpDereference, | 463 | PrefixOpDereference, |
| ... | @@ -860,7 +869,6 @@ struct TypeTableEntryPointer { | ... | @@ -860,7 +869,6 @@ struct TypeTableEntryPointer { |
| 860 | struct TypeTableEntryInt { | 869 | struct TypeTableEntryInt { |
| 861 | int bit_count; | 870 | int bit_count; |
| 862 | bool is_signed; | 871 | bool is_signed; |
| 863 | bool is_wrapping; | ||
| 864 | }; | 872 | }; |
| 865 | 873 | ||
| 866 | struct TypeTableEntryFloat { | 874 | struct TypeTableEntryFloat { |
| ... | @@ -1185,7 +1193,7 @@ struct CodeGen { | ... | @@ -1185,7 +1193,7 @@ struct CodeGen { |
| 1185 | 1193 | ||
| 1186 | struct { | 1194 | struct { |
| 1187 | TypeTableEntry *entry_bool; | 1195 | TypeTableEntry *entry_bool; |
| 1188 | TypeTableEntry *entry_int[2][2][4]; // [signed,unsigned][wrapping,nonwrapping][8,16,32,64] | 1196 | TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64] |
| 1189 | TypeTableEntry *entry_c_int[CIntTypeCount]; | 1197 | TypeTableEntry *entry_c_int[CIntTypeCount]; |
| 1190 | TypeTableEntry *entry_c_long_double; | 1198 | TypeTableEntry *entry_c_long_double; |
| 1191 | TypeTableEntry *entry_c_void; | 1199 | TypeTableEntry *entry_c_void; |
src/analyze.cpp+49-35| ... | @@ -245,7 +245,7 @@ static bool is_slice(TypeTableEntry *type) { | ... | @@ -245,7 +245,7 @@ static bool is_slice(TypeTableEntry *type) { |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { | 247 | TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { |
| 248 | return get_int_type(g, false, false, bits_needed_for_unsigned(x)); | 248 | return get_int_type(g, false, bits_needed_for_unsigned(x)); |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | static TypeTableEntry *get_generic_fn_type(CodeGen *g, AstNode *decl_node) { | 251 | static TypeTableEntry *get_generic_fn_type(CodeGen *g, AstNode *decl_node) { |
| ... | @@ -2037,25 +2037,13 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa | ... | @@ -2037,25 +2037,13 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa |
| 2037 | continue; | 2037 | continue; |
| 2038 | } else if (prev_type->id == TypeTableEntryIdInt && | 2038 | } else if (prev_type->id == TypeTableEntryIdInt && |
| 2039 | cur_type->id == TypeTableEntryIdInt && | 2039 | cur_type->id == TypeTableEntryIdInt && |
| 2040 | prev_type->data.integral.is_signed == cur_type->data.integral.is_signed && | 2040 | prev_type->data.integral.is_signed == cur_type->data.integral.is_signed) |
| 2041 | (cur_type->data.integral.bit_count >= prev_type->data.integral.bit_count && | ||
| 2042 | (cur_type->data.integral.is_wrapping || !prev_type->data.integral.is_wrapping))) | ||
| 2043 | { | 2041 | { |
| 2044 | if (cur_type->data.integral.bit_count > prev_type->data.integral.bit_count) { | 2042 | if (cur_type->data.integral.bit_count > prev_type->data.integral.bit_count) { |
| 2045 | prev_type = cur_type; | 2043 | prev_type = cur_type; |
| 2046 | prev_node = cur_node; | 2044 | prev_node = cur_node; |
| 2047 | } else if (cur_type->data.integral.is_wrapping && !prev_type->data.integral.is_wrapping) { | ||
| 2048 | prev_type = cur_type; | ||
| 2049 | prev_node = cur_node; | ||
| 2050 | } | 2045 | } |
| 2051 | continue; | 2046 | continue; |
| 2052 | } else if (prev_type->id == TypeTableEntryIdInt && | ||
| 2053 | cur_type->id == TypeTableEntryIdInt && | ||
| 2054 | prev_type->data.integral.is_signed == cur_type->data.integral.is_signed && | ||
| 2055 | (prev_type->data.integral.bit_count >= cur_type->data.integral.bit_count && | ||
| 2056 | (prev_type->data.integral.is_wrapping || !cur_type->data.integral.is_wrapping))) | ||
| 2057 | { | ||
| 2058 | continue; | ||
| 2059 | } else if (prev_type->id == TypeTableEntryIdFloat && | 2047 | } else if (prev_type->id == TypeTableEntryIdFloat && |
| 2060 | cur_type->id == TypeTableEntryIdFloat) | 2048 | cur_type->id == TypeTableEntryIdFloat) |
| 2061 | { | 2049 | { |
| ... | @@ -2726,9 +2714,6 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i | ... | @@ -2726,9 +2714,6 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i |
| 2726 | } else if (buf_eql_str(field_name, "is_signed")) { | 2714 | } else if (buf_eql_str(field_name, "is_signed")) { |
| 2727 | return resolve_expr_const_val_as_bool(g, node, child_type->data.integral.is_signed, | 2715 | return resolve_expr_const_val_as_bool(g, node, child_type->data.integral.is_signed, |
| 2728 | depends_on_compile_var); | 2716 | depends_on_compile_var); |
| 2729 | } else if (buf_eql_str(field_name, "is_wrapping")) { | ||
| 2730 | return resolve_expr_const_val_as_bool(g, node, child_type->data.integral.is_wrapping, | ||
| 2731 | depends_on_compile_var); | ||
| 2732 | } else { | 2717 | } else { |
| 2733 | add_node_error(g, node, | 2718 | add_node_error(g, node, |
| 2734 | buf_sprintf("type '%s' has no member called '%s'", | 2719 | buf_sprintf("type '%s' has no member called '%s'", |
| ... | @@ -3122,15 +3107,19 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { | ... | @@ -3122,15 +3107,19 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 3122 | case BinOpTypeAssign: | 3107 | case BinOpTypeAssign: |
| 3123 | return true; | 3108 | return true; |
| 3124 | case BinOpTypeAssignTimes: | 3109 | case BinOpTypeAssignTimes: |
| 3110 | case BinOpTypeAssignTimesWrap: | ||
| 3125 | case BinOpTypeAssignDiv: | 3111 | case BinOpTypeAssignDiv: |
| 3126 | case BinOpTypeAssignMod: | 3112 | case BinOpTypeAssignMod: |
| 3127 | return type->id == TypeTableEntryIdInt || type->id == TypeTableEntryIdFloat; | 3113 | return type->id == TypeTableEntryIdInt || type->id == TypeTableEntryIdFloat; |
| 3128 | case BinOpTypeAssignPlus: | 3114 | case BinOpTypeAssignPlus: |
| 3115 | case BinOpTypeAssignPlusWrap: | ||
| 3129 | case BinOpTypeAssignMinus: | 3116 | case BinOpTypeAssignMinus: |
| 3117 | case BinOpTypeAssignMinusWrap: | ||
| 3130 | return type->id == TypeTableEntryIdInt || | 3118 | return type->id == TypeTableEntryIdInt || |
| 3131 | type->id == TypeTableEntryIdFloat || | 3119 | type->id == TypeTableEntryIdFloat || |
| 3132 | type->id == TypeTableEntryIdPointer; | 3120 | type->id == TypeTableEntryIdPointer; |
| 3133 | case BinOpTypeAssignBitShiftLeft: | 3121 | case BinOpTypeAssignBitShiftLeft: |
| 3122 | case BinOpTypeAssignBitShiftLeftWrap: | ||
| 3134 | case BinOpTypeAssignBitShiftRight: | 3123 | case BinOpTypeAssignBitShiftRight: |
| 3135 | case BinOpTypeAssignBitAnd: | 3124 | case BinOpTypeAssignBitAnd: |
| 3136 | case BinOpTypeAssignBitXor: | 3125 | case BinOpTypeAssignBitXor: |
| ... | @@ -3153,10 +3142,14 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { | ... | @@ -3153,10 +3142,14 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 3153 | case BinOpTypeBinXor: | 3142 | case BinOpTypeBinXor: |
| 3154 | case BinOpTypeBinAnd: | 3143 | case BinOpTypeBinAnd: |
| 3155 | case BinOpTypeBitShiftLeft: | 3144 | case BinOpTypeBitShiftLeft: |
| 3145 | case BinOpTypeBitShiftLeftWrap: | ||
| 3156 | case BinOpTypeBitShiftRight: | 3146 | case BinOpTypeBitShiftRight: |
| 3157 | case BinOpTypeAdd: | 3147 | case BinOpTypeAdd: |
| 3148 | case BinOpTypeAddWrap: | ||
| 3158 | case BinOpTypeSub: | 3149 | case BinOpTypeSub: |
| 3150 | case BinOpTypeSubWrap: | ||
| 3159 | case BinOpTypeMult: | 3151 | case BinOpTypeMult: |
| 3152 | case BinOpTypeMultWrap: | ||
| 3160 | case BinOpTypeDiv: | 3153 | case BinOpTypeDiv: |
| 3161 | case BinOpTypeMod: | 3154 | case BinOpTypeMod: |
| 3162 | case BinOpTypeUnwrapMaybe: | 3155 | case BinOpTypeUnwrapMaybe: |
| ... | @@ -3437,11 +3430,15 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -3437,11 +3430,15 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, |
| 3437 | switch (bin_op_type) { | 3430 | switch (bin_op_type) { |
| 3438 | case BinOpTypeAssign: | 3431 | case BinOpTypeAssign: |
| 3439 | case BinOpTypeAssignTimes: | 3432 | case BinOpTypeAssignTimes: |
| 3433 | case BinOpTypeAssignTimesWrap: | ||
| 3440 | case BinOpTypeAssignDiv: | 3434 | case BinOpTypeAssignDiv: |
| 3441 | case BinOpTypeAssignMod: | 3435 | case BinOpTypeAssignMod: |
| 3442 | case BinOpTypeAssignPlus: | 3436 | case BinOpTypeAssignPlus: |
| 3437 | case BinOpTypeAssignPlusWrap: | ||
| 3443 | case BinOpTypeAssignMinus: | 3438 | case BinOpTypeAssignMinus: |
| 3439 | case BinOpTypeAssignMinusWrap: | ||
| 3444 | case BinOpTypeAssignBitShiftLeft: | 3440 | case BinOpTypeAssignBitShiftLeft: |
| 3441 | case BinOpTypeAssignBitShiftLeftWrap: | ||
| 3445 | case BinOpTypeAssignBitShiftRight: | 3442 | case BinOpTypeAssignBitShiftRight: |
| 3446 | case BinOpTypeAssignBitAnd: | 3443 | case BinOpTypeAssignBitAnd: |
| 3447 | case BinOpTypeAssignBitXor: | 3444 | case BinOpTypeAssignBitXor: |
| ... | @@ -3481,10 +3478,14 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -3481,10 +3478,14 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, |
| 3481 | case BinOpTypeBinXor: | 3478 | case BinOpTypeBinXor: |
| 3482 | case BinOpTypeBinAnd: | 3479 | case BinOpTypeBinAnd: |
| 3483 | case BinOpTypeBitShiftLeft: | 3480 | case BinOpTypeBitShiftLeft: |
| 3481 | case BinOpTypeBitShiftLeftWrap: | ||
| 3484 | case BinOpTypeBitShiftRight: | 3482 | case BinOpTypeBitShiftRight: |
| 3485 | case BinOpTypeAdd: | 3483 | case BinOpTypeAdd: |
| 3484 | case BinOpTypeAddWrap: | ||
| 3486 | case BinOpTypeSub: | 3485 | case BinOpTypeSub: |
| 3486 | case BinOpTypeSubWrap: | ||
| 3487 | case BinOpTypeMult: | 3487 | case BinOpTypeMult: |
| 3488 | case BinOpTypeMultWrap: | ||
| 3488 | case BinOpTypeDiv: | 3489 | case BinOpTypeDiv: |
| 3489 | case BinOpTypeMod: | 3490 | case BinOpTypeMod: |
| 3490 | { | 3491 | { |
| ... | @@ -4911,42 +4912,35 @@ static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import, | ... | @@ -4911,42 +4912,35 @@ static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import, |
| 4911 | { | 4912 | { |
| 4912 | AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0); | 4913 | AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0); |
| 4913 | AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1); | 4914 | AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1); |
| 4914 | AstNode **is_wrap_node = &node->data.fn_call_expr.params.at(2); | ||
| 4915 | 4915 | ||
| 4916 | TypeTableEntry *bool_type = g->builtin_types.entry_bool; | 4916 | TypeTableEntry *bool_type = g->builtin_types.entry_bool; |
| 4917 | TypeTableEntry *usize_type = g->builtin_types.entry_usize; | 4917 | TypeTableEntry *usize_type = g->builtin_types.entry_usize; |
| 4918 | TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node); | 4918 | TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node); |
| 4919 | TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node); | 4919 | TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node); |
| 4920 | TypeTableEntry *is_wrap_type = analyze_expression(g, import, context, bool_type, *is_wrap_node); | ||
| 4921 | 4920 | ||
| 4922 | if (is_signed_type->id == TypeTableEntryIdInvalid || | 4921 | if (is_signed_type->id == TypeTableEntryIdInvalid || |
| 4923 | bit_count_type->id == TypeTableEntryIdInvalid || | 4922 | bit_count_type->id == TypeTableEntryIdInvalid) |
| 4924 | is_wrap_type->id == TypeTableEntryIdInvalid) | ||
| 4925 | { | 4923 | { |
| 4926 | return g->builtin_types.entry_invalid; | 4924 | return g->builtin_types.entry_invalid; |
| 4927 | } | 4925 | } |
| 4928 | 4926 | ||
| 4929 | ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val; | 4927 | ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val; |
| 4930 | ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val; | 4928 | ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val; |
| 4931 | ConstExprValue *is_wrap_val = &get_resolved_expr(*is_wrap_node)->const_val; | ||
| 4932 | 4929 | ||
| 4933 | AstNode *bad_node = nullptr; | 4930 | AstNode *bad_node = nullptr; |
| 4934 | if (!is_signed_val->ok) { | 4931 | if (!is_signed_val->ok) { |
| 4935 | bad_node = *is_signed_node; | 4932 | bad_node = *is_signed_node; |
| 4936 | } else if (!bit_count_val->ok) { | 4933 | } else if (!bit_count_val->ok) { |
| 4937 | bad_node = *bit_count_node; | 4934 | bad_node = *bit_count_node; |
| 4938 | } else if (!is_wrap_val->ok) { | ||
| 4939 | bad_node = *is_wrap_node; | ||
| 4940 | } | 4935 | } |
| 4941 | if (bad_node) { | 4936 | if (bad_node) { |
| 4942 | add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression")); | 4937 | add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression")); |
| 4943 | return g->builtin_types.entry_invalid; | 4938 | return g->builtin_types.entry_invalid; |
| 4944 | } | 4939 | } |
| 4945 | 4940 | ||
| 4946 | bool depends_on_compile_var = is_signed_val->depends_on_compile_var || | 4941 | bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var; |
| 4947 | bit_count_val->depends_on_compile_var || is_wrap_val->depends_on_compile_var; | ||
| 4948 | 4942 | ||
| 4949 | TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool, is_wrap_val->data.x_bool, | 4943 | TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool, |
| 4950 | bit_count_val->data.x_bignum.data.x_uint); | 4944 | bit_count_val->data.x_bignum.data.x_uint); |
| 4951 | return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var); | 4945 | return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var); |
| 4952 | 4946 | ||
| ... | @@ -5727,15 +5721,17 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo | ... | @@ -5727,15 +5721,17 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo |
| 5727 | // TODO const expr eval | 5721 | // TODO const expr eval |
| 5728 | } | 5722 | } |
| 5729 | case PrefixOpNegation: | 5723 | case PrefixOpNegation: |
| 5724 | case PrefixOpNegationWrap: | ||
| 5730 | { | 5725 | { |
| 5731 | TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node); | 5726 | TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node); |
| 5732 | if (expr_type->id == TypeTableEntryIdInvalid) { | 5727 | if (expr_type->id == TypeTableEntryIdInvalid) { |
| 5733 | return expr_type; | 5728 | return expr_type; |
| 5734 | } else if ((expr_type->id == TypeTableEntryIdInt && | 5729 | } else if ((expr_type->id == TypeTableEntryIdInt && |
| 5735 | expr_type->data.integral.is_signed) || | 5730 | expr_type->data.integral.is_signed) || |
| 5736 | expr_type->id == TypeTableEntryIdFloat || | ||
| 5737 | expr_type->id == TypeTableEntryIdNumLitInt || | 5731 | expr_type->id == TypeTableEntryIdNumLitInt || |
| 5738 | expr_type->id == TypeTableEntryIdNumLitFloat) | 5732 | ((expr_type->id == TypeTableEntryIdFloat || |
| 5733 | expr_type->id == TypeTableEntryIdNumLitFloat) && | ||
| 5734 | prefix_op != PrefixOpNegationWrap)) | ||
| 5739 | { | 5735 | { |
| 5740 | ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val; | 5736 | ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val; |
| 5741 | if (!target_const_val->ok) { | 5737 | if (!target_const_val->ok) { |
| ... | @@ -5745,10 +5741,28 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo | ... | @@ -5745,10 +5741,28 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo |
| 5745 | const_val->ok = true; | 5741 | const_val->ok = true; |
| 5746 | const_val->depends_on_compile_var = target_const_val->depends_on_compile_var; | 5742 | const_val->depends_on_compile_var = target_const_val->depends_on_compile_var; |
| 5747 | bignum_negate(&const_val->data.x_bignum, &target_const_val->data.x_bignum); | 5743 | bignum_negate(&const_val->data.x_bignum, &target_const_val->data.x_bignum); |
| 5744 | if (expr_type->id == TypeTableEntryIdFloat || | ||
| 5745 | expr_type->id == TypeTableEntryIdNumLitFloat || | ||
| 5746 | expr_type->id == TypeTableEntryIdNumLitInt) | ||
| 5747 | { | ||
| 5748 | return expr_type; | ||
| 5749 | } | ||
| 5750 | |||
| 5751 | bool overflow = !bignum_fits_in_bits(&const_val->data.x_bignum, | ||
| 5752 | expr_type->data.integral.bit_count, expr_type->data.integral.is_signed); | ||
| 5753 | if (prefix_op == PrefixOpNegationWrap) { | ||
| 5754 | if (overflow) { | ||
| 5755 | const_val->data.x_bignum.is_negative = true; | ||
| 5756 | } | ||
| 5757 | } else if (overflow) { | ||
| 5758 | add_node_error(g, *expr_node, buf_sprintf("negation caused overflow")); | ||
| 5759 | return g->builtin_types.entry_invalid; | ||
| 5760 | } | ||
| 5748 | return expr_type; | 5761 | return expr_type; |
| 5749 | } else { | 5762 | } else { |
| 5750 | add_node_error(g, node, buf_sprintf("invalid negation type: '%s'", | 5763 | const char *fmt = (prefix_op == PrefixOpNegationWrap) ? |
| 5751 | buf_ptr(&expr_type->name))); | 5764 | "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'"; |
| 5765 | add_node_error(g, node, buf_sprintf(fmt, buf_ptr(&expr_type->name))); | ||
| 5752 | return g->builtin_types.entry_invalid; | 5766 | return g->builtin_types.entry_invalid; |
| 5753 | } | 5767 | } |
| 5754 | } | 5768 | } |
| ... | @@ -7059,7 +7073,7 @@ bool is_node_void_expr(AstNode *node) { | ... | @@ -7059,7 +7073,7 @@ bool is_node_void_expr(AstNode *node) { |
| 7059 | return false; | 7073 | return false; |
| 7060 | } | 7074 | } |
| 7061 | 7075 | ||
| 7062 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits) { | 7076 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits) { |
| 7063 | int index; | 7077 | int index; |
| 7064 | if (size_in_bits == 8) { | 7078 | if (size_in_bits == 8) { |
| 7065 | index = 0; | 7079 | index = 0; |
| ... | @@ -7072,11 +7086,11 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, bool is_wrapping, | ... | @@ -7072,11 +7086,11 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, bool is_wrapping, |
| 7072 | } else { | 7086 | } else { |
| 7073 | zig_unreachable(); | 7087 | zig_unreachable(); |
| 7074 | } | 7088 | } |
| 7075 | return &g->builtin_types.entry_int[is_signed ? 0 : 1][is_wrapping ? 0 : 1][index]; | 7089 | return &g->builtin_types.entry_int[is_signed ? 0 : 1][index]; |
| 7076 | } | 7090 | } |
| 7077 | 7091 | ||
| 7078 | TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits) { | 7092 | TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits) { |
| 7079 | return *get_int_type_ptr(g, is_signed, is_wrapping, size_in_bits); | 7093 | return *get_int_type_ptr(g, is_signed, size_in_bits); |
| 7080 | } | 7094 | } |
| 7081 | 7095 | ||
| 7082 | TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) { | 7096 | TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) { |
src/analyze.hpp+2-2| ... | @@ -19,8 +19,8 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent); | ... | @@ -19,8 +19,8 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent); |
| 19 | Expr *get_resolved_expr(AstNode *node); | 19 | Expr *get_resolved_expr(AstNode *node); |
| 20 | bool is_node_void_expr(AstNode *node); | 20 | bool is_node_void_expr(AstNode *node); |
| 21 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); | 21 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); |
| 22 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits); | 22 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits); |
| 23 | TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits); | 23 | TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits); |
| 24 | TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); | 24 | TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); |
| 25 | TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type); | 25 | TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type); |
| 26 | TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type); | 26 | TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type); |
src/ast_render.cpp+44-35| ... | @@ -4,41 +4,49 @@ | ... | @@ -4,41 +4,49 @@ |
| 4 | 4 | ||
| 5 | static const char *bin_op_str(BinOpType bin_op) { | 5 | static const char *bin_op_str(BinOpType bin_op) { |
| 6 | switch (bin_op) { | 6 | switch (bin_op) { |
| 7 | case BinOpTypeInvalid: return "(invalid)"; | 7 | case BinOpTypeInvalid: return "(invalid)"; |
| 8 | case BinOpTypeBoolOr: return "||"; | 8 | case BinOpTypeBoolOr: return "||"; |
| 9 | case BinOpTypeBoolAnd: return "&&"; | 9 | case BinOpTypeBoolAnd: return "&&"; |
| 10 | case BinOpTypeCmpEq: return "=="; | 10 | case BinOpTypeCmpEq: return "=="; |
| 11 | case BinOpTypeCmpNotEq: return "!="; | 11 | case BinOpTypeCmpNotEq: return "!="; |
| 12 | case BinOpTypeCmpLessThan: return "<"; | 12 | case BinOpTypeCmpLessThan: return "<"; |
| 13 | case BinOpTypeCmpGreaterThan: return ">"; | 13 | case BinOpTypeCmpGreaterThan: return ">"; |
| 14 | case BinOpTypeCmpLessOrEq: return "<="; | 14 | case BinOpTypeCmpLessOrEq: return "<="; |
| 15 | case BinOpTypeCmpGreaterOrEq: return ">="; | 15 | case BinOpTypeCmpGreaterOrEq: return ">="; |
| 16 | case BinOpTypeBinOr: return "|"; | 16 | case BinOpTypeBinOr: return "|"; |
| 17 | case BinOpTypeBinXor: return "^"; | 17 | case BinOpTypeBinXor: return "^"; |
| 18 | case BinOpTypeBinAnd: return "&"; | 18 | case BinOpTypeBinAnd: return "&"; |
| 19 | case BinOpTypeBitShiftLeft: return "<<"; | 19 | case BinOpTypeBitShiftLeft: return "<<"; |
| 20 | case BinOpTypeBitShiftRight: return ">>"; | 20 | case BinOpTypeBitShiftLeftWrap: return "<<%"; |
| 21 | case BinOpTypeAdd: return "+"; | 21 | case BinOpTypeBitShiftRight: return ">>"; |
| 22 | case BinOpTypeSub: return "-"; | 22 | case BinOpTypeAdd: return "+"; |
| 23 | case BinOpTypeMult: return "*"; | 23 | case BinOpTypeAddWrap: return "+%"; |
| 24 | case BinOpTypeDiv: return "/"; | 24 | case BinOpTypeSub: return "-"; |
| 25 | case BinOpTypeMod: return "%"; | 25 | case BinOpTypeSubWrap: return "-%"; |
| 26 | case BinOpTypeAssign: return "="; | 26 | case BinOpTypeMult: return "*"; |
| 27 | case BinOpTypeAssignTimes: return "*="; | 27 | case BinOpTypeMultWrap: return "*%"; |
| 28 | case BinOpTypeAssignDiv: return "/="; | 28 | case BinOpTypeDiv: return "/"; |
| 29 | case BinOpTypeAssignMod: return "%="; | 29 | case BinOpTypeMod: return "%"; |
| 30 | case BinOpTypeAssignPlus: return "+="; | 30 | case BinOpTypeAssign: return "="; |
| 31 | case BinOpTypeAssignMinus: return "-="; | 31 | case BinOpTypeAssignTimes: return "*="; |
| 32 | case BinOpTypeAssignBitShiftLeft: return "<<="; | 32 | case BinOpTypeAssignTimesWrap: return "*%="; |
| 33 | case BinOpTypeAssignBitShiftRight: return ">>="; | 33 | case BinOpTypeAssignDiv: return "/="; |
| 34 | case BinOpTypeAssignBitAnd: return "&="; | 34 | case BinOpTypeAssignMod: return "%="; |
| 35 | case BinOpTypeAssignBitXor: return "^="; | 35 | case BinOpTypeAssignPlus: return "+="; |
| 36 | case BinOpTypeAssignBitOr: return "|="; | 36 | case BinOpTypeAssignPlusWrap: return "+%="; |
| 37 | case BinOpTypeAssignBoolAnd: return "&&="; | 37 | case BinOpTypeAssignMinus: return "-="; |
| 38 | case BinOpTypeAssignBoolOr: return "||="; | 38 | case BinOpTypeAssignMinusWrap: return "-%="; |
| 39 | case BinOpTypeUnwrapMaybe: return "??"; | 39 | case BinOpTypeAssignBitShiftLeft: return "<<="; |
| 40 | case BinOpTypeArrayCat: return "++"; | 40 | case BinOpTypeAssignBitShiftLeftWrap: return "<<%="; |
| 41 | case BinOpTypeArrayMult: return "**"; | 41 | case BinOpTypeAssignBitShiftRight: return ">>="; |
| 42 | case BinOpTypeAssignBitAnd: return "&="; | ||
| 43 | case BinOpTypeAssignBitXor: return "^="; | ||
| 44 | case BinOpTypeAssignBitOr: return "|="; | ||
| 45 | case BinOpTypeAssignBoolAnd: return "&&="; | ||
| 46 | case BinOpTypeAssignBoolOr: return "||="; | ||
| 47 | case BinOpTypeUnwrapMaybe: return "??"; | ||
| 48 | case BinOpTypeArrayCat: return "++"; | ||
| 49 | case BinOpTypeArrayMult: return "**"; | ||
| 42 | } | 50 | } |
| 43 | zig_unreachable(); | 51 | zig_unreachable(); |
| 44 | } | 52 | } |
| ... | @@ -47,6 +55,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) { | ... | @@ -47,6 +55,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) { |
| 47 | switch (prefix_op) { | 55 | switch (prefix_op) { |
| 48 | case PrefixOpInvalid: return "(invalid)"; | 56 | case PrefixOpInvalid: return "(invalid)"; |
| 49 | case PrefixOpNegation: return "-"; | 57 | case PrefixOpNegation: return "-"; |
| 58 | case PrefixOpNegationWrap: return "-%"; | ||
| 50 | case PrefixOpBoolNot: return "!"; | 59 | case PrefixOpBoolNot: return "!"; |
| 51 | case PrefixOpBinNot: return "~"; | 60 | case PrefixOpBinNot: return "~"; |
| 52 | case PrefixOpAddressOf: return "&"; | 61 | case PrefixOpAddressOf: return "&"; |
src/codegen.cpp+60-51| ... | @@ -1564,17 +1564,20 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { | ... | @@ -1564,17 +1564,20 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 1564 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | 1564 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 1565 | TypeTableEntry *expr_type = get_expr_type(expr_node); | 1565 | TypeTableEntry *expr_type = get_expr_type(expr_node); |
| 1566 | 1566 | ||
| 1567 | switch (node->data.prefix_op_expr.prefix_op) { | 1567 | PrefixOp op = node->data.prefix_op_expr.prefix_op; |
| 1568 | |||
| 1569 | switch (op) { | ||
| 1568 | case PrefixOpInvalid: | 1570 | case PrefixOpInvalid: |
| 1569 | zig_unreachable(); | 1571 | zig_unreachable(); |
| 1570 | case PrefixOpNegation: | 1572 | case PrefixOpNegation: |
| 1573 | case PrefixOpNegationWrap: | ||
| 1571 | { | 1574 | { |
| 1572 | LLVMValueRef expr = gen_expr(g, expr_node); | 1575 | LLVMValueRef expr = gen_expr(g, expr_node); |
| 1573 | set_debug_source_node(g, node); | 1576 | set_debug_source_node(g, node); |
| 1574 | if (expr_type->id == TypeTableEntryIdFloat) { | 1577 | if (expr_type->id == TypeTableEntryIdFloat) { |
| 1575 | return LLVMBuildFNeg(g->builder, expr, ""); | 1578 | return LLVMBuildFNeg(g->builder, expr, ""); |
| 1576 | } else if (expr_type->id == TypeTableEntryIdInt) { | 1579 | } else if (expr_type->id == TypeTableEntryIdInt) { |
| 1577 | if (expr_type->data.integral.is_wrapping) { | 1580 | if (op == PrefixOpNegationWrap) { |
| 1578 | return LLVMBuildNeg(g->builder, expr, ""); | 1581 | return LLVMBuildNeg(g->builder, expr, ""); |
| 1579 | } else if (want_debug_safety(g, expr_node)) { | 1582 | } else if (want_debug_safety(g, expr_node)) { |
| 1580 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr)); | 1583 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr)); |
| ... | @@ -1796,17 +1799,23 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, | ... | @@ -1796,17 +1799,23 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1796 | set_debug_source_node(g, source_node); | 1799 | set_debug_source_node(g, source_node); |
| 1797 | return LLVMBuildAnd(g->builder, val1, val2, ""); | 1800 | return LLVMBuildAnd(g->builder, val1, val2, ""); |
| 1798 | case BinOpTypeBitShiftLeft: | 1801 | case BinOpTypeBitShiftLeft: |
| 1802 | case BinOpTypeBitShiftLeftWrap: | ||
| 1799 | case BinOpTypeAssignBitShiftLeft: | 1803 | case BinOpTypeAssignBitShiftLeft: |
| 1800 | set_debug_source_node(g, source_node); | 1804 | case BinOpTypeAssignBitShiftLeftWrap: |
| 1801 | assert(op1_type->id == TypeTableEntryIdInt); | 1805 | { |
| 1802 | if (op1_type->data.integral.is_wrapping) { | 1806 | set_debug_source_node(g, source_node); |
| 1803 | return LLVMBuildShl(g->builder, val1, val2, ""); | 1807 | assert(op1_type->id == TypeTableEntryIdInt); |
| 1804 | } else if (want_debug_safety(g, source_node)) { | 1808 | bool is_wrapping = (bin_op == BinOpTypeBitShiftLeftWrap) || |
| 1805 | return gen_overflow_shl_op(g, op1_type, val1, val2); | 1809 | (bin_op == BinOpTypeAssignBitShiftLeftWrap); |
| 1806 | } else if (op1_type->data.integral.is_signed) { | 1810 | if (is_wrapping) { |
| 1807 | return ZigLLVMBuildNSWShl(g->builder, val1, val2, ""); | 1811 | return LLVMBuildShl(g->builder, val1, val2, ""); |
| 1808 | } else { | 1812 | } else if (want_debug_safety(g, source_node)) { |
| 1809 | return ZigLLVMBuildNUWShl(g->builder, val1, val2, ""); | 1813 | return gen_overflow_shl_op(g, op1_type, val1, val2); |
| 1814 | } else if (op1_type->data.integral.is_signed) { | ||
| 1815 | return ZigLLVMBuildNSWShl(g->builder, val1, val2, ""); | ||
| 1816 | } else { | ||
| 1817 | return ZigLLVMBuildNUWShl(g->builder, val1, val2, ""); | ||
| 1818 | } | ||
| 1810 | } | 1819 | } |
| 1811 | case BinOpTypeBitShiftRight: | 1820 | case BinOpTypeBitShiftRight: |
| 1812 | case BinOpTypeAssignBitShiftRight: | 1821 | case BinOpTypeAssignBitShiftRight: |
| ... | @@ -1820,12 +1829,15 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, | ... | @@ -1820,12 +1829,15 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1820 | return LLVMBuildLShr(g->builder, val1, val2, ""); | 1829 | return LLVMBuildLShr(g->builder, val1, val2, ""); |
| 1821 | } | 1830 | } |
| 1822 | case BinOpTypeAdd: | 1831 | case BinOpTypeAdd: |
| 1832 | case BinOpTypeAddWrap: | ||
| 1823 | case BinOpTypeAssignPlus: | 1833 | case BinOpTypeAssignPlus: |
| 1834 | case BinOpTypeAssignPlusWrap: | ||
| 1824 | set_debug_source_node(g, source_node); | 1835 | set_debug_source_node(g, source_node); |
| 1825 | if (op1_type->id == TypeTableEntryIdFloat) { | 1836 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 1826 | return LLVMBuildFAdd(g->builder, val1, val2, ""); | 1837 | return LLVMBuildFAdd(g->builder, val1, val2, ""); |
| 1827 | } else if (op1_type->id == TypeTableEntryIdInt) { | 1838 | } else if (op1_type->id == TypeTableEntryIdInt) { |
| 1828 | if (op1_type->data.integral.is_wrapping) { | 1839 | bool is_wrapping = (bin_op == BinOpTypeAddWrap) || (bin_op == BinOpTypeAssignPlusWrap); |
| 1840 | if (is_wrapping) { | ||
| 1829 | return LLVMBuildAdd(g->builder, val1, val2, ""); | 1841 | return LLVMBuildAdd(g->builder, val1, val2, ""); |
| 1830 | } else if (want_debug_safety(g, source_node)) { | 1842 | } else if (want_debug_safety(g, source_node)) { |
| 1831 | return gen_overflow_op(g, op1_type, AddSubMulAdd, val1, val2); | 1843 | return gen_overflow_op(g, op1_type, AddSubMulAdd, val1, val2); |
| ... | @@ -1838,12 +1850,15 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, | ... | @@ -1838,12 +1850,15 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1838 | zig_unreachable(); | 1850 | zig_unreachable(); |
| 1839 | } | 1851 | } |
| 1840 | case BinOpTypeSub: | 1852 | case BinOpTypeSub: |
| 1853 | case BinOpTypeSubWrap: | ||
| 1841 | case BinOpTypeAssignMinus: | 1854 | case BinOpTypeAssignMinus: |
| 1855 | case BinOpTypeAssignMinusWrap: | ||
| 1842 | set_debug_source_node(g, source_node); | 1856 | set_debug_source_node(g, source_node); |
| 1843 | if (op1_type->id == TypeTableEntryIdFloat) { | 1857 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 1844 | return LLVMBuildFSub(g->builder, val1, val2, ""); | 1858 | return LLVMBuildFSub(g->builder, val1, val2, ""); |
| 1845 | } else if (op1_type->id == TypeTableEntryIdInt) { | 1859 | } else if (op1_type->id == TypeTableEntryIdInt) { |
| 1846 | if (op1_type->data.integral.is_wrapping) { | 1860 | bool is_wrapping = (bin_op == BinOpTypeSubWrap || bin_op == BinOpTypeAssignMinusWrap); |
| 1861 | if (is_wrapping) { | ||
| 1847 | return LLVMBuildSub(g->builder, val1, val2, ""); | 1862 | return LLVMBuildSub(g->builder, val1, val2, ""); |
| 1848 | } else if (want_debug_safety(g, source_node)) { | 1863 | } else if (want_debug_safety(g, source_node)) { |
| 1849 | return gen_overflow_op(g, op1_type, AddSubMulSub, val1, val2); | 1864 | return gen_overflow_op(g, op1_type, AddSubMulSub, val1, val2); |
| ... | @@ -1856,12 +1871,15 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, | ... | @@ -1856,12 +1871,15 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node, |
| 1856 | zig_unreachable(); | 1871 | zig_unreachable(); |
| 1857 | } | 1872 | } |
| 1858 | case BinOpTypeMult: | 1873 | case BinOpTypeMult: |
| 1874 | case BinOpTypeMultWrap: | ||
| 1859 | case BinOpTypeAssignTimes: | 1875 | case BinOpTypeAssignTimes: |
| 1876 | case BinOpTypeAssignTimesWrap: | ||
| 1860 | set_debug_source_node(g, source_node); | 1877 | set_debug_source_node(g, source_node); |
| 1861 | if (op1_type->id == TypeTableEntryIdFloat) { | 1878 | if (op1_type->id == TypeTableEntryIdFloat) { |
| 1862 | return LLVMBuildFMul(g->builder, val1, val2, ""); | 1879 | return LLVMBuildFMul(g->builder, val1, val2, ""); |
| 1863 | } else if (op1_type->id == TypeTableEntryIdInt) { | 1880 | } else if (op1_type->id == TypeTableEntryIdInt) { |
| 1864 | if (op1_type->data.integral.is_wrapping) { | 1881 | bool is_wrapping = (bin_op == BinOpTypeMultWrap || bin_op == BinOpTypeAssignTimesWrap); |
| 1882 | if (is_wrapping) { | ||
| 1865 | return LLVMBuildMul(g->builder, val1, val2, ""); | 1883 | return LLVMBuildMul(g->builder, val1, val2, ""); |
| 1866 | } else if (want_debug_safety(g, source_node)) { | 1884 | } else if (want_debug_safety(g, source_node)) { |
| 1867 | return gen_overflow_op(g, op1_type, AddSubMulMul, val1, val2); | 1885 | return gen_overflow_op(g, op1_type, AddSubMulMul, val1, val2); |
| ... | @@ -2214,11 +2232,15 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { | ... | @@ -2214,11 +2232,15 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { |
| 2214 | zig_unreachable(); | 2232 | zig_unreachable(); |
| 2215 | case BinOpTypeAssign: | 2233 | case BinOpTypeAssign: |
| 2216 | case BinOpTypeAssignTimes: | 2234 | case BinOpTypeAssignTimes: |
| 2235 | case BinOpTypeAssignTimesWrap: | ||
| 2217 | case BinOpTypeAssignDiv: | 2236 | case BinOpTypeAssignDiv: |
| 2218 | case BinOpTypeAssignMod: | 2237 | case BinOpTypeAssignMod: |
| 2219 | case BinOpTypeAssignPlus: | 2238 | case BinOpTypeAssignPlus: |
| 2239 | case BinOpTypeAssignPlusWrap: | ||
| 2220 | case BinOpTypeAssignMinus: | 2240 | case BinOpTypeAssignMinus: |
| 2241 | case BinOpTypeAssignMinusWrap: | ||
| 2221 | case BinOpTypeAssignBitShiftLeft: | 2242 | case BinOpTypeAssignBitShiftLeft: |
| 2243 | case BinOpTypeAssignBitShiftLeftWrap: | ||
| 2222 | case BinOpTypeAssignBitShiftRight: | 2244 | case BinOpTypeAssignBitShiftRight: |
| 2223 | case BinOpTypeAssignBitAnd: | 2245 | case BinOpTypeAssignBitAnd: |
| 2224 | case BinOpTypeAssignBitXor: | 2246 | case BinOpTypeAssignBitXor: |
| ... | @@ -2243,10 +2265,14 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { | ... | @@ -2243,10 +2265,14 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { |
| 2243 | case BinOpTypeBinXor: | 2265 | case BinOpTypeBinXor: |
| 2244 | case BinOpTypeBinAnd: | 2266 | case BinOpTypeBinAnd: |
| 2245 | case BinOpTypeBitShiftLeft: | 2267 | case BinOpTypeBitShiftLeft: |
| 2268 | case BinOpTypeBitShiftLeftWrap: | ||
| 2246 | case BinOpTypeBitShiftRight: | 2269 | case BinOpTypeBitShiftRight: |
| 2247 | case BinOpTypeAdd: | 2270 | case BinOpTypeAdd: |
| 2271 | case BinOpTypeAddWrap: | ||
| 2248 | case BinOpTypeSub: | 2272 | case BinOpTypeSub: |
| 2273 | case BinOpTypeSubWrap: | ||
| 2249 | case BinOpTypeMult: | 2274 | case BinOpTypeMult: |
| 2275 | case BinOpTypeMultWrap: | ||
| 2250 | case BinOpTypeDiv: | 2276 | case BinOpTypeDiv: |
| 2251 | case BinOpTypeMod: | 2277 | case BinOpTypeMod: |
| 2252 | return gen_arithmetic_bin_op_expr(g, node); | 2278 | return gen_arithmetic_bin_op_expr(g, node); |
| ... | @@ -4188,17 +4214,7 @@ static const CIntTypeInfo c_int_type_infos[] = { | ... | @@ -4188,17 +4214,7 @@ static const CIntTypeInfo c_int_type_infos[] = { |
| 4188 | {CIntTypeULongLong, "c_ulonglong", false}, | 4214 | {CIntTypeULongLong, "c_ulonglong", false}, |
| 4189 | }; | 4215 | }; |
| 4190 | 4216 | ||
| 4191 | struct SignWrap { | 4217 | static const bool is_signed_list[] = { false, true, }; |
| 4192 | bool is_signed; | ||
| 4193 | bool is_wrapping; | ||
| 4194 | }; | ||
| 4195 | |||
| 4196 | static const SignWrap sign_wrap_list[] = { | ||
| 4197 | {false, false}, | ||
| 4198 | {false, true}, | ||
| 4199 | {true, false}, | ||
| 4200 | {true, true}, | ||
| 4201 | }; | ||
| 4202 | 4218 | ||
| 4203 | static void define_builtin_types(CodeGen *g) { | 4219 | static void define_builtin_types(CodeGen *g) { |
| 4204 | { | 4220 | { |
| ... | @@ -4238,18 +4254,16 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4238,18 +4254,16 @@ static void define_builtin_types(CodeGen *g) { |
| 4238 | 4254 | ||
| 4239 | for (int int_size_i = 0; int_size_i < array_length(int_sizes_in_bits); int_size_i += 1) { | 4255 | for (int int_size_i = 0; int_size_i < array_length(int_sizes_in_bits); int_size_i += 1) { |
| 4240 | int size_in_bits = int_sizes_in_bits[int_size_i]; | 4256 | int size_in_bits = int_sizes_in_bits[int_size_i]; |
| 4241 | for (int sign_wrap_i = 0; sign_wrap_i < array_length(sign_wrap_list); sign_wrap_i += 1) { | 4257 | for (int is_sign_i = 0; is_sign_i < array_length(is_signed_list); is_sign_i += 1) { |
| 4242 | bool is_signed = sign_wrap_list[sign_wrap_i].is_signed; | 4258 | bool is_signed = is_signed_list[is_sign_i]; |
| 4243 | bool is_wrapping = sign_wrap_list[sign_wrap_i].is_wrapping; | ||
| 4244 | 4259 | ||
| 4245 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); | 4260 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 4246 | entry->type_ref = LLVMIntType(size_in_bits); | 4261 | entry->type_ref = LLVMIntType(size_in_bits); |
| 4247 | entry->deep_const = true; | 4262 | entry->deep_const = true; |
| 4248 | 4263 | ||
| 4249 | const char u_or_i = is_signed ? 'i' : 'u'; | 4264 | const char u_or_i = is_signed ? 'i' : 'u'; |
| 4250 | const char *w_or_none = is_wrapping ? "w" : ""; | ||
| 4251 | buf_resize(&entry->name, 0); | 4265 | buf_resize(&entry->name, 0); |
| 4252 | buf_appendf(&entry->name, "%c%d%s", u_or_i, size_in_bits, w_or_none); | 4266 | buf_appendf(&entry->name, "%c%d", u_or_i, size_in_bits); |
| 4253 | 4267 | ||
| 4254 | unsigned dwarf_tag; | 4268 | unsigned dwarf_tag; |
| 4255 | if (is_signed) { | 4269 | if (is_signed) { |
| ... | @@ -4271,11 +4285,10 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4271,11 +4285,10 @@ static void define_builtin_types(CodeGen *g) { |
| 4271 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | 4285 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), |
| 4272 | debug_size_in_bits, debug_align_in_bits, dwarf_tag); | 4286 | debug_size_in_bits, debug_align_in_bits, dwarf_tag); |
| 4273 | entry->data.integral.is_signed = is_signed; | 4287 | entry->data.integral.is_signed = is_signed; |
| 4274 | entry->data.integral.is_wrapping = is_wrapping; | ||
| 4275 | entry->data.integral.bit_count = size_in_bits; | 4288 | entry->data.integral.bit_count = size_in_bits; |
| 4276 | g->primitive_type_table.put(&entry->name, entry); | 4289 | g->primitive_type_table.put(&entry->name, entry); |
| 4277 | 4290 | ||
| 4278 | get_int_type_ptr(g, is_signed, is_wrapping, size_in_bits)[0] = entry; | 4291 | get_int_type_ptr(g, is_signed, size_in_bits)[0] = entry; |
| 4279 | } | 4292 | } |
| 4280 | } | 4293 | } |
| 4281 | 4294 | ||
| ... | @@ -4297,7 +4310,6 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4297,7 +4310,6 @@ static void define_builtin_types(CodeGen *g) { |
| 4297 | debug_align_in_bits, | 4310 | debug_align_in_bits, |
| 4298 | is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned()); | 4311 | is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned()); |
| 4299 | entry->data.integral.is_signed = is_signed; | 4312 | entry->data.integral.is_signed = is_signed; |
| 4300 | entry->data.integral.is_wrapping = !is_signed; | ||
| 4301 | entry->data.integral.bit_count = size_in_bits; | 4313 | entry->data.integral.bit_count = size_in_bits; |
| 4302 | g->primitive_type_table.put(&entry->name, entry); | 4314 | g->primitive_type_table.put(&entry->name, entry); |
| 4303 | 4315 | ||
| ... | @@ -4319,21 +4331,18 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4319,21 +4331,18 @@ static void define_builtin_types(CodeGen *g) { |
| 4319 | g->primitive_type_table.put(&entry->name, entry); | 4331 | g->primitive_type_table.put(&entry->name, entry); |
| 4320 | } | 4332 | } |
| 4321 | 4333 | ||
| 4322 | for (int sign_wrap_i = 0; sign_wrap_i < array_length(sign_wrap_list); sign_wrap_i += 1) { | 4334 | for (int sign_i = 0; sign_i < array_length(is_signed_list); sign_i += 1) { |
| 4323 | bool is_signed = sign_wrap_list[sign_wrap_i].is_signed; | 4335 | bool is_signed = is_signed_list[sign_i]; |
| 4324 | bool is_wrapping = sign_wrap_list[sign_wrap_i].is_wrapping; | ||
| 4325 | 4336 | ||
| 4326 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); | 4337 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 4327 | entry->deep_const = true; | 4338 | entry->deep_const = true; |
| 4328 | entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8); | 4339 | entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8); |
| 4329 | 4340 | ||
| 4330 | const char u_or_i = is_signed ? 'i' : 'u'; | 4341 | const char u_or_i = is_signed ? 'i' : 'u'; |
| 4331 | const char *w_or_none = is_wrapping ? "w" : ""; | ||
| 4332 | buf_resize(&entry->name, 0); | 4342 | buf_resize(&entry->name, 0); |
| 4333 | buf_appendf(&entry->name, "%csize%s", u_or_i, w_or_none); | 4343 | buf_appendf(&entry->name, "%csize", u_or_i); |
| 4334 | 4344 | ||
| 4335 | entry->data.integral.is_signed = is_signed; | 4345 | entry->data.integral.is_signed = is_signed; |
| 4336 | entry->data.integral.is_wrapping = is_wrapping; | ||
| 4337 | entry->data.integral.bit_count = g->pointer_size_bytes * 8; | 4346 | entry->data.integral.bit_count = g->pointer_size_bytes * 8; |
| 4338 | 4347 | ||
| 4339 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | 4348 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); |
| ... | @@ -4344,9 +4353,9 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4344,9 +4353,9 @@ static void define_builtin_types(CodeGen *g) { |
| 4344 | is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned()); | 4353 | is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned()); |
| 4345 | g->primitive_type_table.put(&entry->name, entry); | 4354 | g->primitive_type_table.put(&entry->name, entry); |
| 4346 | 4355 | ||
| 4347 | if (is_signed && !is_wrapping) { | 4356 | if (is_signed) { |
| 4348 | g->builtin_types.entry_isize = entry; | 4357 | g->builtin_types.entry_isize = entry; |
| 4349 | } else if (!is_signed && !is_wrapping) { | 4358 | } else { |
| 4350 | g->builtin_types.entry_usize = entry; | 4359 | g->builtin_types.entry_usize = entry; |
| 4351 | } | 4360 | } |
| 4352 | } | 4361 | } |
| ... | @@ -4430,14 +4439,14 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -4430,14 +4439,14 @@ static void define_builtin_types(CodeGen *g) { |
| 4430 | g->primitive_type_table.put(&entry->name, entry); | 4439 | g->primitive_type_table.put(&entry->name, entry); |
| 4431 | } | 4440 | } |
| 4432 | 4441 | ||
| 4433 | g->builtin_types.entry_u8 = get_int_type(g, false, false, 8); | 4442 | g->builtin_types.entry_u8 = get_int_type(g, false, 8); |
| 4434 | g->builtin_types.entry_u16 = get_int_type(g, false, false, 16); | 4443 | g->builtin_types.entry_u16 = get_int_type(g, false, 16); |
| 4435 | g->builtin_types.entry_u32 = get_int_type(g, false, false, 32); | 4444 | g->builtin_types.entry_u32 = get_int_type(g, false, 32); |
| 4436 | g->builtin_types.entry_u64 = get_int_type(g, false, false, 64); | 4445 | g->builtin_types.entry_u64 = get_int_type(g, false, 64); |
| 4437 | g->builtin_types.entry_i8 = get_int_type(g, true, false, 8); | 4446 | g->builtin_types.entry_i8 = get_int_type(g, true, 8); |
| 4438 | g->builtin_types.entry_i16 = get_int_type(g, true, false, 16); | 4447 | g->builtin_types.entry_i16 = get_int_type(g, true, 16); |
| 4439 | g->builtin_types.entry_i32 = get_int_type(g, true, false, 32); | 4448 | g->builtin_types.entry_i32 = get_int_type(g, true, 32); |
| 4440 | g->builtin_types.entry_i64 = get_int_type(g, true, false, 64); | 4449 | g->builtin_types.entry_i64 = get_int_type(g, true, 64); |
| 4441 | 4450 | ||
| 4442 | { | 4451 | { |
| 4443 | g->builtin_types.entry_c_void = get_typedecl_type(g, "c_void", g->builtin_types.entry_u8); | 4452 | g->builtin_types.entry_c_void = get_typedecl_type(g, "c_void", g->builtin_types.entry_u8); |
| ... | @@ -4703,7 +4712,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -4703,7 +4712,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 4703 | create_builtin_fn_with_arg_count(g, BuiltinFnIdDivExact, "div_exact", 2); | 4712 | create_builtin_fn_with_arg_count(g, BuiltinFnIdDivExact, "div_exact", 2); |
| 4704 | create_builtin_fn_with_arg_count(g, BuiltinFnIdTruncate, "truncate", 2); | 4713 | create_builtin_fn_with_arg_count(g, BuiltinFnIdTruncate, "truncate", 2); |
| 4705 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileErr, "compile_err", 1); | 4714 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileErr, "compile_err", 1); |
| 4706 | create_builtin_fn_with_arg_count(g, BuiltinFnIdIntType, "int_type", 3); | 4715 | create_builtin_fn_with_arg_count(g, BuiltinFnIdIntType, "int_type", 2); |
| 4707 | } | 4716 | } |
| 4708 | 4717 | ||
| 4709 | static void init(CodeGen *g, Buf *source_path) { | 4718 | static void init(CodeGen *g, Buf *source_path) { |
src/eval.cpp+34-13| ... | @@ -146,7 +146,7 @@ static int64_t min_signed_val(TypeTableEntry *type_entry) { | ... | @@ -146,7 +146,7 @@ static int64_t min_signed_val(TypeTableEntry *type_entry) { |
| 146 | 146 | ||
| 147 | static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val, | 147 | static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val, |
| 148 | ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), | 148 | ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), |
| 149 | TypeTableEntry *type) | 149 | TypeTableEntry *type, bool wrapping_op) |
| 150 | { | 150 | { |
| 151 | bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum); | 151 | bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum); |
| 152 | if (overflow) { | 152 | if (overflow) { |
| ... | @@ -156,7 +156,7 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue | ... | @@ -156,7 +156,7 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue |
| 156 | if (type->id == TypeTableEntryIdInt && !bignum_fits_in_bits(&out_val->data.x_bignum, | 156 | if (type->id == TypeTableEntryIdInt && !bignum_fits_in_bits(&out_val->data.x_bignum, |
| 157 | type->data.integral.bit_count, type->data.integral.is_signed)) | 157 | type->data.integral.bit_count, type->data.integral.is_signed)) |
| 158 | { | 158 | { |
| 159 | if (type->data.integral.is_wrapping) { | 159 | if (wrapping_op) { |
| 160 | if (type->data.integral.is_signed) { | 160 | if (type->data.integral.is_signed) { |
| 161 | out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1; | 161 | out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1; |
| 162 | out_val->data.x_bignum.is_negative = !out_val->data.x_bignum.is_negative; | 162 | out_val->data.x_bignum.is_negative = !out_val->data.x_bignum.is_negative; |
| ... | @@ -187,11 +187,15 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, | ... | @@ -187,11 +187,15 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, |
| 187 | switch (bin_op) { | 187 | switch (bin_op) { |
| 188 | case BinOpTypeAssign: | 188 | case BinOpTypeAssign: |
| 189 | case BinOpTypeAssignTimes: | 189 | case BinOpTypeAssignTimes: |
| 190 | case BinOpTypeAssignTimesWrap: | ||
| 190 | case BinOpTypeAssignDiv: | 191 | case BinOpTypeAssignDiv: |
| 191 | case BinOpTypeAssignMod: | 192 | case BinOpTypeAssignMod: |
| 192 | case BinOpTypeAssignPlus: | 193 | case BinOpTypeAssignPlus: |
| 194 | case BinOpTypeAssignPlusWrap: | ||
| 193 | case BinOpTypeAssignMinus: | 195 | case BinOpTypeAssignMinus: |
| 196 | case BinOpTypeAssignMinusWrap: | ||
| 194 | case BinOpTypeAssignBitShiftLeft: | 197 | case BinOpTypeAssignBitShiftLeft: |
| 198 | case BinOpTypeAssignBitShiftLeftWrap: | ||
| 195 | case BinOpTypeAssignBitShiftRight: | 199 | case BinOpTypeAssignBitShiftRight: |
| 196 | case BinOpTypeAssignBitAnd: | 200 | case BinOpTypeAssignBitAnd: |
| 197 | case BinOpTypeAssignBitXor: | 201 | case BinOpTypeAssignBitXor: |
| ... | @@ -256,21 +260,29 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, | ... | @@ -256,21 +260,29 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, |
| 256 | return 0; | 260 | return 0; |
| 257 | } | 261 | } |
| 258 | case BinOpTypeAdd: | 262 | case BinOpTypeAdd: |
| 259 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type); | 263 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, false); |
| 264 | case BinOpTypeAddWrap: | ||
| 265 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, true); | ||
| 260 | case BinOpTypeBinOr: | 266 | case BinOpTypeBinOr: |
| 261 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_or, op1_type); | 267 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_or, op1_type, false); |
| 262 | case BinOpTypeBinXor: | 268 | case BinOpTypeBinXor: |
| 263 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type); | 269 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type, false); |
| 264 | case BinOpTypeBinAnd: | 270 | case BinOpTypeBinAnd: |
| 265 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_and, op1_type); | 271 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_and, op1_type, false); |
| 266 | case BinOpTypeBitShiftLeft: | 272 | case BinOpTypeBitShiftLeft: |
| 267 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type); | 273 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, false); |
| 274 | case BinOpTypeBitShiftLeftWrap: | ||
| 275 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, true); | ||
| 268 | case BinOpTypeBitShiftRight: | 276 | case BinOpTypeBitShiftRight: |
| 269 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type); | 277 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type, false); |
| 270 | case BinOpTypeSub: | 278 | case BinOpTypeSub: |
| 271 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type); | 279 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, false); |
| 280 | case BinOpTypeSubWrap: | ||
| 281 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, true); | ||
| 272 | case BinOpTypeMult: | 282 | case BinOpTypeMult: |
| 273 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type); | 283 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, false); |
| 284 | case BinOpTypeMultWrap: | ||
| 285 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, true); | ||
| 274 | case BinOpTypeDiv: | 286 | case BinOpTypeDiv: |
| 275 | { | 287 | { |
| 276 | bool is_int = false; | 288 | bool is_int = false; |
| ... | @@ -289,11 +301,11 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, | ... | @@ -289,11 +301,11 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type, |
| 289 | { | 301 | { |
| 290 | return ErrorDivByZero; | 302 | return ErrorDivByZero; |
| 291 | } else { | 303 | } else { |
| 292 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_div, op1_type); | 304 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_div, op1_type, false); |
| 293 | } | 305 | } |
| 294 | } | 306 | } |
| 295 | case BinOpTypeMod: | 307 | case BinOpTypeMod: |
| 296 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type); | 308 | return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type, false); |
| 297 | case BinOpTypeUnwrapMaybe: | 309 | case BinOpTypeUnwrapMaybe: |
| 298 | zig_panic("TODO"); | 310 | zig_panic("TODO"); |
| 299 | case BinOpTypeArrayCat: | 311 | case BinOpTypeArrayCat: |
| ... | @@ -314,11 +326,15 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) | ... | @@ -314,11 +326,15 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) |
| 314 | switch (bin_op) { | 326 | switch (bin_op) { |
| 315 | case BinOpTypeAssign: | 327 | case BinOpTypeAssign: |
| 316 | case BinOpTypeAssignTimes: | 328 | case BinOpTypeAssignTimes: |
| 329 | case BinOpTypeAssignTimesWrap: | ||
| 317 | case BinOpTypeAssignDiv: | 330 | case BinOpTypeAssignDiv: |
| 318 | case BinOpTypeAssignMod: | 331 | case BinOpTypeAssignMod: |
| 319 | case BinOpTypeAssignPlus: | 332 | case BinOpTypeAssignPlus: |
| 333 | case BinOpTypeAssignPlusWrap: | ||
| 320 | case BinOpTypeAssignMinus: | 334 | case BinOpTypeAssignMinus: |
| 335 | case BinOpTypeAssignMinusWrap: | ||
| 321 | case BinOpTypeAssignBitShiftLeft: | 336 | case BinOpTypeAssignBitShiftLeft: |
| 337 | case BinOpTypeAssignBitShiftLeftWrap: | ||
| 322 | case BinOpTypeAssignBitShiftRight: | 338 | case BinOpTypeAssignBitShiftRight: |
| 323 | case BinOpTypeAssignBitAnd: | 339 | case BinOpTypeAssignBitAnd: |
| 324 | case BinOpTypeAssignBitXor: | 340 | case BinOpTypeAssignBitXor: |
| ... | @@ -338,10 +354,14 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) | ... | @@ -338,10 +354,14 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) |
| 338 | case BinOpTypeBinXor: | 354 | case BinOpTypeBinXor: |
| 339 | case BinOpTypeBinAnd: | 355 | case BinOpTypeBinAnd: |
| 340 | case BinOpTypeBitShiftLeft: | 356 | case BinOpTypeBitShiftLeft: |
| 357 | case BinOpTypeBitShiftLeftWrap: | ||
| 341 | case BinOpTypeBitShiftRight: | 358 | case BinOpTypeBitShiftRight: |
| 342 | case BinOpTypeAdd: | 359 | case BinOpTypeAdd: |
| 360 | case BinOpTypeAddWrap: | ||
| 343 | case BinOpTypeSub: | 361 | case BinOpTypeSub: |
| 362 | case BinOpTypeSubWrap: | ||
| 344 | case BinOpTypeMult: | 363 | case BinOpTypeMult: |
| 364 | case BinOpTypeMultWrap: | ||
| 345 | case BinOpTypeDiv: | 365 | case BinOpTypeDiv: |
| 346 | case BinOpTypeMod: | 366 | case BinOpTypeMod: |
| 347 | case BinOpTypeUnwrapMaybe: | 367 | case BinOpTypeUnwrapMaybe: |
| ... | @@ -1098,13 +1118,14 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v | ... | @@ -1098,13 +1118,14 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v |
| 1098 | break; | 1118 | break; |
| 1099 | } | 1119 | } |
| 1100 | case PrefixOpNegation: | 1120 | case PrefixOpNegation: |
| 1121 | case PrefixOpNegationWrap: | ||
| 1101 | if (expr_type->id == TypeTableEntryIdInt) { | 1122 | if (expr_type->id == TypeTableEntryIdInt) { |
| 1102 | assert(expr_type->data.integral.is_signed); | 1123 | assert(expr_type->data.integral.is_signed); |
| 1103 | bignum_negate(&out_val->data.x_bignum, &expr_val.data.x_bignum); | 1124 | bignum_negate(&out_val->data.x_bignum, &expr_val.data.x_bignum); |
| 1104 | out_val->ok = true; | 1125 | out_val->ok = true; |
| 1105 | bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum, | 1126 | bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum, |
| 1106 | expr_type->data.integral.bit_count, expr_type->data.integral.is_signed); | 1127 | expr_type->data.integral.bit_count, expr_type->data.integral.is_signed); |
| 1107 | if (expr_type->data.integral.is_wrapping) { | 1128 | if (prefix_op == PrefixOpNegationWrap) { |
| 1108 | if (overflow) { | 1129 | if (overflow) { |
| 1109 | out_val->data.x_bignum.is_negative = true; | 1130 | out_val->data.x_bignum.is_negative = true; |
| 1110 | } | 1131 | } |
src/parser.cpp+25-16| ... | @@ -1384,6 +1384,7 @@ static PrefixOp tok_to_prefix_op(Token *token) { | ... | @@ -1384,6 +1384,7 @@ static PrefixOp tok_to_prefix_op(Token *token) { |
| 1384 | switch (token->id) { | 1384 | switch (token->id) { |
| 1385 | case TokenIdBang: return PrefixOpBoolNot; | 1385 | case TokenIdBang: return PrefixOpBoolNot; |
| 1386 | case TokenIdDash: return PrefixOpNegation; | 1386 | case TokenIdDash: return PrefixOpNegation; |
| 1387 | case TokenIdMinusPercent: return PrefixOpNegationWrap; | ||
| 1387 | case TokenIdTilde: return PrefixOpBinNot; | 1388 | case TokenIdTilde: return PrefixOpBinNot; |
| 1388 | case TokenIdAmpersand: return PrefixOpAddressOf; | 1389 | case TokenIdAmpersand: return PrefixOpAddressOf; |
| 1389 | case TokenIdStar: return PrefixOpDereference; | 1390 | case TokenIdStar: return PrefixOpDereference; |
| ... | @@ -1399,7 +1400,7 @@ static PrefixOp tok_to_prefix_op(Token *token) { | ... | @@ -1399,7 +1400,7 @@ static PrefixOp tok_to_prefix_op(Token *token) { |
| 1399 | 1400 | ||
| 1400 | /* | 1401 | /* |
| 1401 | PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression | 1402 | PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression |
| 1402 | PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const))) | 1403 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%" |
| 1403 | */ | 1404 | */ |
| 1404 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) { | 1405 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) { |
| 1405 | Token *token = &pc->tokens->at(*token_index); | 1406 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -1458,16 +1459,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo | ... | @@ -1458,16 +1459,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo |
| 1458 | 1459 | ||
| 1459 | static BinOpType tok_to_mult_op(Token *token) { | 1460 | static BinOpType tok_to_mult_op(Token *token) { |
| 1460 | switch (token->id) { | 1461 | switch (token->id) { |
| 1461 | case TokenIdStar: return BinOpTypeMult; | 1462 | case TokenIdStar: return BinOpTypeMult; |
| 1462 | case TokenIdStarStar: return BinOpTypeArrayMult; | 1463 | case TokenIdTimesPercent: return BinOpTypeMultWrap; |
| 1463 | case TokenIdSlash: return BinOpTypeDiv; | 1464 | case TokenIdStarStar: return BinOpTypeArrayMult; |
| 1464 | case TokenIdPercent: return BinOpTypeMod; | 1465 | case TokenIdSlash: return BinOpTypeDiv; |
| 1465 | default: return BinOpTypeInvalid; | 1466 | case TokenIdPercent: return BinOpTypeMod; |
| 1467 | default: return BinOpTypeInvalid; | ||
| 1466 | } | 1468 | } |
| 1467 | } | 1469 | } |
| 1468 | 1470 | ||
| 1469 | /* | 1471 | /* |
| 1470 | MultiplyOperator = "*" | "/" | "%" | "**" | 1472 | MultiplyOperator = "*" | "/" | "%" | "**" | "*%" |
| 1471 | */ | 1473 | */ |
| 1472 | static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mandatory) { | 1474 | static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mandatory) { |
| 1473 | Token *token = &pc->tokens->at(*token_index); | 1475 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -1511,15 +1513,17 @@ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool man | ... | @@ -1511,15 +1513,17 @@ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool man |
| 1511 | 1513 | ||
| 1512 | static BinOpType tok_to_add_op(Token *token) { | 1514 | static BinOpType tok_to_add_op(Token *token) { |
| 1513 | switch (token->id) { | 1515 | switch (token->id) { |
| 1514 | case TokenIdPlus: return BinOpTypeAdd; | 1516 | case TokenIdPlus: return BinOpTypeAdd; |
| 1515 | case TokenIdDash: return BinOpTypeSub; | 1517 | case TokenIdPlusPercent: return BinOpTypeAddWrap; |
| 1516 | case TokenIdPlusPlus: return BinOpTypeArrayCat; | 1518 | case TokenIdDash: return BinOpTypeSub; |
| 1517 | default: return BinOpTypeInvalid; | 1519 | case TokenIdMinusPercent: return BinOpTypeSubWrap; |
| 1520 | case TokenIdPlusPlus: return BinOpTypeArrayCat; | ||
| 1521 | default: return BinOpTypeInvalid; | ||
| 1518 | } | 1522 | } |
| 1519 | } | 1523 | } |
| 1520 | 1524 | ||
| 1521 | /* | 1525 | /* |
| 1522 | AdditionOperator : "+" | "-" | "++" | 1526 | AdditionOperator = "+" | "-" | "++" | "+%" | "-%" |
| 1523 | */ | 1527 | */ |
| 1524 | static BinOpType ast_parse_add_op(ParseContext *pc, int *token_index, bool mandatory) { | 1528 | static BinOpType ast_parse_add_op(ParseContext *pc, int *token_index, bool mandatory) { |
| 1525 | Token *token = &pc->tokens->at(*token_index); | 1529 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -1563,14 +1567,15 @@ static AstNode *ast_parse_add_expr(ParseContext *pc, int *token_index, bool mand | ... | @@ -1563,14 +1567,15 @@ static AstNode *ast_parse_add_expr(ParseContext *pc, int *token_index, bool mand |
| 1563 | 1567 | ||
| 1564 | static BinOpType tok_to_bit_shift_op(Token *token) { | 1568 | static BinOpType tok_to_bit_shift_op(Token *token) { |
| 1565 | switch (token->id) { | 1569 | switch (token->id) { |
| 1566 | case TokenIdBitShiftLeft: return BinOpTypeBitShiftLeft; | 1570 | case TokenIdBitShiftLeft: return BinOpTypeBitShiftLeft; |
| 1567 | case TokenIdBitShiftRight: return BinOpTypeBitShiftRight; | 1571 | case TokenIdBitShiftLeftPercent: return BinOpTypeBitShiftLeftWrap; |
| 1572 | case TokenIdBitShiftRight: return BinOpTypeBitShiftRight; | ||
| 1568 | default: return BinOpTypeInvalid; | 1573 | default: return BinOpTypeInvalid; |
| 1569 | } | 1574 | } |
| 1570 | } | 1575 | } |
| 1571 | 1576 | ||
| 1572 | /* | 1577 | /* |
| 1573 | BitShiftOperator : token(BitShiftLeft) | token(BitShiftRight) | 1578 | BitShiftOperator = "<<" | ">>" | "<<%" |
| 1574 | */ | 1579 | */ |
| 1575 | static BinOpType ast_parse_bit_shift_op(ParseContext *pc, int *token_index, bool mandatory) { | 1580 | static BinOpType ast_parse_bit_shift_op(ParseContext *pc, int *token_index, bool mandatory) { |
| 1576 | Token *token = &pc->tokens->at(*token_index); | 1581 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -2230,11 +2235,15 @@ static BinOpType tok_to_ass_op(Token *token) { | ... | @@ -2230,11 +2235,15 @@ static BinOpType tok_to_ass_op(Token *token) { |
| 2230 | switch (token->id) { | 2235 | switch (token->id) { |
| 2231 | case TokenIdEq: return BinOpTypeAssign; | 2236 | case TokenIdEq: return BinOpTypeAssign; |
| 2232 | case TokenIdTimesEq: return BinOpTypeAssignTimes; | 2237 | case TokenIdTimesEq: return BinOpTypeAssignTimes; |
| 2238 | case TokenIdTimesPercentEq: return BinOpTypeAssignTimesWrap; | ||
| 2233 | case TokenIdDivEq: return BinOpTypeAssignDiv; | 2239 | case TokenIdDivEq: return BinOpTypeAssignDiv; |
| 2234 | case TokenIdModEq: return BinOpTypeAssignMod; | 2240 | case TokenIdModEq: return BinOpTypeAssignMod; |
| 2235 | case TokenIdPlusEq: return BinOpTypeAssignPlus; | 2241 | case TokenIdPlusEq: return BinOpTypeAssignPlus; |
| 2242 | case TokenIdPlusPercentEq: return BinOpTypeAssignPlusWrap; | ||
| 2236 | case TokenIdMinusEq: return BinOpTypeAssignMinus; | 2243 | case TokenIdMinusEq: return BinOpTypeAssignMinus; |
| 2244 | case TokenIdMinusPercentEq: return BinOpTypeAssignMinusWrap; | ||
| 2237 | case TokenIdBitShiftLeftEq: return BinOpTypeAssignBitShiftLeft; | 2245 | case TokenIdBitShiftLeftEq: return BinOpTypeAssignBitShiftLeft; |
| 2246 | case TokenIdBitShiftLeftPercentEq: return BinOpTypeAssignBitShiftLeftWrap; | ||
| 2238 | case TokenIdBitShiftRightEq: return BinOpTypeAssignBitShiftRight; | 2247 | case TokenIdBitShiftRightEq: return BinOpTypeAssignBitShiftRight; |
| 2239 | case TokenIdBitAndEq: return BinOpTypeAssignBitAnd; | 2248 | case TokenIdBitAndEq: return BinOpTypeAssignBitAnd; |
| 2240 | case TokenIdBitXorEq: return BinOpTypeAssignBitXor; | 2249 | case TokenIdBitXorEq: return BinOpTypeAssignBitXor; |
| ... | @@ -2246,7 +2255,7 @@ static BinOpType tok_to_ass_op(Token *token) { | ... | @@ -2246,7 +2255,7 @@ static BinOpType tok_to_ass_op(Token *token) { |
| 2246 | } | 2255 | } |
| 2247 | 2256 | ||
| 2248 | /* | 2257 | /* |
| 2249 | AssignmentOperator : token(Eq) | token(TimesEq) | token(DivEq) | token(ModEq) | token(PlusEq) | token(MinusEq) | token(BitShiftLeftEq) | token(BitShiftRightEq) | token(BitAndEq) | token(BitXorEq) | token(BitOrEq) | token(BoolAndEq) | token(BoolOrEq) | 2258 | AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%=" |
| 2250 | */ | 2259 | */ |
| 2251 | static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool mandatory) { | 2260 | static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool mandatory) { |
| 2252 | Token *token = &pc->tokens->at(*token_index); | 2261 | Token *token = &pc->tokens->at(*token_index); |
src/tokenizer.cpp+88| ... | @@ -154,10 +154,13 @@ enum TokenizeState { | ... | @@ -154,10 +154,13 @@ enum TokenizeState { |
| 154 | TokenizeStateCharLiteral, | 154 | TokenizeStateCharLiteral, |
| 155 | TokenizeStateCharLiteralEnd, | 155 | TokenizeStateCharLiteralEnd, |
| 156 | TokenizeStateSawStar, | 156 | TokenizeStateSawStar, |
| 157 | TokenizeStateSawStarPercent, | ||
| 157 | TokenizeStateSawSlash, | 158 | TokenizeStateSawSlash, |
| 158 | TokenizeStateSawPercent, | 159 | TokenizeStateSawPercent, |
| 159 | TokenizeStateSawPlus, | 160 | TokenizeStateSawPlus, |
| 161 | TokenizeStateSawPlusPercent, | ||
| 160 | TokenizeStateSawDash, | 162 | TokenizeStateSawDash, |
| 163 | TokenizeStateSawMinusPercent, | ||
| 161 | TokenizeStateSawAmpersand, | 164 | TokenizeStateSawAmpersand, |
| 162 | TokenizeStateSawAmpersandAmpersand, | 165 | TokenizeStateSawAmpersandAmpersand, |
| 163 | TokenizeStateSawCaret, | 166 | TokenizeStateSawCaret, |
| ... | @@ -171,6 +174,7 @@ enum TokenizeState { | ... | @@ -171,6 +174,7 @@ enum TokenizeState { |
| 171 | TokenizeStateSawBang, | 174 | TokenizeStateSawBang, |
| 172 | TokenizeStateSawLessThan, | 175 | TokenizeStateSawLessThan, |
| 173 | TokenizeStateSawLessThanLessThan, | 176 | TokenizeStateSawLessThanLessThan, |
| 177 | TokenizeStateSawShiftLeftPercent, | ||
| 174 | TokenizeStateSawGreaterThan, | 178 | TokenizeStateSawGreaterThan, |
| 175 | TokenizeStateSawGreaterThanGreaterThan, | 179 | TokenizeStateSawGreaterThanGreaterThan, |
| 176 | TokenizeStateSawDot, | 180 | TokenizeStateSawDot, |
| ... | @@ -596,6 +600,24 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -596,6 +600,24 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 596 | end_token(&t); | 600 | end_token(&t); |
| 597 | t.state = TokenizeStateStart; | 601 | t.state = TokenizeStateStart; |
| 598 | break; | 602 | break; |
| 603 | case '%': | ||
| 604 | t.cur_tok->id = TokenIdBitShiftLeftPercent; | ||
| 605 | t.state = TokenizeStateSawShiftLeftPercent; | ||
| 606 | break; | ||
| 607 | default: | ||
| 608 | t.pos -= 1; | ||
| 609 | end_token(&t); | ||
| 610 | t.state = TokenizeStateStart; | ||
| 611 | continue; | ||
| 612 | } | ||
| 613 | break; | ||
| 614 | case TokenizeStateSawShiftLeftPercent: | ||
| 615 | switch (c) { | ||
| 616 | case '=': | ||
| 617 | t.cur_tok->id = TokenIdBitShiftLeftPercentEq; | ||
| 618 | end_token(&t); | ||
| 619 | t.state = TokenizeStateStart; | ||
| 620 | break; | ||
| 599 | default: | 621 | default: |
| 600 | t.pos -= 1; | 622 | t.pos -= 1; |
| 601 | end_token(&t); | 623 | end_token(&t); |
| ... | @@ -648,6 +670,24 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -648,6 +670,24 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 648 | end_token(&t); | 670 | end_token(&t); |
| 649 | t.state = TokenizeStateStart; | 671 | t.state = TokenizeStateStart; |
| 650 | break; | 672 | break; |
| 673 | case '%': | ||
| 674 | t.cur_tok->id = TokenIdTimesPercent; | ||
| 675 | t.state = TokenizeStateSawStarPercent; | ||
| 676 | break; | ||
| 677 | default: | ||
| 678 | t.pos -= 1; | ||
| 679 | end_token(&t); | ||
| 680 | t.state = TokenizeStateStart; | ||
| 681 | continue; | ||
| 682 | } | ||
| 683 | break; | ||
| 684 | case TokenizeStateSawStarPercent: | ||
| 685 | switch (c) { | ||
| 686 | case '=': | ||
| 687 | t.cur_tok->id = TokenIdTimesPercentEq; | ||
| 688 | end_token(&t); | ||
| 689 | t.state = TokenizeStateStart; | ||
| 690 | break; | ||
| 651 | default: | 691 | default: |
| 652 | t.pos -= 1; | 692 | t.pos -= 1; |
| 653 | end_token(&t); | 693 | end_token(&t); |
| ... | @@ -691,6 +731,24 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -691,6 +731,24 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 691 | end_token(&t); | 731 | end_token(&t); |
| 692 | t.state = TokenizeStateStart; | 732 | t.state = TokenizeStateStart; |
| 693 | break; | 733 | break; |
| 734 | case '%': | ||
| 735 | t.cur_tok->id = TokenIdPlusPercent; | ||
| 736 | t.state = TokenizeStateSawPlusPercent; | ||
| 737 | break; | ||
| 738 | default: | ||
| 739 | t.pos -= 1; | ||
| 740 | end_token(&t); | ||
| 741 | t.state = TokenizeStateStart; | ||
| 742 | continue; | ||
| 743 | } | ||
| 744 | break; | ||
| 745 | case TokenizeStateSawPlusPercent: | ||
| 746 | switch (c) { | ||
| 747 | case '=': | ||
| 748 | t.cur_tok->id = TokenIdPlusPercentEq; | ||
| 749 | end_token(&t); | ||
| 750 | t.state = TokenizeStateStart; | ||
| 751 | break; | ||
| 694 | default: | 752 | default: |
| 695 | t.pos -= 1; | 753 | t.pos -= 1; |
| 696 | end_token(&t); | 754 | end_token(&t); |
| ... | @@ -1181,6 +1239,24 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -1181,6 +1239,24 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 1181 | end_token(&t); | 1239 | end_token(&t); |
| 1182 | t.state = TokenizeStateStart; | 1240 | t.state = TokenizeStateStart; |
| 1183 | break; | 1241 | break; |
| 1242 | case '%': | ||
| 1243 | t.cur_tok->id = TokenIdMinusPercent; | ||
| 1244 | t.state = TokenizeStateSawMinusPercent; | ||
| 1245 | break; | ||
| 1246 | default: | ||
| 1247 | t.pos -= 1; | ||
| 1248 | end_token(&t); | ||
| 1249 | t.state = TokenizeStateStart; | ||
| 1250 | continue; | ||
| 1251 | } | ||
| 1252 | break; | ||
| 1253 | case TokenizeStateSawMinusPercent: | ||
| 1254 | switch (c) { | ||
| 1255 | case '=': | ||
| 1256 | t.cur_tok->id = TokenIdMinusPercentEq; | ||
| 1257 | end_token(&t); | ||
| 1258 | t.state = TokenizeStateStart; | ||
| 1259 | break; | ||
| 1184 | default: | 1260 | default: |
| 1185 | t.pos -= 1; | 1261 | t.pos -= 1; |
| 1186 | end_token(&t); | 1262 | end_token(&t); |
| ... | @@ -1252,6 +1328,10 @@ void tokenize(Buf *buf, Tokenization *out) { | ... | @@ -1252,6 +1328,10 @@ void tokenize(Buf *buf, Tokenization *out) { |
| 1252 | case TokenizeStateSawDot: | 1328 | case TokenizeStateSawDot: |
| 1253 | case TokenizeStateSawQuestionMark: | 1329 | case TokenizeStateSawQuestionMark: |
| 1254 | case TokenizeStateSawAtSign: | 1330 | case TokenizeStateSawAtSign: |
| 1331 | case TokenizeStateSawStarPercent: | ||
| 1332 | case TokenizeStateSawPlusPercent: | ||
| 1333 | case TokenizeStateSawMinusPercent: | ||
| 1334 | case TokenizeStateSawShiftLeftPercent: | ||
| 1255 | end_token(&t); | 1335 | end_token(&t); |
| 1256 | break; | 1336 | break; |
| 1257 | case TokenizeStateSawDotDot: | 1337 | case TokenizeStateSawDotDot: |
| ... | @@ -1372,6 +1452,14 @@ const char * token_name(TokenId id) { | ... | @@ -1372,6 +1452,14 @@ const char * token_name(TokenId id) { |
| 1372 | case TokenIdMaybeAssign: return "?="; | 1452 | case TokenIdMaybeAssign: return "?="; |
| 1373 | case TokenIdAtSign: return "@"; | 1453 | case TokenIdAtSign: return "@"; |
| 1374 | case TokenIdPercentDot: return "%."; | 1454 | case TokenIdPercentDot: return "%."; |
| 1455 | case TokenIdTimesPercent: return "*%"; | ||
| 1456 | case TokenIdTimesPercentEq: return "*%="; | ||
| 1457 | case TokenIdPlusPercent: return "+%"; | ||
| 1458 | case TokenIdPlusPercentEq: return "+%="; | ||
| 1459 | case TokenIdMinusPercent: return "-%"; | ||
| 1460 | case TokenIdMinusPercentEq: return "-%="; | ||
| 1461 | case TokenIdBitShiftLeftPercent: return "<<%"; | ||
| 1462 | case TokenIdBitShiftLeftPercentEq: return "<<%="; | ||
| 1375 | } | 1463 | } |
| 1376 | return "(invalid token)"; | 1464 | return "(invalid token)"; |
| 1377 | } | 1465 | } |
src/tokenizer.hpp+8| ... | @@ -70,11 +70,19 @@ enum TokenId { | ... | @@ -70,11 +70,19 @@ enum TokenId { |
| 70 | TokenIdBinXor, | 70 | TokenIdBinXor, |
| 71 | TokenIdEq, | 71 | TokenIdEq, |
| 72 | TokenIdTimesEq, | 72 | TokenIdTimesEq, |
| 73 | TokenIdTimesPercent, | ||
| 74 | TokenIdTimesPercentEq, | ||
| 73 | TokenIdDivEq, | 75 | TokenIdDivEq, |
| 74 | TokenIdModEq, | 76 | TokenIdModEq, |
| 75 | TokenIdPlusEq, | 77 | TokenIdPlusEq, |
| 78 | TokenIdPlusPercent, | ||
| 79 | TokenIdPlusPercentEq, | ||
| 76 | TokenIdMinusEq, | 80 | TokenIdMinusEq, |
| 81 | TokenIdMinusPercent, | ||
| 82 | TokenIdMinusPercentEq, | ||
| 77 | TokenIdBitShiftLeftEq, | 83 | TokenIdBitShiftLeftEq, |
| 84 | TokenIdBitShiftLeftPercent, | ||
| 85 | TokenIdBitShiftLeftPercentEq, | ||
| 78 | TokenIdBitShiftRightEq, | 86 | TokenIdBitShiftRightEq, |
| 79 | TokenIdBitAndEq, | 87 | TokenIdBitAndEq, |
| 80 | TokenIdBitXorEq, | 88 | TokenIdBitXorEq, |
std/io.zig+1-1| ... | @@ -235,7 +235,7 @@ fn char_to_digit(c: u8, radix: u8) -> %u8 { | ... | @@ -235,7 +235,7 @@ fn char_to_digit(c: u8, radix: u8) -> %u8 { |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | pub fn buf_print_signed(inline T: type, out_buf: []u8, x: T) -> usize { | 237 | pub fn buf_print_signed(inline T: type, out_buf: []u8, x: T) -> usize { |
| 238 | const uint = @int_type(false, T.bit_count, false); | 238 | const uint = @int_type(false, T.bit_count); |
| 239 | if (x < 0) { | 239 | if (x < 0) { |
| 240 | out_buf[0] = '-'; | 240 | out_buf[0] = '-'; |
| 241 | return 1 + buf_print_unsigned(uint, out_buf[1...], uint(-(x + 1)) + 1); | 241 | return 1 + buf_print_unsigned(uint, out_buf[1...], uint(-(x + 1)) + 1); |
std/rand.zig+5-6| ... | @@ -77,7 +77,7 @@ pub struct Rand { | ... | @@ -77,7 +77,7 @@ pub struct Rand { |
| 77 | 77 | ||
| 78 | /// Get a floating point value in the range 0.0..1.0. | 78 | /// Get a floating point value in the range 0.0..1.0. |
| 79 | pub fn float(r: &Rand, inline T: type) -> T { | 79 | pub fn float(r: &Rand, inline T: type) -> T { |
| 80 | const int_type = @int_type(false, @sizeof(T) * 8, false); | 80 | const int_type = @int_type(false, @sizeof(T) * 8); |
| 81 | // TODO switch statement for constant values | 81 | // TODO switch statement for constant values |
| 82 | const precision = if (T == f32) { | 82 | const precision = if (T == f32) { |
| 83 | 16777216 | 83 | 16777216 |
| ... | @@ -99,7 +99,6 @@ struct MersenneTwister( | ... | @@ -99,7 +99,6 @@ struct MersenneTwister( |
| 99 | l: int, f: int) | 99 | l: int, f: int) |
| 100 | { | 100 | { |
| 101 | const Self = MersenneTwister(int, n, m, r, a, u, d, s, b, t, c, l, f); | 101 | const Self = MersenneTwister(int, n, m, r, a, u, d, s, b, t, c, l, f); |
| 102 | const intw = @int_type(int.is_signed, int.bit_count, true); | ||
| 103 | 102 | ||
| 104 | array: [n]int, | 103 | array: [n]int, |
| 105 | index: usize, | 104 | index: usize, |
| ... | @@ -113,7 +112,7 @@ struct MersenneTwister( | ... | @@ -113,7 +112,7 @@ struct MersenneTwister( |
| 113 | var prev_value = seed; | 112 | var prev_value = seed; |
| 114 | mt.array[0] = prev_value; | 113 | mt.array[0] = prev_value; |
| 115 | {var i: usize = 1; while (i < n; i += 1) { | 114 | {var i: usize = 1; while (i < n; i += 1) { |
| 116 | prev_value = intw(i) + intw(f) * intw(prev_value ^ (prev_value >> (int.bit_count - 2))); | 115 | prev_value = int(i) +% f *% (prev_value ^ (prev_value >> (int.bit_count - 2))); |
| 117 | mt.array[i] = prev_value; | 116 | mt.array[i] = prev_value; |
| 118 | }}; | 117 | }}; |
| 119 | 118 | ||
| ... | @@ -152,12 +151,12 @@ struct MersenneTwister( | ... | @@ -152,12 +151,12 @@ struct MersenneTwister( |
| 152 | mt.index = 0; | 151 | mt.index = 0; |
| 153 | } | 152 | } |
| 154 | 153 | ||
| 155 | var x: intw = mt.array[mt.index]; | 154 | var x = mt.array[mt.index]; |
| 156 | mt.index += 1; | 155 | mt.index += 1; |
| 157 | 156 | ||
| 158 | x ^= ((x >> u) & d); | 157 | x ^= ((x >> u) & d); |
| 159 | x ^= ((x << s) & b); | 158 | x ^= ((x <<% s) & b); |
| 160 | x ^= ((x << t) & c); | 159 | x ^= ((x <<% t) & c); |
| 161 | x ^= (x >> l); | 160 | x ^= (x >> l); |
| 162 | 161 | ||
| 163 | return x; | 162 | return x; |
test/run_tests.cpp-6| ... | @@ -1362,12 +1362,6 @@ fn mul(a: u16, b: u16) -> u16 { | ... | @@ -1362,12 +1362,6 @@ fn mul(a: u16, b: u16) -> u16 { |
| 1362 | ".tmp_source.zig:3:18: note: called from here", | 1362 | ".tmp_source.zig:3:18: note: called from here", |
| 1363 | ".tmp_source.zig:6:7: note: overflow occurred here"); | 1363 | ".tmp_source.zig:6:7: note: overflow occurred here"); |
| 1364 | 1364 | ||
| 1365 | add_compile_fail_case("add incompatible int types", R"SOURCE( | ||
| 1366 | fn add(x: i8w, y: i32) { | ||
| 1367 | const z = x + y; | ||
| 1368 | } | ||
| 1369 | )SOURCE", 1, ".tmp_source.zig:3:17: error: incompatible types: 'i8w' and 'i32'"); | ||
| 1370 | |||
| 1371 | add_compile_fail_case("truncate sign mismatch", R"SOURCE( | 1365 | add_compile_fail_case("truncate sign mismatch", R"SOURCE( |
| 1372 | fn f() { | 1366 | fn f() { |
| 1373 | const x: u32 = 10; | 1367 | const x: u32 = 10; |
test/self_hosted.zig+29-66| ... | @@ -1458,17 +1458,17 @@ fn unsigned_wrapping() { | ... | @@ -1458,17 +1458,17 @@ fn unsigned_wrapping() { |
| 1458 | test_unsigned_wrapping_eval(@max_value(u32)); | 1458 | test_unsigned_wrapping_eval(@max_value(u32)); |
| 1459 | test_unsigned_wrapping_noeval(@max_value(u32)); | 1459 | test_unsigned_wrapping_noeval(@max_value(u32)); |
| 1460 | } | 1460 | } |
| 1461 | fn test_unsigned_wrapping_eval(x: u32w) { | 1461 | fn test_unsigned_wrapping_eval(x: u32) { |
| 1462 | const zero = x + 1; | 1462 | const zero = x +% 1; |
| 1463 | assert(zero == 0); | 1463 | assert(zero == 0); |
| 1464 | const orig = zero - 1; | 1464 | const orig = zero -% 1; |
| 1465 | assert(orig == @max_value(u32)); | 1465 | assert(orig == @max_value(u32)); |
| 1466 | } | 1466 | } |
| 1467 | #static_eval_enable(false) | 1467 | #static_eval_enable(false) |
| 1468 | fn test_unsigned_wrapping_noeval(x: u32w) { | 1468 | fn test_unsigned_wrapping_noeval(x: u32) { |
| 1469 | const zero = x + 1; | 1469 | const zero = x +% 1; |
| 1470 | assert(zero == 0); | 1470 | assert(zero == 0); |
| 1471 | const orig = zero - 1; | 1471 | const orig = zero -% 1; |
| 1472 | assert(orig == @max_value(u32)); | 1472 | assert(orig == @max_value(u32)); |
| 1473 | } | 1473 | } |
| 1474 | 1474 | ||
| ... | @@ -1477,17 +1477,17 @@ fn signed_wrapping() { | ... | @@ -1477,17 +1477,17 @@ fn signed_wrapping() { |
| 1477 | test_signed_wrapping_eval(@max_value(i32)); | 1477 | test_signed_wrapping_eval(@max_value(i32)); |
| 1478 | test_signed_wrapping_noeval(@max_value(i32)); | 1478 | test_signed_wrapping_noeval(@max_value(i32)); |
| 1479 | } | 1479 | } |
| 1480 | fn test_signed_wrapping_eval(x: i32w) { | 1480 | fn test_signed_wrapping_eval(x: i32) { |
| 1481 | const min_val = x + 1; | 1481 | const min_val = x +% 1; |
| 1482 | assert(min_val == @min_value(i32)); | 1482 | assert(min_val == @min_value(i32)); |
| 1483 | const max_val = min_val - 1; | 1483 | const max_val = min_val -% 1; |
| 1484 | assert(max_val == @max_value(i32)); | 1484 | assert(max_val == @max_value(i32)); |
| 1485 | } | 1485 | } |
| 1486 | #static_eval_enable(false) | 1486 | #static_eval_enable(false) |
| 1487 | fn test_signed_wrapping_noeval(x: i32w) { | 1487 | fn test_signed_wrapping_noeval(x: i32) { |
| 1488 | const min_val = x + 1; | 1488 | const min_val = x +% 1; |
| 1489 | assert(min_val == @min_value(i32)); | 1489 | assert(min_val == @min_value(i32)); |
| 1490 | const max_val = min_val - 1; | 1490 | const max_val = min_val -% 1; |
| 1491 | assert(max_val == @max_value(i32)); | 1491 | assert(max_val == @max_value(i32)); |
| 1492 | } | 1492 | } |
| 1493 | 1493 | ||
| ... | @@ -1496,15 +1496,15 @@ fn negation_wrapping() { | ... | @@ -1496,15 +1496,15 @@ fn negation_wrapping() { |
| 1496 | test_negation_wrapping_eval(@min_value(i16)); | 1496 | test_negation_wrapping_eval(@min_value(i16)); |
| 1497 | test_negation_wrapping_noeval(@min_value(i16)); | 1497 | test_negation_wrapping_noeval(@min_value(i16)); |
| 1498 | } | 1498 | } |
| 1499 | fn test_negation_wrapping_eval(x: i16w) { | 1499 | fn test_negation_wrapping_eval(x: i16) { |
| 1500 | assert(x == -32768); | 1500 | assert(x == -32768); |
| 1501 | const neg = -x; | 1501 | const neg = -%x; |
| 1502 | assert(neg == -32768); | 1502 | assert(neg == -32768); |
| 1503 | } | 1503 | } |
| 1504 | #static_eval_enable(false) | 1504 | #static_eval_enable(false) |
| 1505 | fn test_negation_wrapping_noeval(x: i16w) { | 1505 | fn test_negation_wrapping_noeval(x: i16) { |
| 1506 | assert(x == -32768); | 1506 | assert(x == -32768); |
| 1507 | const neg = -x; | 1507 | const neg = -%x; |
| 1508 | assert(neg == -32768); | 1508 | assert(neg == -32768); |
| 1509 | } | 1509 | } |
| 1510 | 1510 | ||
| ... | @@ -1513,13 +1513,13 @@ fn shl_wrapping() { | ... | @@ -1513,13 +1513,13 @@ fn shl_wrapping() { |
| 1513 | test_shl_wrapping_eval(@max_value(u16)); | 1513 | test_shl_wrapping_eval(@max_value(u16)); |
| 1514 | test_shl_wrapping_noeval(@max_value(u16)); | 1514 | test_shl_wrapping_noeval(@max_value(u16)); |
| 1515 | } | 1515 | } |
| 1516 | fn test_shl_wrapping_eval(x: u16w) { | 1516 | fn test_shl_wrapping_eval(x: u16) { |
| 1517 | const shifted = x << 1; | 1517 | const shifted = x <<% 1; |
| 1518 | assert(shifted == 65534); | 1518 | assert(shifted == 65534); |
| 1519 | } | 1519 | } |
| 1520 | #static_eval_enable(false) | 1520 | #static_eval_enable(false) |
| 1521 | fn test_shl_wrapping_noeval(x: u16w) { | 1521 | fn test_shl_wrapping_noeval(x: u16) { |
| 1522 | const shifted = x << 1; | 1522 | const shifted = x <<% 1; |
| 1523 | assert(shifted == 65534); | 1523 | assert(shifted == 65534); |
| 1524 | } | 1524 | } |
| 1525 | 1525 | ||
| ... | @@ -1531,23 +1531,6 @@ fn shl_with_overflow() { | ... | @@ -1531,23 +1531,6 @@ fn shl_with_overflow() { |
| 1531 | assert(result == 0b1011111111111100); | 1531 | assert(result == 0b1011111111111100); |
| 1532 | } | 1532 | } |
| 1533 | 1533 | ||
| 1534 | #attribute("test") | ||
| 1535 | fn combine_non_wrap_with_wrap() { | ||
| 1536 | const x: i32 = 123; | ||
| 1537 | const y: i32w = 456; | ||
| 1538 | const z = x + y; | ||
| 1539 | const z2 = y + x; | ||
| 1540 | assert(@typeof(z) == i32w); | ||
| 1541 | assert(@typeof(z2) == i32w); | ||
| 1542 | |||
| 1543 | const a: i8 = 123; | ||
| 1544 | const b: i32w = 456; | ||
| 1545 | const c = b + a; | ||
| 1546 | const d = a + b; | ||
| 1547 | assert(@typeof(c) == i32w); | ||
| 1548 | assert(@typeof(d) == i32w); | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | #attribute("test") | 1534 | #attribute("test") |
| 1552 | fn c_string_concatenation() { | 1535 | fn c_string_concatenation() { |
| 1553 | const a = c"OK" ++ c" IT " ++ c"WORKED"; | 1536 | const a = c"OK" ++ c" IT " ++ c"WORKED"; |
| ... | @@ -1687,41 +1670,21 @@ struct DivResult { | ... | @@ -1687,41 +1670,21 @@ struct DivResult { |
| 1687 | 1670 | ||
| 1688 | #attribute("test") | 1671 | #attribute("test") |
| 1689 | fn int_type_builtin() { | 1672 | fn int_type_builtin() { |
| 1690 | assert(@int_type(true, 8, false) == i8); | 1673 | assert(@int_type(true, 8) == i8); |
| 1691 | assert(@int_type(true, 16, false) == i16); | 1674 | assert(@int_type(true, 16) == i16); |
| 1692 | assert(@int_type(true, 32, false) == i32); | 1675 | assert(@int_type(true, 32) == i32); |
| 1693 | assert(@int_type(true, 64, false) == i64); | 1676 | assert(@int_type(true, 64) == i64); |
| 1694 | 1677 | ||
| 1695 | assert(@int_type(false, 8, false) == u8); | 1678 | assert(@int_type(false, 8) == u8); |
| 1696 | assert(@int_type(false, 16, false) == u16); | 1679 | assert(@int_type(false, 16) == u16); |
| 1697 | assert(@int_type(false, 32, false) == u32); | 1680 | assert(@int_type(false, 32) == u32); |
| 1698 | assert(@int_type(false, 64, false) == u64); | 1681 | assert(@int_type(false, 64) == u64); |
| 1699 | |||
| 1700 | assert(@int_type(true, 8, true) == i8w); | ||
| 1701 | assert(@int_type(true, 16, true) == i16w); | ||
| 1702 | assert(@int_type(true, 32, true) == i32w); | ||
| 1703 | assert(@int_type(true, 64, true) == i64w); | ||
| 1704 | |||
| 1705 | assert(@int_type(false, 8, true) == u8w); | ||
| 1706 | assert(@int_type(false, 16, true) == u16w); | ||
| 1707 | assert(@int_type(false, 32, true) == u32w); | ||
| 1708 | assert(@int_type(false, 64, true) == u64w); | ||
| 1709 | 1682 | ||
| 1710 | assert(i8.bit_count == 8); | 1683 | assert(i8.bit_count == 8); |
| 1711 | assert(i16.bit_count == 16); | 1684 | assert(i16.bit_count == 16); |
| 1712 | assert(i32.bit_count == 32); | 1685 | assert(i32.bit_count == 32); |
| 1713 | assert(i64.bit_count == 64); | 1686 | assert(i64.bit_count == 64); |
| 1714 | 1687 | ||
| 1715 | assert(!i8.is_wrapping); | ||
| 1716 | assert(!i16.is_wrapping); | ||
| 1717 | assert(!i32.is_wrapping); | ||
| 1718 | assert(!i64.is_wrapping); | ||
| 1719 | |||
| 1720 | assert(i8w.is_wrapping); | ||
| 1721 | assert(i16w.is_wrapping); | ||
| 1722 | assert(i32w.is_wrapping); | ||
| 1723 | assert(i64w.is_wrapping); | ||
| 1724 | |||
| 1725 | assert(i8.is_signed); | 1688 | assert(i8.is_signed); |
| 1726 | assert(i16.is_signed); | 1689 | assert(i16.is_signed); |
| 1727 | assert(i32.is_signed); | 1690 | assert(i32.is_signed); |