| author | |
| committer | |
| log | 7c527c6dfe590a1251b51f6e1cfe8a4ba9bb0d67 |
| tree | 2bf79b09302f3c574b18b50591fdad9a555b6e8f |
| parent | 89c374cd2dff36477ac1513006c03721ef946a2a |
| parent | bbcd959c2b1721d81af5829b56e01cc472b58816 |
| signature |
Stage2 bug fixes20 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 { |
| 1044 | 1044 | ||
| 1045 | .root => return queryFieldSrc(tree.*, query, file, tree.containerDeclRoot()), | 1045 | .root => return queryFieldSrc(tree.*, query, file, tree.containerDeclRoot()), |
| 1046 | 1046 | ||
| 1047 | else => unreachable, | 1047 | // This struct was generated using @Type |
| 1048 | else => return s.srcLoc(mod), | ||
| 1048 | } | 1049 | } |
| 1049 | } | 1050 | } |
| 1050 | 1051 | ||
| ... | @@ -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 | } |
| 1276 | 1278 | ||
| ... | @@ -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"); |
| 4635 | 4637 | ||
| 4636 | // Note this resolves the type of the Decl, not the value; if this Decl | 4638 | // 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 block | 130 | /// 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; |
| 1899 | 1899 | ||
| 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 | } |
| 4111 | 4117 | ||
| ... | @@ -4225,7 +4231,6 @@ fn validateStructInit( | ... | @@ -4225,7 +4231,6 @@ fn validateStructInit( |
| 4225 | } | 4231 | } |
| 4226 | 4232 | ||
| 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 | } |
| 4241 | 4247 | ||
| ... | @@ -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(); |
| 4285 | 4291 | ||
| 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); | ||
| 4290 | 4297 | ||
| 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; |
| 4293 | 4300 | ||
| 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 | } | ||
| 4303 | 4310 | ||
| 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 | }; | ||
| 4309 | 4328 | ||
| 4310 | if ((is_comptime or block.is_comptime) and | 4329 | 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 | } |
| 17081 | 17100 | ||
| 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 | } |
| 17096 | 17115 | ||
| ... | @@ -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 |
| 18778 | 18797 | ||
| 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); |
| 18785 | 18804 | ||
| ... | @@ -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 number | 24356 | // 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 | }, | ||
| 26546 | 26581 | ||
| 26547 | .zero, | 26582 | .zero, |
| 26548 | .one, | 26583 | .one, |
| ... | @@ -27191,8 +27226,8 @@ fn coerceTupleToStruct( | ... | @@ -27191,8 +27226,8 @@ fn coerceTupleToStruct( |
| 27191 | } | 27226 | } |
| 27192 | 27227 | ||
| 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 | } |
| 27198 | 27233 | ||
| ... | @@ -27297,8 +27332,8 @@ fn coerceTupleToTuple( | ... | @@ -27297,8 +27332,8 @@ fn coerceTupleToTuple( |
| 27297 | } | 27332 | } |
| 27298 | 27333 | ||
| 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 | } |
| 27304 | 27339 | ||
| ... | @@ -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 | } |
| 31299 | 31334 | ||
| 31300 | pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { | 31335 | pub 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 | } |
| 31303 | 31341 | ||
| 31304 | fn typeAbiSize(sema: *Sema, ty: Type) !u64 { | 31342 | fn 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 | }; |
| 4680 | 4702 | ||
| 4681 | if (fn_info.return_type.isError() and | 4703 | 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 | } |
| 4686 | 4708 | ||
| ... | @@ -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 | ); |
| 4849 | 4892 | ||
| 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 having | 4979 | // 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 callsite | 4980 | // 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 | }; |
| 89 | 89 | ||
| 90 | pub const Value = opaque { | 90 | pub 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; |
| 93 | 93 | ||
| 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 | } |
| 401 | 401 | ||
| 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; |
| 405 | 406 | ||
| 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), |
| 268 | 269 | ||
| 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 | } |
| 2318 | 2319 | ||
| 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; |
| 2321 | 2337 |
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 | } |
| 2314 | 2314 | ||
| 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 { |
| 2474 | 2477 | ||
| 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 | }, |
| 2488 | 2491 | ||
| 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 | } |
| 2507 | 2511 | ||
| 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 | }, |
| 2519 | 2524 | ||
| 2520 | .array, .vector => return ty.arrayLen() != 0 and | 2525 | .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), |
| 2524 | 2529 | ||
| 2525 | .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0, | 2530 | .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0, |
| 2526 | 2531 | ||
| ... | @@ -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 field | 2536 | 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 | } |
| 2666 | 2671 | ||
| 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 | } |
| 2670 | 2675 | ||
| 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 | } |
| 2674 | 2679 | ||
| 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 | } |
| 2814 | 2819 | ||
| 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 | }; |
| 2819 | 2824 | ||
| 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 { |
| 2971 | 2976 | ||
| 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; | ||
| 3048 | 3062 | ||
| 3049 | const field_align = if (field.abi_align != 0) | 3063 | const field_align = if (field.abi_align != 0) |
| 3050 | field.abi_align | 3064 | 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; | ||
| 3165 | 3182 | ||
| 3166 | const field_align = if (field.abi_align != 0) | 3183 | const field_align = if (field.abi_align != 0) |
| 3167 | field.abi_align | 3184 | 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 { |
| 1911 | 1911 | ||
| 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 | } |
| 446 | 446 | ||
| 447 | void 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 | |||
| 447 | LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, | 456 | LLVMValueRef 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 | } |
| 1067 | 1076 | ||
| 1068 | void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val) { | 1077 | void 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 | } |
| 1075 | 1093 | ||
| 1076 | void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) { | 1094 | void 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); |
| 131 | 131 | ||
| 132 | ZIG_EXTERN_C void ZigLLVMAddAttributeAtIndex(LLVMValueRef Val, unsigned Idx, LLVMAttributeRef A); | ||
| 133 | |||
| 132 | ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, | 134 | ZIG_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); |
| 134 | 136 |
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 | |||
| 1122 | test "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 | |||
| 1433 | test "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 | //a | 566 | //a |
| 567 | } | 567 | } |
| 568 | |||
| 569 | test "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(); |
| 833 | int c_assert_ret_PD(){ | 833 | int c_assert_ret_PD(){ |
| 834 | return c_assert_PD(zig_ret_PD()); | 834 | return c_assert_PD(zig_ret_PD()); |
| 835 | } | 835 | } |
| 836 | |||
| 837 | struct ByRef { | ||
| 838 | int val; | ||
| 839 | int arr[15]; | ||
| 840 | }; | ||
| 841 | struct ByRef c_modify_by_ref_param(struct ByRef in) { | ||
| 842 | in.val = 42; | ||
| 843 | return in; | ||
| 844 | } | ||
| 845 | |||
| 846 | struct 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 | |||
| 859 | void 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 | } |
| 919 | test "CFF: C returns to Zig" { | 919 | test "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 | |||
| 992 | const ByRef = extern struct { | ||
| 993 | val: c_int, | ||
| 994 | arr: [15]c_int, | ||
| 995 | }; | ||
| 996 | extern fn c_modify_by_ref_param(ByRef) ByRef; | ||
| 997 | |||
| 998 | test "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 | |||
| 1005 | const 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 | |||
| 1018 | extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void; | ||
| 1019 | test "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 | } |
| 19 | pub export fn entry1() void { | ||
| 20 | var bla: V = .{ 1, 2, 3, 4 }; | ||
| 21 | _ = bla; | ||
| 22 | } | ||
| 23 | pub export fn entry2() void { | ||
| 24 | var bla: A = .{ 1, 2, 3, 4 }; | ||
| 25 | _ = bla; | ||
| 26 | } | ||
| 19 | 27 | ||
| 20 | // error | 28 | // error |
| 21 | // backend=stage2 | 29 | // backend=stage2 |
| ... | @@ -25,3 +33,5 @@ comptime { | ... | @@ -25,3 +33,5 @@ comptime { |
| 25 | // :8:17: error: expected 8 vector elements; found 0 | 33 | // :8:17: error: expected 8 vector elements; found 0 |
| 26 | // :12:17: error: expected 8 array elements; found 1 | 34 | // :12:17: error: expected 8 array elements; found 1 |
| 27 | // :16:17: error: expected 8 array elements; found 0 | 35 | // :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 @@ | ||
| 1 | var a: u32 = 2; | ||
| 2 | const b = a; | ||
| 3 | pub 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 @@ | ||
| 1 | pub 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 @@ | ||
| 1 | const S = struct { | ||
| 2 | a: u32, | ||
| 3 | b: comptime_int, | ||
| 4 | fn init() S { | ||
| 5 | return .{ .a = 1 }; | ||
| 6 | } | ||
| 7 | }; | ||
| 8 | comptime { | ||
| 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 | ||