authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-21 13:48:23+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-09 14:35:42-07:00
loga3232c6764d9adc2d3b93e9ed76208d60b509f7a
tree82b904f4cef00926db419b127a5ede053f24b6c9
parent10a660ebea6b616644b1010b3766bf9899eeaa75

Merge pull request #13585 from Vexu/stage2-fixes

Stage2 bug fixes

20 files changed, 454 insertions(+), 89 deletions(-)

src/Module.zig+5-3
......@@ -1044,7 +1044,8 @@ pub const Struct = struct {
10441044
10451045 .root => return queryFieldSrc(tree.*, query, file, tree.containerDeclRoot()),
10461046
1047 else => unreachable,
1047 // This struct was generated using @Type
1048 else => return s.srcLoc(mod),
10481049 }
10491050 }
10501051
......@@ -1270,7 +1271,8 @@ pub const Union = struct {
12701271 .tagged_union_enum_tag,
12711272 .tagged_union_enum_tag_trailing,
12721273 => return queryFieldSrc(tree.*, query, file, tree.taggedUnionEnumTag(node)),
1273 else => unreachable,
1274 // This union was generated using @Type
1275 else => return u.srcLoc(mod),
12741276 }
12751277 }
12761278
......@@ -4631,7 +4633,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46314633 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
46324634 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
46334635 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
4634 const decl_tv = try sema.resolveInstValue(&block_scope, init_src, result_ref, undefined);
4636 const decl_tv = try sema.resolveInstValue(&block_scope, init_src, result_ref, "global variable initializer must be comptime-known");
46354637
46364638 // Note this resolves the type of the Decl, not the value; if this Decl
46374639 // is a struct, for example, this resolves `type` (which needs no resolution),
src/Sema.zig+68-30
......@@ -128,7 +128,7 @@ pub const Block = struct {
128128 /// Shared among all child blocks.
129129 sema: *Sema,
130130 /// The namespace to use for lookups from this source block
131 /// When analyzing fields, this is different from src_decl.src_namepsace.
131 /// When analyzing fields, this is different from src_decl.src_namespace.
132132 namespace: *Namespace,
133133 /// The AIR instructions generated for this block.
134134 instructions: std.ArrayListUnmanaged(Air.Inst.Index),
......@@ -1897,10 +1897,15 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
18971897 }
18981898 i -= Air.Inst.Ref.typed_value_map.len;
18991899
1900 const air_tags = sema.air_instructions.items(.tag);
19001901 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {
1902 if (air_tags[i] == .constant) {
1903 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
1904 const val = sema.air_values.items[ty_pl.payload];
1905 if (val.tag() == .variable) return val;
1906 }
19011907 return opv;
19021908 }
1903 const air_tags = sema.air_instructions.items(.tag);
19041909 switch (air_tags[i]) {
19051910 .constant => {
19061911 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
......@@ -4106,6 +4111,7 @@ fn validateStructInit(
41064111 .{fqn},
41074112 );
41084113 }
4114 root_msg = null;
41094115 return sema.failWithOwnedErrorMsg(msg);
41104116 }
41114117
......@@ -4225,7 +4231,6 @@ fn validateStructInit(
42254231 }
42264232
42274233 if (root_msg) |msg| {
4228 root_msg = null;
42294234 if (struct_ty.castTag(.@"struct")) |struct_obj| {
42304235 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
42314236 defer gpa.free(fqn);
......@@ -4236,6 +4241,7 @@ fn validateStructInit(
42364241 .{fqn},
42374242 );
42384243 }
4244 root_msg = null;
42394245 return sema.failWithOwnedErrorMsg(msg);
42404246 }
42414247
......@@ -4283,29 +4289,42 @@ fn zirValidateArrayInit(
42834289 const array_ty = sema.typeOf(array_ptr).childType();
42844290 const array_len = array_ty.arrayLen();
42854291
4286 if (instrs.len != array_len and array_ty.isTuple()) {
4287 const struct_obj = array_ty.castTag(.tuple).?.data;
4288 var root_msg: ?*Module.ErrorMsg = null;
4289 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
4292 if (instrs.len != array_len) switch (array_ty.zigTypeTag()) {
4293 .Struct => {
4294 const struct_obj = array_ty.castTag(.tuple).?.data;
4295 var root_msg: ?*Module.ErrorMsg = null;
4296 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
42904297
4291 for (struct_obj.values) |default_val, i| {
4292 if (i < instrs.len) continue;
4298 for (struct_obj.values) |default_val, i| {
4299 if (i < instrs.len) continue;
42934300
4294 if (default_val.tag() == .unreachable_value) {
4295 const template = "missing tuple field with index {d}";
4296 if (root_msg) |msg| {
4297 try sema.errNote(block, init_src, msg, template, .{i});
4298 } else {
4299 root_msg = try sema.errMsg(block, init_src, template, .{i});
4301 if (default_val.tag() == .unreachable_value) {
4302 const template = "missing tuple field with index {d}";
4303 if (root_msg) |msg| {
4304 try sema.errNote(block, init_src, msg, template, .{i});
4305 } else {
4306 root_msg = try sema.errMsg(block, init_src, template, .{i});
4307 }
43004308 }
43014309 }
4302 }
43034310
4304 if (root_msg) |msg| {
4305 root_msg = null;
4306 return sema.failWithOwnedErrorMsg(msg);
4307 }
4308 }
4311 if (root_msg) |msg| {
4312 root_msg = null;
4313 return sema.failWithOwnedErrorMsg(msg);
4314 }
4315 },
4316 .Array => {
4317 return sema.fail(block, init_src, "expected {d} array elements; found {d}", .{
4318 array_len, instrs.len,
4319 });
4320 },
4321 .Vector => {
4322 return sema.fail(block, init_src, "expected {d} vector elements; found {d}", .{
4323 array_len, instrs.len,
4324 });
4325 },
4326 else => unreachable,
4327 };
43094328
43104329 if ((is_comptime or block.is_comptime) and
43114330 (try sema.resolveDefinedValue(block, init_src, array_ptr)) != null)
......@@ -17054,7 +17073,6 @@ fn finishStructInit(
1705417073 }
1705517074
1705617075 if (root_msg) |msg| {
17057 root_msg = null;
1705817076 if (struct_ty.castTag(.@"struct")) |struct_obj| {
1705917077 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
1706017078 defer gpa.free(fqn);
......@@ -17065,6 +17083,7 @@ fn finishStructInit(
1706517083 .{fqn},
1706617084 );
1706717085 }
17086 root_msg = null;
1706817087 return sema.failWithOwnedErrorMsg(msg);
1706917088 }
1707017089
......@@ -18752,8 +18771,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1875218771
1875318772 const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1875418773 const ptr_ty = try sema.resolveType(block, src, extra.lhs);
18755 const elem_ty = ptr_ty.elemType2();
1875618774 try sema.checkPtrType(block, type_src, ptr_ty);
18775 const elem_ty = ptr_ty.elemType2();
1875718776 const target = sema.mod.getTarget();
1875818777 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(target, sema);
1875918778
......@@ -24281,7 +24300,10 @@ fn coerceExtra(
2428124300 },
2428224301 .Int, .ComptimeInt => switch (inst_ty.zigTypeTag()) {
2428324302 .Float, .ComptimeFloat => float: {
24284 const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse {
24303 if (is_undef) {
24304 return sema.addConstUndef(dest_ty);
24305 }
24306 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {
2428524307 if (dest_ty.zigTypeTag() == .ComptimeInt) {
2428624308 if (!opts.report_err) return error.NotCoercible;
2428724309 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");
......@@ -24301,7 +24323,10 @@ fn coerceExtra(
2430124323 return try sema.addConstant(dest_ty, result_val);
2430224324 },
2430324325 .Int, .ComptimeInt => {
24304 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
24326 if (is_undef) {
24327 return sema.addConstUndef(dest_ty);
24328 }
24329 if (try sema.resolveMaybeUndefVal(inst)) |val| {
2430524330 // comptime-known integer to other number
2430624331 if (!(try sema.intFitsInType(val, dest_ty, null))) {
2430724332 if (!opts.report_err) return error.NotCoercible;
......@@ -24338,7 +24363,10 @@ fn coerceExtra(
2433824363 return try sema.addConstant(dest_ty, result_val);
2433924364 },
2434024365 .Float => {
24341 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
24366 if (is_undef) {
24367 return sema.addConstUndef(dest_ty);
24368 }
24369 if (try sema.resolveMaybeUndefVal(inst)) |val| {
2434224370 const result_val = try val.floatCast(sema.arena, dest_ty, target);
2434324371 if (!val.eql(result_val, dest_ty, sema.mod)) {
2434424372 return sema.fail(
......@@ -24363,7 +24391,10 @@ fn coerceExtra(
2436324391 }
2436424392 },
2436524393 .Int, .ComptimeInt => int: {
24366 const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse {
24394 if (is_undef) {
24395 return sema.addConstUndef(dest_ty);
24396 }
24397 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {
2436724398 if (dest_ty.zigTypeTag() == .ComptimeFloat) {
2436824399 if (!opts.report_err) return error.NotCoercible;
2436924400 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");
......@@ -26517,6 +26548,10 @@ fn beginComptimePtrLoad(
2651726548 .null_value => {
2651826549 return sema.fail(block, src, "attempt to use null value", .{});
2651926550 },
26551 .opt_payload => blk: {
26552 const opt_payload = ptr_val.castTag(.opt_payload).?.data;
26553 break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null);
26554 },
2652026555
2652126556 .zero,
2652226557 .one,
......@@ -27165,8 +27200,8 @@ fn coerceTupleToStruct(
2716527200 }
2716627201
2716727202 if (root_msg) |msg| {
27168 root_msg = null;
2716927203 try sema.addDeclaredHereNote(msg, struct_ty);
27204 root_msg = null;
2717027205 return sema.failWithOwnedErrorMsg(msg);
2717127206 }
2717227207
......@@ -27271,8 +27306,8 @@ fn coerceTupleToTuple(
2727127306 }
2727227307
2727327308 if (root_msg) |msg| {
27274 root_msg = null;
2727527309 try sema.addDeclaredHereNote(msg, tuple_ty);
27310 root_msg = null;
2727627311 return sema.failWithOwnedErrorMsg(msg);
2727727312 }
2727827313
......@@ -31262,7 +31297,10 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3126231297}
3126331298
3126431299pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
31265 return ty.hasRuntimeBitsAdvanced(false, sema);
31300 return ty.hasRuntimeBitsAdvanced(false, .{ .sema = sema }) catch |err| switch (err) {
31301 error.NeedLazy => unreachable,
31302 else => |e| return e,
31303 };
3126631304}
3126731305
3126831306fn typeAbiSize(sema: *Sema, ty: Type) !u64 {
src/codegen/llvm.zig+112-9
......@@ -988,6 +988,25 @@ pub const Object = struct {
988988 args.appendAssumeCapacity(load_inst);
989989 }
990990 },
991 .byref_mut => {
992 const param_ty = fn_info.param_types[it.zig_index - 1];
993 const param_llvm_ty = try dg.lowerType(param_ty);
994 const param = llvm_func.getParam(llvm_arg_i);
995 const alignment = param_ty.abiAlignment(target);
996
997 dg.addArgAttr(llvm_func, llvm_arg_i, "noundef");
998 llvm_arg_i += 1;
999
1000 try args.ensureUnusedCapacity(1);
1001
1002 if (isByRef(param_ty)) {
1003 args.appendAssumeCapacity(param);
1004 } else {
1005 const load_inst = builder.buildLoad(param_llvm_ty, param, "");
1006 load_inst.setAlignment(alignment);
1007 args.appendAssumeCapacity(load_inst);
1008 }
1009 },
9911010 .abi_sized_int => {
9921011 assert(!it.byval_attr);
9931012 const param_ty = fn_info.param_types[it.zig_index - 1];
......@@ -2583,6 +2602,9 @@ pub const DeclGen = struct {
25832602 const alignment = param_ty.abiAlignment(target);
25842603 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
25852604 },
2605 .byref_mut => {
2606 dg.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef");
2607 },
25862608 // No attributes needed for these.
25872609 .no_bits,
25882610 .abi_sized_int,
......@@ -3101,7 +3123,7 @@ pub const DeclGen = struct {
31013123 const param_ty = fn_info.param_types[it.zig_index - 1];
31023124 try llvm_params.append(try dg.lowerType(param_ty));
31033125 },
3104 .byref => {
3126 .byref, .byref_mut => {
31053127 const param_ty = fn_info.param_types[it.zig_index - 1];
31063128 const raw_llvm_ty = try dg.lowerType(param_ty);
31073129 try llvm_params.append(raw_llvm_ty.pointerType(0));
......@@ -4678,9 +4700,9 @@ pub const FuncGen = struct {
46784700 break :blk ret_ptr;
46794701 };
46804702
4681 if (fn_info.return_type.isError() and
4682 self.dg.module.comp.bin_file.options.error_return_tracing)
4683 {
4703 const err_return_tracing = fn_info.return_type.isError() and
4704 self.dg.module.comp.bin_file.options.error_return_tracing;
4705 if (err_return_tracing) {
46844706 try llvm_args.append(self.err_ret_trace.?);
46854707 }
46864708
......@@ -4726,6 +4748,27 @@ pub const FuncGen = struct {
47264748 try llvm_args.append(arg_ptr);
47274749 }
47284750 },
4751 .byref_mut => {
4752 const arg = args[it.zig_index - 1];
4753 const param_ty = self.air.typeOf(arg);
4754 const llvm_arg = try self.resolveInst(arg);
4755
4756 const alignment = param_ty.abiAlignment(target);
4757 const param_llvm_ty = try self.dg.lowerType(param_ty);
4758 const arg_ptr = self.buildAlloca(param_llvm_ty, alignment);
4759 if (isByRef(param_ty)) {
4760 const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, "");
4761 load_inst.setAlignment(alignment);
4762
4763 const store_inst = self.builder.buildStore(load_inst, arg_ptr);
4764 store_inst.setAlignment(alignment);
4765 try llvm_args.append(arg_ptr);
4766 } else {
4767 const store_inst = self.builder.buildStore(llvm_arg, arg_ptr);
4768 store_inst.setAlignment(alignment);
4769 try llvm_args.append(arg_ptr);
4770 }
4771 },
47294772 .abi_sized_int => {
47304773 const arg = args[it.zig_index - 1];
47314774 const param_ty = self.air.typeOf(arg);
......@@ -4847,6 +4890,66 @@ pub const FuncGen = struct {
48474890 "",
48484891 );
48494892
4893 if (callee_ty.zigTypeTag() == .Pointer) {
4894 // Add argument attributes for function pointer calls.
4895 it = iterateParamTypes(self.dg, fn_info);
4896 it.llvm_index += @boolToInt(sret);
4897 it.llvm_index += @boolToInt(err_return_tracing);
4898 while (it.next()) |lowering| switch (lowering) {
4899 .byval => {
4900 const param_index = it.zig_index - 1;
4901 const param_ty = fn_info.param_types[param_index];
4902 if (!isByRef(param_ty)) {
4903 self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
4904 }
4905 },
4906 .byref => {
4907 const param_index = it.zig_index - 1;
4908 const param_ty = fn_info.param_types[param_index];
4909 const param_llvm_ty = try self.dg.lowerType(param_ty);
4910 const alignment = param_ty.abiAlignment(target);
4911 self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
4912 },
4913 .byref_mut => {
4914 self.dg.addArgAttr(call, it.llvm_index - 1, "noundef");
4915 },
4916 // No attributes needed for these.
4917 .no_bits,
4918 .abi_sized_int,
4919 .multiple_llvm_types,
4920 .as_u16,
4921 .float_array,
4922 .i32_array,
4923 .i64_array,
4924 => continue,
4925
4926 .slice => {
4927 assert(!it.byval_attr);
4928 const param_ty = fn_info.param_types[it.zig_index - 1];
4929 const ptr_info = param_ty.ptrInfo().data;
4930 const llvm_arg_i = it.llvm_index - 2;
4931
4932 if (math.cast(u5, it.zig_index - 1)) |i| {
4933 if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {
4934 self.dg.addArgAttr(call, llvm_arg_i, "noalias");
4935 }
4936 }
4937 if (param_ty.zigTypeTag() != .Optional) {
4938 self.dg.addArgAttr(call, llvm_arg_i, "nonnull");
4939 }
4940 if (!ptr_info.mutable) {
4941 self.dg.addArgAttr(call, llvm_arg_i, "readonly");
4942 }
4943 if (ptr_info.@"align" != 0) {
4944 self.dg.addArgAttrInt(call, llvm_arg_i, "align", ptr_info.@"align");
4945 } else {
4946 const elem_align = @max(ptr_info.pointee_type.abiAlignment(target), 1);
4947 self.dg.addArgAttrInt(call, llvm_arg_i, "align", elem_align);
4948 }
4949 },
4950 };
4951 }
4952
48504953 if (return_type.isNoReturn() and attr != .AlwaysTail) {
48514954 _ = self.builder.buildUnreachable();
48524955 return null;
......@@ -4876,7 +4979,7 @@ pub const FuncGen = struct {
48764979 // In this case the function return type is honoring the calling convention by having
48774980 // a different LLVM type than the usual one. We solve this here at the callsite
48784981 // by bitcasting a pointer to our canonical type, then loading it if necessary.
4879 const alignment = return_type.abiAlignment(target);
4982 const alignment = self.dg.object.target_data.abiAlignmentOfType(abi_ret_ty);
48804983 const rp = self.buildAlloca(llvm_ret_ty, alignment);
48814984 const ptr_abi_ty = abi_ret_ty.pointerType(0);
48824985 const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, "");
......@@ -10384,6 +10487,7 @@ const ParamTypeIterator = struct {
1038410487 no_bits,
1038510488 byval,
1038610489 byref,
10490 byref_mut,
1038710491 abi_sized_int,
1038810492 multiple_llvm_types,
1038910493 slice,
......@@ -10425,6 +10529,7 @@ const ParamTypeIterator = struct {
1042510529 it.llvm_index += 1;
1042610530 var buf: Type.Payload.ElemType = undefined;
1042710531 if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) {
10532 it.llvm_index += 1;
1042810533 return .slice;
1042910534 } else if (isByRef(ty)) {
1043010535 return .byref;
......@@ -10547,7 +10652,7 @@ const ParamTypeIterator = struct {
1054710652 it.zig_index += 1;
1054810653 it.llvm_index += 1;
1054910654 switch (aarch64_c_abi.classifyType(ty, it.target)) {
10550 .memory => return .byref,
10655 .memory => return .byref_mut,
1055110656 .float_array => |len| return Lowering{ .float_array = len },
1055210657 .byval => return .byval,
1055310658 .integer => {
......@@ -10578,9 +10683,7 @@ const ParamTypeIterator = struct {
1057810683 return .as_u16;
1057910684 }
1058010685 switch (riscv_c_abi.classifyType(ty, it.target)) {
10581 .memory => {
10582 return .byref;
10583 },
10686 .memory => return .byref_mut,
1058410687 .byval => return .byval,
1058510688 .integer => return .abi_sized_int,
1058610689 .double_integer => return Lowering{ .i64_array = 2 },
src/codegen/llvm/bindings.zig+2-2
......@@ -88,8 +88,8 @@ pub const Context = opaque {
8888};
8989
9090pub const Value = opaque {
91 pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
92 extern fn LLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void;
91 pub const addAttributeAtIndex = ZigLLVMAddAttributeAtIndex;
92 extern fn ZigLLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void;
9393
9494 pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;
9595 extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void;
src/main.zig+5-1
......@@ -1300,7 +1300,11 @@ fn buildOutputType(
13001300 } else if (mem.eql(u8, arg, "--no-gc-sections")) {
13011301 linker_gc_sections = false;
13021302 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
1303 debug_compile_errors = true;
1303 if (!crash_report.is_enabled) {
1304 std.log.warn("Zig was compiled in a release mode. --debug-compile-errors has no effect.", .{});
1305 } else {
1306 debug_compile_errors = true;
1307 }
13041308 } else if (mem.eql(u8, arg, "--verbose-link")) {
13051309 verbose_link = true;
13061310 } else if (mem.eql(u8, arg, "--verbose-cc")) {
src/print_air.zig+5-1
......@@ -400,9 +400,13 @@ const Writer = struct {
400400 }
401401
402402 fn writeTyPlBin(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
403 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
403 const data = w.air.instructions.items(.data);
404 const ty_pl = data[inst].ty_pl;
404405 const extra = w.air.extraData(Air.Bin, ty_pl.payload).data;
405406
407 const inst_ty = w.air.getRefType(data[inst].ty_pl.ty);
408 try w.writeType(s, inst_ty);
409 try s.writeAll(", ");
406410 try w.writeOperand(s, inst, 0, extra.lhs);
407411 try s.writeAll(", ");
408412 try w.writeOperand(s, inst, 1, extra.rhs);
src/print_zir.zig+17-1
......@@ -262,9 +262,10 @@ const Writer = struct {
262262 => try self.writeBreak(stream, inst),
263263 .array_init,
264264 .array_init_ref,
265 => try self.writeArrayInit(stream, inst),
265266 .array_init_anon,
266267 .array_init_anon_ref,
267 => try self.writeArrayInit(stream, inst),
268 => try self.writeArrayInitAnon(stream, inst),
268269
269270 .slice_start => try self.writeSliceStart(stream, inst),
270271 .slice_end => try self.writeSliceEnd(stream, inst),
......@@ -2316,6 +2317,21 @@ const Writer = struct {
23162317 try self.writeSrc(stream, inst_data.src());
23172318 }
23182319
2320 fn writeArrayInitAnon(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2321 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
2322
2323 const extra = self.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
2324 const args = self.code.refSlice(extra.end, extra.data.operands_len);
2325
2326 try stream.writeAll("{");
2327 for (args) |arg, i| {
2328 if (i != 0) try stream.writeAll(", ");
2329 try self.writeInstRef(stream, arg);
2330 }
2331 try stream.writeAll("}) ");
2332 try self.writeSrc(stream, inst_data.src());
2333 }
2334
23192335 fn writeArrayInitSent(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
23202336 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
23212337
src/type.zig+49-32
......@@ -2312,6 +2312,8 @@ pub const Type = extern union {
23122312 }
23132313 }
23142314
2315 const RuntimeBitsError = Module.CompileError || error{NeedLazy};
2316
23152317 /// true if and only if the type takes up space in memory at runtime.
23162318 /// There are two reasons a type will return false:
23172319 /// * the type is a comptime-only type. For example, the type `type` itself.
......@@ -2326,8 +2328,8 @@ pub const Type = extern union {
23262328 pub fn hasRuntimeBitsAdvanced(
23272329 ty: Type,
23282330 ignore_comptime_only: bool,
2329 opt_sema: ?*Sema,
2330 ) Module.CompileError!bool {
2331 strat: AbiAlignmentAdvancedStrat,
2332 ) RuntimeBitsError!bool {
23312333 switch (ty.tag()) {
23322334 .u1,
23332335 .u8,
......@@ -2406,8 +2408,8 @@ pub const Type = extern union {
24062408 return true;
24072409 } else if (ty.childType().zigTypeTag() == .Fn) {
24082410 return !ty.childType().fnInfo().is_generic;
2409 } else if (opt_sema) |sema| {
2410 return !(try sema.typeRequiresComptime(ty));
2411 } else if (strat == .sema) {
2412 return !(try strat.sema.typeRequiresComptime(ty));
24112413 } else {
24122414 return !comptimeOnly(ty);
24132415 }
......@@ -2445,8 +2447,8 @@ pub const Type = extern union {
24452447 }
24462448 if (ignore_comptime_only) {
24472449 return true;
2448 } else if (opt_sema) |sema| {
2449 return !(try sema.typeRequiresComptime(child_ty));
2450 } else if (strat == .sema) {
2451 return !(try strat.sema.typeRequiresComptime(child_ty));
24502452 } else {
24512453 return !comptimeOnly(child_ty);
24522454 }
......@@ -2459,13 +2461,14 @@ pub const Type = extern union {
24592461 // and then later if our guess was incorrect, we emit a compile error.
24602462 return true;
24612463 }
2462 if (opt_sema) |sema| {
2463 _ = try sema.resolveTypeFields(ty);
2464 switch (strat) {
2465 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2466 .eager => assert(struct_obj.haveFieldTypes()),
2467 .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
24642468 }
2465 assert(struct_obj.haveFieldTypes());
24662469 for (struct_obj.fields.values()) |field| {
24672470 if (field.is_comptime) continue;
2468 if (try field.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema))
2471 if (try field.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
24692472 return true;
24702473 } else {
24712474 return false;
......@@ -2474,7 +2477,7 @@ pub const Type = extern union {
24742477
24752478 .enum_full => {
24762479 const enum_full = ty.castTag(.enum_full).?.data;
2477 return enum_full.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema);
2480 return enum_full.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat);
24782481 },
24792482 .enum_simple => {
24802483 const enum_simple = ty.castTag(.enum_simple).?.data;
......@@ -2483,17 +2486,18 @@ pub const Type = extern union {
24832486 .enum_numbered, .enum_nonexhaustive => {
24842487 var buffer: Payload.Bits = undefined;
24852488 const int_tag_ty = ty.intTagType(&buffer);
2486 return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema);
2489 return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat);
24872490 },
24882491
24892492 .@"union" => {
24902493 const union_obj = ty.castTag(.@"union").?.data;
2491 if (opt_sema) |sema| {
2492 _ = try sema.resolveTypeFields(ty);
2494 switch (strat) {
2495 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2496 .eager => assert(union_obj.haveFieldTypes()),
2497 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
24932498 }
2494 assert(union_obj.haveFieldTypes());
24952499 for (union_obj.fields.values()) |value| {
2496 if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema))
2500 if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
24972501 return true;
24982502 } else {
24992503 return false;
......@@ -2501,16 +2505,17 @@ pub const Type = extern union {
25012505 },
25022506 .union_safety_tagged, .union_tagged => {
25032507 const union_obj = ty.cast(Payload.Union).?.data;
2504 if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) {
2508 if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) {
25052509 return true;
25062510 }
25072511
2508 if (opt_sema) |sema| {
2509 _ = try sema.resolveTypeFields(ty);
2512 switch (strat) {
2513 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2514 .eager => assert(union_obj.haveFieldTypes()),
2515 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
25102516 }
2511 assert(union_obj.haveFieldTypes());
25122517 for (union_obj.fields.values()) |value| {
2513 if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema))
2518 if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
25142519 return true;
25152520 } else {
25162521 return false;
......@@ -2518,9 +2523,9 @@ pub const Type = extern union {
25182523 },
25192524
25202525 .array, .vector => return ty.arrayLen() != 0 and
2521 try ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema),
2526 try ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat),
25222527 .array_u8 => return ty.arrayLen() != 0,
2523 .array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema),
2528 .array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat),
25242529
25252530 .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0,
25262531
......@@ -2529,7 +2534,7 @@ pub const Type = extern union {
25292534 for (tuple.types) |field_ty, i| {
25302535 const val = tuple.values[i];
25312536 if (val.tag() != .unreachable_value) continue; // comptime field
2532 if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) return true;
2537 if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) return true;
25332538 }
25342539 return false;
25352540 },
......@@ -2665,11 +2670,11 @@ pub const Type = extern union {
26652670 }
26662671
26672672 pub fn hasRuntimeBits(ty: Type) bool {
2668 return hasRuntimeBitsAdvanced(ty, false, null) catch unreachable;
2673 return hasRuntimeBitsAdvanced(ty, false, .eager) catch unreachable;
26692674 }
26702675
26712676 pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool {
2672 return hasRuntimeBitsAdvanced(ty, true, null) catch unreachable;
2677 return hasRuntimeBitsAdvanced(ty, true, .eager) catch unreachable;
26732678 }
26742679
26752680 pub fn isFnOrHasRuntimeBits(ty: Type) bool {
......@@ -2812,12 +2817,12 @@ pub const Type = extern union {
28122817 }
28132818 }
28142819
2815 const AbiAlignmentAdvanced = union(enum) {
2820 pub const AbiAlignmentAdvanced = union(enum) {
28162821 scalar: u32,
28172822 val: Value,
28182823 };
28192824
2820 const AbiAlignmentAdvancedStrat = union(enum) {
2825 pub const AbiAlignmentAdvancedStrat = union(enum) {
28212826 eager,
28222827 lazy: Allocator,
28232828 sema: *Sema,
......@@ -2971,7 +2976,10 @@ pub const Type = extern union {
29712976
29722977 switch (strat) {
29732978 .eager, .sema => {
2974 if (!(try child_type.hasRuntimeBitsAdvanced(false, opt_sema))) {
2979 if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
2980 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
2981 else => |e| return e,
2982 })) {
29752983 return AbiAlignmentAdvanced{ .scalar = 1 };
29762984 }
29772985 return child_type.abiAlignmentAdvanced(target, strat);
......@@ -2990,7 +2998,10 @@ pub const Type = extern union {
29902998 const code_align = abiAlignment(Type.anyerror, target);
29912999 switch (strat) {
29923000 .eager, .sema => {
2993 if (!(try data.payload.hasRuntimeBitsAdvanced(false, opt_sema))) {
3001 if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3002 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
3003 else => |e| return e,
3004 })) {
29943005 return AbiAlignmentAdvanced{ .scalar = code_align };
29953006 }
29963007 return AbiAlignmentAdvanced{ .scalar = @max(
......@@ -3044,7 +3055,10 @@ pub const Type = extern union {
30443055 const fields = ty.structFields();
30453056 var big_align: u32 = 0;
30463057 for (fields.values()) |field| {
3047 if (!(try field.ty.hasRuntimeBitsAdvanced(false, opt_sema))) continue;
3058 if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3059 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
3060 else => |e| return e,
3061 })) continue;
30483062
30493063 const field_align = if (field.abi_align != 0)
30503064 field.abi_align
......@@ -3161,7 +3175,10 @@ pub const Type = extern union {
31613175 var max_align: u32 = 0;
31623176 if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target);
31633177 for (union_obj.fields.values()) |field| {
3164 if (!(try field.ty.hasRuntimeBitsAdvanced(false, opt_sema))) continue;
3178 if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3179 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
3180 else => |e| return e,
3181 })) continue;
31653182
31663183 const field_align = if (field.abi_align != 0)
31673184 field.abi_align
src/value.zig+10-2
......@@ -1911,7 +1911,11 @@ pub const Value = extern union {
19111911
19121912 .lazy_align => {
19131913 const ty = lhs.castTag(.lazy_align).?.data;
1914 if (try ty.hasRuntimeBitsAdvanced(false, opt_sema)) {
1914 const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
1915 if (ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
1916 error.NeedLazy => unreachable,
1917 else => |e| return e,
1918 }) {
19151919 return .gt;
19161920 } else {
19171921 return .eq;
......@@ -1919,7 +1923,11 @@ pub const Value = extern union {
19191923 },
19201924 .lazy_size => {
19211925 const ty = lhs.castTag(.lazy_size).?.data;
1922 if (try ty.hasRuntimeBitsAdvanced(false, opt_sema)) {
1926 const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
1927 if (ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
1928 error.NeedLazy => unreachable,
1929 else => |e| return e,
1930 }) {
19231931 return .gt;
19241932 } else {
19251933 return .eq;
src/zig_llvm.cpp+24-6
......@@ -444,6 +444,15 @@ LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
444444 return wrap(call_inst);
445445}
446446
447void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A) {
448 if (isa<Function>(unwrap(Val))) {
449 unwrap<Function>(Val)->addAttributeAtIndex(Idx, unwrap(A));
450 } else {
451 unwrap<CallInst>(Val)->addAttributeAtIndex(Idx, unwrap(A));
452 }
453}
454
455
447456LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
448457 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile)
449458{
......@@ -1065,12 +1074,21 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {
10651074 }
10661075}
10671076
1068void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val) {
1069 Function *func = unwrap<Function>(fn_ref);
1070 AttrBuilder attr_builder(func->getContext());
1071 Type *llvm_type = unwrap<Type>(type_val);
1072 attr_builder.addByValAttr(llvm_type);
1073 func->addParamAttrs(ArgNo, attr_builder);
1077void ZigLLVMAddByValAttr(LLVMValueRef Val, unsigned ArgNo, LLVMTypeRef type_val) {
1078 if (isa<Function>(unwrap(Val))) {
1079 Function *func = unwrap<Function>(Val);
1080 AttrBuilder attr_builder(func->getContext());
1081 Type *llvm_type = unwrap<Type>(type_val);
1082 attr_builder.addByValAttr(llvm_type);
1083 func->addParamAttrs(ArgNo, attr_builder);
1084 } else {
1085 CallInst *call = unwrap<CallInst>(Val);
1086 AttrBuilder attr_builder(call->getContext());
1087 Type *llvm_type = unwrap<Type>(type_val);
1088 attr_builder.addByValAttr(llvm_type);
1089 // NOTE: +1 here since index 0 refers to the return value
1090 call->addAttributeAtIndex(ArgNo + 1, attr_builder.getAttribute(Attribute::ByVal));
1091 }
10741092}
10751093
10761094void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) {
src/zig_llvm.h+2
......@@ -129,6 +129,8 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef functio
129129 LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC,
130130 enum ZigLLVM_CallAttr attr, const char *Name);
131131
132ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A);
133
132134ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
133135 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
134136
test/behavior/basic.zig+9
......@@ -1118,3 +1118,12 @@ test "ambiguous reference error ignores current declaration" {
11181118 };
11191119 try expect(S.b.foo == 666);
11201120}
1121
1122test "pointer to zero sized global is mutable" {
1123 const S = struct {
1124 const Thing = struct {};
1125
1126 var thing: Thing = undefined;
1127 };
1128 try expect(@TypeOf(&S.thing) == *S.Thing);
1129}
test/behavior/cast.zig+8
......@@ -1429,3 +1429,11 @@ test "peer type resolution of function pointer and function body" {
14291429 try expect(@TypeOf(a, b) == *const fn () u32);
14301430 try expect(@TypeOf(b, a) == *const fn () u32);
14311431}
1432
1433test "cast typed undefined to int" {
1434 comptime {
1435 const a: u16 = undefined;
1436 const b: u8 = a;
1437 _ = b;
1438 }
1439}
test/behavior/type_info.zig+7
......@@ -565,3 +565,10 @@ test "typeInfo resolves usingnamespace declarations" {
565565 try expect(@typeInfo(B).Struct.decls.len == 2);
566566 //a
567567}
568
569test "value from struct @typeInfo default_value can be loaded at comptime" {
570 comptime {
571 const a = @typeInfo(@TypeOf(.{ .foo = @as(u8, 1) })).Struct.fields[0].default_value;
572 try expect(@ptrCast(*const u8, a).* == 1);
573 }
574}
test/c_abi/cfuncs.c+38
......@@ -833,3 +833,41 @@ struct PD zig_ret_PD();
833833int c_assert_ret_PD(){
834834 return c_assert_PD(zig_ret_PD());
835835}
836
837struct ByRef {
838 int val;
839 int arr[15];
840};
841struct ByRef c_modify_by_ref_param(struct ByRef in) {
842 in.val = 42;
843 return in;
844}
845
846struct ByVal {
847 struct {
848 unsigned long x;
849 unsigned long y;
850 unsigned long z;
851 } origin;
852 struct {
853 unsigned long width;
854 unsigned long height;
855 unsigned long depth;
856 } size;
857};
858
859void c_func_ptr_byval(void *a, void *b, struct ByVal in, unsigned long c, void *d, unsigned long e) {
860 assert_or_panic((intptr_t)a == 1);
861 assert_or_panic((intptr_t)b == 2);
862
863 assert_or_panic(in.origin.x == 9);
864 assert_or_panic(in.origin.y == 10);
865 assert_or_panic(in.origin.z == 11);
866 assert_or_panic(in.size.width == 12);
867 assert_or_panic(in.size.height == 13);
868 assert_or_panic(in.size.depth == 14);
869
870 assert_or_panic(c == 3);
871 assert_or_panic((intptr_t)d == 4);
872 assert_or_panic(e == 5);
873}
test/c_abi/main.zig+44-2
......@@ -917,8 +917,6 @@ test "CFF: C passes to Zig" {
917917 try expectOk(c_send_CFF());
918918}
919919test "CFF: C returns to Zig" {
920 // segfault on aarch64 and mips
921 if (builtin.target.cpu.arch == .aarch64) return error.SkipZigTest;
922920 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
923921 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
924922 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
......@@ -990,3 +988,47 @@ pub export fn zig_assert_PD(lv: PD) c_int {
990988 if (err != 0) std.debug.print("Received {}", .{lv});
991989 return err;
992990}
991
992const ByRef = extern struct {
993 val: c_int,
994 arr: [15]c_int,
995};
996extern fn c_modify_by_ref_param(ByRef) ByRef;
997
998test "C function modifies by ref param" {
999 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
1000
1001 const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined });
1002 try expect(res.val == 42);
1003}
1004
1005const ByVal = extern struct {
1006 origin: extern struct {
1007 x: c_ulong,
1008 y: c_ulong,
1009 z: c_ulong,
1010 },
1011 size: extern struct {
1012 width: c_ulong,
1013 height: c_ulong,
1014 depth: c_ulong,
1015 },
1016};
1017
1018extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void;
1019test "C function that takes byval struct called via function pointer" {
1020 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
1021
1022 var fn_ptr = &c_func_ptr_byval;
1023 fn_ptr(
1024 @intToPtr(*anyopaque, 1),
1025 @intToPtr(*anyopaque, 2),
1026 ByVal{
1027 .origin = .{ .x = 9, .y = 10, .z = 11 },
1028 .size = .{ .width = 12, .height = 13, .depth = 14 },
1029 },
1030 @as(c_ulong, 3),
1031 @intToPtr(*anyopaque, 4),
1032 @as(c_ulong, 5),
1033 );
1034}
test/cases/compile_errors/array_init_invalid_elem_count.zig+10
......@@ -16,6 +16,14 @@ comptime {
1616 var a: A = A{};
1717 _ = a;
1818}
19pub export fn entry1() void {
20 var bla: V = .{ 1, 2, 3, 4 };
21 _ = bla;
22}
23pub export fn entry2() void {
24 var bla: A = .{ 1, 2, 3, 4 };
25 _ = bla;
26}
1927
2028// error
2129// backend=stage2
......@@ -25,3 +33,5 @@ comptime {
2533// :8:17: error: expected 8 vector elements; found 0
2634// :12:17: error: expected 8 array elements; found 1
2735// :16:17: error: expected 8 array elements; found 0
36// :20:19: error: expected 8 vector elements; found 4
37// :24:19: error: expected 8 array elements; found 4
test/cases/compile_errors/global_variable_stored_in_global_const.zig created+12
......@@ -0,0 +1,12 @@
1var a: u32 = 2;
2const b = a;
3pub export fn entry() void {
4 _ = b;
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :2:11: error: unable to resolve comptime value
12// :2:11: note: global variable initializer must be comptime-known
test/cases/compile_errors/inttoptr_non_ptr_type.zig created+9
......@@ -0,0 +1,9 @@
1pub export fn entry() void {
2 _ = @intToPtr(i32, 10);
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:19: error: expected pointer type, found 'i32'
test/cases/compile_errors/missing_struct_field_in_fn_called_at_comptime.zig created+18
......@@ -0,0 +1,18 @@
1const S = struct {
2 a: u32,
3 b: comptime_int,
4 fn init() S {
5 return .{ .a = 1 };
6 }
7};
8comptime {
9 _ = S.init();
10}
11
12// error
13// backend=stage2
14// target=native
15//
16// :5:17: error: missing struct field: b
17// :1:11: note: struct 'tmp.S' declared here
18// :9:15: note: called from here