authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-01 17:38:11-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-01 17:38:11-05:00
log4071b22454eb991beefe9f789911a6ba473ce5a4
tree8bc6fd9eb6814a726223b1cb2e8cbf1dc2757cee
parent6e52f36d46f6dbcd4be6295fea6d54868399c12f
parent6ded2d2adb806845b79f1c5039ab76fdb890a225
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13715 from Vexu/cbe

cbe bug fixes and improvements

21 files changed, 409 insertions(+), 275 deletions(-)

lib/compiler_rt/atomics.zig+1-1
...@@ -453,7 +453,7 @@ fn __atomic_fetch_nand_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {...@@ -453,7 +453,7 @@ fn __atomic_fetch_nand_8(ptr: *u64, val: u64, model: i32) callconv(.C) u64 {
453}453}
454454
455comptime {455comptime {
456 if (supports_atomic_ops) {456 if (supports_atomic_ops and builtin.object_format != .c) {
457 @export(__atomic_load, .{ .name = "__atomic_load", .linkage = linkage });457 @export(__atomic_load, .{ .name = "__atomic_load", .linkage = linkage });
458 @export(__atomic_store, .{ .name = "__atomic_store", .linkage = linkage });458 @export(__atomic_store, .{ .name = "__atomic_store", .linkage = linkage });
459 @export(__atomic_exchange, .{ .name = "__atomic_exchange", .linkage = linkage });459 @export(__atomic_exchange, .{ .name = "__atomic_exchange", .linkage = linkage });
lib/compiler_rt/memcpy.zig+4-1
...@@ -1,8 +1,11 @@...@@ -1,8 +1,11 @@
1const std = @import("std");1const std = @import("std");
2const common = @import("./common.zig");2const common = @import("./common.zig");
3const builtin = @import("builtin");
34
4comptime {5comptime {
5 @export(memcpy, .{ .name = "memcpy", .linkage = common.linkage });6 if (builtin.object_format != .c) {
7 @export(memcpy, .{ .name = "memcpy", .linkage = common.linkage });
8 }
6}9}
710
8pub fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 {11pub fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 {
lib/compiler_rt/memset.zig+5-2
...@@ -1,9 +1,12 @@...@@ -1,9 +1,12 @@
1const std = @import("std");1const std = @import("std");
2const common = @import("./common.zig");2const common = @import("./common.zig");
3const builtin = @import("builtin");
34
4comptime {5comptime {
5 @export(memset, .{ .name = "memset", .linkage = common.linkage });6 if (builtin.object_format != .c) {
6 @export(__memset, .{ .name = "__memset", .linkage = common.linkage });7 @export(memset, .{ .name = "memset", .linkage = common.linkage });
8 @export(__memset, .{ .name = "__memset", .linkage = common.linkage });
9 }
7}10}
811
9pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 {12pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 {
src/AstGen.zig+10-3
...@@ -8551,11 +8551,18 @@ fn shiftOp(...@@ -8551,11 +8551,18 @@ fn shiftOp(
8551 rhs_node: Ast.Node.Index,8551 rhs_node: Ast.Node.Index,
8552 tag: Zir.Inst.Tag,8552 tag: Zir.Inst.Tag,
8553) InnerError!Zir.Inst.Ref {8553) InnerError!Zir.Inst.Ref {
8554 var line = gz.astgen.source_line - gz.decl_line;
8555 var column = gz.astgen.source_column;
8554 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);8556 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
85558557
8556 maybeAdvanceSourceCursorToMainToken(gz, node);8558 switch (gz.astgen.tree.nodes.items(.tag)[node]) {
8557 const line = gz.astgen.source_line - gz.decl_line;8559 .shl, .shr => {
8558 const column = gz.astgen.source_column;8560 maybeAdvanceSourceCursorToMainToken(gz, node);
8561 line = gz.astgen.source_line - gz.decl_line;
8562 column = gz.astgen.source_column;
8563 },
8564 else => {},
8565 }
85598566
8560 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);8567 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
8561 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);8568 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
src/Sema.zig+2-2
...@@ -3645,7 +3645,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3645,7 +3645,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3645 const final_elem_ty = try decl.ty.copy(sema.arena);3645 const final_elem_ty = try decl.ty.copy(sema.arena);
3646 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{3646 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
3647 .pointee_type = final_elem_ty,3647 .pointee_type = final_elem_ty,
3648 .mutable = var_is_mut,3648 .mutable = true,
3649 .@"align" = iac.data.alignment,3649 .@"align" = iac.data.alignment,
3650 .@"addrspace" = target_util.defaultAddressSpace(target, .local),3650 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3651 });3651 });
...@@ -3669,7 +3669,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3669,7 +3669,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
36693669
3670 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{3670 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
3671 .pointee_type = final_elem_ty,3671 .pointee_type = final_elem_ty,
3672 .mutable = var_is_mut,3672 .mutable = true,
3673 .@"align" = inferred_alloc.data.alignment,3673 .@"align" = inferred_alloc.data.alignment,
3674 .@"addrspace" = target_util.defaultAddressSpace(target, .local),3674 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3675 });3675 });
src/codegen/c.zig+353-252
...@@ -50,6 +50,8 @@ pub const CValue = union(enum) {...@@ -50,6 +50,8 @@ pub const CValue = union(enum) {
50 /// Render these bytes literally.50 /// Render these bytes literally.
51 /// TODO make this a [*:0]const u8 to save memory51 /// TODO make this a [*:0]const u8 to save memory
52 bytes: []const u8,52 bytes: []const u8,
53 /// Index of an instruction that should later be rendered inline.
54 inline_index: Air.Inst.Index,
53};55};
5456
55const BlockData = struct {57const BlockData = struct {
...@@ -79,6 +81,7 @@ const ValueRenderLocation = enum {...@@ -79,6 +81,7 @@ const ValueRenderLocation = enum {
79 FunctionArgument,81 FunctionArgument,
80 Initializer,82 Initializer,
81 Other,83 Other,
84 condition,
82};85};
8386
84const BuiltinInfo = enum {87const BuiltinInfo = enum {
...@@ -278,6 +281,19 @@ pub const Function = struct {...@@ -278,6 +281,19 @@ pub const Function = struct {
278 return result;281 return result;
279 }282 }
280283
284 fn resolveInstNoInline(f: *Function, inst: Air.Inst.Ref) !CValue {
285 const operand = try f.resolveInst(inst);
286 if (operand != .inline_index) return operand;
287
288 const inst_ty = f.air.typeOf(inst);
289 const writer = f.object.writer();
290 const local = try f.allocLocal(inst_ty, .Const);
291 try writer.writeAll(" = ");
292 try f.writeCValueInline(operand.inline_index);
293 try writer.writeAll(";\n");
294 return local;
295 }
296
281 fn wantSafety(f: *Function) bool {297 fn wantSafety(f: *Function) bool {
282 return switch (f.object.dg.module.optimizeMode()) {298 return switch (f.object.dg.module.optimizeMode()) {
283 .Debug, .ReleaseSafe => true,299 .Debug, .ReleaseSafe => true,
...@@ -313,10 +329,95 @@ pub const Function = struct {...@@ -313,10 +329,95 @@ pub const Function = struct {
313 .constant => |inst| {329 .constant => |inst| {
314 const ty = f.air.typeOf(inst);330 const ty = f.air.typeOf(inst);
315 const val = f.air.value(inst).?;331 const val = f.air.value(inst).?;
316 return f.object.dg.renderValue(w, ty, val, location);332 try f.object.dg.renderValue(w, ty, val, location);
333 },
334 .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location),
335 .inline_index => |node| {
336 if (location != .condition) try w.writeByte('(');
337 try f.writeCValueInline(node);
338 if (location != .condition) try w.writeByte(')');
317 },339 },
318 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),340 else => try f.object.dg.writeCValue(w, c_value),
319 else => return f.object.dg.writeCValue(w, c_value),341 }
342 }
343
344 const E = error{ OutOfMemory, AnalysisFail };
345
346 fn writeCValueInline(f: *Function, inst: Air.Inst.Index) E!void {
347 switch (f.air.instructions.items(.tag)[inst]) {
348 // zig fmt: off
349 // TODO use a different strategy for add, sub, mul, div
350 // that communicates to the optimizer that wrapping is UB.
351 .add => try airBinOp(f, inst, "+", "add", .None),
352 .sub => try airBinOp(f, inst, "-", "sub", .None),
353 .mul => try airBinOp(f, inst, "*", "mul", .None),
354
355 .div_float => try airBinBuiltinCall(f, inst, "div", .None),
356
357 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
358 .rem => {
359 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
360 const lhs_ty = f.air.typeOf(bin_op.lhs);
361 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
362 // so we only check one.
363 if (lhs_ty.isInt())
364 try airBinOp(f, inst, "%", "rem", .None)
365 else
366 try airBinFloatOp(f, inst, "fmod");
367 },
368 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),
369 .mod => try airBinBuiltinCall(f, inst, "mod", .None),
370
371 .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits),
372 .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits),
373 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits),
374
375 .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits),
376 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits),
377 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),
378 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),
379
380 .min => try airMinMax(f, inst, '<', "fmin"),
381 .max => try airMinMax(f, inst, '>', "fmax"),
382
383 .cmp_gt => try airCmpOp(f, inst, ">", "gt"),
384 .cmp_gte => try airCmpOp(f, inst, ">=", "ge"),
385 .cmp_lt => try airCmpOp(f, inst, "<", "lt"),
386 .cmp_lte => try airCmpOp(f, inst, "<=", "le"),
387
388 .cmp_eq => try airEquality(f, inst, "((", "==", "eq"),
389 .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"),
390
391 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None),
392 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None),
393 .xor => try airBinOp(f, inst, "^", "xor", .None),
394 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None),
395 .shl, => try airBinBuiltinCall(f, inst, "shlw", .Bits),
396 .shl_exact => try airBinOp(f, inst, "<<", "shl", .None),
397 .not => try airNot (f, inst),
398
399 .is_err => try airIsErr(f, inst, false, "!="),
400 .is_non_err => try airIsErr(f, inst, false, "=="),
401 .is_err_ptr => try airIsErr(f, inst, true, "!="),
402 .is_non_err_ptr => try airIsErr(f, inst, true, "=="),
403
404 .is_null => try airIsNull(f, inst, "==", false),
405 .is_non_null => try airIsNull(f, inst, "!=", false),
406 .is_null_ptr => try airIsNull(f, inst, "==", true),
407 .is_non_null_ptr => try airIsNull(f, inst, "!=", true),
408
409 .get_union_tag => try airGetUnionTag(f, inst),
410 .clz => try airUnBuiltinCall(f, inst, "clz", .Bits),
411 .ctz => try airUnBuiltinCall(f, inst, "ctz", .Bits),
412 .popcount => try airUnBuiltinCall(f, inst, "popcount", .Bits),
413 .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .Bits),
414 .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .Bits),
415 .tag_name => try airTagName(f, inst),
416 .error_name => try airErrorName(f, inst),
417
418 .ptrtoint => try airPtrToInt(f, inst),
419 else => unreachable,
420 // zig fmt: on
320 }421 }
321 }422 }
322423
...@@ -342,6 +443,7 @@ pub const Function = struct {...@@ -342,6 +443,7 @@ pub const Function = struct {
342 try w.writeByte('.');443 try w.writeByte('.');
343 return f.writeCValue(w, member, .Other);444 return f.writeCValue(w, member, .Other);
344 },445 },
446 .inline_index => unreachable, // Use resolveInstNoInline
345 else => return f.object.dg.writeCValueMember(w, c_value, member),447 else => return f.object.dg.writeCValueMember(w, c_value, member),
346 }448 }
347 }449 }
...@@ -542,9 +644,14 @@ pub const DeclGen = struct {...@@ -542,9 +644,14 @@ pub const DeclGen = struct {
542 return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty);644 return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty);
543 },645 },
544 },646 },
545 .Union => FieldInfo{647 .Union => switch (container_ty.containerLayout()) {
546 .name = container_ty.unionFields().keys()[index],648 .Auto, .Extern => FieldInfo{
547 .ty = container_ty.unionFields().values()[index].ty,649 .name = container_ty.unionFields().keys()[index],
650 .ty = container_ty.unionFields().values()[index].ty,
651 },
652 .Packed => {
653 return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty);
654 },
548 },655 },
549 .Pointer => field_info: {656 .Pointer => field_info: {
550 assert(container_ty.isSlice());657 assert(container_ty.isSlice());
...@@ -1165,6 +1272,27 @@ pub const DeclGen = struct {...@@ -1165,6 +1272,27 @@ pub const DeclGen = struct {
1165 try writer.writeByte(')');1272 try writer.writeByte(')');
1166 }1273 }
11671274
1275 const index = ty.unionTagFieldIndex(union_obj.tag, dg.module).?;
1276 const field_ty = ty.unionFields().values()[index].ty;
1277 const field_name = ty.unionFields().keys()[index];
1278 if (ty.containerLayout() == .Packed) {
1279 if (field_ty.hasRuntimeBits()) {
1280 if (field_ty.isPtrAtRuntime()) {
1281 try writer.writeByte('(');
1282 try dg.renderTypecast(writer, ty);
1283 try writer.writeByte(')');
1284 } else if (field_ty.zigTypeTag() == .Float) {
1285 try writer.writeByte('(');
1286 try dg.renderTypecast(writer, ty);
1287 try writer.writeByte(')');
1288 }
1289 try dg.renderValue(writer, field_ty, union_obj.val, .Initializer);
1290 } else {
1291 try writer.writeAll("0");
1292 }
1293 return;
1294 }
1295
1168 try writer.writeByte('{');1296 try writer.writeByte('{');
1169 if (ty.unionTagTypeSafety()) |tag_ty| {1297 if (ty.unionTagTypeSafety()) |tag_ty| {
1170 const layout = ty.unionGetLayout(target);1298 const layout = ty.unionGetLayout(target);
...@@ -1176,9 +1304,6 @@ pub const DeclGen = struct {...@@ -1176,9 +1304,6 @@ pub const DeclGen = struct {
1176 try writer.writeAll(".payload = {");1304 try writer.writeAll(".payload = {");
1177 }1305 }
11781306
1179 const index = ty.unionTagFieldIndex(union_obj.tag, dg.module).?;
1180 const field_ty = ty.unionFields().values()[index].ty;
1181 const field_name = ty.unionFields().keys()[index];
1182 var it = ty.unionFields().iterator();1307 var it = ty.unionFields().iterator();
1183 if (field_ty.hasRuntimeBits()) {1308 if (field_ty.hasRuntimeBits()) {
1184 try writer.print(".{ } = ", .{fmtIdent(field_name)});1309 try writer.print(".{ } = ", .{fmtIdent(field_name)});
...@@ -1445,7 +1570,7 @@ pub const DeclGen = struct {...@@ -1445,7 +1570,7 @@ pub const DeclGen = struct {
1445 if (field_id == 0) try buffer.appendSlice(" char empty_tuple;\n");1570 if (field_id == 0) try buffer.appendSlice(" char empty_tuple;\n");
1446 }1571 }
1447 const name_begin = buffer.items.len + "} ".len;1572 const name_begin = buffer.items.len + "} ".len;
1448 try buffer.writer().print("}} zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});1573 try buffer.writer().print("}} zig_T_{}_{d};\n", .{ typeToCIdentifier(t, dg.module), @truncate(u16, t.hash(dg.module)) });
1449 const name_end = buffer.items.len - ";\n".len;1574 const name_end = buffer.items.len - ";\n".len;
14501575
1451 const rendered = try buffer.toOwnedSlice();1576 const rendered = try buffer.toOwnedSlice();
...@@ -1794,9 +1919,17 @@ pub const DeclGen = struct {...@@ -1794,9 +1919,17 @@ pub const DeclGen = struct {
17941919
1795 return w.writeAll(name);1920 return w.writeAll(name);
1796 },1921 },
1797 .Struct, .Union => |tag| if (tag == .Struct and t.containerLayout() == .Packed)1922 .Struct, .Union => |tag| if (t.containerLayout() == .Packed) {
1798 try dg.renderType(w, t.castTag(.@"struct").?.data.backing_int_ty, kind)1923 if (t.castTag(.@"struct")) |struct_obj| {
1799 else if (t.isSimpleTupleOrAnonStruct()) {1924 try dg.renderType(w, struct_obj.data.backing_int_ty, kind);
1925 } else {
1926 var buf: Type.Payload.Bits = .{
1927 .base = .{ .tag = .int_unsigned },
1928 .data = @intCast(u16, t.bitSize(target)),
1929 };
1930 try dg.renderType(w, Type.initPayload(&buf.base), kind);
1931 }
1932 } else if (t.isSimpleTupleOrAnonStruct()) {
1800 const ExpectedContents = struct { types: [8]Type, values: [8]Value };1933 const ExpectedContents = struct { types: [8]Type, values: [8]Value };
1801 var stack align(@alignOf(ExpectedContents)) =1934 var stack align(@alignOf(ExpectedContents)) =
1802 std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa);1935 std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa);
...@@ -1961,7 +2094,7 @@ pub const DeclGen = struct {...@@ -1961,7 +2094,7 @@ pub const DeclGen = struct {
1961 try buffer.appendSlice("static ");2094 try buffer.appendSlice("static ");
1962 try dg.renderType(bw, name_slice_ty, .Complete);2095 try dg.renderType(bw, name_slice_ty, .Complete);
1963 const name_begin = buffer.items.len + " ".len;2096 const name_begin = buffer.items.len + " ".len;
1964 try bw.print(" zig_tagName_{}(", .{typeToCIdentifier(enum_ty, dg.module)});2097 try bw.print(" zig_tagName_{}_{d}(", .{ typeToCIdentifier(enum_ty, dg.module), @enumToInt(enum_ty.getOwnerDecl()) });
1965 const name_end = buffer.items.len - "(".len;2098 const name_end = buffer.items.len - "(".len;
1966 try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0, .Complete);2099 try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0, .Complete);
1967 try buffer.appendSlice(") {\n switch (tag) {\n");2100 try buffer.appendSlice(") {\n switch (tag) {\n");
...@@ -2041,7 +2174,7 @@ pub const DeclGen = struct {...@@ -2041,7 +2174,7 @@ pub const DeclGen = struct {
20412174
2042 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {2175 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
2043 switch (c_value) {2176 switch (c_value) {
2044 .none => unreachable,2177 .none, .inline_index => unreachable,
2045 .local => |i| return w.print("t{d}", .{i}),2178 .local => |i| return w.print("t{d}", .{i}),
2046 .local_ref => |i| return w.print("&t{d}", .{i}),2179 .local_ref => |i| return w.print("&t{d}", .{i}),
2047 .constant => unreachable,2180 .constant => unreachable,
...@@ -2060,7 +2193,7 @@ pub const DeclGen = struct {...@@ -2060,7 +2193,7 @@ pub const DeclGen = struct {
20602193
2061 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {2194 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
2062 switch (c_value) {2195 switch (c_value) {
2063 .none => unreachable,2196 .none, .inline_index => unreachable,
2064 .local => |i| return w.print("(*t{d})", .{i}),2197 .local => |i| return w.print("(*t{d})", .{i}),
2065 .local_ref => |i| return w.print("t{d}", .{i}),2198 .local_ref => |i| return w.print("t{d}", .{i}),
2066 .constant => unreachable,2199 .constant => unreachable,
...@@ -2090,7 +2223,7 @@ pub const DeclGen = struct {...@@ -2090,7 +2223,7 @@ pub const DeclGen = struct {
20902223
2091 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {2224 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
2092 switch (c_value) {2225 switch (c_value) {
2093 .none, .constant, .field, .undef => unreachable,2226 .none, .constant, .field, .undef, .inline_index => unreachable,
2094 .local, .arg, .decl, .identifier, .bytes => {2227 .local, .arg, .decl, .identifier, .bytes => {
2095 try dg.writeCValue(writer, c_value);2228 try dg.writeCValue(writer, c_value);
2096 try writer.writeAll("->");2229 try writer.writeAll("->");
...@@ -2111,11 +2244,16 @@ pub const DeclGen = struct {...@@ -2111,11 +2244,16 @@ pub const DeclGen = struct {
2111 return writer.writeAll(exports.items[0].options.name);2244 return writer.writeAll(exports.items[0].options.name);
2112 } else if (decl.isExtern()) {2245 } else if (decl.isExtern()) {
2113 return writer.writeAll(mem.sliceTo(decl.name, 0));2246 return writer.writeAll(mem.sliceTo(decl.name, 0));
2247 } else if (dg.module.test_functions.get(decl_index)) |_| {
2248 const gpa = dg.gpa;
2249 const name = try decl.getFullyQualifiedName(dg.module);
2250 defer gpa.free(name);
2251 return writer.print("{}_{d}", .{ fmtIdent(name), @enumToInt(decl_index) });
2114 } else {2252 } else {
2115 const gpa = dg.gpa;2253 const gpa = dg.gpa;
2116 const name = try decl.getFullyQualifiedName(dg.module);2254 const name = try decl.getFullyQualifiedName(dg.module);
2117 defer gpa.free(name);2255 defer gpa.free(name);
2118 return writer.print("{ }", .{fmtIdent(name)});2256 return writer.print("{}", .{fmtIdent(name)});
2119 }2257 }
2120 }2258 }
21212259
...@@ -2401,37 +2539,26 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2401,37 +2539,26 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2401 .ptr_add => try airPtrAddSub(f, inst, '+'),2539 .ptr_add => try airPtrAddSub(f, inst, '+'),
2402 .ptr_sub => try airPtrAddSub(f, inst, '-'),2540 .ptr_sub => try airPtrAddSub(f, inst, '-'),
24032541
2404 // TODO use a different strategy for add, sub, mul, div2542 .add => CValue{ .inline_index = inst },
2405 // that communicates to the optimizer that wrapping is UB.2543 .sub => CValue{ .inline_index = inst },
2406 .add => try airBinOp(f, inst, "+", "add", .None),2544 .mul => CValue{ .inline_index = inst },
2407 .sub => try airBinOp(f, inst, "-", "sub", .None),
2408 .mul => try airBinOp(f, inst, "*", "mul", .None),
24092545
2410 .neg => try airFloatNeg(f, inst),2546 .neg => try airFloatNeg(f, inst),
2411 .div_float => try airBinBuiltinCall(f, inst, "div", .None),2547 .div_float => CValue{ .inline_index = inst },
24122548
2413 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),2549 .div_trunc, .div_exact => CValue{ .inline_index = inst },
2414 .rem => blk: {2550 .rem => CValue{ .inline_index = inst },
2415 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2551 .div_floor => CValue{ .inline_index = inst },
2416 const lhs_ty = f.air.typeOf(bin_op.lhs);2552 .mod => CValue{ .inline_index = inst },
2417 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2418 // so we only check one.
2419 break :blk if (lhs_ty.isInt())
2420 try airBinOp(f, inst, "%", "rem", .None)
2421 else
2422 try airBinFloatOp(f, inst, "fmod");
2423 },
2424 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),
2425 .mod => try airBinBuiltinCall(f, inst, "mod", .None),
24262553
2427 .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits),2554 .addwrap => CValue{ .inline_index = inst },
2428 .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits),2555 .subwrap => CValue{ .inline_index = inst },
2429 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits),2556 .mulwrap => CValue{ .inline_index = inst },
24302557
2431 .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits),2558 .add_sat => CValue{ .inline_index = inst },
2432 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits),2559 .sub_sat => CValue{ .inline_index = inst },
2433 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),2560 .mul_sat => CValue{ .inline_index = inst },
2434 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),2561 .shl_sat => CValue{ .inline_index = inst },
24352562
2436 .sqrt,2563 .sqrt,
2437 .sin,2564 .sin,
...@@ -2456,45 +2583,45 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2456,45 +2583,45 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2456 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),2583 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),
2457 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),2584 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),
24582585
2459 .min => try airMinMax(f, inst, '<', "fmin"),2586 .min => CValue{ .inline_index = inst },
2460 .max => try airMinMax(f, inst, '>', "fmax"),2587 .max => CValue{ .inline_index = inst },
24612588
2462 .slice => try airSlice(f, inst),2589 .slice => try airSlice(f, inst),
24632590
2464 .cmp_gt => try airCmpOp(f, inst, ">", "gt"),2591 .cmp_gt => CValue{ .inline_index = inst },
2465 .cmp_gte => try airCmpOp(f, inst, ">=", "ge"),2592 .cmp_gte => CValue{ .inline_index = inst },
2466 .cmp_lt => try airCmpOp(f, inst, "<", "lt"),2593 .cmp_lt => CValue{ .inline_index = inst },
2467 .cmp_lte => try airCmpOp(f, inst, "<=", "le"),2594 .cmp_lte => CValue{ .inline_index = inst },
24682595
2469 .cmp_eq => try airEquality(f, inst, "((", "==", "eq"),2596 .cmp_eq => CValue{ .inline_index = inst },
2470 .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"),2597 .cmp_neq => CValue{ .inline_index = inst },
24712598
2472 .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}),2599 .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}),
2473 .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst),2600 .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst),
24742601
2475 // bool_and and bool_or are non-short-circuit operations2602 // bool_and and bool_or are non-short-circuit operations
2476 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None),2603 .bool_and, .bit_and => CValue{ .inline_index = inst },
2477 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None),2604 .bool_or, .bit_or => CValue{ .inline_index = inst },
2478 .xor => try airBinOp(f, inst, "^", "xor", .None),2605 .xor => CValue{ .inline_index = inst },
2479 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None),2606 .shr, .shr_exact => CValue{ .inline_index = inst },
2480 .shl, => try airBinBuiltinCall(f, inst, "shlw", .Bits),2607 .shl, => CValue{ .inline_index = inst },
2481 .shl_exact => try airBinOp(f, inst, "<<", "shl", .None),2608 .shl_exact => CValue{ .inline_index = inst },
2482 .not => try airNot (f, inst),2609 .not => CValue{ .inline_index = inst },
24832610
2484 .optional_payload => try airOptionalPayload(f, inst),2611 .optional_payload => try airOptionalPayload(f, inst),
2485 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),2612 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),
2486 .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst),2613 .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst),
2487 .wrap_optional => try airWrapOptional(f, inst),2614 .wrap_optional => try airWrapOptional(f, inst),
24882615
2489 .is_err => try airIsErr(f, inst, false, "!="),2616 .is_err => CValue{ .inline_index = inst },
2490 .is_non_err => try airIsErr(f, inst, false, "=="),2617 .is_non_err => CValue{ .inline_index = inst },
2491 .is_err_ptr => try airIsErr(f, inst, true, "!="),2618 .is_err_ptr => CValue{ .inline_index = inst },
2492 .is_non_err_ptr => try airIsErr(f, inst, true, "=="),2619 .is_non_err_ptr => CValue{ .inline_index = inst },
24932620
2494 .is_null => try airIsNull(f, inst, "==", false),2621 .is_null => CValue{ .inline_index = inst },
2495 .is_non_null => try airIsNull(f, inst, "!=", false),2622 .is_non_null => CValue{ .inline_index = inst },
2496 .is_null_ptr => try airIsNull(f, inst, "==", true),2623 .is_null_ptr => CValue{ .inline_index = inst },
2497 .is_non_null_ptr => try airIsNull(f, inst, "!=", true),2624 .is_non_null_ptr => CValue{ .inline_index = inst },
24982625
2499 .alloc => try airAlloc(f, inst),2626 .alloc => try airAlloc(f, inst),
2500 .ret_ptr => try airRetPtr(f, inst),2627 .ret_ptr => try airRetPtr(f, inst),
...@@ -2522,14 +2649,14 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2522,14 +2649,14 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2522 .memset => try airMemset(f, inst),2649 .memset => try airMemset(f, inst),
2523 .memcpy => try airMemcpy(f, inst),2650 .memcpy => try airMemcpy(f, inst),
2524 .set_union_tag => try airSetUnionTag(f, inst),2651 .set_union_tag => try airSetUnionTag(f, inst),
2525 .get_union_tag => try airGetUnionTag(f, inst),2652 .get_union_tag => CValue{ .inline_index = inst },
2526 .clz => try airUnBuiltinCall(f, inst, "clz", .Bits),2653 .clz => CValue{ .inline_index = inst },
2527 .ctz => try airUnBuiltinCall(f, inst, "ctz", .Bits),2654 .ctz => CValue{ .inline_index = inst },
2528 .popcount => try airUnBuiltinCall(f, inst, "popcount", .Bits),2655 .popcount => CValue{ .inline_index = inst },
2529 .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .Bits),2656 .byte_swap => CValue{ .inline_index = inst },
2530 .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .Bits),2657 .bit_reverse => CValue{ .inline_index = inst },
2531 .tag_name => try airTagName(f, inst),2658 .tag_name => CValue{ .inline_index = inst },
2532 .error_name => try airErrorName(f, inst),2659 .error_name => CValue{ .inline_index = inst },
2533 .splat => try airSplat(f, inst),2660 .splat => try airSplat(f, inst),
2534 .select => try airSelect(f, inst),2661 .select => try airSelect(f, inst),
2535 .shuffle => try airShuffle(f, inst),2662 .shuffle => try airShuffle(f, inst),
...@@ -2565,7 +2692,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2565,7 +2692,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2565 .fpext,2692 .fpext,
2566 => try airFloatCast(f, inst),2693 => try airFloatCast(f, inst),
25672694
2568 .ptrtoint => try airPtrToInt(f, inst),2695 .ptrtoint => CValue{ .inline_index = inst },
25692696
2570 .atomic_store_unordered => try airAtomicStore(f, inst, toMemoryOrder(.Unordered)),2697 .atomic_store_unordered => try airAtomicStore(f, inst, toMemoryOrder(.Unordered)),
2571 .atomic_store_monotonic => try airAtomicStore(f, inst, toMemoryOrder(.Monotonic)),2698 .atomic_store_monotonic => try airAtomicStore(f, inst, toMemoryOrder(.Monotonic)),
...@@ -2649,7 +2776,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [...@@ -2649,7 +2776,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
26492776
2650 const inst_ty = f.air.typeOfIndex(inst);2777 const inst_ty = f.air.typeOfIndex(inst);
2651 const ty_op = f.air.instructions.items(.data)[inst].ty_op;2778 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
2652 const operand = try f.resolveInst(ty_op.operand);2779 const operand = try f.resolveInstNoInline(ty_op.operand);
2653 const writer = f.object.writer();2780 const writer = f.object.writer();
2654 const local = try f.allocLocal(inst_ty, .Const);2781 const local = try f.allocLocal(inst_ty, .Const);
2655 try writer.writeAll(" = ");2782 try writer.writeAll(" = ");
...@@ -3224,25 +3351,21 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -3224,25 +3351,21 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3224 return local;3351 return local;
3225}3352}
32263353
3227fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {3354fn airNot(f: *Function, inst: Air.Inst.Index) !void {
3228 if (f.liveness.isUnused(inst)) return CValue.none;
3229
3230 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3355 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3231 const op = try f.resolveInst(ty_op.operand);3356 const op = try f.resolveInst(ty_op.operand);
32323357
3233 const writer = f.object.writer();3358 const writer = f.object.writer();
3234 const inst_ty = f.air.typeOfIndex(inst);3359 const inst_ty = f.air.typeOfIndex(inst);
3235 const local = try f.allocLocal(inst_ty, .Const);
32363360
3237 const target = f.object.dg.module.getTarget();3361 const target = f.object.dg.module.getTarget();
3238 if (inst_ty.bitSize(target) > 64) {}3362 if (inst_ty.bitSize(target) > 64) {}
32393363
3240 try writer.writeAll(" = ");3364 try writer.writeByte('(');
3365 try f.renderTypecast(writer, inst_ty);
3366 try writer.writeByte(')');
3241 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');3367 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');
3242 try f.writeCValue(writer, op, .Other);3368 try f.writeCValue(writer, op, .Other);
3243 try writer.writeAll(";\n");
3244
3245 return local;
3246}3369}
32473370
3248fn airBinOp(3371fn airBinOp(
...@@ -3251,62 +3374,54 @@ fn airBinOp(...@@ -3251,62 +3374,54 @@ fn airBinOp(
3251 operator: []const u8,3374 operator: []const u8,
3252 operation: []const u8,3375 operation: []const u8,
3253 info: BuiltinInfo,3376 info: BuiltinInfo,
3254) !CValue {3377) !void {
3255 if (f.liveness.isUnused(inst)) return CValue.none;
3256
3257 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3378 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
32583379
3259 const operand_ty = f.air.typeOf(bin_op.lhs);3380 const operand_ty = f.air.typeOf(bin_op.lhs);
3260 const target = f.object.dg.module.getTarget();3381 const target = f.object.dg.module.getTarget();
3261 if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat())3382 if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat())
3262 return try airBinBuiltinCall(f, inst, operation, info);3383 return airBinBuiltinCall(f, inst, operation, info);
32633384
3264 const inst_ty = f.air.typeOfIndex(inst);3385 const inst_ty = f.air.typeOfIndex(inst);
3265 const lhs = try f.resolveInst(bin_op.lhs);3386 const lhs = try f.resolveInst(bin_op.lhs);
3266 const rhs = try f.resolveInst(bin_op.rhs);3387 const rhs = try f.resolveInst(bin_op.rhs);
32673388
3268 const writer = f.object.writer();3389 const writer = f.object.writer();
3269 const local = try f.allocLocal(inst_ty, .Const);3390 try writer.writeByte('(');
32703391 try f.renderTypecast(writer, inst_ty);
3271 try writer.writeAll(" = ");3392 try writer.writeAll(")(");
3272 try f.writeCValue(writer, lhs, .Other);3393 try f.writeCValue(writer, lhs, .Other);
3273 try writer.writeByte(' ');3394 try writer.writeByte(' ');
3274 try writer.writeAll(operator);3395 try writer.writeAll(operator);
3275 try writer.writeByte(' ');3396 try writer.writeByte(' ');
3276 try f.writeCValue(writer, rhs, .Other);3397 try f.writeCValue(writer, rhs, .Other);
3277 try writer.writeAll(";\n");3398 try writer.writeByte(')');
3278
3279 return local;
3280}3399}
32813400
3282fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue {3401fn airCmpOp(
3283 if (f.liveness.isUnused(inst)) return CValue.none;3402 f: *Function,
32843403 inst: Air.Inst.Index,
3404 operator: []const u8,
3405 operation: []const u8,
3406) !void {
3285 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3407 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
32863408
3287 const operand_ty = f.air.typeOf(bin_op.lhs);3409 const operand_ty = f.air.typeOf(bin_op.lhs);
3288 const target = f.object.dg.module.getTarget();3410 const target = f.object.dg.module.getTarget();
3289 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)3411 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3290 return try airCmpBuiltinCall(f, inst, operator, "cmp");3412 return airCmpBuiltinCall(f, inst, operator, "cmp");
3291 if (operand_ty.isRuntimeFloat())3413 if (operand_ty.isRuntimeFloat())
3292 return try airCmpBuiltinCall(f, inst, operator, operation);3414 return airCmpBuiltinCall(f, inst, operator, operation);
32933415
3294 const inst_ty = f.air.typeOfIndex(inst);
3295 const lhs = try f.resolveInst(bin_op.lhs);3416 const lhs = try f.resolveInst(bin_op.lhs);
3296 const rhs = try f.resolveInst(bin_op.rhs);3417 const rhs = try f.resolveInst(bin_op.rhs);
32973418
3298 const writer = f.object.writer();3419 const writer = f.object.writer();
3299 const local = try f.allocLocal(inst_ty, .Const);
3300
3301 try writer.writeAll(" = ");
3302 try f.writeCValue(writer, lhs, .Other);3420 try f.writeCValue(writer, lhs, .Other);
3303 try writer.writeByte(' ');3421 try writer.writeByte(' ');
3304 try writer.writeAll(operator);3422 try writer.writeAll(operator);
3305 try writer.writeByte(' ');3423 try writer.writeByte(' ');
3306 try f.writeCValue(writer, rhs, .Other);3424 try f.writeCValue(writer, rhs, .Other);
3307 try writer.writeAll(";\n");
3308
3309 return local;
3310}3425}
33113426
3312fn airEquality(3427fn airEquality(
...@@ -3315,27 +3430,20 @@ fn airEquality(...@@ -3315,27 +3430,20 @@ fn airEquality(
3315 negate_prefix: []const u8,3430 negate_prefix: []const u8,
3316 operator: []const u8,3431 operator: []const u8,
3317 operation: []const u8,3432 operation: []const u8,
3318) !CValue {3433) !void {
3319 if (f.liveness.isUnused(inst)) return CValue.none;
3320
3321 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3434 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
33223435
3323 const operand_ty = f.air.typeOf(bin_op.lhs);3436 const operand_ty = f.air.typeOf(bin_op.lhs);
3324 const target = f.object.dg.module.getTarget();3437 const target = f.object.dg.module.getTarget();
3325 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)3438 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3326 return try airCmpBuiltinCall(f, inst, operator, "cmp");3439 return airCmpBuiltinCall(f, inst, operator, "cmp");
3327 if (operand_ty.isRuntimeFloat())3440 if (operand_ty.isRuntimeFloat())
3328 return try airCmpBuiltinCall(f, inst, operator, operation);3441 return airCmpBuiltinCall(f, inst, operator, operation);
33293442
3330 const lhs = try f.resolveInst(bin_op.lhs);3443 const lhs = try f.resolveInst(bin_op.lhs);
3331 const rhs = try f.resolveInst(bin_op.rhs);3444 const rhs = try f.resolveInst(bin_op.rhs);
33323445
3333 const writer = f.object.writer();3446 const writer = f.object.writer();
3334 const inst_ty = f.air.typeOfIndex(inst);
3335 const local = try f.allocLocal(inst_ty, .Const);
3336
3337 try writer.writeAll(" = ");
3338
3339 if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {3447 if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {
3340 // (A && B) || (C && (A == B))3448 // (A && B) || (C && (A == B))
3341 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload3449 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
...@@ -3352,9 +3460,8 @@ fn airEquality(...@@ -3352,9 +3460,8 @@ fn airEquality(
3352 try f.writeCValue(writer, lhs, .Other);3460 try f.writeCValue(writer, lhs, .Other);
3353 try writer.writeAll(".is_null == ");3461 try writer.writeAll(".is_null == ");
3354 try f.writeCValue(writer, rhs, .Other);3462 try f.writeCValue(writer, rhs, .Other);
3355 try writer.writeAll(".is_null));\n");3463 try writer.writeAll(".is_null))");
33563464 return;
3357 return local;
3358 }3465 }
33593466
3360 try f.writeCValue(writer, lhs, .Other);3467 try f.writeCValue(writer, lhs, .Other);
...@@ -3362,9 +3469,6 @@ fn airEquality(...@@ -3362,9 +3469,6 @@ fn airEquality(
3362 try writer.writeAll(operator);3469 try writer.writeAll(operator);
3363 try writer.writeByte(' ');3470 try writer.writeByte(' ');
3364 try f.writeCValue(writer, rhs, .Other);3471 try f.writeCValue(writer, rhs, .Other);
3365 try writer.writeAll(";\n");
3366
3367 return local;
3368}3472}
33693473
3370fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {3474fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -3418,26 +3522,23 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {...@@ -3418,26 +3522,23 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
3418 return local;3522 return local;
3419}3523}
34203524
3421fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue {3525fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !void {
3422 if (f.liveness.isUnused(inst)) return CValue.none;
3423
3424 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3526 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
34253527
3426 const inst_ty = f.air.typeOfIndex(inst);3528 const inst_ty = f.air.typeOfIndex(inst);
3427 const target = f.object.dg.module.getTarget();3529 const target = f.object.dg.module.getTarget();
3428 if (inst_ty.isInt() and inst_ty.bitSize(target) > 64)3530 if (inst_ty.isInt() and inst_ty.bitSize(target) > 64)
3429 return try airBinBuiltinCall(f, inst, operation[1..], .None);3531 return airBinBuiltinCall(f, inst, operation[1..], .None);
3430 if (inst_ty.isRuntimeFloat())3532 if (inst_ty.isRuntimeFloat())
3431 return try airBinFloatOp(f, inst, operation);3533 return airBinFloatOp(f, inst, operation);
34323534
3433 const lhs = try f.resolveInst(bin_op.lhs);3535 const lhs = try f.resolveInst(bin_op.lhs);
3434 const rhs = try f.resolveInst(bin_op.rhs);3536 const rhs = try f.resolveInst(bin_op.rhs);
34353537
3436 const writer = f.object.writer();3538 const writer = f.object.writer();
3437 const local = try f.allocLocal(inst_ty, .Const);
34383539
3439 // (lhs <> rhs) ? lhs : rhs3540 // (lhs <> rhs) ? lhs : rhs
3440 try writer.writeAll(" = (");3541 try writer.writeAll("(");
3441 try f.writeCValue(writer, lhs, .Other);3542 try f.writeCValue(writer, lhs, .Other);
3442 try writer.writeByte(' ');3543 try writer.writeByte(' ');
3443 try writer.writeByte(operator);3544 try writer.writeByte(operator);
...@@ -3447,9 +3548,6 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons...@@ -3447,9 +3548,6 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
3447 try f.writeCValue(writer, lhs, .Other);3548 try f.writeCValue(writer, lhs, .Other);
3448 try writer.writeAll(" : ");3549 try writer.writeAll(" : ");
3449 try f.writeCValue(writer, rhs, .Other);3550 try f.writeCValue(writer, rhs, .Other);
3450 try writer.writeAll(";\n");
3451
3452 return local;
3453}3551}
34543552
3455fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {3553fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -3759,46 +3857,62 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3759,46 +3857,62 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
3759}3857}
37603858
3761fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {3859fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
3762 const inst_ty = f.air.typeOfIndex(inst);3860 const src_ty = f.air.typeOfIndex(inst);
3763 // No IgnoreComptime until Sema stops giving us garbage Air.3861 // No IgnoreComptime until Sema stops giving us garbage Air.
3764 // https://github.com/ziglang/zig/issues/134103862 // https://github.com/ziglang/zig/issues/13410
3765 if (f.liveness.isUnused(inst) or !inst_ty.hasRuntimeBits()) return CValue.none;3863 if (f.liveness.isUnused(inst) or !src_ty.hasRuntimeBits()) return CValue.none;
37663864
3767 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3865 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3768 const operand = try f.resolveInst(ty_op.operand);3866 const operand = try f.resolveInstNoInline(ty_op.operand);
3867 const dest_ty = f.air.typeOf(ty_op.operand);
3868 const target = f.object.dg.module.getTarget();
3869
3870 if (dest_ty.isAbiInt() and src_ty.isAbiInt()) {
3871 const src_info = src_ty.intInfo(target);
3872 const dest_info = dest_ty.intInfo(target);
3873 if (std.meta.eql(src_info, dest_info)) {
3874 return operand;
3875 }
3876 }
37693877
3770 const writer = f.object.writer();3878 const writer = f.object.writer();
3771 if (inst_ty.isPtrAtRuntime() and3879 if (src_ty.isPtrAtRuntime() and dest_ty.isPtrAtRuntime()) {
3772 f.air.typeOf(ty_op.operand).isPtrAtRuntime())3880 const local = try f.allocLocal(src_ty, .Const);
3773 {
3774 const local = try f.allocLocal(inst_ty, .Const);
3775 try writer.writeAll(" = (");3881 try writer.writeAll(" = (");
3776 try f.renderTypecast(writer, inst_ty);3882 try f.renderTypecast(writer, src_ty);
3777 try writer.writeByte(')');3883 try writer.writeByte(')');
3778 try f.writeCValue(writer, operand, .Other);3884 try f.writeCValue(writer, operand, .Other);
3779 try writer.writeAll(";\n");3885 try writer.writeAll(";\n");
3780 return local;3886 return local;
3781 }3887 }
37823888
3783 const local = try f.allocLocal(inst_ty, .Mut);3889 const local = try f.allocLocal(src_ty, .Mut);
3784 try writer.writeAll(";\n");3890 try writer.writeAll(";\n");
37853891
3892 const operand_lval = if (operand == .constant) blk: {
3893 const operand_local = try f.allocLocal(dest_ty, .Const);
3894 try writer.writeAll(" = ");
3895 try f.writeCValue(writer, operand, .Initializer);
3896 try writer.writeAll(";\n");
3897 break :blk operand_local;
3898 } else operand;
3899
3786 try writer.writeAll("memcpy(&");3900 try writer.writeAll("memcpy(&");
3787 try f.writeCValue(writer, local, .Other);3901 try f.writeCValue(writer, local, .Other);
3788 try writer.writeAll(", &");3902 try writer.writeAll(", &");
3789 try f.writeCValue(writer, operand, .Other);3903 try f.writeCValue(writer, operand_lval, .Other);
3790 try writer.writeAll(", sizeof(");3904 try writer.writeAll(", sizeof(");
3791 try f.renderTypecast(writer, inst_ty);3905 try f.renderTypecast(writer, src_ty);
3792 try writer.writeAll("));\n");3906 try writer.writeAll("));\n");
37933907
3794 // Ensure padding bits have the expected value.3908 // Ensure padding bits have the expected value.
3795 if (inst_ty.isAbiInt()) {3909 if (src_ty.isAbiInt()) {
3796 try f.writeCValue(writer, local, .Other);3910 try f.writeCValue(writer, local, .Other);
3797 try writer.writeAll(" = zig_wrap_");3911 try writer.writeAll(" = zig_wrap_");
3798 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);3912 try f.object.dg.renderTypeForBuiltinFnName(writer, src_ty);
3799 try writer.writeByte('(');3913 try writer.writeByte('(');
3800 try f.writeCValue(writer, local, .Other);3914 try f.writeCValue(writer, local, .Other);
3801 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits);3915 try f.object.dg.renderBuiltinInfo(writer, src_ty, .Bits);
3802 try writer.writeAll(");\n");3916 try writer.writeAll(");\n");
3803 }3917 }
38043918
...@@ -3855,7 +3969,7 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3855,7 +3969,7 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {
3855 const body = f.air.extra[loop.end..][0..loop.data.body_len];3969 const body = f.air.extra[loop.end..][0..loop.data.body_len];
3856 const writer = f.object.writer();3970 const writer = f.object.writer();
3857 try writer.writeAll("while (");3971 try writer.writeAll("while (");
3858 try f.object.dg.renderValue(writer, Type.bool, Value.true, .Other);3972 try f.object.dg.renderValue(writer, Type.bool, Value.true, .condition);
3859 try writer.writeAll(") ");3973 try writer.writeAll(") ");
3860 try genBody(f, body);3974 try genBody(f, body);
3861 try writer.writeByte('\n');3975 try writer.writeByte('\n');
...@@ -3871,7 +3985,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3871,7 +3985,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
3871 const writer = f.object.writer();3985 const writer = f.object.writer();
38723986
3873 try writer.writeAll("if (");3987 try writer.writeAll("if (");
3874 try f.writeCValue(writer, cond, .Other);3988 try f.writeCValue(writer, cond, .condition);
3875 try writer.writeAll(") ");3989 try writer.writeAll(") ");
3876 try genBody(f, then_body);3990 try genBody(f, then_body);
3877 try writer.writeAll(" else ");3991 try writer.writeAll(" else ");
...@@ -3889,10 +4003,14 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3889,10 +4003,14 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
3889 const writer = f.object.writer();4003 const writer = f.object.writer();
38904004
3891 try writer.writeAll("switch (");4005 try writer.writeAll("switch (");
3892 if (condition_ty.tag() == .bool) {4006 if (condition_ty.zigTypeTag() == .Bool) {
3893 try writer.writeByte('(');4007 try writer.writeByte('(');
3894 try f.renderTypecast(writer, Type.u1);4008 try f.renderTypecast(writer, Type.u1);
3895 try writer.writeByte(')');4009 try writer.writeByte(')');
4010 } else if (condition_ty.isPtrAtRuntime()) {
4011 try writer.writeByte('(');
4012 try f.renderTypecast(writer, Type.usize);
4013 try writer.writeByte(')');
3896 }4014 }
3897 try f.writeCValue(writer, condition, .Other);4015 try f.writeCValue(writer, condition, .Other);
3898 try writer.writeAll(") {");4016 try writer.writeAll(") {");
...@@ -3909,6 +4027,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3909,6 +4027,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
3909 for (items) |item| {4027 for (items) |item| {
3910 try f.object.indent_writer.insertNewline();4028 try f.object.indent_writer.insertNewline();
3911 try writer.writeAll("case ");4029 try writer.writeAll("case ");
4030 if (condition_ty.isPtrAtRuntime()) {
4031 try writer.writeByte('(');
4032 try f.renderTypecast(writer, Type.usize);
4033 try writer.writeByte(')');
4034 }
3912 try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other);4035 try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other);
3913 try writer.writeAll(": ");4036 try writer.writeAll(": ");
3914 }4037 }
...@@ -4055,6 +4178,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4055,6 +4178,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4055 if (is_reg) {4178 if (is_reg) {
4056 try f.writeCValue(writer, .{ .local = locals_index }, .Other);4179 try f.writeCValue(writer, .{ .local = locals_index }, .Other);
4057 locals_index += 1;4180 locals_index += 1;
4181 } else if (output == .none) {
4182 try f.writeCValue(writer, local, .FunctionArgument);
4058 } else {4183 } else {
4059 try f.writeCValueDeref(writer, try f.resolveInst(output));4184 try f.writeCValueDeref(writer, try f.resolveInst(output));
4060 }4185 }
...@@ -4131,16 +4256,11 @@ fn airIsNull(...@@ -4131,16 +4256,11 @@ fn airIsNull(
4131 inst: Air.Inst.Index,4256 inst: Air.Inst.Index,
4132 operator: []const u8,4257 operator: []const u8,
4133 is_ptr: bool,4258 is_ptr: bool,
4134) !CValue {4259) !void {
4135 if (f.liveness.isUnused(inst))
4136 return CValue.none;
4137
4138 const un_op = f.air.instructions.items(.data)[inst].un_op;4260 const un_op = f.air.instructions.items(.data)[inst].un_op;
4139 const writer = f.object.writer();4261 const writer = f.object.writer();
4140 const operand = try f.resolveInst(un_op);4262 const operand = try f.resolveInst(un_op);
41414263
4142 const local = try f.allocLocal(Type.initTag(.bool), .Const);
4143 try writer.writeAll(" = ");
4144 try if (is_ptr) f.writeCValueDeref(writer, operand) else f.writeCValue(writer, operand, .Other);4264 try if (is_ptr) f.writeCValueDeref(writer, operand) else f.writeCValue(writer, operand, .Other);
41454265
4146 const operand_ty = f.air.typeOf(un_op);4266 const operand_ty = f.air.typeOf(un_op);
...@@ -4168,8 +4288,6 @@ fn airIsNull(...@@ -4168,8 +4288,6 @@ fn airIsNull(
4168 try writer.writeAll(operator);4288 try writer.writeAll(operator);
4169 try writer.writeByte(' ');4289 try writer.writeByte(' ');
4170 try f.object.dg.renderValue(writer, rhs.ty, rhs.val, .Other);4290 try f.object.dg.renderValue(writer, rhs.ty, rhs.val, .Other);
4171 try writer.writeAll(";\n");
4172 return local;
4173}4291}
41744292
4175fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {4293fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -4358,6 +4476,10 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc...@@ -4358,6 +4476,10 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
4358 u8_ptr_pl.data.pointee_type = Type.u8;4476 u8_ptr_pl.data.pointee_type = Type.u8;
4359 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);4477 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
43604478
4479 if (!std.mem.isAligned(byte_offset, field_ptr_ty.ptrAlignment(target))) {
4480 return f.fail("TODO: CBE: unaligned packed struct field pointer", .{});
4481 }
4482
4361 try writer.writeAll("&((");4483 try writer.writeAll("&((");
4362 try f.renderTypecast(writer, u8_ptr_ty);4484 try f.renderTypecast(writer, u8_ptr_ty);
4363 try writer.writeByte(')');4485 try writer.writeByte(')');
...@@ -4366,7 +4488,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc...@@ -4366,7 +4488,11 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
4366 return local;4488 return local;
4367 } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug4489 } else @as(CValue, CValue.none), // this @as is needed because of a stage1 bug
4368 },4490 },
4369 .@"union", .union_safety_tagged, .union_tagged => .{4491 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
4492 try f.writeCValue(writer, struct_ptr, .Other);
4493 try writer.writeAll(";\n");
4494 return local;
4495 } else .{
4370 .identifier = struct_ty.unionFields().keys()[index],4496 .identifier = struct_ty.unionFields().keys()[index],
4371 },4497 },
4372 .tuple, .anon_struct => field_name: {4498 .tuple, .anon_struct => field_name: {
...@@ -4480,7 +4606,26 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4480,7 +4606,26 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
4480 return local;4606 return local;
4481 },4607 },
4482 },4608 },
4483 .@"union", .union_safety_tagged, .union_tagged => .{4609 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
4610 const operand_lval = if (struct_byval == .constant) blk: {
4611 const operand_local = try f.allocLocal(struct_ty, .Const);
4612 try writer.writeAll(" = ");
4613 try f.writeCValue(writer, struct_byval, .Initializer);
4614 try writer.writeAll(";\n");
4615 break :blk operand_local;
4616 } else struct_byval;
4617
4618 const local = try f.allocLocal(inst_ty, .Mut);
4619 try writer.writeAll(";\n");
4620 try writer.writeAll("memcpy(&");
4621 try f.writeCValue(writer, local, .FunctionArgument);
4622 try writer.writeAll(", &");
4623 try f.writeCValue(writer, operand_lval, .FunctionArgument);
4624 try writer.writeAll(", sizeof(");
4625 try f.renderTypecast(writer, inst_ty);
4626 try writer.writeAll("));\n");
4627 return local;
4628 } else .{
4484 .identifier = struct_ty.unionFields().keys()[extra.field_index],4629 .identifier = struct_ty.unionFields().keys()[extra.field_index],
4485 },4630 },
4486 .tuple, .anon_struct => blk: {4631 .tuple, .anon_struct => blk: {
...@@ -4558,7 +4703,18 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu...@@ -4558,7 +4703,18 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
4558 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;4703 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
4559 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;4704 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
45604705
4561 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) return CValue.none;4706 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {
4707 if (!is_ptr) return CValue.none;
4708
4709 const local = try f.allocLocal(inst_ty, .Const);
4710 const w = f.object.writer();
4711 try w.writeAll(" = (");
4712 try f.renderTypecast(w, inst_ty);
4713 try w.writeByte(')');
4714 try f.writeCValue(w, operand, .Initializer);
4715 try w.writeAll(";\n");
4716 return local;
4717 }
45624718
4563 const writer = f.object.writer();4719 const writer = f.object.writer();
4564 const local = try f.allocLocal(inst_ty, .Const);4720 const local = try f.allocLocal(inst_ty, .Const);
...@@ -4701,21 +4857,15 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4701,21 +4857,15 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
4701 return local;4857 return local;
4702}4858}
47034859
4704fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue {4860fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !void {
4705 if (f.liveness.isUnused(inst))
4706 return CValue.none;
4707
4708 const un_op = f.air.instructions.items(.data)[inst].un_op;4861 const un_op = f.air.instructions.items(.data)[inst].un_op;
4709 const writer = f.object.writer();4862 const writer = f.object.writer();
4710 const operand = try f.resolveInst(un_op);4863 const operand = try f.resolveInst(un_op);
4711 const operand_ty = f.air.typeOf(un_op);4864 const operand_ty = f.air.typeOf(un_op);
4712 const local = try f.allocLocal(Type.initTag(.bool), .Const);
4713 const err_union_ty = if (is_ptr) operand_ty.childType() else operand_ty;4865 const err_union_ty = if (is_ptr) operand_ty.childType() else operand_ty;
4714 const payload_ty = err_union_ty.errorUnionPayload();4866 const payload_ty = err_union_ty.errorUnionPayload();
4715 const error_ty = err_union_ty.errorUnionSet();4867 const error_ty = err_union_ty.errorUnionSet();
47164868
4717 try writer.writeAll(" = ");
4718
4719 if (!error_ty.errorSetIsEmpty())4869 if (!error_ty.errorSetIsEmpty())
4720 if (payload_ty.hasRuntimeBits())4870 if (payload_ty.hasRuntimeBits())
4721 if (is_ptr)4871 if (is_ptr)
...@@ -4730,8 +4880,6 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const...@@ -4730,8 +4880,6 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
4730 try writer.writeAll(operator);4880 try writer.writeAll(operator);
4731 try writer.writeByte(' ');4881 try writer.writeByte(' ');
4732 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);4882 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
4733 try writer.writeAll(";\n");
4734 return local;
4735}4883}
47364884
4737fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {4885fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -4805,21 +4953,16 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4805,21 +4953,16 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
4805 return local;4953 return local;
4806}4954}
48074955
4808fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {4956fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !void {
4809 if (f.liveness.isUnused(inst)) return CValue.none;
4810
4811 const inst_ty = f.air.typeOfIndex(inst);4957 const inst_ty = f.air.typeOfIndex(inst);
4812 const local = try f.allocLocal(inst_ty, .Const);
4813 const un_op = f.air.instructions.items(.data)[inst].un_op;4958 const un_op = f.air.instructions.items(.data)[inst].un_op;
4814 const writer = f.object.writer();4959 const writer = f.object.writer();
4815 const operand = try f.resolveInst(un_op);4960 const operand = try f.resolveInst(un_op);
48164961
4817 try writer.writeAll(" = (");4962 try writer.writeAll("(");
4818 try f.renderTypecast(writer, inst_ty);4963 try f.renderTypecast(writer, inst_ty);
4819 try writer.writeByte(')');4964 try writer.writeByte(')');
4820 try f.writeCValue(writer, operand, .Other);4965 try f.writeCValue(writer, operand, .Other);
4821 try writer.writeAll(";\n");
4822 return local;
4823}4966}
48244967
4825fn airUnBuiltinCall(4968fn airUnBuiltinCall(
...@@ -4827,24 +4970,19 @@ fn airUnBuiltinCall(...@@ -4827,24 +4970,19 @@ fn airUnBuiltinCall(
4827 inst: Air.Inst.Index,4970 inst: Air.Inst.Index,
4828 operation: []const u8,4971 operation: []const u8,
4829 info: BuiltinInfo,4972 info: BuiltinInfo,
4830) !CValue {4973) !void {
4831 if (f.liveness.isUnused(inst)) return CValue.none;
4832
4833 const inst_ty = f.air.typeOfIndex(inst);
4834 const operand = f.air.instructions.items(.data)[inst].ty_op.operand;4974 const operand = f.air.instructions.items(.data)[inst].ty_op.operand;
4835 const operand_ty = f.air.typeOf(operand);4975 const operand_ty = f.air.typeOf(operand);
48364976
4837 const local = try f.allocLocal(inst_ty, .Const);
4838 const writer = f.object.writer();4977 const writer = f.object.writer();
4839 try writer.writeAll(" = zig_");4978 try writer.writeAll("zig_");
4840 try writer.writeAll(operation);4979 try writer.writeAll(operation);
4841 try writer.writeByte('_');4980 try writer.writeByte('_');
4842 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);4981 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
4843 try writer.writeByte('(');4982 try writer.writeByte('(');
4844 try f.writeCValue(writer, try f.resolveInst(operand), .FunctionArgument);4983 try f.writeCValue(writer, try f.resolveInst(operand), .FunctionArgument);
4845 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);4984 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
4846 try writer.writeAll(");\n");4985 try writer.writeAll(")");
4847 return local;
4848}4986}
48494987
4850fn airBinBuiltinCall(4988fn airBinBuiltinCall(
...@@ -4852,16 +4990,12 @@ fn airBinBuiltinCall(...@@ -4852,16 +4990,12 @@ fn airBinBuiltinCall(
4852 inst: Air.Inst.Index,4990 inst: Air.Inst.Index,
4853 operation: []const u8,4991 operation: []const u8,
4854 info: BuiltinInfo,4992 info: BuiltinInfo,
4855) !CValue {4993) !void {
4856 if (f.liveness.isUnused(inst)) return CValue.none;
4857
4858 const inst_ty = f.air.typeOfIndex(inst);
4859 const bin_op = f.air.instructions.items(.data)[inst].bin_op;4994 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4860 const operand_ty = f.air.typeOf(bin_op.lhs);4995 const operand_ty = f.air.typeOf(bin_op.lhs);
48614996
4862 const local = try f.allocLocal(inst_ty, .Const);
4863 const writer = f.object.writer();4997 const writer = f.object.writer();
4864 try writer.writeAll(" = zig_");4998 try writer.writeAll("zig_");
4865 try writer.writeAll(operation);4999 try writer.writeAll(operation);
4866 try writer.writeByte('_');5000 try writer.writeByte('_');
4867 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);5001 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
...@@ -4870,8 +5004,7 @@ fn airBinBuiltinCall(...@@ -4870,8 +5004,7 @@ fn airBinBuiltinCall(
4870 try writer.writeAll(", ");5004 try writer.writeAll(", ");
4871 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);5005 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
4872 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);5006 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
4873 try writer.writeAll(");\n");5007 try writer.writeAll(")");
4874 return local;
4875}5008}
48765009
4877fn airCmpBuiltinCall(5010fn airCmpBuiltinCall(
...@@ -4879,16 +5012,12 @@ fn airCmpBuiltinCall(...@@ -4879,16 +5012,12 @@ fn airCmpBuiltinCall(
4879 inst: Air.Inst.Index,5012 inst: Air.Inst.Index,
4880 operator: []const u8,5013 operator: []const u8,
4881 operation: []const u8,5014 operation: []const u8,
4882) !CValue {5015) !void {
4883 if (f.liveness.isUnused(inst)) return CValue.none;
4884
4885 const inst_ty = f.air.typeOfIndex(inst);
4886 const bin_op = f.air.instructions.items(.data)[inst].bin_op;5016 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4887 const operand_ty = f.air.typeOf(bin_op.lhs);5017 const operand_ty = f.air.typeOf(bin_op.lhs);
48885018
4889 const local = try f.allocLocal(inst_ty, .Const);
4890 const writer = f.object.writer();5019 const writer = f.object.writer();
4891 try writer.writeAll(" = zig_");5020 try writer.writeAll("zig_");
4892 try writer.writeAll(operation);5021 try writer.writeAll(operation);
4893 try writer.writeByte('_');5022 try writer.writeByte('_');
4894 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);5023 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
...@@ -4896,8 +5025,7 @@ fn airCmpBuiltinCall(...@@ -4896,8 +5025,7 @@ fn airCmpBuiltinCall(
4896 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);5025 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
4897 try writer.writeAll(", ");5026 try writer.writeAll(", ");
4898 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);5027 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
4899 try writer.print(") {s} {};\n", .{ operator, try f.fmtIntLiteral(Type.initTag(.i32), Value.zero) });5028 try writer.print(") {s} {}", .{ operator, try f.fmtIntLiteral(Type.initTag(.i32), Value.zero) });
4900 return local;
4901}5029}
49025030
4903fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {5031fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {
...@@ -5127,12 +5255,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5127,12 +5255,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
5127 return CValue.none;5255 return CValue.none;
5128}5256}
51295257
5130fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {5258fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !void {
5131 if (f.liveness.isUnused(inst))
5132 return CValue.none;
5133
5134 const inst_ty = f.air.typeOfIndex(inst);
5135 const local = try f.allocLocal(inst_ty, .Const);
5136 const ty_op = f.air.instructions.items(.data)[inst].ty_op;5259 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
5137 const un_ty = f.air.typeOf(ty_op.operand);5260 const un_ty = f.air.typeOf(ty_op.operand);
5138 const writer = f.object.writer();5261 const writer = f.object.writer();
...@@ -5140,44 +5263,31 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5140,44 +5263,31 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
51405263
5141 const target = f.object.dg.module.getTarget();5264 const target = f.object.dg.module.getTarget();
5142 const layout = un_ty.unionGetLayout(target);5265 const layout = un_ty.unionGetLayout(target);
5143 if (layout.tag_size == 0) return CValue.none;5266 assert(layout.tag_size != 0);
51445267
5145 try writer.writeAll(" = ");
5146 try f.writeCValue(writer, operand, .Other);5268 try f.writeCValue(writer, operand, .Other);
5147 try writer.writeAll(".tag;\n");5269 try writer.writeAll(".tag");
5148 return local;
5149}5270}
51505271
5151fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {5272fn airTagName(f: *Function, inst: Air.Inst.Index) !void {
5152 if (f.liveness.isUnused(inst)) return CValue.none;
5153
5154 const un_op = f.air.instructions.items(.data)[inst].un_op;5273 const un_op = f.air.instructions.items(.data)[inst].un_op;
5155 const inst_ty = f.air.typeOfIndex(inst);
5156 const enum_ty = f.air.typeOf(un_op);5274 const enum_ty = f.air.typeOf(un_op);
5157 const operand = try f.resolveInst(un_op);5275 const operand = try f.resolveInst(un_op);
51585276
5159 const writer = f.object.writer();5277 const writer = f.object.writer();
5160 const local = try f.allocLocal(inst_ty, .Const);5278 try writer.print("{s}(", .{try f.object.dg.getTagNameFn(enum_ty)});
5161 try writer.print(" = {s}(", .{try f.object.dg.getTagNameFn(enum_ty)});
5162 try f.writeCValue(writer, operand, .Other);5279 try f.writeCValue(writer, operand, .Other);
5163 try writer.writeAll(");\n");5280 try writer.writeAll(")");
5164
5165 return local;
5166}5281}
51675282
5168fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {5283fn airErrorName(f: *Function, inst: Air.Inst.Index) !void {
5169 if (f.liveness.isUnused(inst)) return CValue.none;
5170
5171 const un_op = f.air.instructions.items(.data)[inst].un_op;5284 const un_op = f.air.instructions.items(.data)[inst].un_op;
5172 const writer = f.object.writer();5285 const writer = f.object.writer();
5173 const inst_ty = f.air.typeOfIndex(inst);
5174 const operand = try f.resolveInst(un_op);5286 const operand = try f.resolveInst(un_op);
5175 const local = try f.allocLocal(inst_ty, .Const);
51765287
5177 try writer.writeAll(" = zig_errorName[");5288 try writer.writeAll("zig_errorName[");
5178 try f.writeCValue(writer, operand, .Other);5289 try f.writeCValue(writer, operand, .Other);
5179 try writer.writeAll("];\n");5290 try writer.writeAll("]");
5180 return local;
5181}5291}
51825292
5183fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {5293fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -5198,30 +5308,12 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5198,30 +5308,12 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
5198fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {5308fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
5199 if (f.liveness.isUnused(inst)) return CValue.none;5309 if (f.liveness.isUnused(inst)) return CValue.none;
52005310
5201 const inst_ty = f.air.typeOfIndex(inst);
5202 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
5203
5204 const writer = f.object.writer();
5205 const local = try f.allocLocal(inst_ty, .Const);
5206 try writer.writeAll(" = ");
5207
5208 _ = local;
5209 _ = ty_pl;
5210 return f.fail("TODO: C backend: implement airSelect", .{});5311 return f.fail("TODO: C backend: implement airSelect", .{});
5211}5312}
52125313
5213fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {5314fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
5214 if (f.liveness.isUnused(inst)) return CValue.none;5315 if (f.liveness.isUnused(inst)) return CValue.none;
52155316
5216 const inst_ty = f.air.typeOfIndex(inst);
5217 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
5218 const operand = try f.resolveInst(ty_op.operand);
5219 const writer = f.object.writer();
5220 const local = try f.allocLocal(inst_ty, .Const);
5221 try writer.writeAll(" = ");
5222
5223 _ = operand;
5224 _ = local;
5225 return f.fail("TODO: C backend: implement airShuffle", .{});5317 return f.fail("TODO: C backend: implement airShuffle", .{});
5226}5318}
52275319
...@@ -5532,6 +5624,13 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5532,6 +5624,13 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
55325624
5533 const writer = f.object.writer();5625 const writer = f.object.writer();
5534 const local = try f.allocLocal(union_ty, .Const);5626 const local = try f.allocLocal(union_ty, .Const);
5627 if (union_obj.layout == .Packed) {
5628 try writer.writeAll(" = ");
5629 try f.writeCValue(writer, payload, .Initializer);
5630 try writer.writeAll(";\n");
5631 return local;
5632 }
5633
5535 try writer.writeAll(" = {");5634 try writer.writeAll(" = {");
5536 if (union_ty.unionTagTypeSafety()) |tag_ty| {5635 if (union_ty.unionTagTypeSafety()) |tag_ty| {
5537 const layout = union_ty.unionGetLayout(target);5636 const layout = union_ty.unionGetLayout(target);
...@@ -5645,15 +5744,18 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal...@@ -5645,15 +5744,18 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
5645 return local;5744 return local;
5646}5745}
56475746
5648fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {5747fn airBinFloatOp(
5649 if (f.liveness.isUnused(inst)) return CValue.none;5748 f: *Function,
5749 inst: Air.Inst.Index,
5750 operation: []const u8,
5751) !void {
5650 const bin_op = f.air.instructions.items(.data)[inst].bin_op;5752 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
5651 const writer = f.object.writer();5753 const writer = f.object.writer();
5652 const inst_ty = f.air.typeOfIndex(inst);5754 const inst_ty = f.air.typeOfIndex(inst);
5653 const lhs = try f.resolveInst(bin_op.lhs);5755 const lhs = try f.resolveInst(bin_op.lhs);
5654 const rhs = try f.resolveInst(bin_op.rhs);5756 const rhs = try f.resolveInst(bin_op.rhs);
5655 const local = try f.allocLocal(inst_ty, .Const);5757
5656 try writer.writeAll(" = zig_libc_name_");5758 try writer.writeAll("zig_libc_name_");
5657 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);5759 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
5658 try writer.writeByte('(');5760 try writer.writeByte('(');
5659 try writer.writeAll(operation);5761 try writer.writeAll(operation);
...@@ -5661,8 +5763,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa...@@ -5661,8 +5763,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
5661 try f.writeCValue(writer, lhs, .FunctionArgument);5763 try f.writeCValue(writer, lhs, .FunctionArgument);
5662 try writer.writeAll(", ");5764 try writer.writeAll(", ");
5663 try f.writeCValue(writer, rhs, .FunctionArgument);5765 try f.writeCValue(writer, rhs, .FunctionArgument);
5664 try writer.writeAll(");\n");5766 try writer.writeAll(")");
5665 return local;
5666}5767}
56675768
5668fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {5769fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
src/value.zig+6
...@@ -2895,6 +2895,12 @@ pub const Value = extern union {...@@ -2895,6 +2895,12 @@ pub const Value = extern union {
2895 return val;2895 return val;
2896 },2896 },
28972897
2898 .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),
2899 .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),
2900
2901 .opt_payload => return val.castTag(.opt_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
2902 .eu_payload => return val.castTag(.eu_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
2903
2898 else => unreachable,2904 else => unreachable,
2899 }2905 }
2900 }2906 }
test/behavior.zig+1
...@@ -117,6 +117,7 @@ test {...@@ -117,6 +117,7 @@ test {
117 _ = @import("behavior/bugs/13285.zig");117 _ = @import("behavior/bugs/13285.zig");
118 _ = @import("behavior/bugs/13435.zig");118 _ = @import("behavior/bugs/13435.zig");
119 _ = @import("behavior/bugs/13664.zig");119 _ = @import("behavior/bugs/13664.zig");
120 _ = @import("behavior/bugs/13714.zig");
120 _ = @import("behavior/byteswap.zig");121 _ = @import("behavior/byteswap.zig");
121 _ = @import("behavior/byval_arg_var.zig");122 _ = @import("behavior/byval_arg_var.zig");
122 _ = @import("behavior/call.zig");123 _ = @import("behavior/call.zig");
test/behavior/basic.zig+1-1
...@@ -739,7 +739,6 @@ test "thread local variable" {...@@ -739,7 +739,6 @@ test "thread local variable" {
739}739}
740740
741test "result location is optional inside error union" {741test "result location is optional inside error union" {
742 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
743 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO742 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
744 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO743 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
745744
...@@ -771,6 +770,7 @@ threadlocal var buffer: [11]u8 = undefined;...@@ -771,6 +770,7 @@ threadlocal var buffer: [11]u8 = undefined;
771770
772test "auto created variables have correct alignment" {771test "auto created variables have correct alignment" {
773 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO772 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
773 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
774774
775 const S = struct {775 const S = struct {
776 fn foo(str: [*]const u8) u32 {776 fn foo(str: [*]const u8) u32 {
test/behavior/bugs/13064.zig-1
...@@ -5,7 +5,6 @@ const expect = std.testing.expect;...@@ -5,7 +5,6 @@ const expect = std.testing.expect;
5test {5test {
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
98
10 var x: [10][10]u32 = undefined;9 var x: [10][10]u32 = undefined;
1110
test/behavior/bugs/13065.zig-1
...@@ -10,7 +10,6 @@ const U = union(enum) {...@@ -10,7 +10,6 @@ const U = union(enum) {
10test {10test {
11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1413
15 var x = U{ .array = undefined };14 var x = U{ .array = undefined };
1615
test/behavior/bugs/13069.zig-1
...@@ -6,7 +6,6 @@ test {...@@ -6,7 +6,6 @@ test {
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
109
11 var opt_x: ?[3]f32 = [_]f32{0.0} ** 3;10 var opt_x: ?[3]f32 = [_]f32{0.0} ** 3;
1211
test/behavior/bugs/13714.zig created+4
...@@ -0,0 +1,4 @@
1comptime {
2 var image: [1]u8 = undefined;
3 _ = @shlExact(@as(u16, image[0]), 8);
4}
test/behavior/enum.zig-1
...@@ -1101,7 +1101,6 @@ test "enum literal in array literal" {...@@ -1101,7 +1101,6 @@ test "enum literal in array literal" {
1101}1101}
11021102
1103test "tag name functions are unique" {1103test "tag name functions are unique" {
1104 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1105 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1104 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1106 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;1105 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1106 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
test/behavior/floatop.zig-2
...@@ -798,7 +798,6 @@ test "comptime fixed-width float non-zero divided by zero produces signed Inf" {...@@ -798,7 +798,6 @@ test "comptime fixed-width float non-zero divided by zero produces signed Inf" {
798 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO798 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
799 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO799 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
800 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO800 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
801 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
802801
803 inline for (.{ f16, f32, f64, f80, f128 }) |F| {802 inline for (.{ f16, f32, f64, f80, f128 }) |F| {
804 const pos = @as(F, 1) / @as(F, 0);803 const pos = @as(F, 1) / @as(F, 0);
...@@ -897,7 +896,6 @@ test "nan negation f80" {...@@ -897,7 +896,6 @@ test "nan negation f80" {
897 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO896 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
898 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO897 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
899 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO898 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
900 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
901899
902 const nan_comptime = comptime math.nan(f80);900 const nan_comptime = comptime math.nan(f80);
903 const neg_nan_comptime = -nan_comptime;901 const neg_nan_comptime = -nan_comptime;
test/behavior/if.zig-1
...@@ -133,7 +133,6 @@ test "if-else expression with runtime condition result location is inferred opti...@@ -133,7 +133,6 @@ test "if-else expression with runtime condition result location is inferred opti
133 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;133 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
137136
138 const A = struct { b: u64, c: u64 };137 const A = struct { b: u64, c: u64 };
139 var d: bool = true;138 var d: bool = true;
test/behavior/math.zig-3
...@@ -315,8 +315,6 @@ test "comptime_int multi-limb partial shift right" {...@@ -315,8 +315,6 @@ test "comptime_int multi-limb partial shift right" {
315}315}
316316
317test "xor" {317test "xor" {
318 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
319
320 try test_xor();318 try test_xor();
321 comptime try test_xor();319 comptime try test_xor();
322}320}
...@@ -572,7 +570,6 @@ fn testShrTrunc(x: u16) !void {...@@ -572,7 +570,6 @@ fn testShrTrunc(x: u16) !void {
572}570}
573571
574test "f128" {572test "f128" {
575 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
576 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO573 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
577 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO574 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
578 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/optional.zig-1
...@@ -342,7 +342,6 @@ test "optional pointer to zero bit optional payload" {...@@ -342,7 +342,6 @@ test "optional pointer to zero bit optional payload" {
342}342}
343343
344test "optional pointer to zero bit error union payload" {344test "optional pointer to zero bit error union payload" {
345 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO345 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
347 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO346 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
348 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/switch.zig-1
...@@ -548,7 +548,6 @@ test "switch prongs with cases with identical payload types" {...@@ -548,7 +548,6 @@ test "switch prongs with cases with identical payload types" {
548}548}
549549
550test "switch on pointer type" {550test "switch on pointer type" {
551 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
552 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO551 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
553 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO552 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
554553
test/behavior/type.zig+22
...@@ -535,3 +535,25 @@ test "Type.Fn" {...@@ -535,3 +535,25 @@ test "Type.Fn" {
535 try std.testing.expectEqual(T, fn_type);535 try std.testing.expectEqual(T, fn_type);
536 }536 }
537}537}
538
539test "reified struct field name from optional payload" {
540 comptime {
541 const m_name: ?[1]u8 = "a".*;
542 if (m_name) |*name| {
543 const T = @Type(.{ .Struct = .{
544 .layout = .Auto,
545 .fields = &.{.{
546 .name = name,
547 .field_type = u8,
548 .default_value = null,
549 .is_comptime = false,
550 .alignment = 1,
551 }},
552 .decls = &.{},
553 .is_tuple = false,
554 } });
555 var t: T = .{ .a = 123 };
556 try std.testing.expect(t.a == 123);
557 }
558 }
559}
test/behavior/union.zig-1
...@@ -1376,7 +1376,6 @@ test "union field ptr - zero sized field" {...@@ -1376,7 +1376,6 @@ test "union field ptr - zero sized field" {
13761376
1377test "packed union in packed struct" {1377test "packed union in packed struct" {
1378 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1378 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1379 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1380 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1381 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1380 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1382 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1381 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO