authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-23 11:43:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-23 11:43:37-04:00
log3865b6ad8f8ba71dca06c81828ec2e29f3019879
treecfadbebe532708c931bddcc8e5b262d63946c78d
parent79a4b7a2365dc50d01eb6bc29bbb77244a1620cf
parentec2f9ef4e8be5995ab652dde59b12ee340a9e28d
signaturelock-open Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into fix-field-alignment-kludge


24 files changed, 640 insertions(+), 430 deletions(-)

src/all_types.hpp+2
......@@ -895,6 +895,8 @@ struct AstNodeStructField {
895895 Buf *name;
896896 AstNode *type;
897897 AstNode *value;
898 // populated if the "align(A)" is present
899 AstNode *align_expr;
898900};
899901
900902struct AstNodeStringLiteral {
src/analyze.cpp+17-11
......@@ -1147,7 +1147,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_
11471147 if (type_is_invalid(align_result->type))
11481148 return false;
11491149
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);
11511151 if (align_bytes == 0) {
11521152 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
11531153 return false;
......@@ -1179,7 +1179,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
11791179 return true;
11801180 }
11811181 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);
11831183 Buf *result = buf_alloc();
11841184 buf_resize(result, len);
11851185 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 **
11891189 add_node_error(g, node, buf_sprintf("use of undefined value"));
11901190 return false;
11911191 }
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);
11931193 assert(big_c <= UINT8_MAX);
11941194 uint8_t c = (uint8_t)big_c;
11951195 buf_ptr(result)[i] = c;
......@@ -2384,19 +2384,25 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
23842384 if (field->gen_index == SIZE_MAX)
23852385 continue;
23862386
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;
23912397 } 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))) {
23932399 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
23942400 return err;
23952401 }
23962402 }
23972403
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;
24002406 }
24012407 }
24022408
......@@ -6008,7 +6014,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
60086014 {
60096015 if (is_slice(type_entry)) {
60106016 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);
60126018
60136019 ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index];
60146020 if (ptr_val->special == ConstValSpecialUndef) {
src/bigint.cpp+22-1
......@@ -15,6 +15,8 @@
1515#include <limits>
1616#include <algorithm>
1717
18static uint64_t bigint_as_unsigned(const BigInt *bigint);
19
1820static void bigint_normalize(BigInt *dest) {
1921 const uint64_t *digits = bigint_ptr(dest);
2022
......@@ -1660,7 +1662,7 @@ size_t bigint_clz(const BigInt *bi, size_t bit_count) {
16601662 return count;
16611663}
16621664
1663uint64_t bigint_as_unsigned(const BigInt *bigint) {
1665static uint64_t bigint_as_unsigned(const BigInt *bigint) {
16641666 assert(!bigint->is_negative);
16651667 if (bigint->digit_count == 0) {
16661668 return 0;
......@@ -1671,6 +1673,25 @@ uint64_t bigint_as_unsigned(const BigInt *bigint) {
16711673 }
16721674}
16731675
1676uint64_t bigint_as_u64(const BigInt *bigint)
1677{
1678 return bigint_as_unsigned(bigint);
1679}
1680
1681uint32_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
1688size_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
16741695int64_t bigint_as_signed(const BigInt *bigint) {
16751696 if (bigint->digit_count == 0) {
16761697 return 0;
src/bigint.hpp+4-1
......@@ -36,7 +36,10 @@ void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
3636void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative);
3737
3838// panics if number won't fit
39uint64_t bigint_as_unsigned(const BigInt *bigint);
39uint64_t bigint_as_u64(const BigInt *bigint);
40uint32_t bigint_as_u32(const BigInt *bigint);
41size_t bigint_as_usize(const BigInt *bigint);
42
4043int64_t bigint_as_signed(const BigInt *bigint);
4144
4245static 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
28722872 eval_min_max_value_int(g, int_type, &biggest_possible_err_val, true);
28732873
28742874 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)
28762876 {
28772877 ok_bit = neq_zero_bit;
28782878 } else {
src/ir.cpp+24-24
......@@ -5768,7 +5768,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
57685768 buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf)));
57695769 return irb->codegen->invalid_instruction;
57705770 }
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);
57725772 }
57735773
57745774 uint32_t host_int_bytes = 0;
......@@ -5780,7 +5780,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
57805780 buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf)));
57815781 return irb->codegen->invalid_instruction;
57825782 }
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);
57845784 }
57855785
57865786 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
1158911589 return ira->codegen->invalid_instruction;
1159011590 }
1159111591
11592 size_t index = bigint_as_unsigned(&val->data.x_bigint);
11592 size_t index = bigint_as_usize(&val->data.x_bigint);
1159311593 result->value.data.x_err_set = ira->codegen->errors_by_index.at(index);
1159411594 return result;
1159511595 } else {
......@@ -12554,7 +12554,7 @@ static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode
1255412554 if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad)))
1255512555 return false;
1255612556
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);
1255812558 if (align_bytes == 0) {
1255912559 exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1"));
1256012560 return false;
......@@ -12594,7 +12594,7 @@ static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *i
1259412594 if (!const_val)
1259512595 return false;
1259612596
12597 *out = bigint_as_unsigned(&const_val->data.x_bigint);
12597 *out = bigint_as_u64(&const_val->data.x_bigint);
1259812598 return true;
1259912599}
1260012600
......@@ -12642,7 +12642,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
1264212642 if (!const_val)
1264312643 return false;
1264412644
12645 *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum_tag);
12645 *out = (AtomicOrder)bigint_as_u32(&const_val->data.x_enum_tag);
1264612646 return true;
1264712647}
1264812648
......@@ -12662,7 +12662,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi
1266212662 if (!const_val)
1266312663 return false;
1266412664
12665 *out = (AtomicRmwOp)bigint_as_unsigned(&const_val->data.x_enum_tag);
12665 *out = (AtomicRmwOp)bigint_as_u32(&const_val->data.x_enum_tag);
1266612666 return true;
1266712667}
1266812668
......@@ -12682,7 +12682,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob
1268212682 if (!const_val)
1268312683 return false;
1268412684
12685 *out = (GlobalLinkageId)bigint_as_unsigned(&const_val->data.x_enum_tag);
12685 *out = (GlobalLinkageId)bigint_as_u32(&const_val->data.x_enum_tag);
1268612686 return true;
1268712687}
1268812688
......@@ -12702,7 +12702,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod
1270212702 if (!const_val)
1270312703 return false;
1270412704
12705 *out = (FloatMode)bigint_as_unsigned(&const_val->data.x_enum_tag);
12705 *out = (FloatMode)bigint_as_u32(&const_val->data.x_enum_tag);
1270612706 return true;
1270712707}
1270812708
......@@ -12731,7 +12731,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
1273112731 return array_val->data.x_array.data.s_buf;
1273212732 }
1273312733 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);
1273512735 Buf *result = buf_alloc();
1273612736 buf_resize(result, len);
1273712737 for (size_t i = 0; i < len; i += 1) {
......@@ -12741,7 +12741,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
1274112741 ir_add_error(ira, casted_value, buf_sprintf("use of undefined value"));
1274212742 return nullptr;
1274312743 }
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);
1274512745 assert(big_c <= UINT8_MAX);
1274612746 uint8_t c = (uint8_t)big_c;
1274712747 buf_ptr(result)[i] = c;
......@@ -13891,7 +13891,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1389113891 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1389213892 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
1389313893 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);
1389513895 } else {
1389613896 ir_add_error(ira, op1,
1389713897 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
1392413924 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1392513925 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
1392613926 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);
1392813928 } else {
1392913929 ir_add_error(ira, op2,
1393013930 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
1680316803 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
1680416804 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
1680516805 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);
1680716807 if (array_type->id == ZigTypeIdArray) {
1680816808 uint64_t array_len = array_type->data.array.len;
1680916809 if (index >= array_len) {
......@@ -16965,7 +16965,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1696516965 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
1696616966 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
1696716967 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);
1696916969 if (index >= slice_len) {
1697016970 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
1697116971 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
2125021250
2125121251 ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index];
2125221252 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);
2125421254 have_known_len = true;
2125521255 }
2125621256 }
......@@ -21607,7 +21607,7 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
2160721607 zig_panic("TODO memset on null ptr");
2160821608 }
2160921609
21610 size_t count = bigint_as_unsigned(&count_val->data.x_bigint);
21610 size_t count = bigint_as_usize(&count_val->data.x_bigint);
2161121611 size_t end = start + count;
2161221612 if (end > bound_end) {
2161321613 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
2170421704 return ira->codegen->invalid_instruction;
2170521705
2170621706 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);
2170821708
2170921709 ConstExprValue *dest_elements;
2171021710 size_t dest_start;
......@@ -21988,7 +21988,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2198821988 case ConstPtrSpecialBaseArray:
2198921989 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
2199021990 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);
2199221992 break;
2199321993 case ConstPtrSpecialBaseStruct:
2199421994 zig_panic("TODO slice const inner struct");
......@@ -22001,7 +22001,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2200122001 case ConstPtrSpecialHardCodedAddr:
2200222002 array_val = nullptr;
2200322003 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);
2200522005 break;
2200622006 case ConstPtrSpecialFunction:
2200722007 zig_panic("TODO slice of slice cast from function");
......@@ -22012,7 +22012,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2201222012 zig_unreachable();
2201322013 }
2201422014
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);
2201622016 if (!ptr_is_undef && start_scalar > rel_end) {
2201722017 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
2201822018 return ira->codegen->invalid_instruction;
......@@ -22020,7 +22020,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2202022020
2202122021 uint64_t end_scalar;
2202222022 if (end) {
22023 end_scalar = bigint_as_unsigned(&end->value.data.x_bigint);
22023 end_scalar = bigint_as_u64(&end->value.data.x_bigint);
2202422024 } else {
2202522025 end_scalar = rel_end;
2202622026 }
......@@ -23622,7 +23622,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2362223622 BigInt bn;
2362323623 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
2362423624 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);
2362623626 return ErrorNone;
2362723627 }
2362823628 case ZigTypeIdArray:
......@@ -23815,7 +23815,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
2381523815 if (!val)
2381623816 return ira->codegen->invalid_instruction;
2381723817
23818 uint64_t addr = bigint_as_unsigned(&val->data.x_bigint);
23818 uint64_t addr = bigint_as_u64(&val->data.x_bigint);
2381923819 if (!ptr_allows_addr_zero(ptr_type) && addr == 0) {
2382023820 ir_add_error(ira, source_instr,
2382123821 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) {
11251125#endif
11261126}
11271127
1128#if defined(ZIG_OS_WINDOWS)
11291128#define is_wprefix(s, prefix) \
11301129 (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
1131static bool is_stderr_cyg_pty(void) {
1132 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
1133 if (stderr_handle == INVALID_HANDLE_VALUE)
1130bool 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) {
11341136 return false;
1137 }
11351138
11361139 int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;
1137 FILE_NAME_INFO *nameinfo;
11381140 WCHAR *p = NULL;
11391141
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);
11451143 if (nameinfo == NULL) {
1146 return 0;
1144 return false;
11471145 }
11481146 // Check the name of the pipe:
11491147 // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'
1150 if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) {
1148 if (GetFileInformationByHandleEx(handle, FileNameInfo, nameinfo, size)) {
11511149 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
11521150 p = nameinfo->FileName;
11531151 if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
......@@ -1180,12 +1178,14 @@ static bool is_stderr_cyg_pty(void) {
11801178 }
11811179 free(nameinfo);
11821180 return (p != NULL);
1183}
1181#else
1182 return false;
11841183#endif
1184}
11851185
11861186bool os_stderr_tty(void) {
11871187#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));
11891189#elif defined(ZIG_OS_POSIX)
11901190 return isatty(STDERR_FILENO) != 0;
11911191#else
......@@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL
14861486
14871487void os_stderr_set_color(TermColor color) {
14881488#if defined(ZIG_OS_WINDOWS)
1489 if (is_stderr_cyg_pty()) {
1489 if (os_stderr_tty()) {
14901490 set_color_posix(color);
14911491 return;
14921492 }
src/os.hpp+8
......@@ -11,6 +11,7 @@
1111#include "list.hpp"
1212#include "buffer.hpp"
1313#include "error.hpp"
14#include "target.hpp"
1415#include "zig_llvm.h"
1516#include "windows_sdk.h"
1617
......@@ -88,6 +89,11 @@ struct Termination {
8889#define OsFile int
8990#endif
9091
92#if defined(ZIG_OS_WINDOWS)
93#undef fileno
94#define fileno _fileno
95#endif
96
9197struct OsTimeStamp {
9298 uint64_t sec;
9399 uint64_t nsec;
......@@ -152,6 +158,8 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf
152158Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
153159Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
154160
161bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd);
162
155163Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
156164
157165#endif
src/parser.cpp+5-3
......@@ -782,24 +782,26 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
782782 return res;
783783}
784784
785// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
785// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
786786static AstNode *ast_parse_container_field(ParseContext *pc) {
787787 Token *identifier = eat_token_if(pc, TokenIdSymbol);
788788 if (identifier == nullptr)
789789 return nullptr;
790790
791791 AstNode *type_expr = nullptr;
792 if (eat_token_if(pc, TokenIdColon) != nullptr)
792 if (eat_token_if(pc, TokenIdColon) != nullptr) {
793793 type_expr = ast_expect(pc, ast_parse_type_expr);
794 }
795 AstNode *align_expr = ast_parse_byte_align(pc);
794796 AstNode *expr = nullptr;
795797 if (eat_token_if(pc, TokenIdEq) != nullptr)
796798 expr = ast_expect(pc, ast_parse_expr);
797799
798
799800 AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier);
800801 res->data.struct_field.name = token_buf(identifier);
801802 res->data.struct_field.type = type_expr;
802803 res->data.struct_field.value = expr;
804 res->data.struct_field.align_expr = align_expr;
803805 return res;
804806}
805807
src/target.cpp+14-1
......@@ -491,6 +491,16 @@ Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) {
491491 return ErrorNone;
492492}
493493
494static 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
494504void get_native_target(ZigTarget *target) {
495505 // first zero initialize
496506 *target = {};
......@@ -505,6 +515,9 @@ void get_native_target(ZigTarget *target) {
505515 &target->abi,
506516 &oformat);
507517 target->os = get_zig_os_type(os_type);
518 if (target->os == OsWindows) {
519 target->abi = target_get_win32_abi();
520 }
508521 target->is_native = true;
509522 if (target->abi == ZigLLVM_UnknownEnvironment) {
510523 target->abi = target_default_abi(target->arch, target->os);
......@@ -1601,7 +1614,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
16011614 return ZigLLVM_GNU;
16021615 case OsUefi:
16031616 case OsWindows:
1604 return ZigLLVM_MSVC;
1617 return ZigLLVM_MSVC;
16051618 case OsLinux:
16061619 case OsWASI:
16071620 return ZigLLVM_Musl;
std/crypto/benchmark.zig created+198
......@@ -0,0 +1,198 @@
1// zig run benchmark.zig --release-fast --override-std-dir ..
2
3const builtin = @import("builtin");
4const std = @import("../std.zig");
5const time = std.time;
6const Timer = time.Timer;
7const crypto = std.crypto;
8
9const KiB = 1024;
10const MiB = 1024 * KiB;
11
12var prng = std.rand.DefaultPrng.init(0);
13
14const Crypto = struct {
15 ty: type,
16 name: []const u8,
17};
18
19const 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
30pub 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
50const 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
57pub 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
80const exchanges = [_]Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }};
81
82pub 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
108fn 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
120fn 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.
125fn 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
133pub 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);
269269fn Blake2b(comptime out_len: usize) type {
270270 return struct {
271271 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;
274274
275275 const iv = [8]u64{
276276 0x6a09e667f3bcc908,
std/crypto/sha2.zig+2-2
......@@ -420,8 +420,8 @@ pub const Sha512 = Sha2_64(Sha512Params);
420420fn Sha2_64(comptime params: Sha2Params64) type {
421421 return struct {
422422 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;
425425
426426 s: [8]u64,
427427 // Streaming Cache
std/crypto/throughput_test.zig deleted-193
......@@ -1,193 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const time = std.time;
4const Timer = time.Timer;
5const crypto = @import("../crypto.zig");
6
7const KiB = 1024;
8const MiB = 1024 * KiB;
9
10var prng = std.rand.DefaultPrng.init(0);
11
12const Crypto = struct {
13 ty: type,
14 name: []const u8,
15};
16
17const 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
28pub 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
48const 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
55pub 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
78const exchanges = []Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }};
79
80pub 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
106fn 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
118fn 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.
123fn 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
131pub 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
3const builtin = @import("builtin");
4const std = @import("std");
5const time = std.time;
6const Timer = time.Timer;
7const hash = std.hash;
8
9const KiB = 1024;
10const MiB = 1024 * KiB;
11const GiB = 1024 * MiB;
12
13var prng = std.rand.DefaultPrng.init(0);
14
15const 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
23const siphash_key = "0123456789abcdef";
24
25const 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
84const Result = struct {
85 hash: u64,
86 throughput: u64,
87};
88
89const block_size: usize = 8192;
90
91pub 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
122pub 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
155fn 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
170fn 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.
175fn 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
183pub 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");
99const debug = std.debug;
1010const testing = std.testing;
1111
12pub const Polynomial = struct {
13 const IEEE = 0xedb88320;
14 const Castagnoli = 0x82f63b78;
15 const Koopman = 0xeb31d82e;
12pub const Polynomial = enum(u32) {
13 IEEE = 0xedb88320,
14 Castagnoli = 0x82f63b78,
15 Koopman = 0xeb31d82e,
1616};
1717
1818// IEEE is by far the most common CRC and so is aliased by default.
19pub const Crc32 = Crc32WithPoly(Polynomial.IEEE);
19pub const Crc32 = Crc32WithPoly(.IEEE);
2020
2121// slicing-by-8 crc32 implementation.
22pub fn Crc32WithPoly(comptime poly: u32) type {
22pub fn Crc32WithPoly(comptime poly: Polynomial) type {
2323 return struct {
2424 const Self = @This();
2525 const lookup_tables = comptime block: {
......@@ -31,7 +31,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
3131 var j: usize = 0;
3232 while (j < 8) : (j += 1) {
3333 if (crc & 1 == 1) {
34 crc = (crc >> 1) ^ poly;
34 crc = (crc >> 1) ^ @enumToInt(poly);
3535 } else {
3636 crc = (crc >> 1);
3737 }
......@@ -100,7 +100,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
100100}
101101
102102test "crc32 ieee" {
103 const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);
103 const Crc32Ieee = Crc32WithPoly(.IEEE);
104104
105105 testing.expect(Crc32Ieee.hash("") == 0x00000000);
106106 testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
......@@ -108,7 +108,7 @@ test "crc32 ieee" {
108108}
109109
110110test "crc32 castagnoli" {
111 const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);
111 const Crc32Castagnoli = Crc32WithPoly(.Castagnoli);
112112
113113 testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
114114 testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
......@@ -116,7 +116,7 @@ test "crc32 castagnoli" {
116116}
117117
118118// half-byte lookup table implementation.
119pub fn Crc32SmallWithPoly(comptime poly: u32) type {
119pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type {
120120 return struct {
121121 const Self = @This();
122122 const lookup_table = comptime block: {
......@@ -127,7 +127,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
127127 var j: usize = 0;
128128 while (j < 8) : (j += 1) {
129129 if (crc & 1 == 1) {
130 crc = (crc >> 1) ^ poly;
130 crc = (crc >> 1) ^ @enumToInt(poly);
131131 } else {
132132 crc = (crc >> 1);
133133 }
......@@ -164,7 +164,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
164164}
165165
166166test "small crc32 ieee" {
167 const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);
167 const Crc32Ieee = Crc32SmallWithPoly(.IEEE);
168168
169169 testing.expect(Crc32Ieee.hash("") == 0x00000000);
170170 testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
......@@ -172,7 +172,7 @@ test "small crc32 ieee" {
172172}
173173
174174test "small crc32 castagnoli" {
175 const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);
175 const Crc32Castagnoli = Crc32SmallWithPoly(.Castagnoli);
176176
177177 testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
178178 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)
152152
153153 pub fn hash(key: []const u8, input: []const u8) T {
154154 var c = Self.init(key);
155 c.update(input);
156 return c.final();
155 @inlineCall(c.update, input);
156 return @inlineCall(c.final);
157157 }
158158 };
159159}
std/hash/throughput_test.zig deleted-148
......@@ -1,148 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const time = std.time;
4const Timer = time.Timer;
5const hash = std.hash;
6
7const KiB = 1024;
8const MiB = 1024 * KiB;
9const GiB = 1024 * MiB;
10
11var prng = std.rand.DefaultPrng.init(0);
12
13const Hash = struct {
14 ty: type,
15 name: []const u8,
16 init_u8s: ?[]const u8 = null,
17 init_u64: ?u64 = null,
18};
19
20const siphash_key = "0123456789abcdef";
21
22const 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
30const Result = struct {
31 hash: u64,
32 throughput: u64,
33};
34
35pub 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
66fn 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
79fn 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.
84fn 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
92pub 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 {
116116
117117 pub fn hash(seed: u64, input: []const u8) u64 {
118118 var c = Wyhash.init(seed);
119 c.update(input);
120 return c.final();
119 @inlineCall(c.update, input);
120 return @inlineCall(c.final);
121121 }
122122};
123123
std/os/windows.zig+3-4
......@@ -65,7 +65,7 @@ pub const CreateFileError = error{
6565 InvalidUtf8,
6666
6767 /// On Windows, file paths cannot contain these characters:
68 /// '/', '*', '?', '"', '<', '>', '|'
68 /// '*', '?', '"', '<', '>', '|', and '/' (when the ABI is not GNU)
6969 BadPathName,
7070
7171 Unexpected,
......@@ -836,11 +836,10 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
836836 // > converting the name to an NT-style name, except when using the "\\?\"
837837 // > prefix as detailed in the following sections.
838838 // 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.
841839 for (s) |byte| {
842840 switch (byte) {
843 '/', '*', '?', '"', '<', '>', '|' => return error.BadPathName,
841 '*', '?', '"', '<', '>', '|' => return error.BadPathName,
842 '/' => if (builtin.abi == .msvc) return error.BadPathName,
844843 else => {},
845844 }
846845 }
std/zig/ast.zig+1
......@@ -761,6 +761,7 @@ pub const Node = struct {
761761 name_token: TokenIndex,
762762 type_expr: ?*Node,
763763 value_expr: ?*Node,
764 align_expr: ?*Node,
764765
765766 pub fn iterate(self: *ContainerField, index: usize) ?*Node {
766767 var i = index;
std/zig/parse.zig+9-6
......@@ -380,16 +380,18 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
380380 return &node.base;
381381}
382382
383/// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
383/// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
384384fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
385385 const name_token = eatToken(it, .Identifier) orelse return null;
386386
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{
389391 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
390 })
391 else
392 null;
392 });
393 align_expr = try parseByteAlign(arena, it, tree);
394 }
393395
394396 const value_expr = if (eatToken(it, .Equal)) |_|
395397 try expectNode(arena, it, tree, parseExpr, AstError{
......@@ -406,6 +408,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
406408 .name_token = name_token,
407409 .type_expr = type_expr,
408410 .value_expr = value_expr,
411 .align_expr = align_expr,
409412 };
410413 return &node.base;
411414}
std/zig/parser_test.zig+9
......@@ -166,6 +166,15 @@ test "zig fmt: doc comments on param decl" {
166166 );
167167}
168168
169test "zig fmt: aligned struct field" {
170 try testCanonical(
171 \\pub const S = struct {
172 \\ f: i32 align(32),
173 \\};
174 \\
175 );
176}
177
169178test "zig fmt: preserve space between async fn definitions" {
170179 try testCanonical(
171180 \\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
206206 } else if (field.type_expr != null and field.value_expr == null) {
207207 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
208208 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
210223 } else if (field.type_expr == null and field.value_expr != null) {
211224 try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name
212225 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =