| author | |
| committer | |
| log | 3865b6ad8f8ba71dca06c81828ec2e29f3019879 |
| tree | cfadbebe532708c931bddcc8e5b262d63946c78d |
| parent | 79a4b7a2365dc50d01eb6bc29bbb77244a1620cf |
| parent | ec2f9ef4e8be5995ab652dde59b12ee340a9e28d |
| signature |
24 files changed, 640 insertions(+), 430 deletions(-)
src/all_types.hpp+2| ... | @@ -895,6 +895,8 @@ struct AstNodeStructField { | ... | @@ -895,6 +895,8 @@ struct AstNodeStructField { |
| 895 | Buf *name; | 895 | Buf *name; |
| 896 | AstNode *type; | 896 | AstNode *type; |
| 897 | AstNode *value; | 897 | AstNode *value; |
| 898 | // populated if the "align(A)" is present | ||
| 899 | AstNode *align_expr; | ||
| 898 | }; | 900 | }; |
| 899 | 901 | ||
| 900 | struct AstNodeStringLiteral { | 902 | struct AstNodeStringLiteral { |
src/analyze.cpp+17-11| ... | @@ -1147,7 +1147,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_ | ... | @@ -1147,7 +1147,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_ |
| 1147 | if (type_is_invalid(align_result->type)) | 1147 | if (type_is_invalid(align_result->type)) |
| 1148 | return false; | 1148 | return false; |
| 1149 | 1149 | ||
| 1150 | uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint); | 1150 | uint32_t align_bytes = bigint_as_u32(&align_result->data.x_bigint); |
| 1151 | if (align_bytes == 0) { | 1151 | if (align_bytes == 0) { |
| 1152 | add_node_error(g, node, buf_sprintf("alignment must be >= 1")); | 1152 | add_node_error(g, node, buf_sprintf("alignment must be >= 1")); |
| 1153 | return false; | 1153 | return false; |
| ... | @@ -1179,7 +1179,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** | ... | @@ -1179,7 +1179,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** |
| 1179 | return true; | 1179 | return true; |
| 1180 | } | 1180 | } |
| 1181 | expand_undef_array(g, array_val); | 1181 | expand_undef_array(g, array_val); |
| 1182 | size_t len = bigint_as_unsigned(&len_field->data.x_bigint); | 1182 | size_t len = bigint_as_usize(&len_field->data.x_bigint); |
| 1183 | Buf *result = buf_alloc(); | 1183 | Buf *result = buf_alloc(); |
| 1184 | buf_resize(result, len); | 1184 | buf_resize(result, len); |
| 1185 | for (size_t i = 0; i < len; i += 1) { | 1185 | for (size_t i = 0; i < len; i += 1) { |
| ... | @@ -1189,7 +1189,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** | ... | @@ -1189,7 +1189,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** |
| 1189 | add_node_error(g, node, buf_sprintf("use of undefined value")); | 1189 | add_node_error(g, node, buf_sprintf("use of undefined value")); |
| 1190 | return false; | 1190 | return false; |
| 1191 | } | 1191 | } |
| 1192 | uint64_t big_c = bigint_as_unsigned(&char_val->data.x_bigint); | 1192 | uint64_t big_c = bigint_as_u64(&char_val->data.x_bigint); |
| 1193 | assert(big_c <= UINT8_MAX); | 1193 | assert(big_c <= UINT8_MAX); |
| 1194 | uint8_t c = (uint8_t)big_c; | 1194 | uint8_t c = (uint8_t)big_c; |
| 1195 | buf_ptr(result)[i] = c; | 1195 | buf_ptr(result)[i] = c; |
| ... | @@ -2384,19 +2384,25 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2384,19 +2384,25 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2384 | if (field->gen_index == SIZE_MAX) | 2384 | if (field->gen_index == SIZE_MAX) |
| 2385 | continue; | 2385 | continue; |
| 2386 | 2386 | ||
| 2387 | // TODO: https://github.com/ziglang/zig/issues/1512 | 2387 | AstNode *align_expr = field->decl_node->data.struct_field.align_expr; |
| 2388 | size_t this_field_align; | 2388 | if (align_expr != nullptr) { |
| 2389 | if (packed) { | 2389 | if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr, |
| 2390 | this_field_align = 1; | 2390 | &field->align)) |
| 2391 | { | ||
| 2392 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2393 | return err; | ||
| 2394 | } | ||
| 2395 | } else if (packed) { | ||
| 2396 | field->align = 1; | ||
| 2391 | } else { | 2397 | } else { |
| 2392 | if ((err = type_val_resolve_abi_align(g, field->type_val, &this_field_align))) { | 2398 | if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) { |
| 2393 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2399 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2394 | return err; | 2400 | return err; |
| 2395 | } | 2401 | } |
| 2396 | } | 2402 | } |
| 2397 | 2403 | ||
| 2398 | if (this_field_align > struct_type->abi_align) { | 2404 | if (field->align > struct_type->abi_align) { |
| 2399 | struct_type->abi_align = this_field_align; | 2405 | struct_type->abi_align = field->align; |
| 2400 | } | 2406 | } |
| 2401 | } | 2407 | } |
| 2402 | 2408 | ||
| ... | @@ -6008,7 +6014,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -6008,7 +6014,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 6008 | { | 6014 | { |
| 6009 | if (is_slice(type_entry)) { | 6015 | if (is_slice(type_entry)) { |
| 6010 | ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index]; | 6016 | ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index]; |
| 6011 | size_t len = bigint_as_unsigned(&len_val->data.x_bigint); | 6017 | size_t len = bigint_as_usize(&len_val->data.x_bigint); |
| 6012 | 6018 | ||
| 6013 | ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index]; | 6019 | ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index]; |
| 6014 | if (ptr_val->special == ConstValSpecialUndef) { | 6020 | if (ptr_val->special == ConstValSpecialUndef) { |
src/bigint.cpp+22-1| ... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
| 15 | #include <limits> | 15 | #include <limits> |
| 16 | #include <algorithm> | 16 | #include <algorithm> |
| 17 | 17 | ||
| 18 | static uint64_t bigint_as_unsigned(const BigInt *bigint); | ||
| 19 | |||
| 18 | static void bigint_normalize(BigInt *dest) { | 20 | static void bigint_normalize(BigInt *dest) { |
| 19 | const uint64_t *digits = bigint_ptr(dest); | 21 | const uint64_t *digits = bigint_ptr(dest); |
| 20 | 22 | ||
| ... | @@ -1660,7 +1662,7 @@ size_t bigint_clz(const BigInt *bi, size_t bit_count) { | ... | @@ -1660,7 +1662,7 @@ size_t bigint_clz(const BigInt *bi, size_t bit_count) { |
| 1660 | return count; | 1662 | return count; |
| 1661 | } | 1663 | } |
| 1662 | 1664 | ||
| 1663 | uint64_t bigint_as_unsigned(const BigInt *bigint) { | 1665 | static uint64_t bigint_as_unsigned(const BigInt *bigint) { |
| 1664 | assert(!bigint->is_negative); | 1666 | assert(!bigint->is_negative); |
| 1665 | if (bigint->digit_count == 0) { | 1667 | if (bigint->digit_count == 0) { |
| 1666 | return 0; | 1668 | return 0; |
| ... | @@ -1671,6 +1673,25 @@ uint64_t bigint_as_unsigned(const BigInt *bigint) { | ... | @@ -1671,6 +1673,25 @@ uint64_t bigint_as_unsigned(const BigInt *bigint) { |
| 1671 | } | 1673 | } |
| 1672 | } | 1674 | } |
| 1673 | 1675 | ||
| 1676 | uint64_t bigint_as_u64(const BigInt *bigint) | ||
| 1677 | { | ||
| 1678 | return bigint_as_unsigned(bigint); | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | uint32_t bigint_as_u32(const BigInt *bigint) { | ||
| 1682 | uint64_t value64 = bigint_as_unsigned(bigint); | ||
| 1683 | uint32_t value32 = (uint32_t)value64; | ||
| 1684 | assert (value64 == value32); | ||
| 1685 | return value32; | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | size_t bigint_as_usize(const BigInt *bigint) { | ||
| 1689 | uint64_t value64 = bigint_as_unsigned(bigint); | ||
| 1690 | size_t valueUsize = (size_t)value64; | ||
| 1691 | assert (value64 == valueUsize); | ||
| 1692 | return valueUsize; | ||
| 1693 | } | ||
| 1694 | |||
| 1674 | int64_t bigint_as_signed(const BigInt *bigint) { | 1695 | int64_t bigint_as_signed(const BigInt *bigint) { |
| 1675 | if (bigint->digit_count == 0) { | 1696 | if (bigint->digit_count == 0) { |
| 1676 | return 0; | 1697 | return 0; |
src/bigint.hpp+4-1| ... | @@ -36,7 +36,10 @@ void bigint_init_bigfloat(BigInt *dest, const BigFloat *op); | ... | @@ -36,7 +36,10 @@ void bigint_init_bigfloat(BigInt *dest, const BigFloat *op); |
| 36 | void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative); | 36 | void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative); |
| 37 | 37 | ||
| 38 | // panics if number won't fit | 38 | // panics if number won't fit |
| 39 | uint64_t bigint_as_unsigned(const BigInt *bigint); | 39 | uint64_t bigint_as_u64(const BigInt *bigint); |
| 40 | uint32_t bigint_as_u32(const BigInt *bigint); | ||
| 41 | size_t bigint_as_usize(const BigInt *bigint); | ||
| 42 | |||
| 40 | int64_t bigint_as_signed(const BigInt *bigint); | 43 | int64_t bigint_as_signed(const BigInt *bigint); |
| 41 | 44 | ||
| 42 | static inline const uint64_t *bigint_ptr(const BigInt *bigint) { | 45 | static inline const uint64_t *bigint_ptr(const BigInt *bigint) { |
src/codegen.cpp+1-1| ... | @@ -2872,7 +2872,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in | ... | @@ -2872,7 +2872,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in |
| 2872 | eval_min_max_value_int(g, int_type, &biggest_possible_err_val, true); | 2872 | eval_min_max_value_int(g, int_type, &biggest_possible_err_val, true); |
| 2873 | 2873 | ||
| 2874 | if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) && | 2874 | if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) && |
| 2875 | bigint_as_unsigned(&biggest_possible_err_val) < g->errors_by_index.length) | 2875 | bigint_as_usize(&biggest_possible_err_val) < g->errors_by_index.length) |
| 2876 | { | 2876 | { |
| 2877 | ok_bit = neq_zero_bit; | 2877 | ok_bit = neq_zero_bit; |
| 2878 | } else { | 2878 | } else { |
src/ir.cpp+24-24| ... | @@ -5768,7 +5768,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -5768,7 +5768,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode |
| 5768 | buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); | 5768 | buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); |
| 5769 | return irb->codegen->invalid_instruction; | 5769 | return irb->codegen->invalid_instruction; |
| 5770 | } | 5770 | } |
| 5771 | bit_offset_start = bigint_as_unsigned(node->data.pointer_type.bit_offset_start); | 5771 | bit_offset_start = bigint_as_u32(node->data.pointer_type.bit_offset_start); |
| 5772 | } | 5772 | } |
| 5773 | 5773 | ||
| 5774 | uint32_t host_int_bytes = 0; | 5774 | uint32_t host_int_bytes = 0; |
| ... | @@ -5780,7 +5780,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -5780,7 +5780,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode |
| 5780 | buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf))); | 5780 | buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf))); |
| 5781 | return irb->codegen->invalid_instruction; | 5781 | return irb->codegen->invalid_instruction; |
| 5782 | } | 5782 | } |
| 5783 | host_int_bytes = bigint_as_unsigned(node->data.pointer_type.host_int_bytes); | 5783 | host_int_bytes = bigint_as_u32(node->data.pointer_type.host_int_bytes); |
| 5784 | } | 5784 | } |
| 5785 | 5785 | ||
| 5786 | if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { | 5786 | if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { |
| ... | @@ -11589,7 +11589,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -11589,7 +11589,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc |
| 11589 | return ira->codegen->invalid_instruction; | 11589 | return ira->codegen->invalid_instruction; |
| 11590 | } | 11590 | } |
| 11591 | 11591 | ||
| 11592 | size_t index = bigint_as_unsigned(&val->data.x_bigint); | 11592 | size_t index = bigint_as_usize(&val->data.x_bigint); |
| 11593 | result->value.data.x_err_set = ira->codegen->errors_by_index.at(index); | 11593 | result->value.data.x_err_set = ira->codegen->errors_by_index.at(index); |
| 11594 | return result; | 11594 | return result; |
| 11595 | } else { | 11595 | } else { |
| ... | @@ -12554,7 +12554,7 @@ static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode | ... | @@ -12554,7 +12554,7 @@ static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode |
| 12554 | if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad))) | 12554 | if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad))) |
| 12555 | return false; | 12555 | return false; |
| 12556 | 12556 | ||
| 12557 | uint32_t align_bytes = bigint_as_unsigned(&const_val->data.x_bigint); | 12557 | uint32_t align_bytes = bigint_as_u32(&const_val->data.x_bigint); |
| 12558 | if (align_bytes == 0) { | 12558 | if (align_bytes == 0) { |
| 12559 | exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1")); | 12559 | exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1")); |
| 12560 | return false; | 12560 | return false; |
| ... | @@ -12594,7 +12594,7 @@ static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *i | ... | @@ -12594,7 +12594,7 @@ static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *i |
| 12594 | if (!const_val) | 12594 | if (!const_val) |
| 12595 | return false; | 12595 | return false; |
| 12596 | 12596 | ||
| 12597 | *out = bigint_as_unsigned(&const_val->data.x_bigint); | 12597 | *out = bigint_as_u64(&const_val->data.x_bigint); |
| 12598 | return true; | 12598 | return true; |
| 12599 | } | 12599 | } |
| 12600 | 12600 | ||
| ... | @@ -12642,7 +12642,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic | ... | @@ -12642,7 +12642,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic |
| 12642 | if (!const_val) | 12642 | if (!const_val) |
| 12643 | return false; | 12643 | return false; |
| 12644 | 12644 | ||
| 12645 | *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum_tag); | 12645 | *out = (AtomicOrder)bigint_as_u32(&const_val->data.x_enum_tag); |
| 12646 | return true; | 12646 | return true; |
| 12647 | } | 12647 | } |
| 12648 | 12648 | ||
| ... | @@ -12662,7 +12662,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi | ... | @@ -12662,7 +12662,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi |
| 12662 | if (!const_val) | 12662 | if (!const_val) |
| 12663 | return false; | 12663 | return false; |
| 12664 | 12664 | ||
| 12665 | *out = (AtomicRmwOp)bigint_as_unsigned(&const_val->data.x_enum_tag); | 12665 | *out = (AtomicRmwOp)bigint_as_u32(&const_val->data.x_enum_tag); |
| 12666 | return true; | 12666 | return true; |
| 12667 | } | 12667 | } |
| 12668 | 12668 | ||
| ... | @@ -12682,7 +12682,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob | ... | @@ -12682,7 +12682,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob |
| 12682 | if (!const_val) | 12682 | if (!const_val) |
| 12683 | return false; | 12683 | return false; |
| 12684 | 12684 | ||
| 12685 | *out = (GlobalLinkageId)bigint_as_unsigned(&const_val->data.x_enum_tag); | 12685 | *out = (GlobalLinkageId)bigint_as_u32(&const_val->data.x_enum_tag); |
| 12686 | return true; | 12686 | return true; |
| 12687 | } | 12687 | } |
| 12688 | 12688 | ||
| ... | @@ -12702,7 +12702,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod | ... | @@ -12702,7 +12702,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod |
| 12702 | if (!const_val) | 12702 | if (!const_val) |
| 12703 | return false; | 12703 | return false; |
| 12704 | 12704 | ||
| 12705 | *out = (FloatMode)bigint_as_unsigned(&const_val->data.x_enum_tag); | 12705 | *out = (FloatMode)bigint_as_u32(&const_val->data.x_enum_tag); |
| 12706 | return true; | 12706 | return true; |
| 12707 | } | 12707 | } |
| 12708 | 12708 | ||
| ... | @@ -12731,7 +12731,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { | ... | @@ -12731,7 +12731,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| 12731 | return array_val->data.x_array.data.s_buf; | 12731 | return array_val->data.x_array.data.s_buf; |
| 12732 | } | 12732 | } |
| 12733 | expand_undef_array(ira->codegen, array_val); | 12733 | expand_undef_array(ira->codegen, array_val); |
| 12734 | size_t len = bigint_as_unsigned(&len_field->data.x_bigint); | 12734 | size_t len = bigint_as_usize(&len_field->data.x_bigint); |
| 12735 | Buf *result = buf_alloc(); | 12735 | Buf *result = buf_alloc(); |
| 12736 | buf_resize(result, len); | 12736 | buf_resize(result, len); |
| 12737 | for (size_t i = 0; i < len; i += 1) { | 12737 | for (size_t i = 0; i < len; i += 1) { |
| ... | @@ -12741,7 +12741,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { | ... | @@ -12741,7 +12741,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| 12741 | ir_add_error(ira, casted_value, buf_sprintf("use of undefined value")); | 12741 | ir_add_error(ira, casted_value, buf_sprintf("use of undefined value")); |
| 12742 | return nullptr; | 12742 | return nullptr; |
| 12743 | } | 12743 | } |
| 12744 | uint64_t big_c = bigint_as_unsigned(&char_val->data.x_bigint); | 12744 | uint64_t big_c = bigint_as_u64(&char_val->data.x_bigint); |
| 12745 | assert(big_c <= UINT8_MAX); | 12745 | assert(big_c <= UINT8_MAX); |
| 12746 | uint8_t c = (uint8_t)big_c; | 12746 | uint8_t c = (uint8_t)big_c; |
| 12747 | buf_ptr(result)[i] = c; | 12747 | buf_ptr(result)[i] = c; |
| ... | @@ -13891,7 +13891,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i | ... | @@ -13891,7 +13891,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 13891 | op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val; | 13891 | op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val; |
| 13892 | op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; | 13892 | op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; |
| 13893 | ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index]; | 13893 | ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index]; |
| 13894 | op1_array_end = op1_array_index + bigint_as_unsigned(&len_val->data.x_bigint); | 13894 | op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint); |
| 13895 | } else { | 13895 | } else { |
| 13896 | ir_add_error(ira, op1, | 13896 | ir_add_error(ira, op1, |
| 13897 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name))); | 13897 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name))); |
| ... | @@ -13924,7 +13924,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i | ... | @@ -13924,7 +13924,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 13924 | op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val; | 13924 | op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val; |
| 13925 | op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; | 13925 | op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; |
| 13926 | ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index]; | 13926 | ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index]; |
| 13927 | op2_array_end = op2_array_index + bigint_as_unsigned(&len_val->data.x_bigint); | 13927 | op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint); |
| 13928 | } else { | 13928 | } else { |
| 13929 | ir_add_error(ira, op2, | 13929 | ir_add_error(ira, op2, |
| 13930 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name))); | 13930 | buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name))); |
| ... | @@ -16803,7 +16803,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -16803,7 +16803,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 16803 | uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); | 16803 | uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); |
| 16804 | uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); | 16804 | uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); |
| 16805 | if (instr_is_comptime(casted_elem_index)) { | 16805 | if (instr_is_comptime(casted_elem_index)) { |
| 16806 | uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint); | 16806 | uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint); |
| 16807 | if (array_type->id == ZigTypeIdArray) { | 16807 | if (array_type->id == ZigTypeIdArray) { |
| 16808 | uint64_t array_len = array_type->data.array.len; | 16808 | uint64_t array_len = array_type->data.array.len; |
| 16809 | if (index >= array_len) { | 16809 | if (index >= array_len) { |
| ... | @@ -16965,7 +16965,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -16965,7 +16965,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 16965 | ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index]; | 16965 | ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index]; |
| 16966 | IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); | 16966 | IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); |
| 16967 | ConstExprValue *out_val = &result->value; | 16967 | ConstExprValue *out_val = &result->value; |
| 16968 | uint64_t slice_len = bigint_as_unsigned(&len_field->data.x_bigint); | 16968 | uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint); |
| 16969 | if (index >= slice_len) { | 16969 | if (index >= slice_len) { |
| 16970 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, | 16970 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| 16971 | buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64, | 16971 | buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64, |
| ... | @@ -21250,7 +21250,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru | ... | @@ -21250,7 +21250,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru |
| 21250 | 21250 | ||
| 21251 | ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index]; | 21251 | ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index]; |
| 21252 | if (value_is_comptime(len_val)) { | 21252 | if (value_is_comptime(len_val)) { |
| 21253 | known_len = bigint_as_unsigned(&len_val->data.x_bigint); | 21253 | known_len = bigint_as_u64(&len_val->data.x_bigint); |
| 21254 | have_known_len = true; | 21254 | have_known_len = true; |
| 21255 | } | 21255 | } |
| 21256 | } | 21256 | } |
| ... | @@ -21607,7 +21607,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio | ... | @@ -21607,7 +21607,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio |
| 21607 | zig_panic("TODO memset on null ptr"); | 21607 | zig_panic("TODO memset on null ptr"); |
| 21608 | } | 21608 | } |
| 21609 | 21609 | ||
| 21610 | size_t count = bigint_as_unsigned(&count_val->data.x_bigint); | 21610 | size_t count = bigint_as_usize(&count_val->data.x_bigint); |
| 21611 | size_t end = start + count; | 21611 | size_t end = start + count; |
| 21612 | if (end > bound_end) { | 21612 | if (end > bound_end) { |
| 21613 | ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access")); | 21613 | ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access")); |
| ... | @@ -21704,7 +21704,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio | ... | @@ -21704,7 +21704,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio |
| 21704 | return ira->codegen->invalid_instruction; | 21704 | return ira->codegen->invalid_instruction; |
| 21705 | 21705 | ||
| 21706 | if (dest_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | 21706 | if (dest_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 21707 | size_t count = bigint_as_unsigned(&count_val->data.x_bigint); | 21707 | size_t count = bigint_as_usize(&count_val->data.x_bigint); |
| 21708 | 21708 | ||
| 21709 | ConstExprValue *dest_elements; | 21709 | ConstExprValue *dest_elements; |
| 21710 | size_t dest_start; | 21710 | size_t dest_start; |
| ... | @@ -21988,7 +21988,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -21988,7 +21988,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 21988 | case ConstPtrSpecialBaseArray: | 21988 | case ConstPtrSpecialBaseArray: |
| 21989 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; | 21989 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; |
| 21990 | abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index; | 21990 | abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index; |
| 21991 | rel_end = bigint_as_unsigned(&len_val->data.x_bigint); | 21991 | rel_end = bigint_as_usize(&len_val->data.x_bigint); |
| 21992 | break; | 21992 | break; |
| 21993 | case ConstPtrSpecialBaseStruct: | 21993 | case ConstPtrSpecialBaseStruct: |
| 21994 | zig_panic("TODO slice const inner struct"); | 21994 | zig_panic("TODO slice const inner struct"); |
| ... | @@ -22001,7 +22001,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -22001,7 +22001,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 22001 | case ConstPtrSpecialHardCodedAddr: | 22001 | case ConstPtrSpecialHardCodedAddr: |
| 22002 | array_val = nullptr; | 22002 | array_val = nullptr; |
| 22003 | abs_offset = 0; | 22003 | abs_offset = 0; |
| 22004 | rel_end = bigint_as_unsigned(&len_val->data.x_bigint); | 22004 | rel_end = bigint_as_usize(&len_val->data.x_bigint); |
| 22005 | break; | 22005 | break; |
| 22006 | case ConstPtrSpecialFunction: | 22006 | case ConstPtrSpecialFunction: |
| 22007 | zig_panic("TODO slice of slice cast from function"); | 22007 | zig_panic("TODO slice of slice cast from function"); |
| ... | @@ -22012,7 +22012,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -22012,7 +22012,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 22012 | zig_unreachable(); | 22012 | zig_unreachable(); |
| 22013 | } | 22013 | } |
| 22014 | 22014 | ||
| 22015 | uint64_t start_scalar = bigint_as_unsigned(&casted_start->value.data.x_bigint); | 22015 | uint64_t start_scalar = bigint_as_u64(&casted_start->value.data.x_bigint); |
| 22016 | if (!ptr_is_undef && start_scalar > rel_end) { | 22016 | if (!ptr_is_undef && start_scalar > rel_end) { |
| 22017 | ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice")); | 22017 | ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice")); |
| 22018 | return ira->codegen->invalid_instruction; | 22018 | return ira->codegen->invalid_instruction; |
| ... | @@ -22020,7 +22020,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -22020,7 +22020,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 22020 | 22020 | ||
| 22021 | uint64_t end_scalar; | 22021 | uint64_t end_scalar; |
| 22022 | if (end) { | 22022 | if (end) { |
| 22023 | end_scalar = bigint_as_unsigned(&end->value.data.x_bigint); | 22023 | end_scalar = bigint_as_u64(&end->value.data.x_bigint); |
| 22024 | } else { | 22024 | } else { |
| 22025 | end_scalar = rel_end; | 22025 | end_scalar = rel_end; |
| 22026 | } | 22026 | } |
| ... | @@ -23622,7 +23622,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou | ... | @@ -23622,7 +23622,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 23622 | BigInt bn; | 23622 | BigInt bn; |
| 23623 | bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, | 23623 | bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, |
| 23624 | codegen->is_big_endian, false); | 23624 | codegen->is_big_endian, false); |
| 23625 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); | 23625 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_usize(&bn); |
| 23626 | return ErrorNone; | 23626 | return ErrorNone; |
| 23627 | } | 23627 | } |
| 23628 | case ZigTypeIdArray: | 23628 | case ZigTypeIdArray: |
| ... | @@ -23815,7 +23815,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -23815,7 +23815,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc |
| 23815 | if (!val) | 23815 | if (!val) |
| 23816 | return ira->codegen->invalid_instruction; | 23816 | return ira->codegen->invalid_instruction; |
| 23817 | 23817 | ||
| 23818 | uint64_t addr = bigint_as_unsigned(&val->data.x_bigint); | 23818 | uint64_t addr = bigint_as_u64(&val->data.x_bigint); |
| 23819 | if (!ptr_allows_addr_zero(ptr_type) && addr == 0) { | 23819 | if (!ptr_allows_addr_zero(ptr_type) && addr == 0) { |
| 23820 | ir_add_error(ira, source_instr, | 23820 | ir_add_error(ira, source_instr, |
| 23821 | buf_sprintf("pointer type '%s' does not allow address zero", buf_ptr(&ptr_type->name))); | 23821 | buf_sprintf("pointer type '%s' does not allow address zero", buf_ptr(&ptr_type->name))); |
src/os.cpp+15-15| ... | @@ -1125,29 +1125,27 @@ Error os_get_cwd(Buf *out_cwd) { | ... | @@ -1125,29 +1125,27 @@ Error os_get_cwd(Buf *out_cwd) { |
| 1125 | #endif | 1125 | #endif |
| 1126 | } | 1126 | } |
| 1127 | 1127 | ||
| 1128 | #if defined(ZIG_OS_WINDOWS) | ||
| 1129 | #define is_wprefix(s, prefix) \ | 1128 | #define is_wprefix(s, prefix) \ |
| 1130 | (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0) | 1129 | (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0) |
| 1131 | static bool is_stderr_cyg_pty(void) { | 1130 | bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd) { |
| 1132 | HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE); | 1131 | #if defined(ZIG_OS_WINDOWS) |
| 1133 | if (stderr_handle == INVALID_HANDLE_VALUE) | 1132 | HANDLE handle = (HANDLE)_get_osfhandle(fd); |
| 1133 | |||
| 1134 | // Cygwin/msys's pty is a pipe. | ||
| 1135 | if (handle == INVALID_HANDLE_VALUE || GetFileType(handle) != FILE_TYPE_PIPE) { | ||
| 1134 | return false; | 1136 | return false; |
| 1137 | } | ||
| 1135 | 1138 | ||
| 1136 | int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH; | 1139 | int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH; |
| 1137 | FILE_NAME_INFO *nameinfo; | ||
| 1138 | WCHAR *p = NULL; | 1140 | WCHAR *p = NULL; |
| 1139 | 1141 | ||
| 1140 | // Cygwin/msys's pty is a pipe. | 1142 | FILE_NAME_INFO *nameinfo = (FILE_NAME_INFO *)allocate<char>(size); |
| 1141 | if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) { | ||
| 1142 | return 0; | ||
| 1143 | } | ||
| 1144 | nameinfo = (FILE_NAME_INFO *)allocate<char>(size); | ||
| 1145 | if (nameinfo == NULL) { | 1143 | if (nameinfo == NULL) { |
| 1146 | return 0; | 1144 | return false; |
| 1147 | } | 1145 | } |
| 1148 | // Check the name of the pipe: | 1146 | // Check the name of the pipe: |
| 1149 | // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master' | 1147 | // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master' |
| 1150 | if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) { | 1148 | if (GetFileInformationByHandleEx(handle, FileNameInfo, nameinfo, size)) { |
| 1151 | nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0'; | 1149 | nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0'; |
| 1152 | p = nameinfo->FileName; | 1150 | p = nameinfo->FileName; |
| 1153 | if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */ | 1151 | if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */ |
| ... | @@ -1180,12 +1178,14 @@ static bool is_stderr_cyg_pty(void) { | ... | @@ -1180,12 +1178,14 @@ static bool is_stderr_cyg_pty(void) { |
| 1180 | } | 1178 | } |
| 1181 | free(nameinfo); | 1179 | free(nameinfo); |
| 1182 | return (p != NULL); | 1180 | return (p != NULL); |
| 1183 | } | 1181 | #else |
| 1182 | return false; | ||
| 1184 | #endif | 1183 | #endif |
| 1184 | } | ||
| 1185 | 1185 | ||
| 1186 | bool os_stderr_tty(void) { | 1186 | bool os_stderr_tty(void) { |
| 1187 | #if defined(ZIG_OS_WINDOWS) | 1187 | #if defined(ZIG_OS_WINDOWS) |
| 1188 | return _isatty(_fileno(stderr)) != 0 || is_stderr_cyg_pty(); | 1188 | return _isatty(fileno(stderr)) != 0 || os_is_cygwin_pty(fileno(stderr)); |
| 1189 | #elif defined(ZIG_OS_POSIX) | 1189 | #elif defined(ZIG_OS_POSIX) |
| 1190 | return isatty(STDERR_FILENO) != 0; | 1190 | return isatty(STDERR_FILENO) != 0; |
| 1191 | #else | 1191 | #else |
| ... | @@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL | ... | @@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL |
| 1486 | 1486 | ||
| 1487 | void os_stderr_set_color(TermColor color) { | 1487 | void os_stderr_set_color(TermColor color) { |
| 1488 | #if defined(ZIG_OS_WINDOWS) | 1488 | #if defined(ZIG_OS_WINDOWS) |
| 1489 | if (is_stderr_cyg_pty()) { | 1489 | if (os_stderr_tty()) { |
| 1490 | set_color_posix(color); | 1490 | set_color_posix(color); |
| 1491 | return; | 1491 | return; |
| 1492 | } | 1492 | } |
src/os.hpp+8| ... | @@ -11,6 +11,7 @@ | ... | @@ -11,6 +11,7 @@ |
| 11 | #include "list.hpp" | 11 | #include "list.hpp" |
| 12 | #include "buffer.hpp" | 12 | #include "buffer.hpp" |
| 13 | #include "error.hpp" | 13 | #include "error.hpp" |
| 14 | #include "target.hpp" | ||
| 14 | #include "zig_llvm.h" | 15 | #include "zig_llvm.h" |
| 15 | #include "windows_sdk.h" | 16 | #include "windows_sdk.h" |
| 16 | 17 | ||
| ... | @@ -88,6 +89,11 @@ struct Termination { | ... | @@ -88,6 +89,11 @@ struct Termination { |
| 88 | #define OsFile int | 89 | #define OsFile int |
| 89 | #endif | 90 | #endif |
| 90 | 91 | ||
| 92 | #if defined(ZIG_OS_WINDOWS) | ||
| 93 | #undef fileno | ||
| 94 | #define fileno _fileno | ||
| 95 | #endif | ||
| 96 | |||
| 91 | struct OsTimeStamp { | 97 | struct OsTimeStamp { |
| 92 | uint64_t sec; | 98 | uint64_t sec; |
| 93 | uint64_t nsec; | 99 | uint64_t nsec; |
| ... | @@ -152,6 +158,8 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf | ... | @@ -152,6 +158,8 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf |
| 152 | Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); | 158 | Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); |
| 153 | Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); | 159 | Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); |
| 154 | 160 | ||
| 161 | bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd); | ||
| 162 | |||
| 155 | Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths); | 163 | Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths); |
| 156 | 164 | ||
| 157 | #endif | 165 | #endif |
src/parser.cpp+5-3| ... | @@ -782,24 +782,26 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { | ... | @@ -782,24 +782,26 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 782 | return res; | 782 | return res; |
| 783 | } | 783 | } |
| 784 | 784 | ||
| 785 | // ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? | 785 | // ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? |
| 786 | static AstNode *ast_parse_container_field(ParseContext *pc) { | 786 | static AstNode *ast_parse_container_field(ParseContext *pc) { |
| 787 | Token *identifier = eat_token_if(pc, TokenIdSymbol); | 787 | Token *identifier = eat_token_if(pc, TokenIdSymbol); |
| 788 | if (identifier == nullptr) | 788 | if (identifier == nullptr) |
| 789 | return nullptr; | 789 | return nullptr; |
| 790 | 790 | ||
| 791 | AstNode *type_expr = nullptr; | 791 | AstNode *type_expr = nullptr; |
| 792 | if (eat_token_if(pc, TokenIdColon) != nullptr) | 792 | if (eat_token_if(pc, TokenIdColon) != nullptr) { |
| 793 | type_expr = ast_expect(pc, ast_parse_type_expr); | 793 | type_expr = ast_expect(pc, ast_parse_type_expr); |
| 794 | } | ||
| 795 | AstNode *align_expr = ast_parse_byte_align(pc); | ||
| 794 | AstNode *expr = nullptr; | 796 | AstNode *expr = nullptr; |
| 795 | if (eat_token_if(pc, TokenIdEq) != nullptr) | 797 | if (eat_token_if(pc, TokenIdEq) != nullptr) |
| 796 | expr = ast_expect(pc, ast_parse_expr); | 798 | expr = ast_expect(pc, ast_parse_expr); |
| 797 | 799 | ||
| 798 | |||
| 799 | AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier); | 800 | AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier); |
| 800 | res->data.struct_field.name = token_buf(identifier); | 801 | res->data.struct_field.name = token_buf(identifier); |
| 801 | res->data.struct_field.type = type_expr; | 802 | res->data.struct_field.type = type_expr; |
| 802 | res->data.struct_field.value = expr; | 803 | res->data.struct_field.value = expr; |
| 804 | res->data.struct_field.align_expr = align_expr; | ||
| 803 | return res; | 805 | return res; |
| 804 | } | 806 | } |
| 805 | 807 |
src/target.cpp+14-1| ... | @@ -491,6 +491,16 @@ Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) { | ... | @@ -491,6 +491,16 @@ Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) { |
| 491 | return ErrorNone; | 491 | return ErrorNone; |
| 492 | } | 492 | } |
| 493 | 493 | ||
| 494 | static ZigLLVM_EnvironmentType target_get_win32_abi() { | ||
| 495 | FILE* files[] = { stdin, stdout, stderr, nullptr }; | ||
| 496 | for (int i = 0; files[i] != nullptr; i++) { | ||
| 497 | if (os_is_cygwin_pty(fileno(files[i]))) { | ||
| 498 | return ZigLLVM_GNU; | ||
| 499 | } | ||
| 500 | } | ||
| 501 | return ZigLLVM_MSVC; | ||
| 502 | } | ||
| 503 | |||
| 494 | void get_native_target(ZigTarget *target) { | 504 | void get_native_target(ZigTarget *target) { |
| 495 | // first zero initialize | 505 | // first zero initialize |
| 496 | *target = {}; | 506 | *target = {}; |
| ... | @@ -505,6 +515,9 @@ void get_native_target(ZigTarget *target) { | ... | @@ -505,6 +515,9 @@ void get_native_target(ZigTarget *target) { |
| 505 | &target->abi, | 515 | &target->abi, |
| 506 | &oformat); | 516 | &oformat); |
| 507 | target->os = get_zig_os_type(os_type); | 517 | target->os = get_zig_os_type(os_type); |
| 518 | if (target->os == OsWindows) { | ||
| 519 | target->abi = target_get_win32_abi(); | ||
| 520 | } | ||
| 508 | target->is_native = true; | 521 | target->is_native = true; |
| 509 | if (target->abi == ZigLLVM_UnknownEnvironment) { | 522 | if (target->abi == ZigLLVM_UnknownEnvironment) { |
| 510 | target->abi = target_default_abi(target->arch, target->os); | 523 | target->abi = target_default_abi(target->arch, target->os); |
| ... | @@ -1601,7 +1614,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { | ... | @@ -1601,7 +1614,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { |
| 1601 | return ZigLLVM_GNU; | 1614 | return ZigLLVM_GNU; |
| 1602 | case OsUefi: | 1615 | case OsUefi: |
| 1603 | case OsWindows: | 1616 | case OsWindows: |
| 1604 | return ZigLLVM_MSVC; | 1617 | return ZigLLVM_MSVC; |
| 1605 | case OsLinux: | 1618 | case OsLinux: |
| 1606 | case OsWASI: | 1619 | case OsWASI: |
| 1607 | return ZigLLVM_Musl; | 1620 | return ZigLLVM_Musl; |
std/crypto/benchmark.zig created+198| ... | @@ -0,0 +1,198 @@ | ||
| 1 | // zig run benchmark.zig --release-fast --override-std-dir .. | ||
| 2 | |||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const std = @import("../std.zig"); | ||
| 5 | const time = std.time; | ||
| 6 | const Timer = time.Timer; | ||
| 7 | const crypto = std.crypto; | ||
| 8 | |||
| 9 | const KiB = 1024; | ||
| 10 | const MiB = 1024 * KiB; | ||
| 11 | |||
| 12 | var prng = std.rand.DefaultPrng.init(0); | ||
| 13 | |||
| 14 | const Crypto = struct { | ||
| 15 | ty: type, | ||
| 16 | name: []const u8, | ||
| 17 | }; | ||
| 18 | |||
| 19 | const hashes = [_]Crypto{ | ||
| 20 | Crypto{ .ty = crypto.Md5, .name = "md5" }, | ||
| 21 | Crypto{ .ty = crypto.Sha1, .name = "sha1" }, | ||
| 22 | Crypto{ .ty = crypto.Sha256, .name = "sha256" }, | ||
| 23 | Crypto{ .ty = crypto.Sha512, .name = "sha512" }, | ||
| 24 | Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" }, | ||
| 25 | Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" }, | ||
| 26 | Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" }, | ||
| 27 | Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" }, | ||
| 28 | }; | ||
| 29 | |||
| 30 | pub fn benchmarkHash(comptime Hash: var, comptime bytes: comptime_int) !u64 { | ||
| 31 | var h = Hash.init(); | ||
| 32 | |||
| 33 | var block: [Hash.digest_length]u8 = undefined; | ||
| 34 | prng.random.bytes(block[0..]); | ||
| 35 | |||
| 36 | var offset: usize = 0; | ||
| 37 | var timer = try Timer.start(); | ||
| 38 | const start = timer.lap(); | ||
| 39 | while (offset < bytes) : (offset += block.len) { | ||
| 40 | h.update(block[0..]); | ||
| 41 | } | ||
| 42 | const end = timer.read(); | ||
| 43 | |||
| 44 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 45 | const throughput = @floatToInt(u64, bytes / elapsed_s); | ||
| 46 | |||
| 47 | return throughput; | ||
| 48 | } | ||
| 49 | |||
| 50 | const macs = [_]Crypto{ | ||
| 51 | Crypto{ .ty = crypto.Poly1305, .name = "poly1305" }, | ||
| 52 | Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" }, | ||
| 53 | Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" }, | ||
| 54 | Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" }, | ||
| 55 | }; | ||
| 56 | |||
| 57 | pub fn benchmarkMac(comptime Mac: var, comptime bytes: comptime_int) !u64 { | ||
| 58 | std.debug.assert(32 >= Mac.mac_length and 32 >= Mac.minimum_key_length); | ||
| 59 | |||
| 60 | var in: [1 * MiB]u8 = undefined; | ||
| 61 | prng.random.bytes(in[0..]); | ||
| 62 | |||
| 63 | var key: [32]u8 = undefined; | ||
| 64 | prng.random.bytes(key[0..]); | ||
| 65 | |||
| 66 | var offset: usize = 0; | ||
| 67 | var timer = try Timer.start(); | ||
| 68 | const start = timer.lap(); | ||
| 69 | while (offset < bytes) : (offset += in.len) { | ||
| 70 | Mac.create(key[0..], in[0..], key); | ||
| 71 | } | ||
| 72 | const end = timer.read(); | ||
| 73 | |||
| 74 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 75 | const throughput = @floatToInt(u64, bytes / elapsed_s); | ||
| 76 | |||
| 77 | return throughput; | ||
| 78 | } | ||
| 79 | |||
| 80 | const exchanges = [_]Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }}; | ||
| 81 | |||
| 82 | pub fn benchmarkKeyExchange(comptime DhKeyExchange: var, comptime exchange_count: comptime_int) !u64 { | ||
| 83 | std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length); | ||
| 84 | |||
| 85 | var in: [DhKeyExchange.minimum_key_length]u8 = undefined; | ||
| 86 | prng.random.bytes(in[0..]); | ||
| 87 | |||
| 88 | var out: [DhKeyExchange.minimum_key_length]u8 = undefined; | ||
| 89 | prng.random.bytes(out[0..]); | ||
| 90 | |||
| 91 | var offset: usize = 0; | ||
| 92 | var timer = try Timer.start(); | ||
| 93 | const start = timer.lap(); | ||
| 94 | { | ||
| 95 | var i: usize = 0; | ||
| 96 | while (i < exchange_count) : (i += 1) { | ||
| 97 | _ = DhKeyExchange.create(out[0..], out, in); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | const end = timer.read(); | ||
| 101 | |||
| 102 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 103 | const throughput = @floatToInt(u64, exchange_count / elapsed_s); | ||
| 104 | |||
| 105 | return throughput; | ||
| 106 | } | ||
| 107 | |||
| 108 | fn usage() void { | ||
| 109 | std.debug.warn( | ||
| 110 | \\throughput_test [options] | ||
| 111 | \\ | ||
| 112 | \\Options: | ||
| 113 | \\ --filter [test-name] | ||
| 114 | \\ --seed [int] | ||
| 115 | \\ --help | ||
| 116 | \\ | ||
| 117 | ); | ||
| 118 | } | ||
| 119 | |||
| 120 | fn mode(comptime x: comptime_int) comptime_int { | ||
| 121 | return if (builtin.mode == builtin.Mode.Debug) x / 64 else x; | ||
| 122 | } | ||
| 123 | |||
| 124 | // TODO(#1358): Replace with builtin formatted padding when available. | ||
| 125 | fn printPad(stdout: var, s: []const u8) !void { | ||
| 126 | var i: usize = 0; | ||
| 127 | while (i < 12 - s.len) : (i += 1) { | ||
| 128 | try stdout.print(" "); | ||
| 129 | } | ||
| 130 | try stdout.print("{}", s); | ||
| 131 | } | ||
| 132 | |||
| 133 | pub fn main() !void { | ||
| 134 | var stdout_file = try std.io.getStdOut(); | ||
| 135 | var stdout_out_stream = stdout_file.outStream(); | ||
| 136 | const stdout = &stdout_out_stream.stream; | ||
| 137 | |||
| 138 | var buffer: [1024]u8 = undefined; | ||
| 139 | var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); | ||
| 140 | const args = try std.process.argsAlloc(&fixed.allocator); | ||
| 141 | |||
| 142 | var filter: ?[]u8 = ""; | ||
| 143 | |||
| 144 | var i: usize = 1; | ||
| 145 | while (i < args.len) : (i += 1) { | ||
| 146 | if (std.mem.eql(u8, args[i], "--mode")) { | ||
| 147 | try stdout.print("{}\n", builtin.mode); | ||
| 148 | return; | ||
| 149 | } else if (std.mem.eql(u8, args[i], "--seed")) { | ||
| 150 | i += 1; | ||
| 151 | if (i == args.len) { | ||
| 152 | usage(); | ||
| 153 | std.os.exit(1); | ||
| 154 | } | ||
| 155 | |||
| 156 | const seed = try std.fmt.parseUnsigned(u32, args[i], 10); | ||
| 157 | prng.seed(seed); | ||
| 158 | } else if (std.mem.eql(u8, args[i], "--filter")) { | ||
| 159 | i += 1; | ||
| 160 | if (i == args.len) { | ||
| 161 | usage(); | ||
| 162 | std.os.exit(1); | ||
| 163 | } | ||
| 164 | |||
| 165 | filter = args[i]; | ||
| 166 | } else if (std.mem.eql(u8, args[i], "--help")) { | ||
| 167 | usage(); | ||
| 168 | return; | ||
| 169 | } else { | ||
| 170 | usage(); | ||
| 171 | std.os.exit(1); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | inline for (hashes) |H| { | ||
| 176 | if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { | ||
| 177 | const throughput = try benchmarkHash(H.ty, mode(32 * MiB)); | ||
| 178 | try printPad(stdout, H.name); | ||
| 179 | try stdout.print(": {} MiB/s\n", throughput / (1 * MiB)); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | inline for (macs) |M| { | ||
| 184 | if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) { | ||
| 185 | const throughput = try benchmarkMac(M.ty, mode(128 * MiB)); | ||
| 186 | try printPad(stdout, M.name); | ||
| 187 | try stdout.print(": {} MiB/s\n", throughput / (1 * MiB)); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | inline for (exchanges) |E| { | ||
| 192 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { | ||
| 193 | const throughput = try benchmarkKeyExchange(E.ty, mode(1000)); | ||
| 194 | try printPad(stdout, E.name); | ||
| 195 | try stdout.print(": {} exchanges/s\n", throughput); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
std/crypto/blake2.zig+2-2| ... | @@ -269,8 +269,8 @@ pub const Blake2b512 = Blake2b(512); | ... | @@ -269,8 +269,8 @@ pub const Blake2b512 = Blake2b(512); |
| 269 | fn Blake2b(comptime out_len: usize) type { | 269 | fn Blake2b(comptime out_len: usize) type { |
| 270 | return struct { | 270 | return struct { |
| 271 | const Self = @This(); | 271 | const Self = @This(); |
| 272 | const block_length = 128; | 272 | pub const block_length = 128; |
| 273 | const digest_length = out_len / 8; | 273 | pub const digest_length = out_len / 8; |
| 274 | 274 | ||
| 275 | const iv = [8]u64{ | 275 | const iv = [8]u64{ |
| 276 | 0x6a09e667f3bcc908, | 276 | 0x6a09e667f3bcc908, |
std/crypto/sha2.zig+2-2| ... | @@ -420,8 +420,8 @@ pub const Sha512 = Sha2_64(Sha512Params); | ... | @@ -420,8 +420,8 @@ pub const Sha512 = Sha2_64(Sha512Params); |
| 420 | fn Sha2_64(comptime params: Sha2Params64) type { | 420 | fn Sha2_64(comptime params: Sha2Params64) type { |
| 421 | return struct { | 421 | return struct { |
| 422 | const Self = @This(); | 422 | const Self = @This(); |
| 423 | const block_length = 128; | 423 | pub const block_length = 128; |
| 424 | const digest_length = params.out_len / 8; | 424 | pub const digest_length = params.out_len / 8; |
| 425 | 425 | ||
| 426 | s: [8]u64, | 426 | s: [8]u64, |
| 427 | // Streaming Cache | 427 | // Streaming Cache |
std/crypto/throughput_test.zig deleted-193| ... | @@ -1,193 +0,0 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const time = std.time; | ||
| 4 | const Timer = time.Timer; | ||
| 5 | const crypto = @import("../crypto.zig"); | ||
| 6 | |||
| 7 | const KiB = 1024; | ||
| 8 | const MiB = 1024 * KiB; | ||
| 9 | |||
| 10 | var prng = std.rand.DefaultPrng.init(0); | ||
| 11 | |||
| 12 | const Crypto = struct { | ||
| 13 | ty: type, | ||
| 14 | name: []const u8, | ||
| 15 | }; | ||
| 16 | |||
| 17 | const hashes = []Crypto{ | ||
| 18 | Crypto{ .ty = crypto.Md5, .name = "md5" }, | ||
| 19 | Crypto{ .ty = crypto.Sha1, .name = "sha1" }, | ||
| 20 | Crypto{ .ty = crypto.Sha256, .name = "sha256" }, | ||
| 21 | Crypto{ .ty = crypto.Sha512, .name = "sha512" }, | ||
| 22 | Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" }, | ||
| 23 | Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" }, | ||
| 24 | Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" }, | ||
| 25 | Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" }, | ||
| 26 | }; | ||
| 27 | |||
| 28 | pub fn benchmarkHash(comptime Hash: var, comptime bytes: comptime_int) !u64 { | ||
| 29 | var h = Hash.init(); | ||
| 30 | |||
| 31 | var block: [Hash.digest_length]u8 = undefined; | ||
| 32 | prng.random.bytes(block[0..]); | ||
| 33 | |||
| 34 | var offset: usize = 0; | ||
| 35 | var timer = try Timer.start(); | ||
| 36 | const start = timer.lap(); | ||
| 37 | while (offset < bytes) : (offset += block.len) { | ||
| 38 | h.update(block[0..]); | ||
| 39 | } | ||
| 40 | const end = timer.read(); | ||
| 41 | |||
| 42 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 43 | const throughput = @floatToInt(u64, bytes / elapsed_s); | ||
| 44 | |||
| 45 | return throughput; | ||
| 46 | } | ||
| 47 | |||
| 48 | const macs = []Crypto{ | ||
| 49 | Crypto{ .ty = crypto.Poly1305, .name = "poly1305" }, | ||
| 50 | Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" }, | ||
| 51 | Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" }, | ||
| 52 | Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" }, | ||
| 53 | }; | ||
| 54 | |||
| 55 | pub fn benchmarkMac(comptime Mac: var, comptime bytes: comptime_int) !u64 { | ||
| 56 | std.debug.assert(32 >= Mac.mac_length and 32 >= Mac.minimum_key_length); | ||
| 57 | |||
| 58 | var in: [1 * MiB]u8 = undefined; | ||
| 59 | prng.random.bytes(in[0..]); | ||
| 60 | |||
| 61 | var key: [32]u8 = undefined; | ||
| 62 | prng.random.bytes(key[0..]); | ||
| 63 | |||
| 64 | var offset: usize = 0; | ||
| 65 | var timer = try Timer.start(); | ||
| 66 | const start = timer.lap(); | ||
| 67 | while (offset < bytes) : (offset += in.len) { | ||
| 68 | Mac.create(key[0..], in[0..], key); | ||
| 69 | } | ||
| 70 | const end = timer.read(); | ||
| 71 | |||
| 72 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 73 | const throughput = @floatToInt(u64, bytes / elapsed_s); | ||
| 74 | |||
| 75 | return throughput; | ||
| 76 | } | ||
| 77 | |||
| 78 | const exchanges = []Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }}; | ||
| 79 | |||
| 80 | pub fn benchmarkKeyExchange(comptime DhKeyExchange: var, comptime exchange_count: comptime_int) !u64 { | ||
| 81 | std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length); | ||
| 82 | |||
| 83 | var in: [DhKeyExchange.minimum_key_length]u8 = undefined; | ||
| 84 | prng.random.bytes(in[0..]); | ||
| 85 | |||
| 86 | var out: [DhKeyExchange.minimum_key_length]u8 = undefined; | ||
| 87 | prng.random.bytes(out[0..]); | ||
| 88 | |||
| 89 | var offset: usize = 0; | ||
| 90 | var timer = try Timer.start(); | ||
| 91 | const start = timer.lap(); | ||
| 92 | { | ||
| 93 | var i: usize = 0; | ||
| 94 | while (i < exchange_count) : (i += 1) { | ||
| 95 | _ = DhKeyExchange.create(out[0..], out, in); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | const end = timer.read(); | ||
| 99 | |||
| 100 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 101 | const throughput = @floatToInt(u64, exchange_count / elapsed_s); | ||
| 102 | |||
| 103 | return throughput; | ||
| 104 | } | ||
| 105 | |||
| 106 | fn usage() void { | ||
| 107 | std.debug.warn( | ||
| 108 | \\throughput_test [options] | ||
| 109 | \\ | ||
| 110 | \\Options: | ||
| 111 | \\ --filter [test-name] | ||
| 112 | \\ --seed [int] | ||
| 113 | \\ --help | ||
| 114 | \\ | ||
| 115 | ); | ||
| 116 | } | ||
| 117 | |||
| 118 | fn mode(comptime x: comptime_int) comptime_int { | ||
| 119 | return if (builtin.mode == builtin.Mode.Debug) x / 64 else x; | ||
| 120 | } | ||
| 121 | |||
| 122 | // TODO(#1358): Replace with builtin formatted padding when available. | ||
| 123 | fn printPad(stdout: var, s: []const u8) !void { | ||
| 124 | var i: usize = 0; | ||
| 125 | while (i < 12 - s.len) : (i += 1) { | ||
| 126 | try stdout.print(" "); | ||
| 127 | } | ||
| 128 | try stdout.print("{}", s); | ||
| 129 | } | ||
| 130 | |||
| 131 | pub fn main() !void { | ||
| 132 | var stdout_file = try std.io.getStdOut(); | ||
| 133 | var stdout_out_stream = stdout_file.outStream(); | ||
| 134 | const stdout = &stdout_out_stream.stream; | ||
| 135 | |||
| 136 | var buffer: [1024]u8 = undefined; | ||
| 137 | var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); | ||
| 138 | const args = try std.os.argsAlloc(&fixed.allocator); | ||
| 139 | |||
| 140 | var filter: ?[]u8 = ""; | ||
| 141 | |||
| 142 | var i: usize = 1; | ||
| 143 | while (i < args.len) : (i += 1) { | ||
| 144 | if (std.mem.eql(u8, args[i], "--seed")) { | ||
| 145 | i += 1; | ||
| 146 | if (i == args.len) { | ||
| 147 | usage(); | ||
| 148 | std.os.exit(1); | ||
| 149 | } | ||
| 150 | |||
| 151 | const seed = try std.fmt.parseUnsigned(u32, args[i], 10); | ||
| 152 | prng.seed(seed); | ||
| 153 | } else if (std.mem.eql(u8, args[i], "--filter")) { | ||
| 154 | i += 1; | ||
| 155 | if (i == args.len) { | ||
| 156 | usage(); | ||
| 157 | std.os.exit(1); | ||
| 158 | } | ||
| 159 | |||
| 160 | filter = args[i]; | ||
| 161 | } else if (std.mem.eql(u8, args[i], "--help")) { | ||
| 162 | usage(); | ||
| 163 | return; | ||
| 164 | } else { | ||
| 165 | usage(); | ||
| 166 | std.os.exit(1); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | inline for (hashes) |H| { | ||
| 171 | if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { | ||
| 172 | const throughput = try benchmarkHash(H.ty, mode(32 * MiB)); | ||
| 173 | try printPad(stdout, H.name); | ||
| 174 | try stdout.print(": {} MiB/s\n", throughput / (1 * MiB)); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | inline for (macs) |M| { | ||
| 179 | if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) { | ||
| 180 | const throughput = try benchmarkMac(M.ty, mode(128 * MiB)); | ||
| 181 | try printPad(stdout, M.name); | ||
| 182 | try stdout.print(": {} MiB/s\n", throughput / (1 * MiB)); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | inline for (exchanges) |E| { | ||
| 187 | if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) { | ||
| 188 | const throughput = try benchmarkKeyExchange(E.ty, mode(1000)); | ||
| 189 | try printPad(stdout, E.name); | ||
| 190 | try stdout.print(": {} exchanges/s\n", throughput); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | } | ||
std/hash/benchmark.zig created+273| ... | @@ -0,0 +1,273 @@ | ||
| 1 | // zig run benchmark.zig --release-fast --override-std-dir .. | ||
| 2 | |||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const std = @import("std"); | ||
| 5 | const time = std.time; | ||
| 6 | const Timer = time.Timer; | ||
| 7 | const hash = std.hash; | ||
| 8 | |||
| 9 | const KiB = 1024; | ||
| 10 | const MiB = 1024 * KiB; | ||
| 11 | const GiB = 1024 * MiB; | ||
| 12 | |||
| 13 | var prng = std.rand.DefaultPrng.init(0); | ||
| 14 | |||
| 15 | const Hash = struct { | ||
| 16 | ty: type, | ||
| 17 | name: []const u8, | ||
| 18 | has_iterative_api: bool = true, | ||
| 19 | init_u8s: ?[]const u8 = null, | ||
| 20 | init_u64: ?u64 = null, | ||
| 21 | }; | ||
| 22 | |||
| 23 | const siphash_key = "0123456789abcdef"; | ||
| 24 | |||
| 25 | const hashes = [_]Hash{ | ||
| 26 | Hash{ | ||
| 27 | .ty = hash.Wyhash, | ||
| 28 | .name = "wyhash", | ||
| 29 | .init_u64 = 0, | ||
| 30 | }, | ||
| 31 | Hash{ | ||
| 32 | .ty = hash.SipHash64(1, 3), | ||
| 33 | .name = "siphash(1,3)", | ||
| 34 | .init_u8s = siphash_key, | ||
| 35 | }, | ||
| 36 | Hash{ | ||
| 37 | .ty = hash.SipHash64(2, 4), | ||
| 38 | .name = "siphash(2,4)", | ||
| 39 | .init_u8s = siphash_key, | ||
| 40 | }, | ||
| 41 | Hash{ | ||
| 42 | .ty = hash.Fnv1a_64, | ||
| 43 | .name = "fnv1a", | ||
| 44 | }, | ||
| 45 | Hash{ | ||
| 46 | .ty = hash.Adler32, | ||
| 47 | .name = "adler32", | ||
| 48 | }, | ||
| 49 | Hash{ | ||
| 50 | .ty = hash.crc.Crc32WithPoly(.IEEE), | ||
| 51 | .name = "crc32-slicing-by-8", | ||
| 52 | }, | ||
| 53 | Hash{ | ||
| 54 | .ty = hash.crc.Crc32SmallWithPoly(.IEEE), | ||
| 55 | .name = "crc32-half-byte-lookup", | ||
| 56 | }, | ||
| 57 | Hash{ | ||
| 58 | .ty = hash.CityHash32, | ||
| 59 | .name = "cityhash-32", | ||
| 60 | .has_iterative_api = false, | ||
| 61 | }, | ||
| 62 | Hash{ | ||
| 63 | .ty = hash.CityHash64, | ||
| 64 | .name = "cityhash-64", | ||
| 65 | .has_iterative_api = false, | ||
| 66 | }, | ||
| 67 | Hash{ | ||
| 68 | .ty = hash.Murmur2_32, | ||
| 69 | .name = "murmur2-32", | ||
| 70 | .has_iterative_api = false, | ||
| 71 | }, | ||
| 72 | Hash{ | ||
| 73 | .ty = hash.Murmur2_64, | ||
| 74 | .name = "murmur2-64", | ||
| 75 | .has_iterative_api = false, | ||
| 76 | }, | ||
| 77 | Hash{ | ||
| 78 | .ty = hash.Murmur3_32, | ||
| 79 | .name = "murmur3-32", | ||
| 80 | .has_iterative_api = false, | ||
| 81 | }, | ||
| 82 | }; | ||
| 83 | |||
| 84 | const Result = struct { | ||
| 85 | hash: u64, | ||
| 86 | throughput: u64, | ||
| 87 | }; | ||
| 88 | |||
| 89 | const block_size: usize = 8192; | ||
| 90 | |||
| 91 | pub fn benchmarkHash(comptime H: var, bytes: usize) !Result { | ||
| 92 | var h = blk: { | ||
| 93 | if (H.init_u8s) |init| { | ||
| 94 | break :blk H.ty.init(init); | ||
| 95 | } | ||
| 96 | if (H.init_u64) |init| { | ||
| 97 | break :blk H.ty.init(init); | ||
| 98 | } | ||
| 99 | break :blk H.ty.init(); | ||
| 100 | }; | ||
| 101 | |||
| 102 | var block: [block_size]u8 = undefined; | ||
| 103 | prng.random.bytes(block[0..]); | ||
| 104 | |||
| 105 | var offset: usize = 0; | ||
| 106 | var timer = try Timer.start(); | ||
| 107 | const start = timer.lap(); | ||
| 108 | while (offset < bytes) : (offset += block.len) { | ||
| 109 | h.update(block[0..]); | ||
| 110 | } | ||
| 111 | const end = timer.read(); | ||
| 112 | |||
| 113 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 114 | const throughput = @floatToInt(u64, @intToFloat(f64, bytes) / elapsed_s); | ||
| 115 | |||
| 116 | return Result{ | ||
| 117 | .hash = h.final(), | ||
| 118 | .throughput = throughput, | ||
| 119 | }; | ||
| 120 | } | ||
| 121 | |||
| 122 | pub fn benchmarkHashSmallKeys(comptime H: var, key_size: usize, bytes: usize) !Result { | ||
| 123 | const key_count = bytes / key_size; | ||
| 124 | var block: [block_size]u8 = undefined; | ||
| 125 | prng.random.bytes(block[0..]); | ||
| 126 | |||
| 127 | var i: usize = 0; | ||
| 128 | var timer = try Timer.start(); | ||
| 129 | const start = timer.lap(); | ||
| 130 | |||
| 131 | var sum: u64 = 0; | ||
| 132 | while (i < key_count) : (i += 1) { | ||
| 133 | const small_key = block[0..key_size]; | ||
| 134 | sum +%= blk: { | ||
| 135 | if (H.init_u8s) |init| { | ||
| 136 | break :blk H.ty.hash(init, small_key); | ||
| 137 | } | ||
| 138 | if (H.init_u64) |init| { | ||
| 139 | break :blk H.ty.hash(init, small_key); | ||
| 140 | } | ||
| 141 | break :blk H.ty.hash(small_key); | ||
| 142 | }; | ||
| 143 | } | ||
| 144 | const end = timer.read(); | ||
| 145 | |||
| 146 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 147 | const throughput = @floatToInt(u64, @intToFloat(f64, bytes) / elapsed_s); | ||
| 148 | |||
| 149 | return Result{ | ||
| 150 | .hash = sum, | ||
| 151 | .throughput = throughput, | ||
| 152 | }; | ||
| 153 | } | ||
| 154 | |||
| 155 | fn usage() void { | ||
| 156 | std.debug.warn( | ||
| 157 | \\throughput_test [options] | ||
| 158 | \\ | ||
| 159 | \\Options: | ||
| 160 | \\ --filter [test-name] | ||
| 161 | \\ --seed [int] | ||
| 162 | \\ --count [int] | ||
| 163 | \\ --key-size [int] | ||
| 164 | \\ --iterative-only | ||
| 165 | \\ --help | ||
| 166 | \\ | ||
| 167 | ); | ||
| 168 | } | ||
| 169 | |||
| 170 | fn mode(comptime x: comptime_int) comptime_int { | ||
| 171 | return if (builtin.mode == builtin.Mode.Debug) x / 64 else x; | ||
| 172 | } | ||
| 173 | |||
| 174 | // TODO(#1358): Replace with builtin formatted padding when available. | ||
| 175 | fn printPad(stdout: var, s: []const u8) !void { | ||
| 176 | var i: usize = 0; | ||
| 177 | while (i < 12 - s.len) : (i += 1) { | ||
| 178 | try stdout.print(" "); | ||
| 179 | } | ||
| 180 | try stdout.print("{}", s); | ||
| 181 | } | ||
| 182 | |||
| 183 | pub fn main() !void { | ||
| 184 | var stdout_file = try std.io.getStdOut(); | ||
| 185 | var stdout_out_stream = stdout_file.outStream(); | ||
| 186 | const stdout = &stdout_out_stream.stream; | ||
| 187 | |||
| 188 | var buffer: [1024]u8 = undefined; | ||
| 189 | var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); | ||
| 190 | const args = try std.process.argsAlloc(&fixed.allocator); | ||
| 191 | |||
| 192 | var filter: ?[]u8 = ""; | ||
| 193 | var count: usize = mode(128 * MiB); | ||
| 194 | var key_size: usize = 32; | ||
| 195 | var seed: u32 = 0; | ||
| 196 | var test_iterative_only = false; | ||
| 197 | |||
| 198 | var i: usize = 1; | ||
| 199 | while (i < args.len) : (i += 1) { | ||
| 200 | if (std.mem.eql(u8, args[i], "--mode")) { | ||
| 201 | try stdout.print("{}\n", builtin.mode); | ||
| 202 | return; | ||
| 203 | } else if (std.mem.eql(u8, args[i], "--seed")) { | ||
| 204 | i += 1; | ||
| 205 | if (i == args.len) { | ||
| 206 | usage(); | ||
| 207 | std.os.exit(1); | ||
| 208 | } | ||
| 209 | |||
| 210 | seed = try std.fmt.parseUnsigned(u32, args[i], 10); | ||
| 211 | // we seed later | ||
| 212 | } else if (std.mem.eql(u8, args[i], "--filter")) { | ||
| 213 | i += 1; | ||
| 214 | if (i == args.len) { | ||
| 215 | usage(); | ||
| 216 | std.os.exit(1); | ||
| 217 | } | ||
| 218 | |||
| 219 | filter = args[i]; | ||
| 220 | } else if (std.mem.eql(u8, args[i], "--count")) { | ||
| 221 | i += 1; | ||
| 222 | if (i == args.len) { | ||
| 223 | usage(); | ||
| 224 | std.os.exit(1); | ||
| 225 | } | ||
| 226 | |||
| 227 | const c = try std.fmt.parseUnsigned(usize, args[i], 10); | ||
| 228 | count = c * MiB; | ||
| 229 | } else if (std.mem.eql(u8, args[i], "--key-size")) { | ||
| 230 | i += 1; | ||
| 231 | if (i == args.len) { | ||
| 232 | usage(); | ||
| 233 | std.os.exit(1); | ||
| 234 | } | ||
| 235 | |||
| 236 | key_size = try std.fmt.parseUnsigned(usize, args[i], 10); | ||
| 237 | if (key_size > block_size) { | ||
| 238 | try stdout.print("key_size cannot exceed block size of {}\n", block_size); | ||
| 239 | std.os.exit(1); | ||
| 240 | } | ||
| 241 | } else if (std.mem.eql(u8, args[i], "--iterative-only")) { | ||
| 242 | test_iterative_only = true; | ||
| 243 | } else if (std.mem.eql(u8, args[i], "--help")) { | ||
| 244 | usage(); | ||
| 245 | return; | ||
| 246 | } else { | ||
| 247 | usage(); | ||
| 248 | std.os.exit(1); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | inline for (hashes) |H| { | ||
| 253 | if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { | ||
| 254 | if (!test_iterative_only or H.has_iterative_api) { | ||
| 255 | try stdout.print("{}\n", H.name); | ||
| 256 | |||
| 257 | // Always reseed prior to every call so we are hashing the same buffer contents. | ||
| 258 | // This allows easier comparison between different implementations. | ||
| 259 | if (H.has_iterative_api) { | ||
| 260 | prng.seed(seed); | ||
| 261 | const result = try benchmarkHash(H, count); | ||
| 262 | try stdout.print(" iterative: {:4} MiB/s [{x:0<16}]\n", result.throughput / (1 * MiB), result.hash); | ||
| 263 | } | ||
| 264 | |||
| 265 | if (!test_iterative_only) { | ||
| 266 | prng.seed(seed); | ||
| 267 | const result_small = try benchmarkHashSmallKeys(H, key_size, count); | ||
| 268 | try stdout.print(" small keys: {:4} MiB/s [{x:0<16}]\n", result_small.throughput / (1 * MiB), result_small.hash); | ||
| 269 | } | ||
| 270 | } | ||
| 271 | } | ||
| 272 | } | ||
| 273 | } | ||
std/hash/crc.zig+13-13| ... | @@ -9,17 +9,17 @@ const std = @import("../std.zig"); | ... | @@ -9,17 +9,17 @@ const std = @import("../std.zig"); |
| 9 | const debug = std.debug; | 9 | const debug = std.debug; |
| 10 | const testing = std.testing; | 10 | const testing = std.testing; |
| 11 | 11 | ||
| 12 | pub const Polynomial = struct { | 12 | pub const Polynomial = enum(u32) { |
| 13 | const IEEE = 0xedb88320; | 13 | IEEE = 0xedb88320, |
| 14 | const Castagnoli = 0x82f63b78; | 14 | Castagnoli = 0x82f63b78, |
| 15 | const Koopman = 0xeb31d82e; | 15 | Koopman = 0xeb31d82e, |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | // IEEE is by far the most common CRC and so is aliased by default. | 18 | // IEEE is by far the most common CRC and so is aliased by default. |
| 19 | pub const Crc32 = Crc32WithPoly(Polynomial.IEEE); | 19 | pub const Crc32 = Crc32WithPoly(.IEEE); |
| 20 | 20 | ||
| 21 | // slicing-by-8 crc32 implementation. | 21 | // slicing-by-8 crc32 implementation. |
| 22 | pub fn Crc32WithPoly(comptime poly: u32) type { | 22 | pub fn Crc32WithPoly(comptime poly: Polynomial) type { |
| 23 | return struct { | 23 | return struct { |
| 24 | const Self = @This(); | 24 | const Self = @This(); |
| 25 | const lookup_tables = comptime block: { | 25 | const lookup_tables = comptime block: { |
| ... | @@ -31,7 +31,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { | ... | @@ -31,7 +31,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 31 | var j: usize = 0; | 31 | var j: usize = 0; |
| 32 | while (j < 8) : (j += 1) { | 32 | while (j < 8) : (j += 1) { |
| 33 | if (crc & 1 == 1) { | 33 | if (crc & 1 == 1) { |
| 34 | crc = (crc >> 1) ^ poly; | 34 | crc = (crc >> 1) ^ @enumToInt(poly); |
| 35 | } else { | 35 | } else { |
| 36 | crc = (crc >> 1); | 36 | crc = (crc >> 1); |
| 37 | } | 37 | } |
| ... | @@ -100,7 +100,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { | ... | @@ -100,7 +100,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | test "crc32 ieee" { | 102 | test "crc32 ieee" { |
| 103 | const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE); | 103 | const Crc32Ieee = Crc32WithPoly(.IEEE); |
| 104 | 104 | ||
| 105 | testing.expect(Crc32Ieee.hash("") == 0x00000000); | 105 | testing.expect(Crc32Ieee.hash("") == 0x00000000); |
| 106 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); | 106 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); |
| ... | @@ -108,7 +108,7 @@ test "crc32 ieee" { | ... | @@ -108,7 +108,7 @@ test "crc32 ieee" { |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | test "crc32 castagnoli" { | 110 | test "crc32 castagnoli" { |
| 111 | const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli); | 111 | const Crc32Castagnoli = Crc32WithPoly(.Castagnoli); |
| 112 | 112 | ||
| 113 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); | 113 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); |
| 114 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); | 114 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); |
| ... | @@ -116,7 +116,7 @@ test "crc32 castagnoli" { | ... | @@ -116,7 +116,7 @@ test "crc32 castagnoli" { |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | // half-byte lookup table implementation. | 118 | // half-byte lookup table implementation. |
| 119 | pub fn Crc32SmallWithPoly(comptime poly: u32) type { | 119 | pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type { |
| 120 | return struct { | 120 | return struct { |
| 121 | const Self = @This(); | 121 | const Self = @This(); |
| 122 | const lookup_table = comptime block: { | 122 | const lookup_table = comptime block: { |
| ... | @@ -127,7 +127,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { | ... | @@ -127,7 +127,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 127 | var j: usize = 0; | 127 | var j: usize = 0; |
| 128 | while (j < 8) : (j += 1) { | 128 | while (j < 8) : (j += 1) { |
| 129 | if (crc & 1 == 1) { | 129 | if (crc & 1 == 1) { |
| 130 | crc = (crc >> 1) ^ poly; | 130 | crc = (crc >> 1) ^ @enumToInt(poly); |
| 131 | } else { | 131 | } else { |
| 132 | crc = (crc >> 1); | 132 | crc = (crc >> 1); |
| 133 | } | 133 | } |
| ... | @@ -164,7 +164,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { | ... | @@ -164,7 +164,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | test "small crc32 ieee" { | 166 | test "small crc32 ieee" { |
| 167 | const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE); | 167 | const Crc32Ieee = Crc32SmallWithPoly(.IEEE); |
| 168 | 168 | ||
| 169 | testing.expect(Crc32Ieee.hash("") == 0x00000000); | 169 | testing.expect(Crc32Ieee.hash("") == 0x00000000); |
| 170 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); | 170 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); |
| ... | @@ -172,7 +172,7 @@ test "small crc32 ieee" { | ... | @@ -172,7 +172,7 @@ test "small crc32 ieee" { |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | test "small crc32 castagnoli" { | 174 | test "small crc32 castagnoli" { |
| 175 | const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli); | 175 | const Crc32Castagnoli = Crc32SmallWithPoly(.Castagnoli); |
| 176 | 176 | ||
| 177 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); | 177 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); |
| 178 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); | 178 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); |
std/hash/siphash.zig+2-2| ... | @@ -152,8 +152,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) | ... | @@ -152,8 +152,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) |
| 152 | 152 | ||
| 153 | pub fn hash(key: []const u8, input: []const u8) T { | 153 | pub fn hash(key: []const u8, input: []const u8) T { |
| 154 | var c = Self.init(key); | 154 | var c = Self.init(key); |
| 155 | c.update(input); | 155 | @inlineCall(c.update, input); |
| 156 | return c.final(); | 156 | return @inlineCall(c.final); |
| 157 | } | 157 | } |
| 158 | }; | 158 | }; |
| 159 | } | 159 | } |
std/hash/throughput_test.zig deleted-148| ... | @@ -1,148 +0,0 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const time = std.time; | ||
| 4 | const Timer = time.Timer; | ||
| 5 | const hash = std.hash; | ||
| 6 | |||
| 7 | const KiB = 1024; | ||
| 8 | const MiB = 1024 * KiB; | ||
| 9 | const GiB = 1024 * MiB; | ||
| 10 | |||
| 11 | var prng = std.rand.DefaultPrng.init(0); | ||
| 12 | |||
| 13 | const Hash = struct { | ||
| 14 | ty: type, | ||
| 15 | name: []const u8, | ||
| 16 | init_u8s: ?[]const u8 = null, | ||
| 17 | init_u64: ?u64 = null, | ||
| 18 | }; | ||
| 19 | |||
| 20 | const siphash_key = "0123456789abcdef"; | ||
| 21 | |||
| 22 | const hashes = [_]Hash{ | ||
| 23 | Hash{ .ty = hash.Wyhash, .name = "wyhash", .init_u64 = 0 }, | ||
| 24 | Hash{ .ty = hash.SipHash64(1, 3), .name = "siphash(1,3)", .init_u8s = siphash_key }, | ||
| 25 | Hash{ .ty = hash.SipHash64(2, 4), .name = "siphash(2,4)", .init_u8s = siphash_key }, | ||
| 26 | Hash{ .ty = hash.Fnv1a_64, .name = "fnv1a" }, | ||
| 27 | Hash{ .ty = hash.Crc32, .name = "crc32" }, | ||
| 28 | }; | ||
| 29 | |||
| 30 | const Result = struct { | ||
| 31 | hash: u64, | ||
| 32 | throughput: u64, | ||
| 33 | }; | ||
| 34 | |||
| 35 | pub fn benchmarkHash(comptime H: var, bytes: usize) !Result { | ||
| 36 | var h = blk: { | ||
| 37 | if (H.init_u8s) |init| { | ||
| 38 | break :blk H.ty.init(init); | ||
| 39 | } | ||
| 40 | if (H.init_u64) |init| { | ||
| 41 | break :blk H.ty.init(init); | ||
| 42 | } | ||
| 43 | break :blk H.ty.init(); | ||
| 44 | }; | ||
| 45 | |||
| 46 | var block: [8192]u8 = undefined; | ||
| 47 | prng.random.bytes(block[0..]); | ||
| 48 | |||
| 49 | var offset: usize = 0; | ||
| 50 | var timer = try Timer.start(); | ||
| 51 | const start = timer.lap(); | ||
| 52 | while (offset < bytes) : (offset += block.len) { | ||
| 53 | h.update(block[0..]); | ||
| 54 | } | ||
| 55 | const end = timer.read(); | ||
| 56 | |||
| 57 | const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s; | ||
| 58 | const throughput = @floatToInt(u64, @intToFloat(f64, bytes) / elapsed_s); | ||
| 59 | |||
| 60 | return Result{ | ||
| 61 | .hash = h.final(), | ||
| 62 | .throughput = throughput, | ||
| 63 | }; | ||
| 64 | } | ||
| 65 | |||
| 66 | fn usage() void { | ||
| 67 | std.debug.warn( | ||
| 68 | \\throughput_test [options] | ||
| 69 | \\ | ||
| 70 | \\Options: | ||
| 71 | \\ --filter [test-name] | ||
| 72 | \\ --seed [int] | ||
| 73 | \\ --count [int] | ||
| 74 | \\ --help | ||
| 75 | \\ | ||
| 76 | ); | ||
| 77 | } | ||
| 78 | |||
| 79 | fn mode(comptime x: comptime_int) comptime_int { | ||
| 80 | return if (builtin.mode == builtin.Mode.Debug) x / 64 else x; | ||
| 81 | } | ||
| 82 | |||
| 83 | // TODO(#1358): Replace with builtin formatted padding when available. | ||
| 84 | fn printPad(stdout: var, s: []const u8) !void { | ||
| 85 | var i: usize = 0; | ||
| 86 | while (i < 12 - s.len) : (i += 1) { | ||
| 87 | try stdout.print(" "); | ||
| 88 | } | ||
| 89 | try stdout.print("{}", s); | ||
| 90 | } | ||
| 91 | |||
| 92 | pub fn main() !void { | ||
| 93 | var stdout_file = try std.io.getStdOut(); | ||
| 94 | var stdout_out_stream = stdout_file.outStream(); | ||
| 95 | const stdout = &stdout_out_stream.stream; | ||
| 96 | |||
| 97 | var buffer: [1024]u8 = undefined; | ||
| 98 | var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); | ||
| 99 | const args = try std.process.argsAlloc(&fixed.allocator); | ||
| 100 | |||
| 101 | var filter: ?[]u8 = ""; | ||
| 102 | var count: usize = mode(128 * MiB); | ||
| 103 | |||
| 104 | var i: usize = 1; | ||
| 105 | while (i < args.len) : (i += 1) { | ||
| 106 | if (std.mem.eql(u8, args[i], "--seed")) { | ||
| 107 | i += 1; | ||
| 108 | if (i == args.len) { | ||
| 109 | usage(); | ||
| 110 | std.os.exit(1); | ||
| 111 | } | ||
| 112 | |||
| 113 | const seed = try std.fmt.parseUnsigned(u32, args[i], 10); | ||
| 114 | prng.seed(seed); | ||
| 115 | } else if (std.mem.eql(u8, args[i], "--filter")) { | ||
| 116 | i += 1; | ||
| 117 | if (i == args.len) { | ||
| 118 | usage(); | ||
| 119 | std.os.exit(1); | ||
| 120 | } | ||
| 121 | |||
| 122 | filter = args[i]; | ||
| 123 | } else if (std.mem.eql(u8, args[i], "--count")) { | ||
| 124 | i += 1; | ||
| 125 | if (i == args.len) { | ||
| 126 | usage(); | ||
| 127 | std.os.exit(1); | ||
| 128 | } | ||
| 129 | |||
| 130 | const c = try std.fmt.parseUnsigned(u32, args[i], 10); | ||
| 131 | count = c * MiB; | ||
| 132 | } else if (std.mem.eql(u8, args[i], "--help")) { | ||
| 133 | usage(); | ||
| 134 | return; | ||
| 135 | } else { | ||
| 136 | usage(); | ||
| 137 | std.os.exit(1); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | inline for (hashes) |H| { | ||
| 142 | if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) { | ||
| 143 | const result = try benchmarkHash(H, count); | ||
| 144 | try printPad(stdout, H.name); | ||
| 145 | try stdout.print(": {:4} MiB/s [{:16}]\n", result.throughput / (1 * MiB), result.hash); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | } | ||
std/hash/wyhash.zig+2-2| ... | @@ -116,8 +116,8 @@ pub const Wyhash = struct { | ... | @@ -116,8 +116,8 @@ pub const Wyhash = struct { |
| 116 | 116 | ||
| 117 | pub fn hash(seed: u64, input: []const u8) u64 { | 117 | pub fn hash(seed: u64, input: []const u8) u64 { |
| 118 | var c = Wyhash.init(seed); | 118 | var c = Wyhash.init(seed); |
| 119 | c.update(input); | 119 | @inlineCall(c.update, input); |
| 120 | return c.final(); | 120 | return @inlineCall(c.final); |
| 121 | } | 121 | } |
| 122 | }; | 122 | }; |
| 123 | 123 |
std/os/windows.zig+3-4| ... | @@ -65,7 +65,7 @@ pub const CreateFileError = error{ | ... | @@ -65,7 +65,7 @@ pub const CreateFileError = error{ |
| 65 | InvalidUtf8, | 65 | InvalidUtf8, |
| 66 | 66 | ||
| 67 | /// On Windows, file paths cannot contain these characters: | 67 | /// On Windows, file paths cannot contain these characters: |
| 68 | /// '/', '*', '?', '"', '<', '>', '|' | 68 | /// '*', '?', '"', '<', '>', '|', and '/' (when the ABI is not GNU) |
| 69 | BadPathName, | 69 | BadPathName, |
| 70 | 70 | ||
| 71 | Unexpected, | 71 | Unexpected, |
| ... | @@ -836,11 +836,10 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) | ... | @@ -836,11 +836,10 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) |
| 836 | // > converting the name to an NT-style name, except when using the "\\?\" | 836 | // > converting the name to an NT-style name, except when using the "\\?\" |
| 837 | // > prefix as detailed in the following sections. | 837 | // > prefix as detailed in the following sections. |
| 838 | // from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation | 838 | // from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation |
| 839 | // Because we want the larger maximum path length for absolute paths, we | ||
| 840 | // disallow forward slashes in zig std lib file functions on Windows. | ||
| 841 | for (s) |byte| { | 839 | for (s) |byte| { |
| 842 | switch (byte) { | 840 | switch (byte) { |
| 843 | '/', '*', '?', '"', '<', '>', '|' => return error.BadPathName, | 841 | '*', '?', '"', '<', '>', '|' => return error.BadPathName, |
| 842 | '/' => if (builtin.abi == .msvc) return error.BadPathName, | ||
| 844 | else => {}, | 843 | else => {}, |
| 845 | } | 844 | } |
| 846 | } | 845 | } |
std/zig/ast.zig+1| ... | @@ -761,6 +761,7 @@ pub const Node = struct { | ... | @@ -761,6 +761,7 @@ pub const Node = struct { |
| 761 | name_token: TokenIndex, | 761 | name_token: TokenIndex, |
| 762 | type_expr: ?*Node, | 762 | type_expr: ?*Node, |
| 763 | value_expr: ?*Node, | 763 | value_expr: ?*Node, |
| 764 | align_expr: ?*Node, | ||
| 764 | 765 | ||
| 765 | pub fn iterate(self: *ContainerField, index: usize) ?*Node { | 766 | pub fn iterate(self: *ContainerField, index: usize) ?*Node { |
| 766 | var i = index; | 767 | var i = index; |
std/zig/parse.zig+9-6| ... | @@ -380,16 +380,18 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | ... | @@ -380,16 +380,18 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 380 | return &node.base; | 380 | return &node.base; |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | /// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? | 383 | /// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? |
| 384 | fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | 384 | fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 385 | const name_token = eatToken(it, .Identifier) orelse return null; | 385 | const name_token = eatToken(it, .Identifier) orelse return null; |
| 386 | 386 | ||
| 387 | const type_expr = if (eatToken(it, .Colon)) |_| | 387 | var align_expr: ?*Node = null; |
| 388 | try expectNode(arena, it, tree, parseTypeExpr, AstError{ | 388 | var type_expr: ?*Node = null; |
| 389 | if (eatToken(it, .Colon)) |_| { | ||
| 390 | type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{ | ||
| 389 | .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index }, | 391 | .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index }, |
| 390 | }) | 392 | }); |
| 391 | else | 393 | align_expr = try parseByteAlign(arena, it, tree); |
| 392 | null; | 394 | } |
| 393 | 395 | ||
| 394 | const value_expr = if (eatToken(it, .Equal)) |_| | 396 | const value_expr = if (eatToken(it, .Equal)) |_| |
| 395 | try expectNode(arena, it, tree, parseExpr, AstError{ | 397 | try expectNode(arena, it, tree, parseExpr, AstError{ |
| ... | @@ -406,6 +408,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No | ... | @@ -406,6 +408,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No |
| 406 | .name_token = name_token, | 408 | .name_token = name_token, |
| 407 | .type_expr = type_expr, | 409 | .type_expr = type_expr, |
| 408 | .value_expr = value_expr, | 410 | .value_expr = value_expr, |
| 411 | .align_expr = align_expr, | ||
| 409 | }; | 412 | }; |
| 410 | return &node.base; | 413 | return &node.base; |
| 411 | } | 414 | } |
std/zig/parser_test.zig+9| ... | @@ -166,6 +166,15 @@ test "zig fmt: doc comments on param decl" { | ... | @@ -166,6 +166,15 @@ test "zig fmt: doc comments on param decl" { |
| 166 | ); | 166 | ); |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | test "zig fmt: aligned struct field" { | ||
| 170 | try testCanonical( | ||
| 171 | \\pub const S = struct { | ||
| 172 | \\ f: i32 align(32), | ||
| 173 | \\}; | ||
| 174 | \\ | ||
| 175 | ); | ||
| 176 | } | ||
| 177 | |||
| 169 | test "zig fmt: preserve space between async fn definitions" { | 178 | test "zig fmt: preserve space between async fn definitions" { |
| 170 | try testCanonical( | 179 | try testCanonical( |
| 171 | \\async fn a() void {} | 180 | \\async fn a() void {} |
std/zig/render.zig+14-1| ... | @@ -206,7 +206,20 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i | ... | @@ -206,7 +206,20 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i |
| 206 | } else if (field.type_expr != null and field.value_expr == null) { | 206 | } else if (field.type_expr != null and field.value_expr == null) { |
| 207 | try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name | 207 | try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name |
| 208 | try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // : | 208 | try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // : |
| 209 | return renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type, | 209 | |
| 210 | if (field.align_expr) |align_value_expr| { | ||
| 211 | try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type | ||
| 212 | const lparen_token = tree.prevToken(align_value_expr.firstToken()); | ||
| 213 | const align_kw = tree.prevToken(lparen_token); | ||
| 214 | const rparen_token = tree.nextToken(align_value_expr.lastToken()); | ||
| 215 | try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align | ||
| 216 | try renderToken(tree, stream, lparen_token, indent, start_col, Space.None); // ( | ||
| 217 | try renderExpression(allocator, stream, tree, indent, start_col, align_value_expr, Space.None); // alignment | ||
| 218 | try renderToken(tree, stream, rparen_token, indent, start_col, Space.Comma); // ) | ||
| 219 | } else { | ||
| 220 | try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type, | ||
| 221 | } | ||
| 222 | |||
| 210 | } else if (field.type_expr == null and field.value_expr != null) { | 223 | } else if (field.type_expr == null and field.value_expr != null) { |
| 211 | try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name | 224 | try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name |
| 212 | try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // = | 225 | try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // = |