authorgravatar for daniele.cocca@gmail.comDaniele Cocca <daniele.cocca@gmail.com> 2022-03-15 21:53:48+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-16 19:58:45-07:00
log312536540baf26728a56304811f63f01a7414b7a
tree5a5f168ec6001971e8cf3d2496fc6dec1d095355
parentd78b8c10b9b33a5b1a21e9fa981576fd408939e5

CBE: better handling of sentineled slices/arrays

Adds the sentinel element to the type name to avoid ambiguous declarations, and outputs the sentinel element (if needed) even in what would otherwise be empty arrays.

2 files changed, 25 insertions(+), 23 deletions(-)

src/codegen/c.zig+25-12
...@@ -616,27 +616,33 @@ pub const DeclGen = struct {...@@ -616,27 +616,33 @@ pub const DeclGen = struct {
616 .Array => {616 .Array => {
617 // First try specific tag representations for more efficiency.617 // First try specific tag representations for more efficiency.
618 switch (val.tag()) {618 switch (val.tag()) {
619 .undef, .empty_struct_value, .empty_array => try writer.writeAll("{}"),619 .undef, .empty_struct_value, .empty_array => {
620 try writer.writeByte('{');
621 const ai = ty.arrayInfo();
622 if (ai.sentinel) |s| {
623 try dg.renderValue(writer, ai.elem_type, s);
624 }
625 try writer.writeByte('}');
626 },
620 else => {627 else => {
621 // Fall back to generic implementation.628 // Fall back to generic implementation.
622 var arena = std.heap.ArenaAllocator.init(dg.module.gpa);629 var arena = std.heap.ArenaAllocator.init(dg.module.gpa);
623 defer arena.deinit();630 defer arena.deinit();
624 const arena_allocator = arena.allocator();631 const arena_allocator = arena.allocator();
625632
626 try writer.writeAll("{");633 try writer.writeByte('{');
634 const ai = ty.arrayInfo();
627 var index: usize = 0;635 var index: usize = 0;
628 const len = ty.arrayLen();636 while (index < ai.len) : (index += 1) {
629 const elem_ty = ty.elemType();
630 while (index < len) : (index += 1) {
631 if (index != 0) try writer.writeAll(",");637 if (index != 0) try writer.writeAll(",");
632 const elem_val = try val.elemValue(arena_allocator, index);638 const elem_val = try val.elemValue(arena_allocator, index);
633 try dg.renderValue(writer, elem_ty, elem_val);639 try dg.renderValue(writer, ai.elem_type, elem_val);
634 }640 }
635 if (ty.sentinel()) |sentinel_val| {641 if (ai.sentinel) |s| {
636 if (index != 0) try writer.writeAll(",");642 if (index != 0) try writer.writeAll(",");
637 try dg.renderValue(writer, elem_ty, sentinel_val);643 try dg.renderValue(writer, ai.elem_type, s);
638 }644 }
639 try writer.writeAll("}");645 try writer.writeByte('}');
640 },646 },
641 }647 }
642 },648 },
...@@ -925,14 +931,21 @@ pub const DeclGen = struct {...@@ -925,14 +931,21 @@ pub const DeclGen = struct {
925 const ptr_alignment = Value.initTag(.abi_align_default);931 const ptr_alignment = Value.initTag(.abi_align_default);
926 try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, ptr_alignment);932 try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, ptr_alignment);
927933
934 const ptr_sentinel = ptr_type.ptrInfo().data.sentinel;
935 const child_type = t.childType();
936
928 try bw.writeAll("; size_t len; } ");937 try bw.writeAll("; size_t len; } ");
929 const name_index = buffer.items.len;938 const name_index = buffer.items.len;
930 const elem_type = t.elemType();
931 if (t.isConstPtr()) {939 if (t.isConstPtr()) {
932 try bw.print("zig_L_{s};\n", .{typeToCIdentifier(elem_type)});940 try bw.print("zig_L_{s}", .{typeToCIdentifier(child_type)});
933 } else {941 } else {
934 try bw.print("zig_M_{s};\n", .{typeToCIdentifier(elem_type)});942 try bw.print("zig_M_{s}", .{typeToCIdentifier(child_type)});
943 }
944 if (ptr_sentinel) |s| {
945 try bw.writeAll("_s_");
946 try dg.renderValue(bw, child_type, s);
935 }947 }
948 try bw.writeAll(";\n");
936949
937 const rendered = buffer.toOwnedSlice();950 const rendered = buffer.toOwnedSlice();
938 errdefer dg.typedefs.allocator.free(rendered);951 errdefer dg.typedefs.allocator.free(rendered);
test/behavior/array.zig-11
...@@ -238,7 +238,6 @@ const Sub = struct { b: u8 };...@@ -238,7 +238,6 @@ const Sub = struct { b: u8 };
238const Str = struct { a: []Sub };238const Str = struct { a: []Sub };
239test "set global var array via slice embedded in struct" {239test "set global var array via slice embedded in struct" {
240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
241 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
242 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
243242
244 var s = Str{ .a = s_array[0..] };243 var s = Str{ .a = s_array[0..] };
...@@ -254,7 +253,6 @@ test "set global var array via slice embedded in struct" {...@@ -254,7 +253,6 @@ test "set global var array via slice embedded in struct" {
254253
255test "read/write through global variable array of struct fields initialized via array mult" {254test "read/write through global variable array of struct fields initialized via array mult" {
256 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;255 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
257 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
259257
260 const S = struct {258 const S = struct {
...@@ -275,7 +273,6 @@ test "read/write through global variable array of struct fields initialized via...@@ -275,7 +273,6 @@ test "read/write through global variable array of struct fields initialized via
275273
276test "implicit cast single-item pointer" {274test "implicit cast single-item pointer" {
277 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;275 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
278 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
280277
281 try testImplicitCastSingleItemPtr();278 try testImplicitCastSingleItemPtr();
...@@ -295,7 +292,6 @@ fn testArrayByValAtComptime(b: [2]u8) u8 {...@@ -295,7 +292,6 @@ fn testArrayByValAtComptime(b: [2]u8) u8 {
295292
296test "comptime evaluating function that takes array by value" {293test "comptime evaluating function that takes array by value" {
297 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;294 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
298 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
299 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO295 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
300296
301 const arr = [_]u8{ 1, 2 };297 const arr = [_]u8{ 1, 2 };
...@@ -307,7 +303,6 @@ test "comptime evaluating function that takes array by value" {...@@ -307,7 +303,6 @@ test "comptime evaluating function that takes array by value" {
307303
308test "runtime initialize array elem and then implicit cast to slice" {304test "runtime initialize array elem and then implicit cast to slice" {
309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;305 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
310 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
311 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO306 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
312307
313 var two: i32 = 2;308 var two: i32 = 2;
...@@ -317,7 +312,6 @@ test "runtime initialize array elem and then implicit cast to slice" {...@@ -317,7 +312,6 @@ test "runtime initialize array elem and then implicit cast to slice" {
317312
318test "array literal as argument to function" {313test "array literal as argument to function" {
319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;314 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
320 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
321 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO315 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
322316
323 const S = struct {317 const S = struct {
...@@ -345,7 +339,6 @@ test "array literal as argument to function" {...@@ -345,7 +339,6 @@ test "array literal as argument to function" {
345339
346test "double nested array to const slice cast in array literal" {340test "double nested array to const slice cast in array literal" {
347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;341 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
348 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
350343
351 const S = struct {344 const S = struct {
...@@ -406,7 +399,6 @@ test "double nested array to const slice cast in array literal" {...@@ -406,7 +399,6 @@ test "double nested array to const slice cast in array literal" {
406399
407test "anonymous literal in array" {400test "anonymous literal in array" {
408 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
409 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
410 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
411403
412 const S = struct {404 const S = struct {
...@@ -431,7 +423,6 @@ test "anonymous literal in array" {...@@ -431,7 +423,6 @@ test "anonymous literal in array" {
431423
432test "access the null element of a null terminated array" {424test "access the null element of a null terminated array" {
433 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;425 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
434 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
435 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO426 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
436427
437 const S = struct {428 const S = struct {
...@@ -448,7 +439,6 @@ test "access the null element of a null terminated array" {...@@ -448,7 +439,6 @@ test "access the null element of a null terminated array" {
448439
449test "type deduction for array subscript expression" {440test "type deduction for array subscript expression" {
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;441 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
451 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
453443
454 const S = struct {444 const S = struct {
...@@ -468,7 +458,6 @@ test "sentinel element count towards the ABI size calculation" {...@@ -468,7 +458,6 @@ test "sentinel element count towards the ABI size calculation" {
468 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO458 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
469 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO459 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
470 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO460 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
471 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
472 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO461 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO462 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
474463