authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-07 18:25:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-07 18:25:01-07:00
log6a3a0fe7ae20e620ec6ad80bf87c72b284d2aafa
treecb977f8239695b217b49ecd68e1be1bf77f085ce
parent8e07b0c4b97817b89b0cd59c8e558348cfb5005b
parent3a03872af76652515e467c1f33d918ead2c0a6b0

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


7 files changed, 82 insertions(+), 193 deletions(-)

lib/std/builtin.zig+1
...@@ -858,6 +858,7 @@ pub fn panicOutOfBounds(index: usize, len: usize) noreturn {...@@ -858,6 +858,7 @@ pub fn panicOutOfBounds(index: usize, len: usize) noreturn {
858858
859pub noinline fn returnError(maybe_st: ?*StackTrace) void {859pub noinline fn returnError(maybe_st: ?*StackTrace) void {
860 @setCold(true);860 @setCold(true);
861 @setRuntimeSafety(false);
861 const st = maybe_st orelse return;862 const st = maybe_st orelse return;
862 addErrRetTraceAddr(st, @returnAddress());863 addErrRetTraceAddr(st, @returnAddress());
863}864}
src/Sema.zig+14-1
...@@ -18427,7 +18427,20 @@ fn safetyPanic(...@@ -18427,7 +18427,20 @@ fn safetyPanic(
18427fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {18427fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
18428 sema.branch_count += 1;18428 sema.branch_count += 1;
18429 if (sema.branch_count > sema.branch_quota) {18429 if (sema.branch_count > sema.branch_quota) {
18430 return sema.fail(block, src, "evaluation exceeded {d} backwards branches", .{sema.branch_quota});18430 const msg = try sema.errMsg(
18431 block,
18432 src,
18433 "evaluation exceeded {d} backwards branches",
18434 .{sema.branch_quota},
18435 );
18436 try sema.errNote(
18437 block,
18438 src,
18439 msg,
18440 "use @setEvalBranchQuota() to raise the branch limit from {d}",
18441 .{sema.branch_quota},
18442 );
18443 return sema.failWithOwnedErrorMsg(block, msg);
18431 }18444 }
18432}18445}
1843318446
src/codegen/llvm.zig+49-191
...@@ -858,69 +858,34 @@ pub const Object = struct {...@@ -858,69 +858,34 @@ pub const Object = struct {
858 try args.append(aggregate);858 try args.append(aggregate);
859 },859 },
860 .multiple_llvm_ints => {860 .multiple_llvm_ints => {
861 const param_ty = fn_info.param_types[it.zig_index - 1];
862 const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];861 const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];
863 const is_by_ref = isByRef(param_ty);862 const param_ty = fn_info.param_types[it.zig_index - 1];
864 switch (param_ty.zigTypeTag()) {863 const param_llvm_ty = try dg.lowerType(param_ty);
865 .Struct => {864 const param_alignment = param_ty.abiAlignment(target);
866 const fields = param_ty.structFields().values();865 const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty);
867 if (is_by_ref) {866 arg_ptr.setAlignment(param_alignment);
868 const param_llvm_ty = try dg.lowerType(param_ty);867 var field_types_buf: [8]*const llvm.Type = undefined;
869 const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty);868 const field_types = field_types_buf[0..llvm_ints.len];
870 arg_ptr.setAlignment(param_ty.abiAlignment(target));869 for (llvm_ints) |int_bits, i| {
871870 field_types[i] = dg.context.intType(int_bits);
872 var field_i: u32 = 0;
873 var field_offset: u32 = 0;
874 for (llvm_ints) |int_bits| {
875 const param = llvm_func.getParam(llvm_arg_i);
876 llvm_arg_i += 1;
877
878 const big_int_ty = dg.context.intType(int_bits);
879 var bits_used: u32 = 0;
880 while (bits_used < int_bits) {
881 const field = fields[field_i];
882 const field_alignment = field.normalAlignment(target);
883 const prev_offset = field_offset;
884 field_offset = std.mem.alignForwardGeneric(u32, field_offset, field_alignment);
885 if (field_offset > prev_offset) {
886 // Padding counts as bits used.
887 bits_used += (field_offset - prev_offset) * 8;
888 if (bits_used >= int_bits) break;
889 }
890 const field_size = @intCast(u16, field.ty.abiSize(target));
891 const field_abi_bits = field_size * 8;
892 const field_int_ty = dg.context.intType(field_abi_bits);
893 const shifted = if (bits_used == 0) param else s: {
894 const shift_amt = big_int_ty.constInt(bits_used, .False);
895 break :s builder.buildLShr(param, shift_amt, "");
896 };
897 const field_as_int = builder.buildTrunc(shifted, field_int_ty, "");
898 var ty_buf: Type.Payload.Pointer = undefined;
899 const llvm_i = llvmFieldIndex(param_ty, field_i, target, &ty_buf).?;
900 const field_ptr = builder.buildStructGEP(arg_ptr, llvm_i, "");
901 const casted_ptr = builder.buildBitCast(field_ptr, field_int_ty.pointerType(0), "");
902 const store_inst = builder.buildStore(field_as_int, casted_ptr);
903 store_inst.setAlignment(field_alignment);
904
905 field_i += 1;
906 if (field_i >= fields.len) break;
907
908 bits_used += field_abi_bits;
909 field_offset += field_size;
910 }
911 if (field_i >= fields.len) break;
912 }
913
914 try args.append(arg_ptr);
915 } else {
916 @panic("TODO: LLVM backend: implement C calling convention on x86_64 with byval struct parameter");
917 }
918 },
919 .Union => {
920 @panic("TODO: LLVM backend: implement C calling convention on x86_64 with union parameter");
921 },
922 else => unreachable,
923 }871 }
872 const ints_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);
873 const casted_ptr = builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), "");
874 for (llvm_ints) |_, i_usize| {
875 const i = @intCast(c_uint, i_usize);
876 const param = llvm_func.getParam(i);
877 const field_ptr = builder.buildStructGEP(casted_ptr, i, "");
878 const store_inst = builder.buildStore(param, field_ptr);
879 store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8);
880 }
881
882 const is_by_ref = isByRef(param_ty);
883 const loaded = if (is_by_ref) arg_ptr else l: {
884 const load_inst = builder.buildLoad(arg_ptr, "");
885 load_inst.setAlignment(param_alignment);
886 break :l load_inst;
887 };
888 try args.append(loaded);
924 },889 },
925 };890 };
926 }891 }
...@@ -2822,65 +2787,11 @@ pub const DeclGen = struct {...@@ -2822,65 +2787,11 @@ pub const DeclGen = struct {
2822 llvm_params.appendAssumeCapacity(len_llvm_ty);2787 llvm_params.appendAssumeCapacity(len_llvm_ty);
2823 },2788 },
2824 .multiple_llvm_ints => {2789 .multiple_llvm_ints => {
2825 const param_ty = fn_info.param_types[it.zig_index - 1];
2826 const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];2790 const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];
2827 try llvm_params.ensureUnusedCapacity(it.llvm_types_len);2791 try llvm_params.ensureUnusedCapacity(it.llvm_types_len);
28282792 for (llvm_ints) |int_bits| {
2829 // The reason we have all this logic instead of simply appending2793 const big_int_ty = dg.context.intType(int_bits);
2830 // big_int_ty is for the special case of a pointer type;2794 llvm_params.appendAssumeCapacity(big_int_ty);
2831 // we want to use a pointer type instead of inttoptr at the callsites,
2832 // which may prevent optimization.
2833 switch (param_ty.zigTypeTag()) {
2834 .Struct => {
2835 const fields = param_ty.structFields().values();
2836 var field_i: u32 = 0;
2837 var field_offset: u32 = 0;
2838 llvm_arg: for (llvm_ints) |int_bits| {
2839 const big_int_ty = dg.context.intType(int_bits);
2840 var bits_used: u32 = 0;
2841 while (bits_used < int_bits) {
2842 const field = fields[field_i];
2843 const field_alignment = field.normalAlignment(target);
2844 const prev_offset = field_offset;
2845 field_offset = std.mem.alignForwardGeneric(u32, field_offset, field_alignment);
2846 if (field_offset > prev_offset) {
2847 // Padding counts as bits used.
2848 bits_used += (field_offset - prev_offset) * 8;
2849 if (bits_used >= int_bits) break;
2850 }
2851 const field_size = @intCast(u16, field.ty.abiSize(target));
2852 const field_abi_bits = field_size * 8;
2853
2854 // Special case for when the entire LLVM integer represents
2855 // one field; in this case keep the type information
2856 // to avoid the potentially costly ptrtoint/bitcast.
2857 if (bits_used == 0 and field_abi_bits == int_bits) {
2858 const llvm_field_ty = try dg.lowerType(field.ty);
2859 llvm_params.appendAssumeCapacity(llvm_field_ty);
2860 field_i += 1;
2861 if (field_i >= fields.len) {
2862 break :llvm_arg;
2863 } else {
2864 continue :llvm_arg;
2865 }
2866 }
2867
2868 field_i += 1;
2869 if (field_i >= fields.len) break;
2870
2871 bits_used += field_abi_bits;
2872 field_offset += field_size;
2873 }
2874 llvm_params.appendAssumeCapacity(big_int_ty);
2875 if (field_i >= fields.len) break;
2876 }
2877 },
2878 else => {
2879 for (llvm_ints) |int_bits| {
2880 const big_int_ty = dg.context.intType(int_bits);
2881 llvm_params.appendAssumeCapacity(big_int_ty);
2882 }
2883 },
2884 }2795 }
2885 },2796 },
2886 };2797 };
...@@ -4300,80 +4211,27 @@ pub const FuncGen = struct {...@@ -4300,80 +4211,27 @@ pub const FuncGen = struct {
4300 const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];4211 const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len];
4301 const llvm_arg = try self.resolveInst(arg);4212 const llvm_arg = try self.resolveInst(arg);
4302 const is_by_ref = isByRef(param_ty);4213 const is_by_ref = isByRef(param_ty);
4303 try llvm_args.ensureUnusedCapacity(it.llvm_types_len);4214 const arg_ptr = if (is_by_ref) llvm_arg else p: {
4304 switch (param_ty.zigTypeTag()) {4215 const p = self.buildAlloca(llvm_arg.typeOf());
4305 .Struct => {4216 const store_inst = self.builder.buildStore(llvm_arg, p);
4306 const fields = param_ty.structFields().values();4217 store_inst.setAlignment(param_ty.abiAlignment(target));
4307 var field_i: u32 = 0;4218 break :p p;
4308 var field_offset: u32 = 0;4219 };
4309 for (llvm_ints) |int_bits| {
4310 const big_int_ty = self.dg.context.intType(int_bits);
4311 var int_arg: *const llvm.Value = undefined;
4312 var bits_used: u32 = 0;
4313 while (bits_used < int_bits) {
4314 const field = fields[field_i];
4315 const field_alignment = field.normalAlignment(target);
4316 const prev_offset = field_offset;
4317 field_offset = std.mem.alignForwardGeneric(u32, field_offset, field_alignment);
4318 if (field_offset > prev_offset) {
4319 // Padding counts as bits used.
4320 bits_used += (field_offset - prev_offset) * 8;
4321 if (bits_used >= int_bits) break;
4322 }
4323 var ty_buf: Type.Payload.Pointer = undefined;
4324 const llvm_i = llvmFieldIndex(param_ty, field_i, target, &ty_buf).?;
4325 const field_size = @intCast(u16, field.ty.abiSize(target));
4326 const field_abi_bits = field_size * 8;
4327
4328 // Special case for when the entire LLVM integer represents
4329 // one field; in this case keep the type information
4330 // to avoid the potentially costly ptrtoint/bitcast.
4331 if (bits_used == 0 and field_abi_bits == int_bits) {
4332 int_arg = if (is_by_ref) f: {
4333 const field_ptr = self.builder.buildStructGEP(llvm_arg, llvm_i, "");
4334 const load_inst = self.builder.buildLoad(field_ptr, "");
4335 load_inst.setAlignment(field_alignment);
4336 break :f load_inst;
4337 } else self.builder.buildExtractValue(llvm_arg, llvm_i, "");
4338 field_i += 1;
4339 break;
4340 }
4341
4342 const field_int_ty = self.dg.context.intType(field_abi_bits);
4343 const llvm_field = if (is_by_ref) f: {
4344 const field_ptr = self.builder.buildStructGEP(llvm_arg, llvm_i, "");
4345 const casted_ptr = self.builder.buildBitCast(field_ptr, field_int_ty.pointerType(0), "");
4346 const load_inst = self.builder.buildLoad(casted_ptr, "");
4347 load_inst.setAlignment(field_alignment);
4348 break :f load_inst;
4349 } else f: {
4350 const llvm_field = self.builder.buildExtractValue(llvm_arg, llvm_i, "");
4351 break :f self.builder.buildBitCast(llvm_field, field_int_ty, "");
4352 };
4353
4354 const extended = self.builder.buildZExt(llvm_field, big_int_ty, "");
4355 if (bits_used == 0) {
4356 int_arg = extended;
4357 } else {
4358 const shift_amt = big_int_ty.constInt(bits_used, .False);
4359 const shifted = self.builder.buildShl(extended, shift_amt, "");
4360 int_arg = self.builder.buildOr(int_arg, shifted, "");
4361 }
4362
4363 field_i += 1;
4364 if (field_i >= fields.len) break;
43654220
4366 bits_used += field_abi_bits;4221 var field_types_buf: [8]*const llvm.Type = undefined;
4367 field_offset += field_size;4222 const field_types = field_types_buf[0..llvm_ints.len];
4368 }4223 for (llvm_ints) |int_bits, i| {
4369 llvm_args.appendAssumeCapacity(int_arg);4224 field_types[i] = self.dg.context.intType(int_bits);
4370 if (field_i >= fields.len) break;4225 }
4371 }4226 const ints_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);
4372 },4227 const casted_ptr = self.builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), "");
4373 .Union => {4228 try llvm_args.ensureUnusedCapacity(it.llvm_types_len);
4374 return self.todo("airCall C calling convention on x86_64 with union argument ", .{});4229 for (llvm_ints) |_, i_usize| {
4375 },4230 const i = @intCast(c_uint, i_usize);
4376 else => unreachable,4231 const field_ptr = self.builder.buildStructGEP(casted_ptr, i, "");
4232 const load_inst = self.builder.buildLoad(field_ptr, "");
4233 load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8);
4234 llvm_args.appendAssumeCapacity(load_inst);
4377 }4235 }
4378 },4236 },
4379 };4237 };
src/stage1/ir.cpp+4-1
...@@ -5769,8 +5769,10 @@ static bool ir_emit_backward_branch(IrAnalyze *ira, AstNode* source_node) {...@@ -5769,8 +5769,10 @@ static bool ir_emit_backward_branch(IrAnalyze *ira, AstNode* source_node) {
57695769
5770 *bbc += 1;5770 *bbc += 1;
5771 if (*bbc > *quota) {5771 if (*bbc > *quota) {
5772 ir_add_error_node(ira, source_node,5772 ErrorMsg *msg = ir_add_error_node(ira, source_node,
5773 buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", *quota));5773 buf_sprintf("evaluation exceeded %" ZIG_PRI_usize " backwards branches", *quota));
5774 add_error_note(ira->codegen, msg, source_node,
5775 buf_sprintf("use @setEvalBranchQuota to raise branch limit from %" ZIG_PRI_usize, *quota));
5774 return false;5776 return false;
5775 }5777 }
5776 return true;5778 return true;
...@@ -21573,6 +21575,7 @@ done_with_return_type:...@@ -21573,6 +21575,7 @@ done_with_return_type:
21573 // handle `[N]T`21575 // handle `[N]T`
21574 target_len = target->type->data.array.len;21576 target_len = target->type->data.array.len;
21575 target_sentinel = target->type->data.array.sentinel;21577 target_sentinel = target->type->data.array.sentinel;
21578 expand_undef_array(ira->codegen, target);
21576 target_elements = target->data.x_array.data.s_none.elements;21579 target_elements = target->data.x_array.data.s_none.elements;
21577 break;21580 break;
21578 } else if (target->type->id == ZigTypeIdPointer && target->type->data.pointer.child_type->id == ZigTypeIdArray) {21581 } else if (target->type->id == ZigTypeIdPointer && target->type->data.pointer.child_type->id == ZigTypeIdArray) {
test/behavior.zig+1
...@@ -83,6 +83,7 @@ test {...@@ -83,6 +83,7 @@ test {
83 _ = @import("behavior/bugs/11181.zig");83 _ = @import("behavior/bugs/11181.zig");
84 _ = @import("behavior/bugs/11213.zig");84 _ = @import("behavior/bugs/11213.zig");
85 _ = @import("behavior/bugs/12003.zig");85 _ = @import("behavior/bugs/12003.zig");
86 _ = @import("behavior/bugs/12033.zig");
86 _ = @import("behavior/byteswap.zig");87 _ = @import("behavior/byteswap.zig");
87 _ = @import("behavior/byval_arg_var.zig");88 _ = @import("behavior/byval_arg_var.zig");
88 _ = @import("behavior/call.zig");89 _ = @import("behavior/call.zig");
test/behavior/bugs/12033.zig created+12
...@@ -0,0 +1,12 @@
1const std = @import("std");
2
3test {
4 const string = "Hello!\x00World!";
5 try std.testing.expect(@TypeOf(string) == *const [13:0]u8);
6
7 const slice_without_sentinel: []const u8 = string[0..6];
8 try std.testing.expect(@TypeOf(slice_without_sentinel) == []const u8);
9
10 const slice_with_sentinel: [:0]const u8 = string[0..6 :0];
11 try std.testing.expect(@TypeOf(slice_with_sentinel) == [:0]const u8);
12}
test/cases/recursive_inline_function.1.zig+1
...@@ -14,6 +14,7 @@ inline fn fibonacci(n: usize) usize {...@@ -14,6 +14,7 @@ inline fn fibonacci(n: usize) usize {
14// error14// error
15//15//
16// :11:21: error: evaluation exceeded 1000 backwards branches16// :11:21: error: evaluation exceeded 1000 backwards branches
17// :11:21: note: use @setEvalBranchQuota() to raise the branch limit from 1000
17// :11:40: note: called from here (6 times)18// :11:40: note: called from here (6 times)
18// :11:21: note: called from here (495 times)19// :11:21: note: called from here (495 times)
19// :5:24: note: called from here20// :5:24: note: called from here