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.
This commit is contained in:
Daniele Cocca 2022-03-15 21:53:48 +00:00 committed by Andrew Kelley
parent d78b8c10b9
commit 312536540b
2 changed files with 25 additions and 23 deletions

View File

@ -616,27 +616,33 @@ pub const DeclGen = struct {
.Array => {
// First try specific tag representations for more efficiency.
switch (val.tag()) {
.undef, .empty_struct_value, .empty_array => try writer.writeAll("{}"),
.undef, .empty_struct_value, .empty_array => {
try writer.writeByte('{');
const ai = ty.arrayInfo();
if (ai.sentinel) |s| {
try dg.renderValue(writer, ai.elem_type, s);
}
try writer.writeByte('}');
},
else => {
// Fall back to generic implementation.
var arena = std.heap.ArenaAllocator.init(dg.module.gpa);
defer arena.deinit();
const arena_allocator = arena.allocator();
try writer.writeAll("{");
try writer.writeByte('{');
const ai = ty.arrayInfo();
var index: usize = 0;
const len = ty.arrayLen();
const elem_ty = ty.elemType();
while (index < len) : (index += 1) {
while (index < ai.len) : (index += 1) {
if (index != 0) try writer.writeAll(",");
const elem_val = try val.elemValue(arena_allocator, index);
try dg.renderValue(writer, elem_ty, elem_val);
try dg.renderValue(writer, ai.elem_type, elem_val);
}
if (ty.sentinel()) |sentinel_val| {
if (ai.sentinel) |s| {
if (index != 0) try writer.writeAll(",");
try dg.renderValue(writer, elem_ty, sentinel_val);
try dg.renderValue(writer, ai.elem_type, s);
}
try writer.writeAll("}");
try writer.writeByte('}');
},
}
},
@ -925,14 +931,21 @@ pub const DeclGen = struct {
const ptr_alignment = Value.initTag(.abi_align_default);
try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, ptr_alignment);
const ptr_sentinel = ptr_type.ptrInfo().data.sentinel;
const child_type = t.childType();
try bw.writeAll("; size_t len; } ");
const name_index = buffer.items.len;
const elem_type = t.elemType();
if (t.isConstPtr()) {
try bw.print("zig_L_{s};\n", .{typeToCIdentifier(elem_type)});
try bw.print("zig_L_{s}", .{typeToCIdentifier(child_type)});
} else {
try bw.print("zig_M_{s};\n", .{typeToCIdentifier(elem_type)});
try bw.print("zig_M_{s}", .{typeToCIdentifier(child_type)});
}
if (ptr_sentinel) |s| {
try bw.writeAll("_s_");
try dg.renderValue(bw, child_type, s);
}
try bw.writeAll(";\n");
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);

View File

@ -238,7 +238,6 @@ const Sub = struct { b: u8 };
const Str = struct { a: []Sub };
test "set global var array via slice embedded in struct" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
var s = Str{ .a = s_array[0..] };
@ -254,7 +253,6 @@ test "set global var array via slice embedded in struct" {
test "read/write through global variable array of struct fields initialized via array mult" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
@ -275,7 +273,6 @@ test "read/write through global variable array of struct fields initialized via
test "implicit cast single-item pointer" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
try testImplicitCastSingleItemPtr();
@ -295,7 +292,6 @@ fn testArrayByValAtComptime(b: [2]u8) u8 {
test "comptime evaluating function that takes array by value" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const arr = [_]u8{ 1, 2 };
@ -307,7 +303,6 @@ test "comptime evaluating function that takes array by value" {
test "runtime initialize array elem and then implicit cast to slice" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
var two: i32 = 2;
@ -317,7 +312,6 @@ test "runtime initialize array elem and then implicit cast to slice" {
test "array literal as argument to function" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
@ -345,7 +339,6 @@ test "array literal as argument to function" {
test "double nested array to const slice cast in array literal" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
@ -406,7 +399,6 @@ test "double nested array to const slice cast in array literal" {
test "anonymous literal in array" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
@ -431,7 +423,6 @@ test "anonymous literal in array" {
test "access the null element of a null terminated array" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
@ -448,7 +439,6 @@ test "access the null element of a null terminated array" {
test "type deduction for array subscript expression" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
@ -468,7 +458,6 @@ test "sentinel element count towards the ABI size calculation" {
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO