authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-19 17:09:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-19 17:09:18-07:00
log6926e6e705b7d1c0a69ec20b6b0e1ea280f036d1
treebccebf1e310cc17a63318f1906f996143fc2c0e7
parent87d5db057b53fc643ac0c316653a46ada54b3c91
parentdf10e998ee4a935f49943fb5c0ef134f336c6ee3

Merge remote-tracking branch 'origin/master' into llvm13


10 files changed, 208 insertions(+), 27 deletions(-)

lib/std/fmt.zig+7
......@@ -544,6 +544,13 @@ pub fn formatType(
544544 return formatText(value, actual_fmt, options, writer);
545545 }
546546 }
547 if (comptime std.meta.trait.isZigString(info.child)) {
548 for (value) |item, i| {
549 if (i != 0) try formatText(", ", actual_fmt, options, writer);
550 try formatText(item, actual_fmt, options, writer);
551 }
552 return;
553 }
547554 @compileError("Unknown format string: '" ++ actual_fmt ++ "' for type '" ++ @typeName(T) ++ "'");
548555 },
549556 .Enum, .Union, .Struct => {
lib/std/rand.zig+30
......@@ -47,6 +47,19 @@ pub const Random = struct {
4747 return r.int(u1) != 0;
4848 }
4949
50 /// Returns a random value from an enum, evenly distributed.
51 pub fn enumValue(r: *Random, comptime EnumType: type) EnumType {
52 if (comptime !std.meta.trait.is(.Enum)(EnumType)) {
53 @compileError("Random.enumValue requires an enum type, not a " ++ @typeName(EnumType));
54 }
55
56 // We won't use int -> enum casting because enum elements can have
57 // arbitrary values. Instead we'll randomly pick one of the type's values.
58 const values = std.enums.values(EnumType);
59 const index = r.uintLessThan(usize, values.len);
60 return values[index];
61 }
62
5063 /// Returns a random int `i` such that `0 <= i <= maxInt(T)`.
5164 /// `i` is evenly distributed.
5265 pub fn int(r: *Random, comptime T: type) T {
......@@ -377,6 +390,23 @@ fn testRandomBoolean() !void {
377390 try expect(r.random.boolean() == true);
378391}
379392
393test "Random enum" {
394 try testRandomEnumValue();
395 comptime try testRandomEnumValue();
396}
397fn testRandomEnumValue() !void {
398 const TestEnum = enum {
399 First,
400 Second,
401 Third,
402 };
403 var r = SequentialPrng.init();
404 r.next_value = 0;
405 try expect(r.random.enumValue(TestEnum) == TestEnum.First);
406 try expect(r.random.enumValue(TestEnum) == TestEnum.First);
407 try expect(r.random.enumValue(TestEnum) == TestEnum.First);
408}
409
380410test "Random intLessThan" {
381411 @setEvalBranchQuota(10000);
382412 try testRandomIntLessThan();
src/Sema.zig+1-1
......@@ -8323,7 +8323,7 @@ fn coerceNum(
83238323 return sema.mod.fail(&block.base, inst_src, "TODO float to int", .{});
83248324 } else if (src_zig_tag == .Int or src_zig_tag == .ComptimeInt) {
83258325 if (!val.intFitsInType(dest_type, target)) {
8326 return sema.mod.fail(&block.base, inst_src, "type {} cannot represent integer value {}", .{ inst_ty, val });
8326 return sema.mod.fail(&block.base, inst_src, "type {} cannot represent integer value {}", .{ dest_type, val });
83278327 }
83288328 return try sema.addConstant(dest_type, val);
83298329 }
src/codegen.zig+2
......@@ -1247,6 +1247,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
12471247 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
12481248 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
12491249 .arm, .armeb => try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_and),
1250 .x86_64 => try self.genX8664BinMath(inst, bin_op.lhs, bin_op.rhs),
12501251 else => return self.fail("TODO implement bitwise and for {}", .{self.target.cpu.arch}),
12511252 };
12521253 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -1256,6 +1257,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
12561257 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
12571258 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
12581259 .arm, .armeb => try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_or),
1260 .x86_64 => try self.genX8664BinMath(inst, bin_op.lhs, bin_op.rhs),
12591261 else => return self.fail("TODO implement bitwise or for {}", .{self.target.cpu.arch}),
12601262 };
12611263 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
src/link/MachO.zig+23-14
......@@ -54,6 +54,11 @@ d_sym: ?DebugSymbols = null,
5454/// For x86_64 that's 4KB, whereas for aarch64, that's 16KB.
5555page_size: u16,
5656
57/// TODO Should we figure out embedding code signatures for other Apple platforms as part of the linker?
58/// Or should this be a separate tool?
59/// https://github.com/ziglang/zig/issues/9567
60requires_adhoc_codesig: bool,
61
5762/// We commit 0x1000 = 4096 bytes of space to the header and
5863/// the table of load commands. This should be plenty for any
5964/// potential future extensions.
......@@ -391,6 +396,13 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
391396
392397pub fn createEmpty(gpa: *Allocator, options: link.Options) !*MachO {
393398 const self = try gpa.create(MachO);
399 const cpu_arch = options.target.cpu.arch;
400 const os_tag = options.target.os.tag;
401 const abi = options.target.abi;
402 const page_size: u16 = if (cpu_arch == .aarch64) 0x4000 else 0x1000;
403 // Adhoc code signature is required when targeting aarch64-macos either directly or indirectly via the simulator
404 // ABI such as aarch64-ios-simulator, etc.
405 const requires_adhoc_codesig = cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator);
394406
395407 self.* = .{
396408 .base = .{
......@@ -399,7 +411,8 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*MachO {
399411 .allocator = gpa,
400412 .file = null,
401413 },
402 .page_size = if (options.target.cpu.arch == .aarch64) 0x4000 else 0x1000,
414 .page_size = page_size,
415 .requires_adhoc_codesig = requires_adhoc_codesig,
403416 };
404417
405418 return self;
......@@ -433,7 +446,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
433446 defer tracy.end();
434447
435448 const output_mode = self.base.options.output_mode;
436 const target = self.base.options.target;
437449
438450 switch (output_mode) {
439451 .Exe => {
......@@ -459,7 +471,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
459471 try ds.flushModule(self.base.allocator, self.base.options);
460472 }
461473
462 if (target.cpu.arch == .aarch64) {
474 if (self.requires_adhoc_codesig) {
463475 // Preallocate space for the code signature.
464476 // We need to do this at this stage so that we have the load commands with proper values
465477 // written out to the file.
......@@ -492,11 +504,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
492504 assert(!self.strtab_dirty);
493505 assert(!self.strtab_needs_relocation);
494506
495 if (target.cpu.arch == .aarch64) {
496 switch (output_mode) {
497 .Exe, .Lib => try self.writeCodeSignature(), // code signing always comes last
498 else => {},
499 }
507 if (self.requires_adhoc_codesig) {
508 try self.writeCodeSignature(); // code signing always comes last
500509 }
501510}
502511
......@@ -2841,7 +2850,7 @@ fn addDataInCodeLC(self: *MachO) !void {
28412850}
28422851
28432852fn addCodeSignatureLC(self: *MachO) !void {
2844 if (self.code_signature_cmd_index == null and self.base.options.target.cpu.arch == .aarch64) {
2853 if (self.code_signature_cmd_index == null and self.requires_adhoc_codesig) {
28452854 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);
28462855 try self.load_commands.append(self.base.allocator, .{
28472856 .LinkeditData = .{
......@@ -2935,14 +2944,14 @@ fn flushZld(self: *MachO) !void {
29352944 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size);
29362945 }
29372946
2938 if (self.base.options.target.cpu.arch == .aarch64) {
2947 if (self.requires_adhoc_codesig) {
29392948 try self.writeCodeSignaturePadding();
29402949 }
29412950
29422951 try self.writeLoadCommands();
29432952 try self.writeHeader();
29442953
2945 if (self.base.options.target.cpu.arch == .aarch64) {
2954 if (self.requires_adhoc_codesig) {
29462955 try self.writeCodeSignature();
29472956 }
29482957}
......@@ -4454,7 +4463,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
44544463 try self.load_commands.append(self.base.allocator, .{ .Uuid = uuid_cmd });
44554464 self.load_commands_dirty = true;
44564465 }
4457 if (self.code_signature_cmd_index == null) {
4466 if (self.code_signature_cmd_index == null and self.requires_adhoc_codesig) {
44584467 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);
44594468 try self.load_commands.append(self.base.allocator, .{
44604469 .LinkeditData = .{
......@@ -5719,8 +5728,8 @@ fn writeStringTableZld(self: *MachO) !void {
57195728
57205729 try self.base.file.?.pwriteAll(self.strtab.items, symtab.stroff);
57215730
5722 if (symtab.strsize > self.strtab.items.len and self.base.options.target.cpu.arch == .x86_64) {
5723 // This is the last section, so we need to pad it out.
5731 if (symtab.strsize > self.strtab.items.len) {
5732 // This is potentially the last section, so we need to pad it out.
57245733 try self.base.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1);
57255734 }
57265735}
src/stage1/codegen.cpp+8-5
......@@ -3831,10 +3831,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable,
38313831 LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
38323832 LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
38333833
3834 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
3835 LLVMValueRef mask = LLVMConstAllOnes(LLVMIntType(size_in_bits));
3836 mask = LLVMConstZExt(mask, LLVMTypeOf(containing_int));
3837 LLVMValueRef masked_value = LLVMBuildAnd(g->builder, shifted_value, mask, "");
3838
38343839 if (handle_is_ptr(g, child_type)) {
38353840 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
3836 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
3837 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
3841 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, masked_value, same_size_int, "");
38383842 LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, result_loc,
38393843 LLVMPointerType(same_size_int, 0), "");
38403844 LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);
......@@ -3842,12 +3846,11 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable,
38423846 }
38433847
38443848 if (child_type->id == ZigTypeIdFloat) {
3845 LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
3846 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
3849 LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, masked_value, same_size_int, "");
38473850 return LLVMBuildBitCast(g->builder, truncated_int, get_llvm_type(g, child_type), "");
38483851 }
38493852
3850 return LLVMBuildTrunc(g->builder, shifted_value, get_llvm_type(g, child_type), "");
3853 return LLVMBuildTrunc(g->builder, masked_value, get_llvm_type(g, child_type), "");
38513854}
38523855
38533856static bool value_is_all_undef_array(CodeGen *g, ZigValue *const_val, size_t len) {
src/type.zig+16-7
......@@ -534,15 +534,24 @@ pub const Type = extern union {
534534 return a_data.error_set.eql(b_data.error_set) and a_data.payload.eql(b_data.payload);
535535 },
536536 .ErrorSet => {
537 const a_is_anyerror = a.tag() == .anyerror;
538 const b_is_anyerror = b.tag() == .anyerror;
537 if (a.tag() == .anyerror and b.tag() == .anyerror) {
538 return true;
539 }
539540
540 if (a_is_anyerror and b_is_anyerror) return true;
541 if (a_is_anyerror or b_is_anyerror) return false;
541 if (a.tag() == .error_set and b.tag() == .error_set) {
542 return a.castTag(.error_set).?.data.owner_decl == b.castTag(.error_set).?.data.owner_decl;
543 }
542544
543 std.debug.panic("TODO implement Type equality comparison of {} and {}", .{
544 a.tag(), b.tag(),
545 });
545 if (a.tag() == .error_set_inferred and b.tag() == .error_set_inferred) {
546 return a.castTag(.error_set_inferred).?.data.func == b.castTag(.error_set_inferred).?.data.func;
547 }
548
549 if (a.tag() == .error_set_single and b.tag() == .error_set_single) {
550 const a_data = a.castTag(.error_set_single).?.data;
551 const b_data = b.castTag(.error_set_single).?.data;
552 return std.mem.eql(u8, a_data, b_data);
553 }
554 return false;
546555 },
547556 .Opaque,
548557 .Float,
test/behavior.zig+1
......@@ -71,6 +71,7 @@ test {
7171 _ = @import("behavior/bugs/7047.zig");
7272 _ = @import("behavior/bugs/7003.zig");
7373 _ = @import("behavior/bugs/7250.zig");
74 _ = @import("behavior/bugs/9584.zig");
7475 _ = @import("behavior/bugs/394.zig");
7576 _ = @import("behavior/bugs/421.zig");
7677 _ = @import("behavior/bugs/529.zig");
test/behavior/bugs/9584.zig created+60
......@@ -0,0 +1,60 @@
1const std = @import("std");
2
3const A = packed struct {
4 a: bool,
5 b: bool,
6 c: bool,
7 d: bool,
8
9 e: bool,
10 f: bool,
11 g: bool,
12 h: bool,
13};
14
15const X = union {
16 x: A,
17 y: u64,
18};
19
20pub fn a(
21 x0: i32,
22 x1: i32,
23 x2: i32,
24 x3: i32,
25 x4: i32,
26 flag_a: bool,
27 flag_b: bool,
28) !void {
29 _ = x0;
30 _ = x1;
31 _ = x2;
32 _ = x3;
33 _ = x4;
34 _ = flag_a;
35 // With this bug present, `flag_b` would actually contain the value 17.
36 // Note: this bug only presents itself on debug mode.
37 try std.testing.expect(@ptrCast(*const u8, &flag_b).* == 1);
38}
39
40pub fn b(x: *X) !void {
41 try a(0, 1, 2, 3, 4, x.x.a, x.x.b);
42}
43
44test "bug 9584" {
45 var flags = A{
46 .a = false,
47 .b = true,
48 .c = false,
49 .d = false,
50
51 .e = false,
52 .f = true,
53 .g = false,
54 .h = false,
55 };
56 var x = X{
57 .x = flags,
58 };
59 try b(&x);
60}
test/cases.zig+60
......@@ -1535,6 +1535,48 @@ pub fn addCases(ctx: *TestContext) !void {
15351535 \\}
15361536 , "");
15371537 }
1538 {
1539 var case = ctx.exe("runtime bitwise and", linux_x64);
1540
1541 case.addCompareOutput(
1542 \\pub fn main() void {
1543 \\ var i: u32 = 10;
1544 \\ var j: u32 = 11;
1545 \\ assert(i & 1 == 0);
1546 \\ assert(j & 1 == 1);
1547 \\ var m1: u32 = 0b1111;
1548 \\ var m2: u32 = 0b0000;
1549 \\ assert(m1 & 0b1010 == 0b1010);
1550 \\ assert(m2 & 0b1010 == 0b0000);
1551 \\}
1552 \\fn assert(b: bool) void {
1553 \\ if (!b) unreachable;
1554 \\}
1555 ,
1556 "",
1557 );
1558 }
1559 {
1560 var case = ctx.exe("runtime bitwise or", linux_x64);
1561
1562 case.addCompareOutput(
1563 \\pub fn main() void {
1564 \\ var i: u32 = 10;
1565 \\ var j: u32 = 11;
1566 \\ assert(i | 1 == 11);
1567 \\ assert(j | 1 == 11);
1568 \\ var m1: u32 = 0b1111;
1569 \\ var m2: u32 = 0b0000;
1570 \\ assert(m1 | 0b1010 == 0b1111);
1571 \\ assert(m2 | 0b1010 == 0b1010);
1572 \\}
1573 \\fn assert(b: bool) void {
1574 \\ if (!b) unreachable;
1575 \\}
1576 ,
1577 "",
1578 );
1579 }
15381580 {
15391581 var case = ctx.exe("merge error sets", linux_x64);
15401582
......@@ -1567,6 +1609,24 @@ pub fn addCases(ctx: *TestContext) !void {
15671609 ":2:20: note: '||' merges error sets; 'or' performs boolean OR",
15681610 });
15691611 }
1612 {
1613 var case = ctx.exe("error set equality", linux_x64);
1614
1615 case.addCompareOutput(
1616 \\pub fn main() void {
1617 \\ assert(@TypeOf(error.Foo) == @TypeOf(error.Foo));
1618 \\ assert(@TypeOf(error.Bar) != @TypeOf(error.Foo));
1619 \\ assert(anyerror == anyerror);
1620 \\ assert(error{Foo} != error{Foo});
1621 \\ // TODO put inferred error sets here when @typeInfo works
1622 \\}
1623 \\fn assert(b: bool) void {
1624 \\ if (!b) unreachable;
1625 \\}
1626 ,
1627 "",
1628 );
1629 }
15701630 {
15711631 var case = ctx.exe("inline assembly", linux_x64);
15721632