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
6969
7070AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression
7171
72AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||="
72AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
7373
7474BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression
7575
......@@ -111,17 +111,17 @@ BinaryAndExpression = BitShiftExpression "&" BinaryAndExpression | BitShiftExpre
111111
112112BitShiftExpression = AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression
113113
114BitShiftOperator = "<<" | ">>"
114BitShiftOperator = "<<" | ">>" | "<<%"
115115
116116AdditionExpression = MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression
117117
118AdditionOperator = "+" | "-" | "++"
118AdditionOperator = "+" | "-" | "++" | "+%" | "-%"
119119
120120MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
121121
122122CurlySuffixExpression = TypeExpr option(ContainerInitExpression)
123123
124MultiplyOperator = "*" | "/" | "%" | "**"
124MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
125125
126126PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
127127
......@@ -141,7 +141,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
141141
142142StructLiteralField = "." "Symbol" "=" Expression
143143
144PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??"
144PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"
145145
146146PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." "Symbol")
147147
......@@ -181,26 +181,15 @@ x{}
181181Type name C equivalent Description
182182
183183i8 int8_t signed 8-bit integer
184u8 (none) unsigned 8-bit integer
184u8 uint8_t unsigned 8-bit integer
185185i16 int16_t signed 16-bit integer
186u16 (none) unsigned 16-bit integer
186u16 uint16_t unsigned 16-bit integer
187187i32 int32_t signed 32-bit integer
188u32 (none) unsigned 32-bit integer
188u32 uint32_t unsigned 32-bit integer
189189i64 int64_t signed 64-bit integer
190u64 (none) unsigned 64-bit integer
190u64 uint64_t unsigned 64-bit integer
191191isize intptr_t signed pointer sized integer
192usize (none) 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
192usize uintptr_t unsigned pointer sized integer
204193
205194c_short short for ABI compatibility with C
206195c_ushort unsigned short for ABI compatibility with C
......@@ -213,8 +202,8 @@ c_ulonglong unsigned long long for ABI compatibility with C
213202c_long_double long double for ABI compatibility with C
214203c_void void for ABI compatibility with C
215204
216f32 float 32-bit IEE754 floating point
217f64 double 64-bit IEE754 floating point
205f32 float 32-bit floating point
206f64 double 64-bit floating point
218207```
219208
220209### Boolean Type
......@@ -595,9 +584,8 @@ const b: u8 = @truncate(u8, a);
595584This function, when semantically analyzed, causes a compile error with the message `msg`.
596585
597586There 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) -> type
589### @int_type(inline is_signed: bool, inline bit_count: u8) -> type
601590
602This function returns an integer type with the given signness, bit count, and
603wrapping behavior.
591This function returns an integer type with the given signness and bit count.
doc/vim/syntax/zig.vim-1
......@@ -17,7 +17,6 @@ syn keyword zigConstant null undefined
1717syn keyword zigKeyword fn use
1818syn keyword zigType bool f32 f64 void unreachable type error
1919syn 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
2120syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong
2221
2322syn keyword zigBoolean true false
src/all_types.hpp+10-2
......@@ -315,11 +315,15 @@ enum BinOpType {
315315 BinOpTypeInvalid,
316316 BinOpTypeAssign,
317317 BinOpTypeAssignTimes,
318 BinOpTypeAssignTimesWrap,
318319 BinOpTypeAssignDiv,
319320 BinOpTypeAssignMod,
320321 BinOpTypeAssignPlus,
322 BinOpTypeAssignPlusWrap,
321323 BinOpTypeAssignMinus,
324 BinOpTypeAssignMinusWrap,
322325 BinOpTypeAssignBitShiftLeft,
326 BinOpTypeAssignBitShiftLeftWrap,
323327 BinOpTypeAssignBitShiftRight,
324328 BinOpTypeAssignBitAnd,
325329 BinOpTypeAssignBitXor,
......@@ -338,10 +342,14 @@ enum BinOpType {
338342 BinOpTypeBinXor,
339343 BinOpTypeBinAnd,
340344 BinOpTypeBitShiftLeft,
345 BinOpTypeBitShiftLeftWrap,
341346 BinOpTypeBitShiftRight,
342347 BinOpTypeAdd,
348 BinOpTypeAddWrap,
343349 BinOpTypeSub,
350 BinOpTypeSubWrap,
344351 BinOpTypeMult,
352 BinOpTypeMultWrap,
345353 BinOpTypeDiv,
346354 BinOpTypeMod,
347355 BinOpTypeUnwrapMaybe,
......@@ -449,6 +457,7 @@ enum PrefixOp {
449457 PrefixOpBoolNot,
450458 PrefixOpBinNot,
451459 PrefixOpNegation,
460 PrefixOpNegationWrap,
452461 PrefixOpAddressOf,
453462 PrefixOpConstAddressOf,
454463 PrefixOpDereference,
......@@ -860,7 +869,6 @@ struct TypeTableEntryPointer {
860869struct TypeTableEntryInt {
861870 int bit_count;
862871 bool is_signed;
863 bool is_wrapping;
864872};
865873
866874struct TypeTableEntryFloat {
......@@ -1185,7 +1193,7 @@ struct CodeGen {
11851193
11861194 struct {
11871195 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]
11891197 TypeTableEntry *entry_c_int[CIntTypeCount];
11901198 TypeTableEntry *entry_c_long_double;
11911199 TypeTableEntry *entry_c_void;
src/analyze.cpp+49-35
......@@ -245,7 +245,7 @@ static bool is_slice(TypeTableEntry *type) {
245245}
246246
247247TypeTableEntry *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));
249249}
250250
251251static TypeTableEntry *get_generic_fn_type(CodeGen *g, AstNode *decl_node) {
......@@ -2037,25 +2037,13 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa
20372037 continue;
20382038 } else if (prev_type->id == TypeTableEntryIdInt &&
20392039 cur_type->id == TypeTableEntryIdInt &&
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)))
2040 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
20432041 {
20442042 if (cur_type->data.integral.bit_count > prev_type->data.integral.bit_count) {
20452043 prev_type = cur_type;
20462044 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;
20502045 }
20512046 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;
20592047 } else if (prev_type->id == TypeTableEntryIdFloat &&
20602048 cur_type->id == TypeTableEntryIdFloat)
20612049 {
......@@ -2726,9 +2714,6 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
27262714 } else if (buf_eql_str(field_name, "is_signed")) {
27272715 return resolve_expr_const_val_as_bool(g, node, child_type->data.integral.is_signed,
27282716 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);
27322717 } else {
27332718 add_node_error(g, node,
27342719 buf_sprintf("type '%s' has no member called '%s'",
......@@ -3122,15 +3107,19 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {
31223107 case BinOpTypeAssign:
31233108 return true;
31243109 case BinOpTypeAssignTimes:
3110 case BinOpTypeAssignTimesWrap:
31253111 case BinOpTypeAssignDiv:
31263112 case BinOpTypeAssignMod:
31273113 return type->id == TypeTableEntryIdInt || type->id == TypeTableEntryIdFloat;
31283114 case BinOpTypeAssignPlus:
3115 case BinOpTypeAssignPlusWrap:
31293116 case BinOpTypeAssignMinus:
3117 case BinOpTypeAssignMinusWrap:
31303118 return type->id == TypeTableEntryIdInt ||
31313119 type->id == TypeTableEntryIdFloat ||
31323120 type->id == TypeTableEntryIdPointer;
31333121 case BinOpTypeAssignBitShiftLeft:
3122 case BinOpTypeAssignBitShiftLeftWrap:
31343123 case BinOpTypeAssignBitShiftRight:
31353124 case BinOpTypeAssignBitAnd:
31363125 case BinOpTypeAssignBitXor:
......@@ -3153,10 +3142,14 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {
31533142 case BinOpTypeBinXor:
31543143 case BinOpTypeBinAnd:
31553144 case BinOpTypeBitShiftLeft:
3145 case BinOpTypeBitShiftLeftWrap:
31563146 case BinOpTypeBitShiftRight:
31573147 case BinOpTypeAdd:
3148 case BinOpTypeAddWrap:
31583149 case BinOpTypeSub:
3150 case BinOpTypeSubWrap:
31593151 case BinOpTypeMult:
3152 case BinOpTypeMultWrap:
31603153 case BinOpTypeDiv:
31613154 case BinOpTypeMod:
31623155 case BinOpTypeUnwrapMaybe:
......@@ -3437,11 +3430,15 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
34373430 switch (bin_op_type) {
34383431 case BinOpTypeAssign:
34393432 case BinOpTypeAssignTimes:
3433 case BinOpTypeAssignTimesWrap:
34403434 case BinOpTypeAssignDiv:
34413435 case BinOpTypeAssignMod:
34423436 case BinOpTypeAssignPlus:
3437 case BinOpTypeAssignPlusWrap:
34433438 case BinOpTypeAssignMinus:
3439 case BinOpTypeAssignMinusWrap:
34443440 case BinOpTypeAssignBitShiftLeft:
3441 case BinOpTypeAssignBitShiftLeftWrap:
34453442 case BinOpTypeAssignBitShiftRight:
34463443 case BinOpTypeAssignBitAnd:
34473444 case BinOpTypeAssignBitXor:
......@@ -3481,10 +3478,14 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
34813478 case BinOpTypeBinXor:
34823479 case BinOpTypeBinAnd:
34833480 case BinOpTypeBitShiftLeft:
3481 case BinOpTypeBitShiftLeftWrap:
34843482 case BinOpTypeBitShiftRight:
34853483 case BinOpTypeAdd:
3484 case BinOpTypeAddWrap:
34863485 case BinOpTypeSub:
3486 case BinOpTypeSubWrap:
34873487 case BinOpTypeMult:
3488 case BinOpTypeMultWrap:
34883489 case BinOpTypeDiv:
34893490 case BinOpTypeMod:
34903491 {
......@@ -4911,42 +4912,35 @@ static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,
49114912{
49124913 AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0);
49134914 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
49164916 TypeTableEntry *bool_type = g->builtin_types.entry_bool;
49174917 TypeTableEntry *usize_type = g->builtin_types.entry_usize;
49184918 TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node);
49194919 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
49224921 if (is_signed_type->id == TypeTableEntryIdInvalid ||
4923 bit_count_type->id == TypeTableEntryIdInvalid ||
4924 is_wrap_type->id == TypeTableEntryIdInvalid)
4922 bit_count_type->id == TypeTableEntryIdInvalid)
49254923 {
49264924 return g->builtin_types.entry_invalid;
49274925 }
49284926
49294927 ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val;
49304928 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
49334930 AstNode *bad_node = nullptr;
49344931 if (!is_signed_val->ok) {
49354932 bad_node = *is_signed_node;
49364933 } else if (!bit_count_val->ok) {
49374934 bad_node = *bit_count_node;
4938 } else if (!is_wrap_val->ok) {
4939 bad_node = *is_wrap_node;
49404935 }
49414936 if (bad_node) {
49424937 add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression"));
49434938 return g->builtin_types.entry_invalid;
49444939 }
49454940
4946 bool depends_on_compile_var = is_signed_val->depends_on_compile_var ||
4947 bit_count_val->depends_on_compile_var || is_wrap_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;
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,
49504944 bit_count_val->data.x_bignum.data.x_uint);
49514945 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
57275721 // TODO const expr eval
57285722 }
57295723 case PrefixOpNegation:
5724 case PrefixOpNegationWrap:
57305725 {
57315726 TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
57325727 if (expr_type->id == TypeTableEntryIdInvalid) {
57335728 return expr_type;
57345729 } else if ((expr_type->id == TypeTableEntryIdInt &&
57355730 expr_type->data.integral.is_signed) ||
5736 expr_type->id == TypeTableEntryIdFloat ||
57375731 expr_type->id == TypeTableEntryIdNumLitInt ||
5738 expr_type->id == TypeTableEntryIdNumLitFloat)
5732 ((expr_type->id == TypeTableEntryIdFloat ||
5733 expr_type->id == TypeTableEntryIdNumLitFloat) &&
5734 prefix_op != PrefixOpNegationWrap))
57395735 {
57405736 ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
57415737 if (!target_const_val->ok) {
......@@ -5745,10 +5741,28 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
57455741 const_val->ok = true;
57465742 const_val->depends_on_compile_var = target_const_val->depends_on_compile_var;
57475743 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 }
57485761 return expr_type;
57495762 } else {
5750 add_node_error(g, node, buf_sprintf("invalid negation type: '%s'",
5751 buf_ptr(&expr_type->name)));
5763 const char *fmt = (prefix_op == PrefixOpNegationWrap) ?
5764 "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
5765 add_node_error(g, node, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
57525766 return g->builtin_types.entry_invalid;
57535767 }
57545768 }
......@@ -7059,7 +7073,7 @@ bool is_node_void_expr(AstNode *node) {
70597073 return false;
70607074}
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) {
70637077 int index;
70647078 if (size_in_bits == 8) {
70657079 index = 0;
......@@ -7072,11 +7086,11 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, bool is_wrapping,
70727086 } else {
70737087 zig_unreachable();
70747088 }
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];
70767090}
70777091
7078TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, bool is_wrapping, int size_in_bits) {
7079 return *get_int_type_ptr(g, is_signed, is_wrapping, size_in_bits);
7092TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits) {
7093 return *get_int_type_ptr(g, is_signed, size_in_bits);
70807094}
70817095
70827096TypeTableEntry **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);
1919Expr *get_resolved_expr(AstNode *node);
2020bool is_node_void_expr(AstNode *node);
2121uint64_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);
23TypeTableEntry *get_int_type(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, int size_in_bits);
2424TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
2525TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
2626TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type);
src/ast_render.cpp+44-35
......@@ -4,41 +4,49 @@
44
55static const char *bin_op_str(BinOpType bin_op) {
66 switch (bin_op) {
7 case BinOpTypeInvalid: return "(invalid)";
8 case BinOpTypeBoolOr: return "||";
9 case BinOpTypeBoolAnd: return "&&";
10 case BinOpTypeCmpEq: return "==";
11 case BinOpTypeCmpNotEq: return "!=";
12 case BinOpTypeCmpLessThan: return "<";
13 case BinOpTypeCmpGreaterThan: return ">";
14 case BinOpTypeCmpLessOrEq: return "<=";
15 case BinOpTypeCmpGreaterOrEq: return ">=";
16 case BinOpTypeBinOr: return "|";
17 case BinOpTypeBinXor: return "^";
18 case BinOpTypeBinAnd: return "&";
19 case BinOpTypeBitShiftLeft: return "<<";
20 case BinOpTypeBitShiftRight: return ">>";
21 case BinOpTypeAdd: return "+";
22 case BinOpTypeSub: return "-";
23 case BinOpTypeMult: return "*";
24 case BinOpTypeDiv: return "/";
25 case BinOpTypeMod: return "%";
26 case BinOpTypeAssign: return "=";
27 case BinOpTypeAssignTimes: return "*=";
28 case BinOpTypeAssignDiv: return "/=";
29 case BinOpTypeAssignMod: return "%=";
30 case BinOpTypeAssignPlus: return "+=";
31 case BinOpTypeAssignMinus: return "-=";
32 case BinOpTypeAssignBitShiftLeft: return "<<=";
33 case BinOpTypeAssignBitShiftRight: return ">>=";
34 case BinOpTypeAssignBitAnd: return "&=";
35 case BinOpTypeAssignBitXor: return "^=";
36 case BinOpTypeAssignBitOr: return "|=";
37 case BinOpTypeAssignBoolAnd: return "&&=";
38 case BinOpTypeAssignBoolOr: return "||=";
39 case BinOpTypeUnwrapMaybe: return "??";
40 case BinOpTypeArrayCat: return "++";
41 case BinOpTypeArrayMult: return "**";
7 case BinOpTypeInvalid: return "(invalid)";
8 case BinOpTypeBoolOr: return "||";
9 case BinOpTypeBoolAnd: return "&&";
10 case BinOpTypeCmpEq: return "==";
11 case BinOpTypeCmpNotEq: return "!=";
12 case BinOpTypeCmpLessThan: return "<";
13 case BinOpTypeCmpGreaterThan: return ">";
14 case BinOpTypeCmpLessOrEq: return "<=";
15 case BinOpTypeCmpGreaterOrEq: return ">=";
16 case BinOpTypeBinOr: return "|";
17 case BinOpTypeBinXor: return "^";
18 case BinOpTypeBinAnd: return "&";
19 case BinOpTypeBitShiftLeft: return "<<";
20 case BinOpTypeBitShiftLeftWrap: return "<<%";
21 case BinOpTypeBitShiftRight: return ">>";
22 case BinOpTypeAdd: return "+";
23 case BinOpTypeAddWrap: return "+%";
24 case BinOpTypeSub: return "-";
25 case BinOpTypeSubWrap: return "-%";
26 case BinOpTypeMult: return "*";
27 case BinOpTypeMultWrap: return "*%";
28 case BinOpTypeDiv: return "/";
29 case BinOpTypeMod: return "%";
30 case BinOpTypeAssign: return "=";
31 case BinOpTypeAssignTimes: return "*=";
32 case BinOpTypeAssignTimesWrap: return "*%=";
33 case BinOpTypeAssignDiv: return "/=";
34 case BinOpTypeAssignMod: return "%=";
35 case BinOpTypeAssignPlus: return "+=";
36 case BinOpTypeAssignPlusWrap: return "+%=";
37 case BinOpTypeAssignMinus: return "-=";
38 case BinOpTypeAssignMinusWrap: return "-%=";
39 case BinOpTypeAssignBitShiftLeft: return "<<=";
40 case BinOpTypeAssignBitShiftLeftWrap: 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 "**";
4250 }
4351 zig_unreachable();
4452}
......@@ -47,6 +55,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
4755 switch (prefix_op) {
4856 case PrefixOpInvalid: return "(invalid)";
4957 case PrefixOpNegation: return "-";
58 case PrefixOpNegationWrap: return "-%";
5059 case PrefixOpBoolNot: return "!";
5160 case PrefixOpBinNot: return "~";
5261 case PrefixOpAddressOf: return "&";
src/codegen.cpp+60-51
......@@ -1564,17 +1564,20 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
15641564 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
15651565 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) {
15681570 case PrefixOpInvalid:
15691571 zig_unreachable();
15701572 case PrefixOpNegation:
1573 case PrefixOpNegationWrap:
15711574 {
15721575 LLVMValueRef expr = gen_expr(g, expr_node);
15731576 set_debug_source_node(g, node);
15741577 if (expr_type->id == TypeTableEntryIdFloat) {
15751578 return LLVMBuildFNeg(g->builder, expr, "");
15761579 } else if (expr_type->id == TypeTableEntryIdInt) {
1577 if (expr_type->data.integral.is_wrapping) {
1580 if (op == PrefixOpNegationWrap) {
15781581 return LLVMBuildNeg(g->builder, expr, "");
15791582 } else if (want_debug_safety(g, expr_node)) {
15801583 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
......@@ -1796,17 +1799,23 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
17961799 set_debug_source_node(g, source_node);
17971800 return LLVMBuildAnd(g->builder, val1, val2, "");
17981801 case BinOpTypeBitShiftLeft:
1802 case BinOpTypeBitShiftLeftWrap:
17991803 case BinOpTypeAssignBitShiftLeft:
1800 set_debug_source_node(g, source_node);
1801 assert(op1_type->id == TypeTableEntryIdInt);
1802 if (op1_type->data.integral.is_wrapping) {
1803 return LLVMBuildShl(g->builder, val1, val2, "");
1804 } else if (want_debug_safety(g, source_node)) {
1805 return gen_overflow_shl_op(g, op1_type, val1, val2);
1806 } else if (op1_type->data.integral.is_signed) {
1807 return ZigLLVMBuildNSWShl(g->builder, val1, val2, "");
1808 } else {
1809 return ZigLLVMBuildNUWShl(g->builder, val1, val2, "");
1804 case BinOpTypeAssignBitShiftLeftWrap:
1805 {
1806 set_debug_source_node(g, source_node);
1807 assert(op1_type->id == TypeTableEntryIdInt);
1808 bool is_wrapping = (bin_op == BinOpTypeBitShiftLeftWrap) ||
1809 (bin_op == BinOpTypeAssignBitShiftLeftWrap);
1810 if (is_wrapping) {
1811 return LLVMBuildShl(g->builder, val1, val2, "");
1812 } else if (want_debug_safety(g, source_node)) {
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 }
18101819 }
18111820 case BinOpTypeBitShiftRight:
18121821 case BinOpTypeAssignBitShiftRight:
......@@ -1820,12 +1829,15 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
18201829 return LLVMBuildLShr(g->builder, val1, val2, "");
18211830 }
18221831 case BinOpTypeAdd:
1832 case BinOpTypeAddWrap:
18231833 case BinOpTypeAssignPlus:
1834 case BinOpTypeAssignPlusWrap:
18241835 set_debug_source_node(g, source_node);
18251836 if (op1_type->id == TypeTableEntryIdFloat) {
18261837 return LLVMBuildFAdd(g->builder, val1, val2, "");
18271838 } 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) {
18291841 return LLVMBuildAdd(g->builder, val1, val2, "");
18301842 } else if (want_debug_safety(g, source_node)) {
18311843 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,
18381850 zig_unreachable();
18391851 }
18401852 case BinOpTypeSub:
1853 case BinOpTypeSubWrap:
18411854 case BinOpTypeAssignMinus:
1855 case BinOpTypeAssignMinusWrap:
18421856 set_debug_source_node(g, source_node);
18431857 if (op1_type->id == TypeTableEntryIdFloat) {
18441858 return LLVMBuildFSub(g->builder, val1, val2, "");
18451859 } 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) {
18471862 return LLVMBuildSub(g->builder, val1, val2, "");
18481863 } else if (want_debug_safety(g, source_node)) {
18491864 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,
18561871 zig_unreachable();
18571872 }
18581873 case BinOpTypeMult:
1874 case BinOpTypeMultWrap:
18591875 case BinOpTypeAssignTimes:
1876 case BinOpTypeAssignTimesWrap:
18601877 set_debug_source_node(g, source_node);
18611878 if (op1_type->id == TypeTableEntryIdFloat) {
18621879 return LLVMBuildFMul(g->builder, val1, val2, "");
18631880 } 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) {
18651883 return LLVMBuildMul(g->builder, val1, val2, "");
18661884 } else if (want_debug_safety(g, source_node)) {
18671885 return gen_overflow_op(g, op1_type, AddSubMulMul, val1, val2);
......@@ -2214,11 +2232,15 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) {
22142232 zig_unreachable();
22152233 case BinOpTypeAssign:
22162234 case BinOpTypeAssignTimes:
2235 case BinOpTypeAssignTimesWrap:
22172236 case BinOpTypeAssignDiv:
22182237 case BinOpTypeAssignMod:
22192238 case BinOpTypeAssignPlus:
2239 case BinOpTypeAssignPlusWrap:
22202240 case BinOpTypeAssignMinus:
2241 case BinOpTypeAssignMinusWrap:
22212242 case BinOpTypeAssignBitShiftLeft:
2243 case BinOpTypeAssignBitShiftLeftWrap:
22222244 case BinOpTypeAssignBitShiftRight:
22232245 case BinOpTypeAssignBitAnd:
22242246 case BinOpTypeAssignBitXor:
......@@ -2243,10 +2265,14 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) {
22432265 case BinOpTypeBinXor:
22442266 case BinOpTypeBinAnd:
22452267 case BinOpTypeBitShiftLeft:
2268 case BinOpTypeBitShiftLeftWrap:
22462269 case BinOpTypeBitShiftRight:
22472270 case BinOpTypeAdd:
2271 case BinOpTypeAddWrap:
22482272 case BinOpTypeSub:
2273 case BinOpTypeSubWrap:
22492274 case BinOpTypeMult:
2275 case BinOpTypeMultWrap:
22502276 case BinOpTypeDiv:
22512277 case BinOpTypeMod:
22522278 return gen_arithmetic_bin_op_expr(g, node);
......@@ -4188,17 +4214,7 @@ static const CIntTypeInfo c_int_type_infos[] = {
41884214 {CIntTypeULongLong, "c_ulonglong", false},
41894215};
41904216
4191struct SignWrap {
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};
4217static const bool is_signed_list[] = { false, true, };
42024218
42034219static void define_builtin_types(CodeGen *g) {
42044220 {
......@@ -4238,18 +4254,16 @@ static void define_builtin_types(CodeGen *g) {
42384254
42394255 for (int int_size_i = 0; int_size_i < array_length(int_sizes_in_bits); int_size_i += 1) {
42404256 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) {
4242 bool is_signed = sign_wrap_list[sign_wrap_i].is_signed;
4243 bool is_wrapping = sign_wrap_list[sign_wrap_i].is_wrapping;
4257 for (int is_sign_i = 0; is_sign_i < array_length(is_signed_list); is_sign_i += 1) {
4258 bool is_signed = is_signed_list[is_sign_i];
42444259
42454260 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
42464261 entry->type_ref = LLVMIntType(size_in_bits);
42474262 entry->deep_const = true;
42484263
42494264 const char u_or_i = is_signed ? 'i' : 'u';
4250 const char *w_or_none = is_wrapping ? "w" : "";
42514265 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
42544268 unsigned dwarf_tag;
42554269 if (is_signed) {
......@@ -4271,11 +4285,10 @@ static void define_builtin_types(CodeGen *g) {
42714285 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
42724286 debug_size_in_bits, debug_align_in_bits, dwarf_tag);
42734287 entry->data.integral.is_signed = is_signed;
4274 entry->data.integral.is_wrapping = is_wrapping;
42754288 entry->data.integral.bit_count = size_in_bits;
42764289 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;
42794292 }
42804293 }
42814294
......@@ -4297,7 +4310,6 @@ static void define_builtin_types(CodeGen *g) {
42974310 debug_align_in_bits,
42984311 is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
42994312 entry->data.integral.is_signed = is_signed;
4300 entry->data.integral.is_wrapping = !is_signed;
43014313 entry->data.integral.bit_count = size_in_bits;
43024314 g->primitive_type_table.put(&entry->name, entry);
43034315
......@@ -4319,21 +4331,18 @@ static void define_builtin_types(CodeGen *g) {
43194331 g->primitive_type_table.put(&entry->name, entry);
43204332 }
43214333
4322 for (int sign_wrap_i = 0; sign_wrap_i < array_length(sign_wrap_list); sign_wrap_i += 1) {
4323 bool is_signed = sign_wrap_list[sign_wrap_i].is_signed;
4324 bool is_wrapping = sign_wrap_list[sign_wrap_i].is_wrapping;
4334 for (int sign_i = 0; sign_i < array_length(is_signed_list); sign_i += 1) {
4335 bool is_signed = is_signed_list[sign_i];
43254336
43264337 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
43274338 entry->deep_const = true;
43284339 entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
43294340
43304341 const char u_or_i = is_signed ? 'i' : 'u';
4331 const char *w_or_none = is_wrapping ? "w" : "";
43324342 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
43354345 entry->data.integral.is_signed = is_signed;
4336 entry->data.integral.is_wrapping = is_wrapping;
43374346 entry->data.integral.bit_count = g->pointer_size_bytes * 8;
43384347
43394348 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) {
43444353 is_signed ? LLVMZigEncoding_DW_ATE_signed() : LLVMZigEncoding_DW_ATE_unsigned());
43454354 g->primitive_type_table.put(&entry->name, entry);
43464355
4347 if (is_signed && !is_wrapping) {
4356 if (is_signed) {
43484357 g->builtin_types.entry_isize = entry;
4349 } else if (!is_signed && !is_wrapping) {
4358 } else {
43504359 g->builtin_types.entry_usize = entry;
43514360 }
43524361 }
......@@ -4430,14 +4439,14 @@ static void define_builtin_types(CodeGen *g) {
44304439 g->primitive_type_table.put(&entry->name, entry);
44314440 }
44324441
4433 g->builtin_types.entry_u8 = get_int_type(g, false, false, 8);
4434 g->builtin_types.entry_u16 = get_int_type(g, false, false, 16);
4435 g->builtin_types.entry_u32 = get_int_type(g, false, false, 32);
4436 g->builtin_types.entry_u64 = get_int_type(g, false, false, 64);
4437 g->builtin_types.entry_i8 = get_int_type(g, true, false, 8);
4438 g->builtin_types.entry_i16 = get_int_type(g, true, false, 16);
4439 g->builtin_types.entry_i32 = get_int_type(g, true, false, 32);
4440 g->builtin_types.entry_i64 = get_int_type(g, true, false, 64);
4442 g->builtin_types.entry_u8 = get_int_type(g, false, 8);
4443 g->builtin_types.entry_u16 = get_int_type(g, false, 16);
4444 g->builtin_types.entry_u32 = get_int_type(g, false, 32);
4445 g->builtin_types.entry_u64 = get_int_type(g, false, 64);
4446 g->builtin_types.entry_i8 = get_int_type(g, true, 8);
4447 g->builtin_types.entry_i16 = get_int_type(g, true, 16);
4448 g->builtin_types.entry_i32 = get_int_type(g, true, 32);
4449 g->builtin_types.entry_i64 = get_int_type(g, true, 64);
44414450
44424451 {
44434452 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) {
47034712 create_builtin_fn_with_arg_count(g, BuiltinFnIdDivExact, "div_exact", 2);
47044713 create_builtin_fn_with_arg_count(g, BuiltinFnIdTruncate, "truncate", 2);
47054714 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);
47074716}
47084717
47094718static 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) {
146146
147147static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
148148 ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *),
149 TypeTableEntry *type)
149 TypeTableEntry *type, bool wrapping_op)
150150{
151151 bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum);
152152 if (overflow) {
......@@ -156,7 +156,7 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
156156 if (type->id == TypeTableEntryIdInt && !bignum_fits_in_bits(&out_val->data.x_bignum,
157157 type->data.integral.bit_count, type->data.integral.is_signed))
158158 {
159 if (type->data.integral.is_wrapping) {
159 if (wrapping_op) {
160160 if (type->data.integral.is_signed) {
161161 out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1;
162162 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,
187187 switch (bin_op) {
188188 case BinOpTypeAssign:
189189 case BinOpTypeAssignTimes:
190 case BinOpTypeAssignTimesWrap:
190191 case BinOpTypeAssignDiv:
191192 case BinOpTypeAssignMod:
192193 case BinOpTypeAssignPlus:
194 case BinOpTypeAssignPlusWrap:
193195 case BinOpTypeAssignMinus:
196 case BinOpTypeAssignMinusWrap:
194197 case BinOpTypeAssignBitShiftLeft:
198 case BinOpTypeAssignBitShiftLeftWrap:
195199 case BinOpTypeAssignBitShiftRight:
196200 case BinOpTypeAssignBitAnd:
197201 case BinOpTypeAssignBitXor:
......@@ -256,21 +260,29 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
256260 return 0;
257261 }
258262 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);
260266 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);
262268 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);
264270 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);
266272 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);
268276 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);
270278 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);
272282 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);
274286 case BinOpTypeDiv:
275287 {
276288 bool is_int = false;
......@@ -289,11 +301,11 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
289301 {
290302 return ErrorDivByZero;
291303 } 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);
293305 }
294306 }
295307 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);
297309 case BinOpTypeUnwrapMaybe:
298310 zig_panic("TODO");
299311 case BinOpTypeArrayCat:
......@@ -314,11 +326,15 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)
314326 switch (bin_op) {
315327 case BinOpTypeAssign:
316328 case BinOpTypeAssignTimes:
329 case BinOpTypeAssignTimesWrap:
317330 case BinOpTypeAssignDiv:
318331 case BinOpTypeAssignMod:
319332 case BinOpTypeAssignPlus:
333 case BinOpTypeAssignPlusWrap:
320334 case BinOpTypeAssignMinus:
335 case BinOpTypeAssignMinusWrap:
321336 case BinOpTypeAssignBitShiftLeft:
337 case BinOpTypeAssignBitShiftLeftWrap:
322338 case BinOpTypeAssignBitShiftRight:
323339 case BinOpTypeAssignBitAnd:
324340 case BinOpTypeAssignBitXor:
......@@ -338,10 +354,14 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)
338354 case BinOpTypeBinXor:
339355 case BinOpTypeBinAnd:
340356 case BinOpTypeBitShiftLeft:
357 case BinOpTypeBitShiftLeftWrap:
341358 case BinOpTypeBitShiftRight:
342359 case BinOpTypeAdd:
360 case BinOpTypeAddWrap:
343361 case BinOpTypeSub:
362 case BinOpTypeSubWrap:
344363 case BinOpTypeMult:
364 case BinOpTypeMultWrap:
345365 case BinOpTypeDiv:
346366 case BinOpTypeMod:
347367 case BinOpTypeUnwrapMaybe:
......@@ -1098,13 +1118,14 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v
10981118 break;
10991119 }
11001120 case PrefixOpNegation:
1121 case PrefixOpNegationWrap:
11011122 if (expr_type->id == TypeTableEntryIdInt) {
11021123 assert(expr_type->data.integral.is_signed);
11031124 bignum_negate(&out_val->data.x_bignum, &expr_val.data.x_bignum);
11041125 out_val->ok = true;
11051126 bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum,
11061127 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) {
11081129 if (overflow) {
11091130 out_val->data.x_bignum.is_negative = true;
11101131 }
src/parser.cpp+25-16
......@@ -1384,6 +1384,7 @@ static PrefixOp tok_to_prefix_op(Token *token) {
13841384 switch (token->id) {
13851385 case TokenIdBang: return PrefixOpBoolNot;
13861386 case TokenIdDash: return PrefixOpNegation;
1387 case TokenIdMinusPercent: return PrefixOpNegationWrap;
13871388 case TokenIdTilde: return PrefixOpBinNot;
13881389 case TokenIdAmpersand: return PrefixOpAddressOf;
13891390 case TokenIdStar: return PrefixOpDereference;
......@@ -1399,7 +1400,7 @@ static PrefixOp tok_to_prefix_op(Token *token) {
13991400
14001401/*
14011402PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
1402PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))
1403PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"
14031404*/
14041405static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
14051406 Token *token = &pc->tokens->at(*token_index);
......@@ -1458,16 +1459,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo
14581459
14591460static BinOpType tok_to_mult_op(Token *token) {
14601461 switch (token->id) {
1461 case TokenIdStar: return BinOpTypeMult;
1462 case TokenIdStarStar: return BinOpTypeArrayMult;
1463 case TokenIdSlash: return BinOpTypeDiv;
1464 case TokenIdPercent: return BinOpTypeMod;
1465 default: return BinOpTypeInvalid;
1462 case TokenIdStar: return BinOpTypeMult;
1463 case TokenIdTimesPercent: return BinOpTypeMultWrap;
1464 case TokenIdStarStar: return BinOpTypeArrayMult;
1465 case TokenIdSlash: return BinOpTypeDiv;
1466 case TokenIdPercent: return BinOpTypeMod;
1467 default: return BinOpTypeInvalid;
14661468 }
14671469}
14681470
14691471/*
1470MultiplyOperator = "*" | "/" | "%" | "**"
1472MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
14711473*/
14721474static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mandatory) {
14731475 Token *token = &pc->tokens->at(*token_index);
......@@ -1511,15 +1513,17 @@ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool man
15111513
15121514static BinOpType tok_to_add_op(Token *token) {
15131515 switch (token->id) {
1514 case TokenIdPlus: return BinOpTypeAdd;
1515 case TokenIdDash: return BinOpTypeSub;
1516 case TokenIdPlusPlus: return BinOpTypeArrayCat;
1517 default: return BinOpTypeInvalid;
1516 case TokenIdPlus: return BinOpTypeAdd;
1517 case TokenIdPlusPercent: return BinOpTypeAddWrap;
1518 case TokenIdDash: return BinOpTypeSub;
1519 case TokenIdMinusPercent: return BinOpTypeSubWrap;
1520 case TokenIdPlusPlus: return BinOpTypeArrayCat;
1521 default: return BinOpTypeInvalid;
15181522 }
15191523}
15201524
15211525/*
1522AdditionOperator : "+" | "-" | "++"
1526AdditionOperator = "+" | "-" | "++" | "+%" | "-%"
15231527*/
15241528static BinOpType ast_parse_add_op(ParseContext *pc, int *token_index, bool mandatory) {
15251529 Token *token = &pc->tokens->at(*token_index);
......@@ -1563,14 +1567,15 @@ static AstNode *ast_parse_add_expr(ParseContext *pc, int *token_index, bool mand
15631567
15641568static BinOpType tok_to_bit_shift_op(Token *token) {
15651569 switch (token->id) {
1566 case TokenIdBitShiftLeft: return BinOpTypeBitShiftLeft;
1567 case TokenIdBitShiftRight: return BinOpTypeBitShiftRight;
1570 case TokenIdBitShiftLeft: return BinOpTypeBitShiftLeft;
1571 case TokenIdBitShiftLeftPercent: return BinOpTypeBitShiftLeftWrap;
1572 case TokenIdBitShiftRight: return BinOpTypeBitShiftRight;
15681573 default: return BinOpTypeInvalid;
15691574 }
15701575}
15711576
15721577/*
1573BitShiftOperator : token(BitShiftLeft) | token(BitShiftRight)
1578BitShiftOperator = "<<" | ">>" | "<<%"
15741579*/
15751580static BinOpType ast_parse_bit_shift_op(ParseContext *pc, int *token_index, bool mandatory) {
15761581 Token *token = &pc->tokens->at(*token_index);
......@@ -2230,11 +2235,15 @@ static BinOpType tok_to_ass_op(Token *token) {
22302235 switch (token->id) {
22312236 case TokenIdEq: return BinOpTypeAssign;
22322237 case TokenIdTimesEq: return BinOpTypeAssignTimes;
2238 case TokenIdTimesPercentEq: return BinOpTypeAssignTimesWrap;
22332239 case TokenIdDivEq: return BinOpTypeAssignDiv;
22342240 case TokenIdModEq: return BinOpTypeAssignMod;
22352241 case TokenIdPlusEq: return BinOpTypeAssignPlus;
2242 case TokenIdPlusPercentEq: return BinOpTypeAssignPlusWrap;
22362243 case TokenIdMinusEq: return BinOpTypeAssignMinus;
2244 case TokenIdMinusPercentEq: return BinOpTypeAssignMinusWrap;
22372245 case TokenIdBitShiftLeftEq: return BinOpTypeAssignBitShiftLeft;
2246 case TokenIdBitShiftLeftPercentEq: return BinOpTypeAssignBitShiftLeftWrap;
22382247 case TokenIdBitShiftRightEq: return BinOpTypeAssignBitShiftRight;
22392248 case TokenIdBitAndEq: return BinOpTypeAssignBitAnd;
22402249 case TokenIdBitXorEq: return BinOpTypeAssignBitXor;
......@@ -2246,7 +2255,7 @@ static BinOpType tok_to_ass_op(Token *token) {
22462255}
22472256
22482257/*
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 = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
22502259*/
22512260static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool mandatory) {
22522261 Token *token = &pc->tokens->at(*token_index);
src/tokenizer.cpp+88
......@@ -154,10 +154,13 @@ enum TokenizeState {
154154 TokenizeStateCharLiteral,
155155 TokenizeStateCharLiteralEnd,
156156 TokenizeStateSawStar,
157 TokenizeStateSawStarPercent,
157158 TokenizeStateSawSlash,
158159 TokenizeStateSawPercent,
159160 TokenizeStateSawPlus,
161 TokenizeStateSawPlusPercent,
160162 TokenizeStateSawDash,
163 TokenizeStateSawMinusPercent,
161164 TokenizeStateSawAmpersand,
162165 TokenizeStateSawAmpersandAmpersand,
163166 TokenizeStateSawCaret,
......@@ -171,6 +174,7 @@ enum TokenizeState {
171174 TokenizeStateSawBang,
172175 TokenizeStateSawLessThan,
173176 TokenizeStateSawLessThanLessThan,
177 TokenizeStateSawShiftLeftPercent,
174178 TokenizeStateSawGreaterThan,
175179 TokenizeStateSawGreaterThanGreaterThan,
176180 TokenizeStateSawDot,
......@@ -596,6 +600,24 @@ void tokenize(Buf *buf, Tokenization *out) {
596600 end_token(&t);
597601 t.state = TokenizeStateStart;
598602 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;
599621 default:
600622 t.pos -= 1;
601623 end_token(&t);
......@@ -648,6 +670,24 @@ void tokenize(Buf *buf, Tokenization *out) {
648670 end_token(&t);
649671 t.state = TokenizeStateStart;
650672 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;
651691 default:
652692 t.pos -= 1;
653693 end_token(&t);
......@@ -691,6 +731,24 @@ void tokenize(Buf *buf, Tokenization *out) {
691731 end_token(&t);
692732 t.state = TokenizeStateStart;
693733 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;
694752 default:
695753 t.pos -= 1;
696754 end_token(&t);
......@@ -1181,6 +1239,24 @@ void tokenize(Buf *buf, Tokenization *out) {
11811239 end_token(&t);
11821240 t.state = TokenizeStateStart;
11831241 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;
11841260 default:
11851261 t.pos -= 1;
11861262 end_token(&t);
......@@ -1252,6 +1328,10 @@ void tokenize(Buf *buf, Tokenization *out) {
12521328 case TokenizeStateSawDot:
12531329 case TokenizeStateSawQuestionMark:
12541330 case TokenizeStateSawAtSign:
1331 case TokenizeStateSawStarPercent:
1332 case TokenizeStateSawPlusPercent:
1333 case TokenizeStateSawMinusPercent:
1334 case TokenizeStateSawShiftLeftPercent:
12551335 end_token(&t);
12561336 break;
12571337 case TokenizeStateSawDotDot:
......@@ -1372,6 +1452,14 @@ const char * token_name(TokenId id) {
13721452 case TokenIdMaybeAssign: return "?=";
13731453 case TokenIdAtSign: return "@";
13741454 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 "<<%=";
13751463 }
13761464 return "(invalid token)";
13771465}
src/tokenizer.hpp+8
......@@ -70,11 +70,19 @@ enum TokenId {
7070 TokenIdBinXor,
7171 TokenIdEq,
7272 TokenIdTimesEq,
73 TokenIdTimesPercent,
74 TokenIdTimesPercentEq,
7375 TokenIdDivEq,
7476 TokenIdModEq,
7577 TokenIdPlusEq,
78 TokenIdPlusPercent,
79 TokenIdPlusPercentEq,
7680 TokenIdMinusEq,
81 TokenIdMinusPercent,
82 TokenIdMinusPercentEq,
7783 TokenIdBitShiftLeftEq,
84 TokenIdBitShiftLeftPercent,
85 TokenIdBitShiftLeftPercentEq,
7886 TokenIdBitShiftRightEq,
7987 TokenIdBitAndEq,
8088 TokenIdBitXorEq,
std/io.zig+1-1
......@@ -235,7 +235,7 @@ fn char_to_digit(c: u8, radix: u8) -> %u8 {
235235}
236236
237237pub 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);
239239 if (x < 0) {
240240 out_buf[0] = '-';
241241 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 {
7777
7878 /// Get a floating point value in the range 0.0..1.0.
7979 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);
8181 // TODO switch statement for constant values
8282 const precision = if (T == f32) {
8383 16777216
......@@ -99,7 +99,6 @@ struct MersenneTwister(
9999 l: int, f: int)
100100{
101101 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
104103 array: [n]int,
105104 index: usize,
......@@ -113,7 +112,7 @@ struct MersenneTwister(
113112 var prev_value = seed;
114113 mt.array[0] = prev_value;
115114 {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)));
117116 mt.array[i] = prev_value;
118117 }};
119118
......@@ -152,12 +151,12 @@ struct MersenneTwister(
152151 mt.index = 0;
153152 }
154153
155 var x: intw = mt.array[mt.index];
154 var x = mt.array[mt.index];
156155 mt.index += 1;
157156
158157 x ^= ((x >> u) & d);
159 x ^= ((x << s) & b);
160 x ^= ((x << t) & c);
158 x ^= ((x <<% s) & b);
159 x ^= ((x <<% t) & c);
161160 x ^= (x >> l);
162161
163162 return x;
test/run_tests.cpp-6
......@@ -1362,12 +1362,6 @@ fn mul(a: u16, b: u16) -> u16 {
13621362 ".tmp_source.zig:3:18: note: called from here",
13631363 ".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
13711365 add_compile_fail_case("truncate sign mismatch", R"SOURCE(
13721366fn f() {
13731367 const x: u32 = 10;
test/self_hosted.zig+29-66
......@@ -1458,17 +1458,17 @@ fn unsigned_wrapping() {
14581458 test_unsigned_wrapping_eval(@max_value(u32));
14591459 test_unsigned_wrapping_noeval(@max_value(u32));
14601460}
1461fn test_unsigned_wrapping_eval(x: u32w) {
1462 const zero = x + 1;
1461fn test_unsigned_wrapping_eval(x: u32) {
1462 const zero = x +% 1;
14631463 assert(zero == 0);
1464 const orig = zero - 1;
1464 const orig = zero -% 1;
14651465 assert(orig == @max_value(u32));
14661466}
14671467#static_eval_enable(false)
1468fn test_unsigned_wrapping_noeval(x: u32w) {
1469 const zero = x + 1;
1468fn test_unsigned_wrapping_noeval(x: u32) {
1469 const zero = x +% 1;
14701470 assert(zero == 0);
1471 const orig = zero - 1;
1471 const orig = zero -% 1;
14721472 assert(orig == @max_value(u32));
14731473}
14741474
......@@ -1477,17 +1477,17 @@ fn signed_wrapping() {
14771477 test_signed_wrapping_eval(@max_value(i32));
14781478 test_signed_wrapping_noeval(@max_value(i32));
14791479}
1480fn test_signed_wrapping_eval(x: i32w) {
1481 const min_val = x + 1;
1480fn test_signed_wrapping_eval(x: i32) {
1481 const min_val = x +% 1;
14821482 assert(min_val == @min_value(i32));
1483 const max_val = min_val - 1;
1483 const max_val = min_val -% 1;
14841484 assert(max_val == @max_value(i32));
14851485}
14861486#static_eval_enable(false)
1487fn test_signed_wrapping_noeval(x: i32w) {
1488 const min_val = x + 1;
1487fn test_signed_wrapping_noeval(x: i32) {
1488 const min_val = x +% 1;
14891489 assert(min_val == @min_value(i32));
1490 const max_val = min_val - 1;
1490 const max_val = min_val -% 1;
14911491 assert(max_val == @max_value(i32));
14921492}
14931493
......@@ -1496,15 +1496,15 @@ fn negation_wrapping() {
14961496 test_negation_wrapping_eval(@min_value(i16));
14971497 test_negation_wrapping_noeval(@min_value(i16));
14981498}
1499fn test_negation_wrapping_eval(x: i16w) {
1499fn test_negation_wrapping_eval(x: i16) {
15001500 assert(x == -32768);
1501 const neg = -x;
1501 const neg = -%x;
15021502 assert(neg == -32768);
15031503}
15041504#static_eval_enable(false)
1505fn test_negation_wrapping_noeval(x: i16w) {
1505fn test_negation_wrapping_noeval(x: i16) {
15061506 assert(x == -32768);
1507 const neg = -x;
1507 const neg = -%x;
15081508 assert(neg == -32768);
15091509}
15101510
......@@ -1513,13 +1513,13 @@ fn shl_wrapping() {
15131513 test_shl_wrapping_eval(@max_value(u16));
15141514 test_shl_wrapping_noeval(@max_value(u16));
15151515}
1516fn test_shl_wrapping_eval(x: u16w) {
1517 const shifted = x << 1;
1516fn test_shl_wrapping_eval(x: u16) {
1517 const shifted = x <<% 1;
15181518 assert(shifted == 65534);
15191519}
15201520#static_eval_enable(false)
1521fn test_shl_wrapping_noeval(x: u16w) {
1522 const shifted = x << 1;
1521fn test_shl_wrapping_noeval(x: u16) {
1522 const shifted = x <<% 1;
15231523 assert(shifted == 65534);
15241524}
15251525
......@@ -1531,23 +1531,6 @@ fn shl_with_overflow() {
15311531 assert(result == 0b1011111111111100);
15321532}
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
15511534#attribute("test")
15521535fn c_string_concatenation() {
15531536 const a = c"OK" ++ c" IT " ++ c"WORKED";
......@@ -1687,41 +1670,21 @@ struct DivResult {
16871670
16881671#attribute("test")
16891672fn int_type_builtin() {
1690 assert(@int_type(true, 8, false) == i8);
1691 assert(@int_type(true, 16, false) == i16);
1692 assert(@int_type(true, 32, false) == i32);
1693 assert(@int_type(true, 64, false) == i64);
1694
1695 assert(@int_type(false, 8, false) == u8);
1696 assert(@int_type(false, 16, false) == u16);
1697 assert(@int_type(false, 32, false) == u32);
1698 assert(@int_type(false, 64, false) == 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);
1673 assert(@int_type(true, 8) == i8);
1674 assert(@int_type(true, 16) == i16);
1675 assert(@int_type(true, 32) == i32);
1676 assert(@int_type(true, 64) == i64);
1677
1678 assert(@int_type(false, 8) == u8);
1679 assert(@int_type(false, 16) == u16);
1680 assert(@int_type(false, 32) == u32);
1681 assert(@int_type(false, 64) == u64);
17091682
17101683 assert(i8.bit_count == 8);
17111684 assert(i16.bit_count == 16);
17121685 assert(i32.bit_count == 32);
17131686 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
17251688 assert(i8.is_signed);
17261689 assert(i16.is_signed);
17271690 assert(i32.is_signed);