| 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 | 895 | Buf *name; |
| 896 | 896 | AstNode *type; |
| 897 | 897 | AstNode *value; |
| 898 | // populated if the "align(A)" is present | |
| 899 | AstNode *align_expr; | |
| 898 | 900 | }; |
| 899 | 901 | |
| 900 | 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 | 1147 | if (type_is_invalid(align_result->type)) |
| 1148 | 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 | 1151 | if (align_bytes == 0) { |
| 1152 | 1152 | add_node_error(g, node, buf_sprintf("alignment must be >= 1")); |
| 1153 | 1153 | return false; |
| ... | ... | @@ -1179,7 +1179,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** |
| 1179 | 1179 | return true; |
| 1180 | 1180 | } |
| 1181 | 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 | 1183 | Buf *result = buf_alloc(); |
| 1184 | 1184 | buf_resize(result, len); |
| 1185 | 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 | 1189 | add_node_error(g, node, buf_sprintf("use of undefined value")); |
| 1190 | 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 | 1193 | assert(big_c <= UINT8_MAX); |
| 1194 | 1194 | uint8_t c = (uint8_t)big_c; |
| 1195 | 1195 | buf_ptr(result)[i] = c; |
| ... | ... | @@ -2384,19 +2384,25 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2384 | 2384 | if (field->gen_index == SIZE_MAX) |
| 2385 | 2385 | continue; |
| 2386 | 2386 | |
| 2387 | // TODO: https://github.com/ziglang/zig/issues/1512 | |
| 2388 | size_t this_field_align; | |
| 2389 | if (packed) { | |
| 2390 | this_field_align = 1; | |
| 2387 | AstNode *align_expr = field->decl_node->data.struct_field.align_expr; | |
| 2388 | if (align_expr != nullptr) { | |
| 2389 | if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr, | |
| 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 | 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 | 2399 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2394 | 2400 | return err; |
| 2395 | 2401 | } |
| 2396 | 2402 | } |
| 2397 | 2403 | |
| 2398 | if (this_field_align > struct_type->abi_align) { | |
| 2399 | struct_type->abi_align = this_field_align; | |
| 2404 | if (field->align > struct_type->abi_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 | 6014 | { |
| 6009 | 6015 | if (is_slice(type_entry)) { |
| 6010 | 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 | 6019 | ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index]; |
| 6014 | 6020 | if (ptr_val->special == ConstValSpecialUndef) { |
src/bigint.cpp+22-1| ... | ... | @@ -15,6 +15,8 @@ |
| 15 | 15 | #include <limits> |
| 16 | 16 | #include <algorithm> |
| 17 | 17 | |
| 18 | static uint64_t bigint_as_unsigned(const BigInt *bigint); | |
| 19 | ||
| 18 | 20 | static void bigint_normalize(BigInt *dest) { |
| 19 | 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 | 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 | 1666 | assert(!bigint->is_negative); |
| 1665 | 1667 | if (bigint->digit_count == 0) { |
| 1666 | 1668 | return 0; |
| ... | ... | @@ -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 | 1695 | int64_t bigint_as_signed(const BigInt *bigint) { |
| 1675 | 1696 | if (bigint->digit_count == 0) { |
| 1676 | 1697 | return 0; |
src/bigint.hpp+4-1| ... | ... | @@ -36,7 +36,10 @@ void bigint_init_bigfloat(BigInt *dest, const BigFloat *op); |
| 36 | 36 | void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative); |
| 37 | 37 | |
| 38 | 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 | 43 | int64_t bigint_as_signed(const BigInt *bigint); |
| 41 | 44 | |
| 42 | 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 | 2872 | eval_min_max_value_int(g, int_type, &biggest_possible_err_val, true); |
| 2873 | 2873 | |
| 2874 | 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 | 2877 | ok_bit = neq_zero_bit; |
| 2878 | 2878 | } else { |
src/ir.cpp+24-24| ... | ... | @@ -5768,7 +5768,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode |
| 5768 | 5768 | buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); |
| 5769 | 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 | 5774 | uint32_t host_int_bytes = 0; |
| ... | ... | @@ -5780,7 +5780,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode |
| 5780 | 5780 | buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf))); |
| 5781 | 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 | 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 | 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 | 11593 | result->value.data.x_err_set = ira->codegen->errors_by_index.at(index); |
| 11594 | 11594 | return result; |
| 11595 | 11595 | } else { |
| ... | ... | @@ -12554,7 +12554,7 @@ static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode |
| 12554 | 12554 | if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad))) |
| 12555 | 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 | 12558 | if (align_bytes == 0) { |
| 12559 | 12559 | exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1")); |
| 12560 | 12560 | return false; |
| ... | ... | @@ -12594,7 +12594,7 @@ static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *i |
| 12594 | 12594 | if (!const_val) |
| 12595 | 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 | 12598 | return true; |
| 12599 | 12599 | } |
| 12600 | 12600 | |
| ... | ... | @@ -12642,7 +12642,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic |
| 12642 | 12642 | if (!const_val) |
| 12643 | 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 | 12646 | return true; |
| 12647 | 12647 | } |
| 12648 | 12648 | |
| ... | ... | @@ -12662,7 +12662,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi |
| 12662 | 12662 | if (!const_val) |
| 12663 | 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 | 12666 | return true; |
| 12667 | 12667 | } |
| 12668 | 12668 | |
| ... | ... | @@ -12682,7 +12682,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob |
| 12682 | 12682 | if (!const_val) |
| 12683 | 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 | 12686 | return true; |
| 12687 | 12687 | } |
| 12688 | 12688 | |
| ... | ... | @@ -12702,7 +12702,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod |
| 12702 | 12702 | if (!const_val) |
| 12703 | 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 | 12706 | return true; |
| 12707 | 12707 | } |
| 12708 | 12708 | |
| ... | ... | @@ -12731,7 +12731,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| 12731 | 12731 | return array_val->data.x_array.data.s_buf; |
| 12732 | 12732 | } |
| 12733 | 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 | 12735 | Buf *result = buf_alloc(); |
| 12736 | 12736 | buf_resize(result, len); |
| 12737 | 12737 | for (size_t i = 0; i < len; i += 1) { |
| ... | ... | @@ -12741,7 +12741,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| 12741 | 12741 | ir_add_error(ira, casted_value, buf_sprintf("use of undefined value")); |
| 12742 | 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 | 12745 | assert(big_c <= UINT8_MAX); |
| 12746 | 12746 | uint8_t c = (uint8_t)big_c; |
| 12747 | 12747 | buf_ptr(result)[i] = c; |
| ... | ... | @@ -13891,7 +13891,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i |
| 13891 | 13891 | op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val; |
| 13892 | 13892 | op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; |
| 13893 | 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 | 13895 | } else { |
| 13896 | 13896 | ir_add_error(ira, op1, |
| 13897 | 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 | 13924 | op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val; |
| 13925 | 13925 | op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; |
| 13926 | 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 | 13928 | } else { |
| 13929 | 13929 | ir_add_error(ira, op2, |
| 13930 | 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 | 16803 | uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); |
| 16804 | 16804 | uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); |
| 16805 | 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 | 16807 | if (array_type->id == ZigTypeIdArray) { |
| 16808 | 16808 | uint64_t array_len = array_type->data.array.len; |
| 16809 | 16809 | if (index >= array_len) { |
| ... | ... | @@ -16965,7 +16965,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 16965 | 16965 | ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index]; |
| 16966 | 16966 | IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); |
| 16967 | 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 | 16969 | if (index >= slice_len) { |
| 16970 | 16970 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| 16971 | 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 | 21250 | |
| 21251 | 21251 | ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index]; |
| 21252 | 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 | 21254 | have_known_len = true; |
| 21255 | 21255 | } |
| 21256 | 21256 | } |
| ... | ... | @@ -21607,7 +21607,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio |
| 21607 | 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 | 21611 | size_t end = start + count; |
| 21612 | 21612 | if (end > bound_end) { |
| 21613 | 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 | 21704 | return ira->codegen->invalid_instruction; |
| 21705 | 21705 | |
| 21706 | 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 | 21709 | ConstExprValue *dest_elements; |
| 21710 | 21710 | size_t dest_start; |
| ... | ... | @@ -21988,7 +21988,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 21988 | 21988 | case ConstPtrSpecialBaseArray: |
| 21989 | 21989 | array_val = parent_ptr->data.x_ptr.data.base_array.array_val; |
| 21990 | 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 | 21992 | break; |
| 21993 | 21993 | case ConstPtrSpecialBaseStruct: |
| 21994 | 21994 | zig_panic("TODO slice const inner struct"); |
| ... | ... | @@ -22001,7 +22001,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 22001 | 22001 | case ConstPtrSpecialHardCodedAddr: |
| 22002 | 22002 | array_val = nullptr; |
| 22003 | 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 | 22005 | break; |
| 22006 | 22006 | case ConstPtrSpecialFunction: |
| 22007 | 22007 | zig_panic("TODO slice of slice cast from function"); |
| ... | ... | @@ -22012,7 +22012,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 22012 | 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 | 22016 | if (!ptr_is_undef && start_scalar > rel_end) { |
| 22017 | 22017 | ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice")); |
| 22018 | 22018 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -22020,7 +22020,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 22020 | 22020 | |
| 22021 | 22021 | uint64_t end_scalar; |
| 22022 | 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 | 22024 | } else { |
| 22025 | 22025 | end_scalar = rel_end; |
| 22026 | 22026 | } |
| ... | ... | @@ -23622,7 +23622,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 23622 | 23622 | BigInt bn; |
| 23623 | 23623 | bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, |
| 23624 | 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 | 23626 | return ErrorNone; |
| 23627 | 23627 | } |
| 23628 | 23628 | case ZigTypeIdArray: |
| ... | ... | @@ -23815,7 +23815,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc |
| 23815 | 23815 | if (!val) |
| 23816 | 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 | 23819 | if (!ptr_allows_addr_zero(ptr_type) && addr == 0) { |
| 23820 | 23820 | ir_add_error(ira, source_instr, |
| 23821 | 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 | 1125 | #endif |
| 1126 | 1126 | } |
| 1127 | 1127 | |
| 1128 | #if defined(ZIG_OS_WINDOWS) | |
| 1129 | 1128 | #define is_wprefix(s, prefix) \ |
| 1130 | 1129 | (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0) |
| 1131 | static bool is_stderr_cyg_pty(void) { | |
| 1132 | HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE); | |
| 1133 | if (stderr_handle == INVALID_HANDLE_VALUE) | |
| 1130 | bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd) { | |
| 1131 | #if defined(ZIG_OS_WINDOWS) | |
| 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 | 1136 | return false; |
| 1137 | } | |
| 1135 | 1138 | |
| 1136 | 1139 | int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH; |
| 1137 | FILE_NAME_INFO *nameinfo; | |
| 1138 | 1140 | WCHAR *p = NULL; |
| 1139 | 1141 | |
| 1140 | // Cygwin/msys's pty is a pipe. | |
| 1141 | if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) { | |
| 1142 | return 0; | |
| 1143 | } | |
| 1144 | nameinfo = (FILE_NAME_INFO *)allocate<char>(size); | |
| 1142 | FILE_NAME_INFO *nameinfo = (FILE_NAME_INFO *)allocate<char>(size); | |
| 1145 | 1143 | if (nameinfo == NULL) { |
| 1146 | return 0; | |
| 1144 | return false; | |
| 1147 | 1145 | } |
| 1148 | 1146 | // Check the name of the pipe: |
| 1149 | 1147 | // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master' |
| 1150 | if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) { | |
| 1148 | if (GetFileInformationByHandleEx(handle, FileNameInfo, nameinfo, size)) { | |
| 1151 | 1149 | nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0'; |
| 1152 | 1150 | p = nameinfo->FileName; |
| 1153 | 1151 | if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */ |
| ... | ... | @@ -1180,12 +1178,14 @@ static bool is_stderr_cyg_pty(void) { |
| 1180 | 1178 | } |
| 1181 | 1179 | free(nameinfo); |
| 1182 | 1180 | return (p != NULL); |
| 1183 | } | |
| 1181 | #else | |
| 1182 | return false; | |
| 1184 | 1183 | #endif |
| 1184 | } | |
| 1185 | 1185 | |
| 1186 | 1186 | bool os_stderr_tty(void) { |
| 1187 | 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 | 1189 | #elif defined(ZIG_OS_POSIX) |
| 1190 | 1190 | return isatty(STDERR_FILENO) != 0; |
| 1191 | 1191 | #else |
| ... | ... | @@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL |
| 1486 | 1486 | |
| 1487 | 1487 | void os_stderr_set_color(TermColor color) { |
| 1488 | 1488 | #if defined(ZIG_OS_WINDOWS) |
| 1489 | if (is_stderr_cyg_pty()) { | |
| 1489 | if (os_stderr_tty()) { | |
| 1490 | 1490 | set_color_posix(color); |
| 1491 | 1491 | return; |
| 1492 | 1492 | } |
src/os.hpp+8| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | #include "list.hpp" |
| 12 | 12 | #include "buffer.hpp" |
| 13 | 13 | #include "error.hpp" |
| 14 | #include "target.hpp" | |
| 14 | 15 | #include "zig_llvm.h" |
| 15 | 16 | #include "windows_sdk.h" |
| 16 | 17 | |
| ... | ... | @@ -88,6 +89,11 @@ struct Termination { |
| 88 | 89 | #define OsFile int |
| 89 | 90 | #endif |
| 90 | 91 | |
| 92 | #if defined(ZIG_OS_WINDOWS) | |
| 93 | #undef fileno | |
| 94 | #define fileno _fileno | |
| 95 | #endif | |
| 96 | ||
| 91 | 97 | struct OsTimeStamp { |
| 92 | 98 | uint64_t sec; |
| 93 | 99 | uint64_t nsec; |
| ... | ... | @@ -152,6 +158,8 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf |
| 152 | 158 | Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); |
| 153 | 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 | 163 | Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths); |
| 156 | 164 | |
| 157 | 165 | #endif |
src/parser.cpp+5-3| ... | ... | @@ -782,24 +782,26 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 782 | 782 | return res; |
| 783 | 783 | } |
| 784 | 784 | |
| 785 | // ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? | |
| 785 | // ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? | |
| 786 | 786 | static AstNode *ast_parse_container_field(ParseContext *pc) { |
| 787 | 787 | Token *identifier = eat_token_if(pc, TokenIdSymbol); |
| 788 | 788 | if (identifier == nullptr) |
| 789 | 789 | return nullptr; |
| 790 | 790 | |
| 791 | 791 | AstNode *type_expr = nullptr; |
| 792 | if (eat_token_if(pc, TokenIdColon) != nullptr) | |
| 792 | if (eat_token_if(pc, TokenIdColon) != nullptr) { | |
| 793 | 793 | type_expr = ast_expect(pc, ast_parse_type_expr); |
| 794 | } | |
| 795 | AstNode *align_expr = ast_parse_byte_align(pc); | |
| 794 | 796 | AstNode *expr = nullptr; |
| 795 | 797 | if (eat_token_if(pc, TokenIdEq) != nullptr) |
| 796 | 798 | expr = ast_expect(pc, ast_parse_expr); |
| 797 | 799 | |
| 798 | ||
| 799 | 800 | AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier); |
| 800 | 801 | res->data.struct_field.name = token_buf(identifier); |
| 801 | 802 | res->data.struct_field.type = type_expr; |
| 802 | 803 | res->data.struct_field.value = expr; |
| 804 | res->data.struct_field.align_expr = align_expr; | |
| 803 | 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 | 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 | 504 | void get_native_target(ZigTarget *target) { |
| 495 | 505 | // first zero initialize |
| 496 | 506 | *target = {}; |
| ... | ... | @@ -505,6 +515,9 @@ void get_native_target(ZigTarget *target) { |
| 505 | 515 | &target->abi, |
| 506 | 516 | &oformat); |
| 507 | 517 | target->os = get_zig_os_type(os_type); |
| 518 | if (target->os == OsWindows) { | |
| 519 | target->abi = target_get_win32_abi(); | |
| 520 | } | |
| 508 | 521 | target->is_native = true; |
| 509 | 522 | if (target->abi == ZigLLVM_UnknownEnvironment) { |
| 510 | 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 | 1614 | return ZigLLVM_GNU; |
| 1602 | 1615 | case OsUefi: |
| 1603 | 1616 | case OsWindows: |
| 1604 | return ZigLLVM_MSVC; | |
| 1617 | return ZigLLVM_MSVC; | |
| 1605 | 1618 | case OsLinux: |
| 1606 | 1619 | case OsWASI: |
| 1607 | 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 | 269 | fn Blake2b(comptime out_len: usize) type { |
| 270 | 270 | return struct { |
| 271 | 271 | const Self = @This(); |
| 272 | const block_length = 128; | |
| 273 | const digest_length = out_len / 8; | |
| 272 | pub const block_length = 128; | |
| 273 | pub const digest_length = out_len / 8; | |
| 274 | 274 | |
| 275 | 275 | const iv = [8]u64{ |
| 276 | 276 | 0x6a09e667f3bcc908, |
std/crypto/sha2.zig+2-2| ... | ... | @@ -420,8 +420,8 @@ pub const Sha512 = Sha2_64(Sha512Params); |
| 420 | 420 | fn Sha2_64(comptime params: Sha2Params64) type { |
| 421 | 421 | return struct { |
| 422 | 422 | const Self = @This(); |
| 423 | const block_length = 128; | |
| 424 | const digest_length = params.out_len / 8; | |
| 423 | pub const block_length = 128; | |
| 424 | pub const digest_length = params.out_len / 8; | |
| 425 | 425 | |
| 426 | 426 | s: [8]u64, |
| 427 | 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 | 9 | const debug = std.debug; |
| 10 | 10 | const testing = std.testing; |
| 11 | 11 | |
| 12 | pub const Polynomial = struct { | |
| 13 | const IEEE = 0xedb88320; | |
| 14 | const Castagnoli = 0x82f63b78; | |
| 15 | const Koopman = 0xeb31d82e; | |
| 12 | pub const Polynomial = enum(u32) { | |
| 13 | IEEE = 0xedb88320, | |
| 14 | Castagnoli = 0x82f63b78, | |
| 15 | Koopman = 0xeb31d82e, | |
| 16 | 16 | }; |
| 17 | 17 | |
| 18 | 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 | 21 | // slicing-by-8 crc32 implementation. |
| 22 | pub fn Crc32WithPoly(comptime poly: u32) type { | |
| 22 | pub fn Crc32WithPoly(comptime poly: Polynomial) type { | |
| 23 | 23 | return struct { |
| 24 | 24 | const Self = @This(); |
| 25 | 25 | const lookup_tables = comptime block: { |
| ... | ... | @@ -31,7 +31,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 31 | 31 | var j: usize = 0; |
| 32 | 32 | while (j < 8) : (j += 1) { |
| 33 | 33 | if (crc & 1 == 1) { |
| 34 | crc = (crc >> 1) ^ poly; | |
| 34 | crc = (crc >> 1) ^ @enumToInt(poly); | |
| 35 | 35 | } else { |
| 36 | 36 | crc = (crc >> 1); |
| 37 | 37 | } |
| ... | ... | @@ -100,7 +100,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | 102 | test "crc32 ieee" { |
| 103 | const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE); | |
| 103 | const Crc32Ieee = Crc32WithPoly(.IEEE); | |
| 104 | 104 | |
| 105 | 105 | testing.expect(Crc32Ieee.hash("") == 0x00000000); |
| 106 | 106 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); |
| ... | ... | @@ -108,7 +108,7 @@ test "crc32 ieee" { |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | 110 | test "crc32 castagnoli" { |
| 111 | const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli); | |
| 111 | const Crc32Castagnoli = Crc32WithPoly(.Castagnoli); | |
| 112 | 112 | |
| 113 | 113 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); |
| 114 | 114 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); |
| ... | ... | @@ -116,7 +116,7 @@ test "crc32 castagnoli" { |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | // half-byte lookup table implementation. |
| 119 | pub fn Crc32SmallWithPoly(comptime poly: u32) type { | |
| 119 | pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type { | |
| 120 | 120 | return struct { |
| 121 | 121 | const Self = @This(); |
| 122 | 122 | const lookup_table = comptime block: { |
| ... | ... | @@ -127,7 +127,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 127 | 127 | var j: usize = 0; |
| 128 | 128 | while (j < 8) : (j += 1) { |
| 129 | 129 | if (crc & 1 == 1) { |
| 130 | crc = (crc >> 1) ^ poly; | |
| 130 | crc = (crc >> 1) ^ @enumToInt(poly); | |
| 131 | 131 | } else { |
| 132 | 132 | crc = (crc >> 1); |
| 133 | 133 | } |
| ... | ... | @@ -164,7 +164,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | 166 | test "small crc32 ieee" { |
| 167 | const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE); | |
| 167 | const Crc32Ieee = Crc32SmallWithPoly(.IEEE); | |
| 168 | 168 | |
| 169 | 169 | testing.expect(Crc32Ieee.hash("") == 0x00000000); |
| 170 | 170 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); |
| ... | ... | @@ -172,7 +172,7 @@ test "small crc32 ieee" { |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | 174 | test "small crc32 castagnoli" { |
| 175 | const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli); | |
| 175 | const Crc32Castagnoli = Crc32SmallWithPoly(.Castagnoli); | |
| 176 | 176 | |
| 177 | 177 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); |
| 178 | 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 | 152 | |
| 153 | 153 | pub fn hash(key: []const u8, input: []const u8) T { |
| 154 | 154 | var c = Self.init(key); |
| 155 | c.update(input); | |
| 156 | return c.final(); | |
| 155 | @inlineCall(c.update, input); | |
| 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 | 116 | |
| 117 | 117 | pub fn hash(seed: u64, input: []const u8) u64 { |
| 118 | 118 | var c = Wyhash.init(seed); |
| 119 | c.update(input); | |
| 120 | return c.final(); | |
| 119 | @inlineCall(c.update, input); | |
| 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 | 65 | InvalidUtf8, |
| 66 | 66 | |
| 67 | 67 | /// On Windows, file paths cannot contain these characters: |
| 68 | /// '/', '*', '?', '"', '<', '>', '|' | |
| 68 | /// '*', '?', '"', '<', '>', '|', and '/' (when the ABI is not GNU) | |
| 69 | 69 | BadPathName, |
| 70 | 70 | |
| 71 | 71 | Unexpected, |
| ... | ... | @@ -836,11 +836,10 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) |
| 836 | 836 | // > converting the name to an NT-style name, except when using the "\\?\" |
| 837 | 837 | // > prefix as detailed in the following sections. |
| 838 | 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 | 839 | for (s) |byte| { |
| 842 | 840 | switch (byte) { |
| 843 | '/', '*', '?', '"', '<', '>', '|' => return error.BadPathName, | |
| 841 | '*', '?', '"', '<', '>', '|' => return error.BadPathName, | |
| 842 | '/' => if (builtin.abi == .msvc) return error.BadPathName, | |
| 844 | 843 | else => {}, |
| 845 | 844 | } |
| 846 | 845 | } |
std/zig/ast.zig+1| ... | ... | @@ -761,6 +761,7 @@ pub const Node = struct { |
| 761 | 761 | name_token: TokenIndex, |
| 762 | 762 | type_expr: ?*Node, |
| 763 | 763 | value_expr: ?*Node, |
| 764 | align_expr: ?*Node, | |
| 764 | 765 | |
| 765 | 766 | pub fn iterate(self: *ContainerField, index: usize) ?*Node { |
| 766 | 767 | var i = index; |
std/zig/parse.zig+9-6| ... | ... | @@ -380,16 +380,18 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 380 | 380 | return &node.base; |
| 381 | 381 | } |
| 382 | 382 | |
| 383 | /// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? | |
| 383 | /// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? | |
| 384 | 384 | fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 385 | 385 | const name_token = eatToken(it, .Identifier) orelse return null; |
| 386 | 386 | |
| 387 | const type_expr = if (eatToken(it, .Colon)) |_| | |
| 388 | try expectNode(arena, it, tree, parseTypeExpr, AstError{ | |
| 387 | var align_expr: ?*Node = null; | |
| 388 | var type_expr: ?*Node = null; | |
| 389 | if (eatToken(it, .Colon)) |_| { | |
| 390 | type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{ | |
| 389 | 391 | .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index }, |
| 390 | }) | |
| 391 | else | |
| 392 | null; | |
| 392 | }); | |
| 393 | align_expr = try parseByteAlign(arena, it, tree); | |
| 394 | } | |
| 393 | 395 | |
| 394 | 396 | const value_expr = if (eatToken(it, .Equal)) |_| |
| 395 | 397 | try expectNode(arena, it, tree, parseExpr, AstError{ |
| ... | ... | @@ -406,6 +408,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No |
| 406 | 408 | .name_token = name_token, |
| 407 | 409 | .type_expr = type_expr, |
| 408 | 410 | .value_expr = value_expr, |
| 411 | .align_expr = align_expr, | |
| 409 | 412 | }; |
| 410 | 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 | 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 | 178 | test "zig fmt: preserve space between async fn definitions" { |
| 170 | 179 | try testCanonical( |
| 171 | 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 | 206 | } else if (field.type_expr != null and field.value_expr == null) { |
| 207 | 207 | try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name |
| 208 | 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 | 223 | } else if (field.type_expr == null and field.value_expr != null) { |
| 211 | 224 | try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name |
| 212 | 225 | try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // = |