authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-21 13:48:23+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-11-21 13:48:23+02:00
log7c527c6dfe590a1251b51f6e1cfe8a4ba9bb0d67
tree2bf79b09302f3c574b18b50591fdad9a555b6e8f
parent89c374cd2dff36477ac1513006c03721ef946a2a
parentbbcd959c2b1721d81af5829b56e01cc472b58816
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

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 {...@@ -1044,7 +1044,8 @@ pub const Struct = struct {
10441044
1045 .root => return queryFieldSrc(tree.*, query, file, tree.containerDeclRoot()),1045 .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),
1048 }1049 }
1049 }1050 }
10501051
...@@ -1270,7 +1271,8 @@ pub const Union = struct {...@@ -1270,7 +1271,8 @@ pub const Union = struct {
1270 .tagged_union_enum_tag,1271 .tagged_union_enum_tag,
1271 .tagged_union_enum_tag_trailing,1272 .tagged_union_enum_tag_trailing,
1272 => return queryFieldSrc(tree.*, query, file, tree.taggedUnionEnumTag(node)),1273 => return queryFieldSrc(tree.*, query, file, tree.taggedUnionEnumTag(node)),
1273 else => unreachable,1274 // This union was generated using @Type
1275 else => return u.srcLoc(mod),
1274 }1276 }
1275 }1277 }
12761278
...@@ -4631,7 +4633,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4631,7 +4633,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4631 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };4633 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
4632 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };4634 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
4633 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };4635 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
4636 // Note this resolves the type of the Decl, not the value; if this Decl4638 // Note this resolves the type of the Decl, not the value; if this Decl
4637 // is a struct, for example, this resolves `type` (which needs no resolution),4639 // 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 {...@@ -128,7 +128,7 @@ pub const Block = struct {
128 /// Shared among all child blocks.128 /// Shared among all child blocks.
129 sema: *Sema,129 sema: *Sema,
130 /// The namespace to use for lookups from this source block130 /// 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.
132 namespace: *Namespace,132 namespace: *Namespace,
133 /// The AIR instructions generated for this block.133 /// The AIR instructions generated for this block.
134 instructions: std.ArrayListUnmanaged(Air.Inst.Index),134 instructions: std.ArrayListUnmanaged(Air.Inst.Index),
...@@ -1897,10 +1897,15 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(...@@ -1897,10 +1897,15 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
1897 }1897 }
1898 i -= Air.Inst.Ref.typed_value_map.len;1898 i -= Air.Inst.Ref.typed_value_map.len;
18991899
1900 const air_tags = sema.air_instructions.items(.tag);
1900 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {1901 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 }
1901 return opv;1907 return opv;
1902 }1908 }
1903 const air_tags = sema.air_instructions.items(.tag);
1904 switch (air_tags[i]) {1909 switch (air_tags[i]) {
1905 .constant => {1910 .constant => {
1906 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;1911 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
...@@ -4106,6 +4111,7 @@ fn validateStructInit(...@@ -4106,6 +4111,7 @@ fn validateStructInit(
4106 .{fqn},4111 .{fqn},
4107 );4112 );
4108 }4113 }
4114 root_msg = null;
4109 return sema.failWithOwnedErrorMsg(msg);4115 return sema.failWithOwnedErrorMsg(msg);
4110 }4116 }
41114117
...@@ -4225,7 +4231,6 @@ fn validateStructInit(...@@ -4225,7 +4231,6 @@ fn validateStructInit(
4225 }4231 }
42264232
4227 if (root_msg) |msg| {4233 if (root_msg) |msg| {
4228 root_msg = null;
4229 if (struct_ty.castTag(.@"struct")) |struct_obj| {4234 if (struct_ty.castTag(.@"struct")) |struct_obj| {
4230 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);4235 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
4231 defer gpa.free(fqn);4236 defer gpa.free(fqn);
...@@ -4236,6 +4241,7 @@ fn validateStructInit(...@@ -4236,6 +4241,7 @@ fn validateStructInit(
4236 .{fqn},4241 .{fqn},
4237 );4242 );
4238 }4243 }
4244 root_msg = null;
4239 return sema.failWithOwnedErrorMsg(msg);4245 return sema.failWithOwnedErrorMsg(msg);
4240 }4246 }
42414247
...@@ -4283,29 +4289,42 @@ fn zirValidateArrayInit(...@@ -4283,29 +4289,42 @@ fn zirValidateArrayInit(
4283 const array_ty = sema.typeOf(array_ptr).childType();4289 const array_ty = sema.typeOf(array_ptr).childType();
4284 const array_len = array_ty.arrayLen();4290 const array_len = array_ty.arrayLen();
42854291
4286 if (instrs.len != array_len and array_ty.isTuple()) {4292 if (instrs.len != array_len) switch (array_ty.zigTypeTag()) {
4287 const struct_obj = array_ty.castTag(.tuple).?.data;4293 .Struct => {
4288 var root_msg: ?*Module.ErrorMsg = null;4294 const struct_obj = array_ty.castTag(.tuple).?.data;
4289 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);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| {4298 for (struct_obj.values) |default_val, i| {
4292 if (i < instrs.len) continue;4299 if (i < instrs.len) continue;
42934300
4294 if (default_val.tag() == .unreachable_value) {4301 if (default_val.tag() == .unreachable_value) {
4295 const template = "missing tuple field with index {d}";4302 const template = "missing tuple field with index {d}";
4296 if (root_msg) |msg| {4303 if (root_msg) |msg| {
4297 try sema.errNote(block, init_src, msg, template, .{i});4304 try sema.errNote(block, init_src, msg, template, .{i});
4298 } else {4305 } else {
4299 root_msg = try sema.errMsg(block, init_src, template, .{i});4306 root_msg = try sema.errMsg(block, init_src, template, .{i});
4307 }
4300 }4308 }
4301 }4309 }
4302 }
43034310
4304 if (root_msg) |msg| {4311 if (root_msg) |msg| {
4305 root_msg = null;4312 root_msg = null;
4306 return sema.failWithOwnedErrorMsg(msg);4313 return sema.failWithOwnedErrorMsg(msg);
4307 }4314 }
4308 }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
4310 if ((is_comptime or block.is_comptime) and4329 if ((is_comptime or block.is_comptime) and
4311 (try sema.resolveDefinedValue(block, init_src, array_ptr)) != null)4330 (try sema.resolveDefinedValue(block, init_src, array_ptr)) != null)
...@@ -17080,7 +17099,6 @@ fn finishStructInit(...@@ -17080,7 +17099,6 @@ fn finishStructInit(
17080 }17099 }
1708117100
17082 if (root_msg) |msg| {17101 if (root_msg) |msg| {
17083 root_msg = null;
17084 if (struct_ty.castTag(.@"struct")) |struct_obj| {17102 if (struct_ty.castTag(.@"struct")) |struct_obj| {
17085 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);17103 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
17086 defer gpa.free(fqn);17104 defer gpa.free(fqn);
...@@ -17091,6 +17109,7 @@ fn finishStructInit(...@@ -17091,6 +17109,7 @@ fn finishStructInit(
17091 .{fqn},17109 .{fqn},
17092 );17110 );
17093 }17111 }
17112 root_msg = null;
17094 return sema.failWithOwnedErrorMsg(msg);17113 return sema.failWithOwnedErrorMsg(msg);
17095 }17114 }
1709617115
...@@ -18778,8 +18797,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18778,8 +18797,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1877818797
18779 const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };18798 const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
18780 const ptr_ty = try sema.resolveType(block, src, extra.lhs);18799 const ptr_ty = try sema.resolveType(block, src, extra.lhs);
18781 const elem_ty = ptr_ty.elemType2();
18782 try sema.checkPtrType(block, type_src, ptr_ty);18800 try sema.checkPtrType(block, type_src, ptr_ty);
18801 const elem_ty = ptr_ty.elemType2();
18783 const target = sema.mod.getTarget();18802 const target = sema.mod.getTarget();
18784 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(target, sema);18803 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(target, sema);
1878518804
...@@ -24307,7 +24326,10 @@ fn coerceExtra(...@@ -24307,7 +24326,10 @@ fn coerceExtra(
24307 },24326 },
24308 .Int, .ComptimeInt => switch (inst_ty.zigTypeTag()) {24327 .Int, .ComptimeInt => switch (inst_ty.zigTypeTag()) {
24309 .Float, .ComptimeFloat => float: {24328 .Float, .ComptimeFloat => float: {
24310 const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse {24329 if (is_undef) {
24330 return sema.addConstUndef(dest_ty);
24331 }
24332 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {
24311 if (dest_ty.zigTypeTag() == .ComptimeInt) {24333 if (dest_ty.zigTypeTag() == .ComptimeInt) {
24312 if (!opts.report_err) return error.NotCoercible;24334 if (!opts.report_err) return error.NotCoercible;
24313 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");24335 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");
...@@ -24327,7 +24349,10 @@ fn coerceExtra(...@@ -24327,7 +24349,10 @@ fn coerceExtra(
24327 return try sema.addConstant(dest_ty, result_val);24349 return try sema.addConstant(dest_ty, result_val);
24328 },24350 },
24329 .Int, .ComptimeInt => {24351 .Int, .ComptimeInt => {
24330 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {24352 if (is_undef) {
24353 return sema.addConstUndef(dest_ty);
24354 }
24355 if (try sema.resolveMaybeUndefVal(inst)) |val| {
24331 // comptime-known integer to other number24356 // comptime-known integer to other number
24332 if (!(try sema.intFitsInType(val, dest_ty, null))) {24357 if (!(try sema.intFitsInType(val, dest_ty, null))) {
24333 if (!opts.report_err) return error.NotCoercible;24358 if (!opts.report_err) return error.NotCoercible;
...@@ -24364,7 +24389,10 @@ fn coerceExtra(...@@ -24364,7 +24389,10 @@ fn coerceExtra(
24364 return try sema.addConstant(dest_ty, result_val);24389 return try sema.addConstant(dest_ty, result_val);
24365 },24390 },
24366 .Float => {24391 .Float => {
24367 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {24392 if (is_undef) {
24393 return sema.addConstUndef(dest_ty);
24394 }
24395 if (try sema.resolveMaybeUndefVal(inst)) |val| {
24368 const result_val = try val.floatCast(sema.arena, dest_ty, target);24396 const result_val = try val.floatCast(sema.arena, dest_ty, target);
24369 if (!val.eql(result_val, dest_ty, sema.mod)) {24397 if (!val.eql(result_val, dest_ty, sema.mod)) {
24370 return sema.fail(24398 return sema.fail(
...@@ -24389,7 +24417,10 @@ fn coerceExtra(...@@ -24389,7 +24417,10 @@ fn coerceExtra(
24389 }24417 }
24390 },24418 },
24391 .Int, .ComptimeInt => int: {24419 .Int, .ComptimeInt => int: {
24392 const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse {24420 if (is_undef) {
24421 return sema.addConstUndef(dest_ty);
24422 }
24423 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {
24393 if (dest_ty.zigTypeTag() == .ComptimeFloat) {24424 if (dest_ty.zigTypeTag() == .ComptimeFloat) {
24394 if (!opts.report_err) return error.NotCoercible;24425 if (!opts.report_err) return error.NotCoercible;
24395 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");24426 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");
...@@ -26543,6 +26574,10 @@ fn beginComptimePtrLoad(...@@ -26543,6 +26574,10 @@ fn beginComptimePtrLoad(
26543 .null_value => {26574 .null_value => {
26544 return sema.fail(block, src, "attempt to use null value", .{});26575 return sema.fail(block, src, "attempt to use null value", .{});
26545 },26576 },
26577 .opt_payload => blk: {
26578 const opt_payload = ptr_val.castTag(.opt_payload).?.data;
26579 break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null);
26580 },
2654626581
26547 .zero,26582 .zero,
26548 .one,26583 .one,
...@@ -27191,8 +27226,8 @@ fn coerceTupleToStruct(...@@ -27191,8 +27226,8 @@ fn coerceTupleToStruct(
27191 }27226 }
2719227227
27193 if (root_msg) |msg| {27228 if (root_msg) |msg| {
27194 root_msg = null;
27195 try sema.addDeclaredHereNote(msg, struct_ty);27229 try sema.addDeclaredHereNote(msg, struct_ty);
27230 root_msg = null;
27196 return sema.failWithOwnedErrorMsg(msg);27231 return sema.failWithOwnedErrorMsg(msg);
27197 }27232 }
2719827233
...@@ -27297,8 +27332,8 @@ fn coerceTupleToTuple(...@@ -27297,8 +27332,8 @@ fn coerceTupleToTuple(
27297 }27332 }
2729827333
27299 if (root_msg) |msg| {27334 if (root_msg) |msg| {
27300 root_msg = null;
27301 try sema.addDeclaredHereNote(msg, tuple_ty);27335 try sema.addDeclaredHereNote(msg, tuple_ty);
27336 root_msg = null;
27302 return sema.failWithOwnedErrorMsg(msg);27337 return sema.failWithOwnedErrorMsg(msg);
27303 }27338 }
2730427339
...@@ -31298,7 +31333,10 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31298,7 +31333,10 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31298}31333}
3129931334
31300pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {31335pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
31301 return ty.hasRuntimeBitsAdvanced(false, sema);31336 return ty.hasRuntimeBitsAdvanced(false, .{ .sema = sema }) catch |err| switch (err) {
31337 error.NeedLazy => unreachable,
31338 else => |e| return e,
31339 };
31302}31340}
3130331341
31304fn typeAbiSize(sema: *Sema, ty: Type) !u64 {31342fn typeAbiSize(sema: *Sema, ty: Type) !u64 {
src/codegen/llvm.zig+112-9
...@@ -988,6 +988,25 @@ pub const Object = struct {...@@ -988,6 +988,25 @@ pub const Object = struct {
988 args.appendAssumeCapacity(load_inst);988 args.appendAssumeCapacity(load_inst);
989 }989 }
990 },990 },
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 },
991 .abi_sized_int => {1010 .abi_sized_int => {
992 assert(!it.byval_attr);1011 assert(!it.byval_attr);
993 const param_ty = fn_info.param_types[it.zig_index - 1];1012 const param_ty = fn_info.param_types[it.zig_index - 1];
...@@ -2583,6 +2602,9 @@ pub const DeclGen = struct {...@@ -2583,6 +2602,9 @@ pub const DeclGen = struct {
2583 const alignment = param_ty.abiAlignment(target);2602 const alignment = param_ty.abiAlignment(target);
2584 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);2603 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
2585 },2604 },
2605 .byref_mut => {
2606 dg.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef");
2607 },
2586 // No attributes needed for these.2608 // No attributes needed for these.
2587 .no_bits,2609 .no_bits,
2588 .abi_sized_int,2610 .abi_sized_int,
...@@ -3101,7 +3123,7 @@ pub const DeclGen = struct {...@@ -3101,7 +3123,7 @@ pub const DeclGen = struct {
3101 const param_ty = fn_info.param_types[it.zig_index - 1];3123 const param_ty = fn_info.param_types[it.zig_index - 1];
3102 try llvm_params.append(try dg.lowerType(param_ty));3124 try llvm_params.append(try dg.lowerType(param_ty));
3103 },3125 },
3104 .byref => {3126 .byref, .byref_mut => {
3105 const param_ty = fn_info.param_types[it.zig_index - 1];3127 const param_ty = fn_info.param_types[it.zig_index - 1];
3106 const raw_llvm_ty = try dg.lowerType(param_ty);3128 const raw_llvm_ty = try dg.lowerType(param_ty);
3107 try llvm_params.append(raw_llvm_ty.pointerType(0));3129 try llvm_params.append(raw_llvm_ty.pointerType(0));
...@@ -4678,9 +4700,9 @@ pub const FuncGen = struct {...@@ -4678,9 +4700,9 @@ pub const FuncGen = struct {
4678 break :blk ret_ptr;4700 break :blk ret_ptr;
4679 };4701 };
46804702
4681 if (fn_info.return_type.isError() and4703 const err_return_tracing = fn_info.return_type.isError() and
4682 self.dg.module.comp.bin_file.options.error_return_tracing)4704 self.dg.module.comp.bin_file.options.error_return_tracing;
4683 {4705 if (err_return_tracing) {
4684 try llvm_args.append(self.err_ret_trace.?);4706 try llvm_args.append(self.err_ret_trace.?);
4685 }4707 }
46864708
...@@ -4726,6 +4748,27 @@ pub const FuncGen = struct {...@@ -4726,6 +4748,27 @@ pub const FuncGen = struct {
4726 try llvm_args.append(arg_ptr);4748 try llvm_args.append(arg_ptr);
4727 }4749 }
4728 },4750 },
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 },
4729 .abi_sized_int => {4772 .abi_sized_int => {
4730 const arg = args[it.zig_index - 1];4773 const arg = args[it.zig_index - 1];
4731 const param_ty = self.air.typeOf(arg);4774 const param_ty = self.air.typeOf(arg);
...@@ -4847,6 +4890,66 @@ pub const FuncGen = struct {...@@ -4847,6 +4890,66 @@ pub const FuncGen = struct {
4847 "",4890 "",
4848 );4891 );
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
4850 if (return_type.isNoReturn() and attr != .AlwaysTail) {4953 if (return_type.isNoReturn() and attr != .AlwaysTail) {
4851 _ = self.builder.buildUnreachable();4954 _ = self.builder.buildUnreachable();
4852 return null;4955 return null;
...@@ -4876,7 +4979,7 @@ pub const FuncGen = struct {...@@ -4876,7 +4979,7 @@ pub const FuncGen = struct {
4876 // In this case the function return type is honoring the calling convention by having4979 // In this case the function return type is honoring the calling convention by having
4877 // a different LLVM type than the usual one. We solve this here at the callsite4980 // a different LLVM type than the usual one. We solve this here at the callsite
4878 // by bitcasting a pointer to our canonical type, then loading it if necessary.4981 // 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);
4880 const rp = self.buildAlloca(llvm_ret_ty, alignment);4983 const rp = self.buildAlloca(llvm_ret_ty, alignment);
4881 const ptr_abi_ty = abi_ret_ty.pointerType(0);4984 const ptr_abi_ty = abi_ret_ty.pointerType(0);
4882 const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, "");4985 const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, "");
...@@ -10384,6 +10487,7 @@ const ParamTypeIterator = struct {...@@ -10384,6 +10487,7 @@ const ParamTypeIterator = struct {
10384 no_bits,10487 no_bits,
10385 byval,10488 byval,
10386 byref,10489 byref,
10490 byref_mut,
10387 abi_sized_int,10491 abi_sized_int,
10388 multiple_llvm_types,10492 multiple_llvm_types,
10389 slice,10493 slice,
...@@ -10425,6 +10529,7 @@ const ParamTypeIterator = struct {...@@ -10425,6 +10529,7 @@ const ParamTypeIterator = struct {
10425 it.llvm_index += 1;10529 it.llvm_index += 1;
10426 var buf: Type.Payload.ElemType = undefined;10530 var buf: Type.Payload.ElemType = undefined;
10427 if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) {10531 if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) {
10532 it.llvm_index += 1;
10428 return .slice;10533 return .slice;
10429 } else if (isByRef(ty)) {10534 } else if (isByRef(ty)) {
10430 return .byref;10535 return .byref;
...@@ -10547,7 +10652,7 @@ const ParamTypeIterator = struct {...@@ -10547,7 +10652,7 @@ const ParamTypeIterator = struct {
10547 it.zig_index += 1;10652 it.zig_index += 1;
10548 it.llvm_index += 1;10653 it.llvm_index += 1;
10549 switch (aarch64_c_abi.classifyType(ty, it.target)) {10654 switch (aarch64_c_abi.classifyType(ty, it.target)) {
10550 .memory => return .byref,10655 .memory => return .byref_mut,
10551 .float_array => |len| return Lowering{ .float_array = len },10656 .float_array => |len| return Lowering{ .float_array = len },
10552 .byval => return .byval,10657 .byval => return .byval,
10553 .integer => {10658 .integer => {
...@@ -10578,9 +10683,7 @@ const ParamTypeIterator = struct {...@@ -10578,9 +10683,7 @@ const ParamTypeIterator = struct {
10578 return .as_u16;10683 return .as_u16;
10579 }10684 }
10580 switch (riscv_c_abi.classifyType(ty, it.target)) {10685 switch (riscv_c_abi.classifyType(ty, it.target)) {
10581 .memory => {10686 .memory => return .byref_mut,
10582 return .byref;
10583 },
10584 .byval => return .byval,10687 .byval => return .byval,
10585 .integer => return .abi_sized_int,10688 .integer => return .abi_sized_int,
10586 .double_integer => return Lowering{ .i64_array = 2 },10689 .double_integer => return Lowering{ .i64_array = 2 },
src/codegen/llvm/bindings.zig+2-2
...@@ -88,8 +88,8 @@ pub const Context = opaque {...@@ -88,8 +88,8 @@ pub const Context = opaque {
88};88};
8989
90pub const Value = opaque {90pub const Value = opaque {
91 pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;91 pub const addAttributeAtIndex = ZigLLVMAddAttributeAtIndex;
92 extern fn LLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void;92 extern fn ZigLLVMAddAttributeAtIndex(*Value, Idx: AttributeIndex, A: *Attribute) void;
9393
94 pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;94 pub const removeEnumAttributeAtIndex = LLVMRemoveEnumAttributeAtIndex;
95 extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void;95 extern fn LLVMRemoveEnumAttributeAtIndex(F: *Value, Idx: AttributeIndex, KindID: c_uint) void;
src/main.zig+5-1
...@@ -1304,7 +1304,11 @@ fn buildOutputType(...@@ -1304,7 +1304,11 @@ fn buildOutputType(
1304 } else if (mem.eql(u8, arg, "--no-gc-sections")) {1304 } else if (mem.eql(u8, arg, "--no-gc-sections")) {
1305 linker_gc_sections = false;1305 linker_gc_sections = false;
1306 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {1306 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
1307 debug_compile_errors = true;1307 if (!crash_report.is_enabled) {
1308 std.log.warn("Zig was compiled in a release mode. --debug-compile-errors has no effect.", .{});
1309 } else {
1310 debug_compile_errors = true;
1311 }
1308 } else if (mem.eql(u8, arg, "--verbose-link")) {1312 } else if (mem.eql(u8, arg, "--verbose-link")) {
1309 verbose_link = true;1313 verbose_link = true;
1310 } else if (mem.eql(u8, arg, "--verbose-cc")) {1314 } else if (mem.eql(u8, arg, "--verbose-cc")) {
src/print_air.zig+5-1
...@@ -400,9 +400,13 @@ const Writer = struct {...@@ -400,9 +400,13 @@ const Writer = struct {
400 }400 }
401401
402 fn writeTyPlBin(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {402 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;
404 const extra = w.air.extraData(Air.Bin, ty_pl.payload).data;405 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(", ");
406 try w.writeOperand(s, inst, 0, extra.lhs);410 try w.writeOperand(s, inst, 0, extra.lhs);
407 try s.writeAll(", ");411 try s.writeAll(", ");
408 try w.writeOperand(s, inst, 1, extra.rhs);412 try w.writeOperand(s, inst, 1, extra.rhs);
src/print_zir.zig+17-1
...@@ -262,9 +262,10 @@ const Writer = struct {...@@ -262,9 +262,10 @@ const Writer = struct {
262 => try self.writeBreak(stream, inst),262 => try self.writeBreak(stream, inst),
263 .array_init,263 .array_init,
264 .array_init_ref,264 .array_init_ref,
265 => try self.writeArrayInit(stream, inst),
265 .array_init_anon,266 .array_init_anon,
266 .array_init_anon_ref,267 .array_init_anon_ref,
267 => try self.writeArrayInit(stream, inst),268 => try self.writeArrayInitAnon(stream, inst),
268269
269 .slice_start => try self.writeSliceStart(stream, inst),270 .slice_start => try self.writeSliceStart(stream, inst),
270 .slice_end => try self.writeSliceEnd(stream, inst),271 .slice_end => try self.writeSliceEnd(stream, inst),
...@@ -2316,6 +2317,21 @@ const Writer = struct {...@@ -2316,6 +2317,21 @@ const Writer = struct {
2316 try self.writeSrc(stream, inst_data.src());2317 try self.writeSrc(stream, inst_data.src());
2317 }2318 }
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
2319 fn writeArrayInitSent(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {2335 fn writeArrayInitSent(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
2320 const inst_data = self.code.instructions.items(.data)[inst].pl_node;2336 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 {...@@ -2312,6 +2312,8 @@ pub const Type = extern union {
2312 }2312 }
2313 }2313 }
23142314
2315 const RuntimeBitsError = Module.CompileError || error{NeedLazy};
2316
2315 /// true if and only if the type takes up space in memory at runtime.2317 /// true if and only if the type takes up space in memory at runtime.
2316 /// There are two reasons a type will return false:2318 /// There are two reasons a type will return false:
2317 /// * the type is a comptime-only type. For example, the type `type` itself.2319 /// * the type is a comptime-only type. For example, the type `type` itself.
...@@ -2326,8 +2328,8 @@ pub const Type = extern union {...@@ -2326,8 +2328,8 @@ pub const Type = extern union {
2326 pub fn hasRuntimeBitsAdvanced(2328 pub fn hasRuntimeBitsAdvanced(
2327 ty: Type,2329 ty: Type,
2328 ignore_comptime_only: bool,2330 ignore_comptime_only: bool,
2329 opt_sema: ?*Sema,2331 strat: AbiAlignmentAdvancedStrat,
2330 ) Module.CompileError!bool {2332 ) RuntimeBitsError!bool {
2331 switch (ty.tag()) {2333 switch (ty.tag()) {
2332 .u1,2334 .u1,
2333 .u8,2335 .u8,
...@@ -2406,8 +2408,8 @@ pub const Type = extern union {...@@ -2406,8 +2408,8 @@ pub const Type = extern union {
2406 return true;2408 return true;
2407 } else if (ty.childType().zigTypeTag() == .Fn) {2409 } else if (ty.childType().zigTypeTag() == .Fn) {
2408 return !ty.childType().fnInfo().is_generic;2410 return !ty.childType().fnInfo().is_generic;
2409 } else if (opt_sema) |sema| {2411 } else if (strat == .sema) {
2410 return !(try sema.typeRequiresComptime(ty));2412 return !(try strat.sema.typeRequiresComptime(ty));
2411 } else {2413 } else {
2412 return !comptimeOnly(ty);2414 return !comptimeOnly(ty);
2413 }2415 }
...@@ -2445,8 +2447,8 @@ pub const Type = extern union {...@@ -2445,8 +2447,8 @@ pub const Type = extern union {
2445 }2447 }
2446 if (ignore_comptime_only) {2448 if (ignore_comptime_only) {
2447 return true;2449 return true;
2448 } else if (opt_sema) |sema| {2450 } else if (strat == .sema) {
2449 return !(try sema.typeRequiresComptime(child_ty));2451 return !(try strat.sema.typeRequiresComptime(child_ty));
2450 } else {2452 } else {
2451 return !comptimeOnly(child_ty);2453 return !comptimeOnly(child_ty);
2452 }2454 }
...@@ -2459,13 +2461,14 @@ pub const Type = extern union {...@@ -2459,13 +2461,14 @@ pub const Type = extern union {
2459 // and then later if our guess was incorrect, we emit a compile error.2461 // and then later if our guess was incorrect, we emit a compile error.
2460 return true;2462 return true;
2461 }2463 }
2462 if (opt_sema) |sema| {2464 switch (strat) {
2463 _ = try sema.resolveTypeFields(ty);2465 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2466 .eager => assert(struct_obj.haveFieldTypes()),
2467 .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
2464 }2468 }
2465 assert(struct_obj.haveFieldTypes());
2466 for (struct_obj.fields.values()) |field| {2469 for (struct_obj.fields.values()) |field| {
2467 if (field.is_comptime) continue;2470 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))
2469 return true;2472 return true;
2470 } else {2473 } else {
2471 return false;2474 return false;
...@@ -2474,7 +2477,7 @@ pub const Type = extern union {...@@ -2474,7 +2477,7 @@ pub const Type = extern union {
24742477
2475 .enum_full => {2478 .enum_full => {
2476 const enum_full = ty.castTag(.enum_full).?.data;2479 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);
2478 },2481 },
2479 .enum_simple => {2482 .enum_simple => {
2480 const enum_simple = ty.castTag(.enum_simple).?.data;2483 const enum_simple = ty.castTag(.enum_simple).?.data;
...@@ -2483,17 +2486,18 @@ pub const Type = extern union {...@@ -2483,17 +2486,18 @@ pub const Type = extern union {
2483 .enum_numbered, .enum_nonexhaustive => {2486 .enum_numbered, .enum_nonexhaustive => {
2484 var buffer: Payload.Bits = undefined;2487 var buffer: Payload.Bits = undefined;
2485 const int_tag_ty = ty.intTagType(&buffer);2488 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);
2487 },2490 },
24882491
2489 .@"union" => {2492 .@"union" => {
2490 const union_obj = ty.castTag(.@"union").?.data;2493 const union_obj = ty.castTag(.@"union").?.data;
2491 if (opt_sema) |sema| {2494 switch (strat) {
2492 _ = try sema.resolveTypeFields(ty);2495 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2496 .eager => assert(union_obj.haveFieldTypes()),
2497 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
2493 }2498 }
2494 assert(union_obj.haveFieldTypes());
2495 for (union_obj.fields.values()) |value| {2499 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))
2497 return true;2501 return true;
2498 } else {2502 } else {
2499 return false;2503 return false;
...@@ -2501,16 +2505,17 @@ pub const Type = extern union {...@@ -2501,16 +2505,17 @@ pub const Type = extern union {
2501 },2505 },
2502 .union_safety_tagged, .union_tagged => {2506 .union_safety_tagged, .union_tagged => {
2503 const union_obj = ty.cast(Payload.Union).?.data;2507 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)) {
2505 return true;2509 return true;
2506 }2510 }
25072511
2508 if (opt_sema) |sema| {2512 switch (strat) {
2509 _ = try sema.resolveTypeFields(ty);2513 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2514 .eager => assert(union_obj.haveFieldTypes()),
2515 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
2510 }2516 }
2511 assert(union_obj.haveFieldTypes());
2512 for (union_obj.fields.values()) |value| {2517 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))
2514 return true;2519 return true;
2515 } else {2520 } else {
2516 return false;2521 return false;
...@@ -2518,9 +2523,9 @@ pub const Type = extern union {...@@ -2518,9 +2523,9 @@ pub const Type = extern union {
2518 },2523 },
25192524
2520 .array, .vector => return ty.arrayLen() != 0 and2525 .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),
2522 .array_u8 => return ty.arrayLen() != 0,2527 .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
2525 .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0,2530 .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0,
25262531
...@@ -2529,7 +2534,7 @@ pub const Type = extern union {...@@ -2529,7 +2534,7 @@ pub const Type = extern union {
2529 for (tuple.types) |field_ty, i| {2534 for (tuple.types) |field_ty, i| {
2530 const val = tuple.values[i];2535 const val = tuple.values[i];
2531 if (val.tag() != .unreachable_value) continue; // comptime field2536 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;
2533 }2538 }
2534 return false;2539 return false;
2535 },2540 },
...@@ -2665,11 +2670,11 @@ pub const Type = extern union {...@@ -2665,11 +2670,11 @@ pub const Type = extern union {
2665 }2670 }
26662671
2667 pub fn hasRuntimeBits(ty: Type) bool {2672 pub fn hasRuntimeBits(ty: Type) bool {
2668 return hasRuntimeBitsAdvanced(ty, false, null) catch unreachable;2673 return hasRuntimeBitsAdvanced(ty, false, .eager) catch unreachable;
2669 }2674 }
26702675
2671 pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool {2676 pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool {
2672 return hasRuntimeBitsAdvanced(ty, true, null) catch unreachable;2677 return hasRuntimeBitsAdvanced(ty, true, .eager) catch unreachable;
2673 }2678 }
26742679
2675 pub fn isFnOrHasRuntimeBits(ty: Type) bool {2680 pub fn isFnOrHasRuntimeBits(ty: Type) bool {
...@@ -2812,12 +2817,12 @@ pub const Type = extern union {...@@ -2812,12 +2817,12 @@ pub const Type = extern union {
2812 }2817 }
2813 }2818 }
28142819
2815 const AbiAlignmentAdvanced = union(enum) {2820 pub const AbiAlignmentAdvanced = union(enum) {
2816 scalar: u32,2821 scalar: u32,
2817 val: Value,2822 val: Value,
2818 };2823 };
28192824
2820 const AbiAlignmentAdvancedStrat = union(enum) {2825 pub const AbiAlignmentAdvancedStrat = union(enum) {
2821 eager,2826 eager,
2822 lazy: Allocator,2827 lazy: Allocator,
2823 sema: *Sema,2828 sema: *Sema,
...@@ -2971,7 +2976,10 @@ pub const Type = extern union {...@@ -2971,7 +2976,10 @@ pub const Type = extern union {
29712976
2972 switch (strat) {2977 switch (strat) {
2973 .eager, .sema => {2978 .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 })) {
2975 return AbiAlignmentAdvanced{ .scalar = 1 };2983 return AbiAlignmentAdvanced{ .scalar = 1 };
2976 }2984 }
2977 return child_type.abiAlignmentAdvanced(target, strat);2985 return child_type.abiAlignmentAdvanced(target, strat);
...@@ -2990,7 +2998,10 @@ pub const Type = extern union {...@@ -2990,7 +2998,10 @@ pub const Type = extern union {
2990 const code_align = abiAlignment(Type.anyerror, target);2998 const code_align = abiAlignment(Type.anyerror, target);
2991 switch (strat) {2999 switch (strat) {
2992 .eager, .sema => {3000 .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 })) {
2994 return AbiAlignmentAdvanced{ .scalar = code_align };3005 return AbiAlignmentAdvanced{ .scalar = code_align };
2995 }3006 }
2996 return AbiAlignmentAdvanced{ .scalar = @max(3007 return AbiAlignmentAdvanced{ .scalar = @max(
...@@ -3044,7 +3055,10 @@ pub const Type = extern union {...@@ -3044,7 +3055,10 @@ pub const Type = extern union {
3044 const fields = ty.structFields();3055 const fields = ty.structFields();
3045 var big_align: u32 = 0;3056 var big_align: u32 = 0;
3046 for (fields.values()) |field| {3057 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
3049 const field_align = if (field.abi_align != 0)3063 const field_align = if (field.abi_align != 0)
3050 field.abi_align3064 field.abi_align
...@@ -3161,7 +3175,10 @@ pub const Type = extern union {...@@ -3161,7 +3175,10 @@ pub const Type = extern union {
3161 var max_align: u32 = 0;3175 var max_align: u32 = 0;
3162 if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target);3176 if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target);
3163 for (union_obj.fields.values()) |field| {3177 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
3166 const field_align = if (field.abi_align != 0)3183 const field_align = if (field.abi_align != 0)
3167 field.abi_align3184 field.abi_align
src/value.zig+10-2
...@@ -1911,7 +1911,11 @@ pub const Value = extern union {...@@ -1911,7 +1911,11 @@ pub const Value = extern union {
19111911
1912 .lazy_align => {1912 .lazy_align => {
1913 const ty = lhs.castTag(.lazy_align).?.data;1913 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 }) {
1915 return .gt;1919 return .gt;
1916 } else {1920 } else {
1917 return .eq;1921 return .eq;
...@@ -1919,7 +1923,11 @@ pub const Value = extern union {...@@ -1919,7 +1923,11 @@ pub const Value = extern union {
1919 },1923 },
1920 .lazy_size => {1924 .lazy_size => {
1921 const ty = lhs.castTag(.lazy_size).?.data;1925 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 }) {
1923 return .gt;1931 return .gt;
1924 } else {1932 } else {
1925 return .eq;1933 return .eq;
src/zig_llvm.cpp+24-6
...@@ -444,6 +444,15 @@ LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,...@@ -444,6 +444,15 @@ LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
444 return wrap(call_inst);444 return wrap(call_inst);
445}445}
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
447LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,456LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
448 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile)457 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile)
449{458{
...@@ -1065,12 +1074,21 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {...@@ -1065,12 +1074,21 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) {
1065 }1074 }
1066}1075}
10671076
1068void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val) {1077void ZigLLVMAddByValAttr(LLVMValueRef Val, unsigned ArgNo, LLVMTypeRef type_val) {
1069 Function *func = unwrap<Function>(fn_ref);1078 if (isa<Function>(unwrap(Val))) {
1070 AttrBuilder attr_builder(func->getContext());1079 Function *func = unwrap<Function>(Val);
1071 Type *llvm_type = unwrap<Type>(type_val);1080 AttrBuilder attr_builder(func->getContext());
1072 attr_builder.addByValAttr(llvm_type);1081 Type *llvm_type = unwrap<Type>(type_val);
1073 func->addParamAttrs(ArgNo, attr_builder);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 }
1074}1092}
10751093
1076void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) {1094void 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...@@ -129,6 +129,8 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef functio
129 LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC,129 LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC,
130 enum ZigLLVM_CallAttr attr, const char *Name);130 enum ZigLLVM_CallAttr attr, const char *Name);
131131
132ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A);
133
132ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,134ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
133 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);135 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" {...@@ -1118,3 +1118,12 @@ test "ambiguous reference error ignores current declaration" {
1118 };1118 };
1119 try expect(S.b.foo == 666);1119 try expect(S.b.foo == 666);
1120}1120}
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" {...@@ -1429,3 +1429,11 @@ test "peer type resolution of function pointer and function body" {
1429 try expect(@TypeOf(a, b) == *const fn () u32);1429 try expect(@TypeOf(a, b) == *const fn () u32);
1430 try expect(@TypeOf(b, a) == *const fn () u32);1430 try expect(@TypeOf(b, a) == *const fn () u32);
1431}1431}
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" {...@@ -565,3 +565,10 @@ test "typeInfo resolves usingnamespace declarations" {
565 try expect(@typeInfo(B).Struct.decls.len == 2);565 try expect(@typeInfo(B).Struct.decls.len == 2);
566 //a566 //a
567}567}
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();...@@ -833,3 +833,41 @@ struct PD zig_ret_PD();
833int c_assert_ret_PD(){833int c_assert_ret_PD(){
834 return c_assert_PD(zig_ret_PD());834 return c_assert_PD(zig_ret_PD());
835}835}
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" {...@@ -917,8 +917,6 @@ test "CFF: C passes to Zig" {
917 try expectOk(c_send_CFF());917 try expectOk(c_send_CFF());
918}918}
919test "CFF: C returns to Zig" {919test "CFF: C returns to Zig" {
920 // segfault on aarch64 and mips
921 if (builtin.target.cpu.arch == .aarch64) return error.SkipZigTest;
922 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;920 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
923 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;921 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
924 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;922 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
...@@ -990,3 +988,47 @@ pub export fn zig_assert_PD(lv: PD) c_int {...@@ -990,3 +988,47 @@ pub export fn zig_assert_PD(lv: PD) c_int {
990 if (err != 0) std.debug.print("Received {}", .{lv});988 if (err != 0) std.debug.print("Received {}", .{lv});
991 return err;989 return err;
992}990}
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 {...@@ -16,6 +16,14 @@ comptime {
16 var a: A = A{};16 var a: A = A{};
17 _ = a;17 _ = a;
18}18}
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
20// error28// error
21// backend=stage229// backend=stage2
...@@ -25,3 +33,5 @@ comptime {...@@ -25,3 +33,5 @@ comptime {
25// :8:17: error: expected 8 vector elements; found 033// :8:17: error: expected 8 vector elements; found 0
26// :12:17: error: expected 8 array elements; found 134// :12:17: error: expected 8 array elements; found 1
27// :16:17: error: expected 8 array elements; found 035// :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