diff --git a/src/codegen/c.zig b/src/codegen/c.zig index a0b1bc30b9..464f144f5a 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -61,6 +61,11 @@ const FormatTypeAsCIdentContext = struct { mod: *Module, }; +const ValueRenderLocation = enum { + FunctionArgument, + Other, +}; + /// TODO make this not cut off at 128 bytes fn formatTypeAsCIdentifier( data: FormatTypeAsCIdentContext, @@ -259,7 +264,7 @@ pub const Function = struct { 0, ); try writer.writeAll(" = "); - try f.object.dg.renderValue(writer, ty, val); + try f.object.dg.renderValue(writer, ty, val, .Other); try writer.writeAll(";\n "); return decl_c_value; }, @@ -298,7 +303,7 @@ pub const Function = struct { .constant => |inst| { const ty = f.air.typeOf(inst); const val = f.air.value(inst).?; - return f.object.dg.renderValue(w, ty, val); + return f.object.dg.renderValue(w, ty, val, .Other); }, else => return f.object.dg.writeCValue(w, c_value), } @@ -310,7 +315,7 @@ pub const Function = struct { const ty = f.air.typeOf(inst); const val = f.air.value(inst).?; try w.writeAll("(*"); - try f.object.dg.renderValue(w, ty, val); + try f.object.dg.renderValue(w, ty, val, .Other); return w.writeByte(')'); }, else => return f.object.dg.writeCValueDeref(w, c_value), @@ -384,7 +389,7 @@ pub const DeclGen = struct { try dg.renderTypecast(writer, ty); try writer.writeAll("){"); var buf: Type.SlicePtrFieldTypeBuffer = undefined; - try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr()); + try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Other); try writer.writeAll(", "); try writer.print("{d}", .{val.sliceLen(dg.module)}); try writer.writeAll("}"); @@ -544,6 +549,7 @@ pub const DeclGen = struct { writer: anytype, ty: Type, val: Value, + location: ValueRenderLocation, ) error{ OutOfMemory, AnalysisFail }!void { const target = dg.module.getTarget(); if (val.isUndefDeep()) { @@ -636,9 +642,9 @@ pub const DeclGen = struct { try writer.writeByte('('); try dg.renderTypecast(writer, ty); try writer.writeAll("){"); - try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr); + try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, location); try writer.writeAll(", "); - try dg.renderValue(writer, Type.usize, slice.len); + try dg.renderValue(writer, Type.usize, slice.len, location); try writer.writeAll("}"); }, .function => { @@ -670,7 +676,7 @@ pub const DeclGen = struct { try writer.writeByte('{'); const ai = ty.arrayInfo(); if (ai.sentinel) |s| { - try dg.renderValue(writer, ai.elem_type, s); + try dg.renderValue(writer, ai.elem_type, s, location); } try writer.writeByte('}'); }, @@ -680,17 +686,23 @@ pub const DeclGen = struct { defer arena.deinit(); const arena_allocator = arena.allocator(); + if (location == .FunctionArgument) { + try writer.writeByte('('); + try dg.renderTypecast(writer, ty); + try writer.writeByte(')'); + } + try writer.writeByte('{'); const ai = ty.arrayInfo(); var index: usize = 0; while (index < ai.len) : (index += 1) { if (index != 0) try writer.writeAll(","); const elem_val = try val.elemValue(dg.module, arena_allocator, index); - try dg.renderValue(writer, ai.elem_type, elem_val); + try dg.renderValue(writer, ai.elem_type, elem_val, .Other); } if (ai.sentinel) |s| { if (index != 0) try writer.writeAll(","); - try dg.renderValue(writer, ai.elem_type, s); + try dg.renderValue(writer, ai.elem_type, s, .Other); } try writer.writeByte('}'); }, @@ -701,7 +713,7 @@ pub const DeclGen = struct { var opt_buf: Type.Payload.ElemType = undefined; const payload_type = ty.optionalChild(&opt_buf); if (ty.isPtrLikeOptional()) { - return dg.renderValue(writer, payload_type, val); + return dg.renderValue(writer, payload_type, val, location); } if (payload_type.abiSize(target) == 0) { const is_null = val.castTag(.opt_payload) == null; @@ -713,7 +725,7 @@ pub const DeclGen = struct { if (val.castTag(.opt_payload)) |pl| { const payload_val = pl.data; try writer.writeAll(" .is_null = false, .payload = "); - try dg.renderValue(writer, payload_type, payload_val); + try dg.renderValue(writer, payload_type, payload_val, location); try writer.writeAll(" }"); } else { try writer.writeAll(" .is_null = true }"); @@ -740,7 +752,7 @@ pub const DeclGen = struct { if (!payload_type.hasRuntimeBits()) { // We use the error type directly as the type. const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val; - return dg.renderValue(writer, error_type, err_val); + return dg.renderValue(writer, error_type, err_val, location); } try writer.writeByte('('); @@ -749,11 +761,11 @@ pub const DeclGen = struct { if (val.castTag(.eu_payload)) |pl| { const payload_val = pl.data; try writer.writeAll(" .payload = "); - try dg.renderValue(writer, payload_type, payload_val); + try dg.renderValue(writer, payload_type, payload_val, location); try writer.writeAll(", .error = 0 }"); } else { try writer.writeAll(" .error = "); - try dg.renderValue(writer, error_type, val); + try dg.renderValue(writer, error_type, val, location); try writer.writeAll(" }"); } }, @@ -767,7 +779,7 @@ pub const DeclGen = struct { const enum_full = ty.cast(Type.Payload.EnumFull).?.data; if (enum_full.values.count() != 0) { const tag_val = enum_full.values.keys()[field_index]; - return dg.renderValue(writer, enum_full.tag_ty, tag_val); + return dg.renderValue(writer, enum_full.tag_ty, tag_val, location); } else { return writer.print("{d}", .{field_index}); } @@ -776,7 +788,7 @@ pub const DeclGen = struct { const enum_obj = ty.castTag(.enum_numbered).?.data; if (enum_obj.values.count() != 0) { const tag_val = enum_obj.values.keys()[field_index]; - return dg.renderValue(writer, enum_obj.tag_ty, tag_val); + return dg.renderValue(writer, enum_obj.tag_ty, tag_val, location); } else { return writer.print("{d}", .{field_index}); } @@ -787,7 +799,7 @@ pub const DeclGen = struct { else => { var int_tag_ty_buffer: Type.Payload.Bits = undefined; const int_tag_ty = ty.intTagType(&int_tag_ty_buffer); - return dg.renderValue(writer, int_tag_ty, val); + return dg.renderValue(writer, int_tag_ty, val, location); }, } }, @@ -814,7 +826,7 @@ pub const DeclGen = struct { if (!field_ty.hasRuntimeBits()) continue; if (i != 0) try writer.writeAll(","); - try dg.renderValue(writer, field_ty, field_val); + try dg.renderValue(writer, field_ty, field_val, location); } try writer.writeAll("}"); @@ -831,7 +843,7 @@ pub const DeclGen = struct { if (ty.unionTagType()) |tag_ty| { if (layout.tag_size != 0) { try writer.writeAll(".tag = "); - try dg.renderValue(writer, tag_ty, union_obj.tag); + try dg.renderValue(writer, tag_ty, union_obj.tag, location); try writer.writeAll(", "); } try writer.writeAll(".payload = {"); @@ -842,7 +854,7 @@ pub const DeclGen = struct { const field_name = ty.unionFields().keys()[index]; if (field_ty.hasRuntimeBits()) { try writer.print(".{ } = ", .{fmtIdent(field_name)}); - try dg.renderValue(writer, field_ty, union_obj.val); + try dg.renderValue(writer, field_ty, union_obj.val, location); } if (ty.unionTagType()) |_| { try writer.writeAll("}"); @@ -988,7 +1000,7 @@ pub const DeclGen = struct { } if (ptr_sentinel) |s| { try bw.writeAll("_s_"); - try dg.renderValue(bw, child_type, s); + try dg.renderValue(bw, child_type, s, .Other); } try bw.writeAll(";\n"); @@ -1629,7 +1641,7 @@ pub fn genDecl(o: *Object) !void { try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align"); try w.writeAll(" = "); if (variable.init.tag() != .unreachable_value) { - try o.dg.renderValue(w, tv.ty, variable.init); + try o.dg.renderValue(w, tv.ty, variable.init, .Other); } try w.writeAll(";"); try o.indent_writer.insertNewline(); @@ -1644,7 +1656,7 @@ pub fn genDecl(o: *Object) !void { try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align"); try writer.writeAll(" = "); - try o.dg.renderValue(writer, tv.ty, tv.val); + try o.dg.renderValue(writer, tv.ty, tv.val, .Other); try writer.writeAll(";\n"); } } @@ -2748,7 +2760,7 @@ fn airCall( try writer.writeAll(", "); } if (f.air.value(arg)) |val| { - try f.object.dg.renderValue(writer, f.air.typeOf(arg), val); + try f.object.dg.renderValue(writer, f.air.typeOf(arg), val, .FunctionArgument); } else { const val = try f.resolveInst(arg); try f.writeCValue(writer, val); @@ -2964,7 +2976,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { for (items) |item| { try f.object.indent_writer.insertNewline(); try writer.writeAll("case "); - try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?); + try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other); try writer.writeAll(": "); } // The case body must be noreturn so we don't need to insert a break. @@ -3414,14 +3426,14 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { try f.writeCValueDeref(writer, operand); try writer.writeAll(" = "); - try f.object.dg.renderValue(writer, error_ty, Value.zero); + try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other); try writer.writeAll(";\n "); return operand; } try f.writeCValueDeref(writer, operand); try writer.writeAll(".error = "); - try f.object.dg.renderValue(writer, error_ty, Value.zero); + try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other); try writer.writeAll(";\n"); // Then return the payload pointer (only if it is used) diff --git a/test/behavior/array.zig b/test/behavior/array.zig index 13a4763a91..bf5e74e819 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -148,7 +148,7 @@ test "void arrays" { try expect(array.len == 4); } -test "nested arrays" { +test "nested arrays of strings" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; @@ -162,6 +162,22 @@ test "nested arrays" { } } +test "nested arrays of integers" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + + const array_of_numbers = [_][2]u8{ + [2]u8{ 1, 2 }, + [2]u8{ 3, 4 }, + }; + + try expect(array_of_numbers[0][0] == 1); + try expect(array_of_numbers[0][1] == 2); + try expect(array_of_numbers[1][0] == 3); + try expect(array_of_numbers[1][1] == 4); +} + test "implicit comptime in array type size" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index 7d02229ff4..eabb6c77f4 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -349,7 +349,6 @@ fn numberLiteralArg(a: anytype) !void { } test "function call with anon list literal" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; @@ -364,9 +363,19 @@ test "function call with anon list literal" { try expect(vec[1] == 8); try expect(vec[2] == 7); } + + fn doThe2DTest() !void { + try consume2DVec(.{ .{ 9, 8 }, .{ 7, 6 } }); + } + + fn consume2DVec(vec: [2][2]f32) !void { + _ = vec; + } }; try S.doTheTest(); comptime try S.doTheTest(); + try S.doThe2DTest(); + comptime try S.doThe2DTest(); } test "ability to give comptime types and non comptime types to same parameter" {