authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-07-27 23:04:24-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-07-27 23:08:27-07:00
log8552d7fd19836f3350b7303f9bd897708b966805
tree0189be7c4bc284bfb693db3eb007844bd168b213
parent3eb5afd245d8e2059a8cf4b8aa4e201ec0613535

explicit wrapping integer operations

instead of wrapping integer types closes #159

15 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
6969
70AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression70AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression
7171
72AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||="72AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
7373
74BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression74BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression
7575
...@@ -111,17 +111,17 @@ BinaryAndExpression = BitShiftExpression "&" BinaryAndExpression | BitShiftExpre...@@ -111,17 +111,17 @@ BinaryAndExpression = BitShiftExpression "&" BinaryAndExpression | BitShiftExpre
111111
112BitShiftExpression = AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression112BitShiftExpression = AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression
113113
114BitShiftOperator = "<<" | ">>"114BitShiftOperator = "<<" | ">>" | "<<%"
115115
116AdditionExpression = MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression116AdditionExpression = MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression
117117
118AdditionOperator = "+" | "-" | "++"118AdditionOperator = "+" | "-" | "++" | "+%" | "-%"
119119
120MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression120MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
121121
122CurlySuffixExpression = TypeExpr option(ContainerInitExpression)122CurlySuffixExpression = TypeExpr option(ContainerInitExpression)
123123
124MultiplyOperator = "*" | "/" | "%" | "**"124MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
125125
126PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression126PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
127127
...@@ -141,7 +141,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")...@@ -141,7 +141,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
141141
142StructLiteralField = "." "Symbol" "=" Expression142StructLiteralField = "." "Symbol" "=" Expression
143143
144PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??"144PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"
145145
146PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")146PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")
147147
...@@ -181,26 +181,15 @@ x{}...@@ -181,26 +181,15 @@ x{}
181Type name C equivalent Description181Type name C equivalent Description
182182
183i8 int8_t signed 8-bit integer183i8 int8_t signed 8-bit integer
184u8 (none) unsigned 8-bit integer184u8 uint8_t unsigned 8-bit integer
185i16 int16_t signed 16-bit integer185i16 int16_t signed 16-bit integer
186u16 (none) unsigned 16-bit integer186u16 uint16_t unsigned 16-bit integer
187i32 int32_t signed 32-bit integer187i32 int32_t signed 32-bit integer
188u32 (none) unsigned 32-bit integer188u32 uint32_t unsigned 32-bit integer
189i64 int64_t signed 64-bit integer189i64 int64_t signed 64-bit integer
190u64 (none) unsigned 64-bit integer190u64 uint64_t unsigned 64-bit integer
191isize intptr_t signed pointer sized integer191isize intptr_t signed pointer sized integer
192usize (none) unsigned pointer sized integer192usize uintptr_t unsigned pointer sized integer
193
194i8w (none) wrapping signed 8-bit integer
195u8w uint8_t wrapping unsigned 8-bit integer
196i16w (none) wrapping signed 16-bit integer
197u16w uint16_t wrapping unsigned 16-bit integer
198i32w (none) wrapping signed 32-bit integer
199u32w uint32_t wrapping unsigned 32-bit integer
200i64w (none) wrapping signed 64-bit integer
201u64w uint64_t wrapping unsigned 64-bit integer
202isizew (none) wrapping signed pointer sized integer
203usizew uintptr_t wrapping unsigned pointer sized integer
204193
205c_short short for ABI compatibility with C194c_short short for ABI compatibility with C
206c_ushort unsigned short for ABI compatibility with C195c_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
213c_long_double long double for ABI compatibility with C202c_long_double long double for ABI compatibility with C
214c_void void for ABI compatibility with C203c_void void for ABI compatibility with C
215204
216f32 float 32-bit IEE754 floating point205f32 float 32-bit floating point
217f64 double 64-bit IEE754 floating point206f64 double 64-bit floating point
218```207```
219208
220### Boolean Type209### Boolean Type
...@@ -595,9 +584,8 @@ const b: u8 = @truncate(u8, a);...@@ -595,9 +584,8 @@ const b: u8 = @truncate(u8, a);
595This function, when semantically analyzed, causes a compile error with the message `msg`.584This function, when semantically analyzed, causes a compile error with the message `msg`.
596585
597There are several ways that code avoids being semantically checked, such as using `if`586There are several ways that code avoids being semantically checked, such as using `if`
598or `switch` with compile variables, and inline functions.587or `switch` with compile time constants, and inline functions.
599588
600### @int_type(inline is_signed: bool, inline bit_count: u8, inline is_wrapping: bool) -> type589### @int_type(inline is_signed: bool, inline bit_count: u8) -> type
601590
602This function returns an integer type with the given signness, bit count, and591This function returns an integer type with the given signness and bit count.
603wrapping 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
17syn keyword zigKeyword fn use17syn keyword zigKeyword fn use
18syn keyword zigType bool f32 f64 void unreachable type error18syn keyword zigType bool f32 f64 void unreachable type error
19syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize19syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize
20syn keyword zigType i8w u8w i16w u16w i32w u32w i64w u64w isizew usizew
21syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong20syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong
2221
23syn keyword zigBoolean true false22syn 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 {
860struct TypeTableEntryInt {869struct TypeTableEntryInt {
861 int bit_count;870 int bit_count;
862 bool is_signed;871 bool is_signed;
863 bool is_wrapping;
864};872};
865873
866struct TypeTableEntryFloat {874struct TypeTableEntryFloat {
...@@ -1185,7 +1193,7 @@ struct CodeGen {...@@ -1185,7 +1193,7 @@ struct CodeGen {
11851193
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}
246246
247TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {247TypeTableEntry *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}
250250
251static TypeTableEntry *get_generic_fn_type(CodeGen *g, AstNode *decl_node) {251static 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);
49154915
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);
49214920
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 }
49284926
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;
49324929
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 }
49454940
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;
49484942
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);
49524946
...@@ -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 eval5721 // 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}
70617075
7062TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits) {7076TypeTableEntry **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}
70777091
7078TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits) {7092TypeTableEntry *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}
70817095
7082TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {7096TypeTableEntry **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);
19Expr *get_resolved_expr(AstNode *node);19Expr *get_resolved_expr(AstNode *node);
20bool is_node_void_expr(AstNode *node);20bool is_node_void_expr(AstNode *node);
21uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);21uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
22TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits);22TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
23TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits);23TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);
24TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);24TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
25TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);25TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
26TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type);26TypeTableEntry *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 @@
44
5static const char *bin_op_str(BinOpType bin_op) {5static 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);
15661566
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};
41904216
4191struct SignWrap {4217static const bool is_signed_list[] = { false, true, };
4192 bool is_signed;
4193 bool is_wrapping;
4194};
4195
4196static const SignWrap sign_wrap_list[] = {
4197 {false, false},
4198 {false, true},
4199 {true, false},
4200 {true, true},
4201};
42024218
4203static void define_builtin_types(CodeGen *g) {4219static 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) {
42384254
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;
42444259
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;
42484263
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);
42534267
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);
42774290
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 }
42814294
...@@ -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);
43034315
...@@ -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 }
43214333
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;
43254336
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);
43294340
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);
43344344
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;
43384347
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);
43464355
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 }
44324441
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);
44414450
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}
47084717
4709static void init(CodeGen *g, Buf *source_path) {4718static 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) {
146146
147static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,147static 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) {
13991400
1400/*1401/*
1401PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression1402PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
1402PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))1403PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"
1403*/1404*/
1404static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {1405static 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
14581459
1459static BinOpType tok_to_mult_op(Token *token) {1460static 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}
14681470
1469/*1471/*
1470MultiplyOperator = "*" | "/" | "%" | "**"1472MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
1471*/1473*/
1472static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mandatory) {1474static 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
15111513
1512static BinOpType tok_to_add_op(Token *token) {1514static 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}
15201524
1521/*1525/*
1522AdditionOperator : "+" | "-" | "++"1526AdditionOperator = "+" | "-" | "++" | "+%" | "-%"
1523*/1527*/
1524static BinOpType ast_parse_add_op(ParseContext *pc, int *token_index, bool mandatory) {1528static 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
15631567
1564static BinOpType tok_to_bit_shift_op(Token *token) {1568static 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}
15711576
1572/*1577/*
1573BitShiftOperator : token(BitShiftLeft) | token(BitShiftRight)1578BitShiftOperator = "<<" | ">>" | "<<%"
1574*/1579*/
1575static BinOpType ast_parse_bit_shift_op(ParseContext *pc, int *token_index, bool mandatory) {1580static 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}
22472256
2248/*2257/*
2249AssignmentOperator : 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)2258AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
2250*/2259*/
2251static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool mandatory) {2260static 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}
236236
237pub fn buf_print_signed(inline T: type, out_buf: []u8, x: T) -> usize {237pub 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 {
7777
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 values81 // TODO switch statement for constant values
82 const precision = if (T == f32) {82 const precision = if (T == f32) {
83 1677721683 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);
103102
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 }};
119118
...@@ -152,12 +151,12 @@ struct MersenneTwister(...@@ -152,12 +151,12 @@ struct MersenneTwister(
152 mt.index = 0;151 mt.index = 0;
153 }152 }
154153
155 var x: intw = mt.array[mt.index];154 var x = mt.array[mt.index];
156 mt.index += 1;155 mt.index += 1;
157156
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);
162161
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");
13641364
1365 add_compile_fail_case("add incompatible int types", R"SOURCE(
1366fn 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(
1372fn f() {1366fn 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}
1461fn test_unsigned_wrapping_eval(x: u32w) {1461fn 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)
1468fn test_unsigned_wrapping_noeval(x: u32w) {1468fn 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}
14741474
...@@ -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}
1480fn test_signed_wrapping_eval(x: i32w) {1480fn 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)
1487fn test_signed_wrapping_noeval(x: i32w) {1487fn 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}
14931493
...@@ -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}
1499fn test_negation_wrapping_eval(x: i16w) {1499fn 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)
1505fn test_negation_wrapping_noeval(x: i16w) {1505fn 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}
15101510
...@@ -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}
1516fn test_shl_wrapping_eval(x: u16w) {1516fn 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)
1521fn test_shl_wrapping_noeval(x: u16w) {1521fn 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}
15251525
...@@ -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}
15331533
1534#attribute("test")
1535fn 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")
1552fn c_string_concatenation() {1535fn 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 {
16871670
1688#attribute("test")1671#attribute("test")
1689fn int_type_builtin() {1672fn 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);
16941677
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);
17091682
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);
17141687
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);