diff --git a/src/cgen/emit.zig b/src/cgen/emit.zig index 505e088..ec0ddff 100644 --- a/src/cgen/emit.zig +++ b/src/cgen/emit.zig @@ -332,18 +332,22 @@ fn emitSampler(allocator: std.mem.Allocator, globals: []const Parser.Global, fil const label = try std.fmt.bufPrint(&label_buf, "FM_VAL_{d}", .{value_idx}); value_idx += 1; - try writeIndent(file, current_depth); - try file.writeAll("size_t idx_"); - try file.writeAll(label); - try file.writeAll(" = data[off] % "); - const count_str = try std.fmt.bufPrint(&num_buf, "{d}", .{vals.len}); - try file.writeAll(count_str); - try file.writeAll(";\n"); - - var src_buf: [256]u8 = undefined; - const src = try std.fmt.bufPrint(&src_buf, "&{s}[idx_{s} * {s}]", .{ label, label, bytes_str }); - try emitMemcpy(file, current_depth, dst_expr, src, bytes_str); - try incrementOffset(file, current_depth, "1"); + if (vals.len == 1) { + try emitMemcpy(file, current_depth, dst_expr, label, bytes_str); + } else { + try writeIndent(file, current_depth); + try file.writeAll("size_t idx_"); + try file.writeAll(label); + try file.writeAll(" = data[off] % "); + const count_str = try std.fmt.bufPrint(&num_buf, "{d}", .{vals.len}); + try file.writeAll(count_str); + try file.writeAll(";\n"); + + var src_buf: [256]u8 = undefined; + const src = try std.fmt.bufPrint(&src_buf, "&{s}[idx_{s} * {s}]", .{ label, label, bytes_str }); + try emitMemcpy(file, current_depth, dst_expr, src, bytes_str); + try incrementOffset(file, current_depth, "1"); + } }, .pointers => |ptrs| { if (ptrs.len == 0) continue; @@ -351,18 +355,24 @@ fn emitSampler(allocator: std.mem.Allocator, globals: []const Parser.Global, fil const ptr_label = try std.fmt.bufPrint(&ptr_label_buf, "FM_PTR_{d}", .{ptr_idx}); ptr_idx += 1; - try writeIndent(file, current_depth); - try file.writeAll("size_t idx_"); - try file.writeAll(ptr_label); - try file.writeAll(" = data[off] % "); - const count_str = try std.fmt.bufPrint(&num_buf, "{d}", .{ptrs.len}); - try file.writeAll(count_str); - try file.writeAll(";\n"); - - var src_buf: [128]u8 = undefined; - const src = try std.fmt.bufPrint(&src_buf, "&{s}[idx_{s}]", .{ ptr_label, ptr_label }); - try emitMemcpy(file, current_depth, dst_expr, src, bytes_str); - try incrementOffset(file, current_depth, "1"); + if (ptrs.len == 1) { + var src_buf: [128]u8 = undefined; + const src = try std.fmt.bufPrint(&src_buf, "&{s}[0]", .{ptr_label}); + try emitMemcpy(file, current_depth, dst_expr, src, bytes_str); + } else { + try writeIndent(file, current_depth); + try file.writeAll("size_t idx_"); + try file.writeAll(ptr_label); + try file.writeAll(" = data[off] % "); + const count_str = try std.fmt.bufPrint(&num_buf, "{d}", .{ptrs.len}); + try file.writeAll(count_str); + try file.writeAll(";\n"); + + var src_buf: [128]u8 = undefined; + const src = try std.fmt.bufPrint(&src_buf, "&{s}[idx_{s}]", .{ ptr_label, ptr_label }); + try emitMemcpy(file, current_depth, dst_expr, src, bytes_str); + try incrementOffset(file, current_depth, "1"); + } }, } diff --git a/src/seed.zig b/src/seed.zig index 3b3b4a1..e3df49c 100644 --- a/src/seed.zig +++ b/src/seed.zig @@ -13,7 +13,8 @@ pub fn neededBytesFromGlobals(globals: []const ir.Global) usize { const field_mult = dimsProduct(f.dims); const bytes: usize = switch (f.domain) { .top => (f.bit_width + 7) / 8, - .values, .pointers => 1, + .values => |vals| if (vals.len <= 1) 0 else 1, + .pointers => |ptrs| if (ptrs.len <= 1) 0 else 1, }; total += bytes * global_mult * field_mult; } diff --git a/tests/big_pool/README.md b/tests/big_pool/README.md new file mode 100644 index 0000000..f3f31db --- /dev/null +++ b/tests/big_pool/README.md @@ -0,0 +1,3 @@ +Fix for a large `uint8_t` array with a one-value `.values` domain (`target.c` + `target.c.in`). There is also `counter` so the expected global prefix stays small once the bug is fixed. + +Used to catch the case where the sampler still bumped `off` on every array element even though the domain had nothing to choose from. diff --git a/tests/big_pool/target.c b/tests/big_pool/target.c new file mode 100644 index 0000000..cced20c --- /dev/null +++ b/tests/big_pool/target.c @@ -0,0 +1,5 @@ +#include + +uint8_t big_pool[16000]; +int counter; + diff --git a/tests/big_pool/target.c.in b/tests/big_pool/target.c.in new file mode 100644 index 0000000..b79f38f --- /dev/null +++ b/tests/big_pool/target.c.in @@ -0,0 +1,15 @@ +.{ .{ + .name = "big_pool", + .source_file = "tests/big_pool/target.c", + .size_bytes = 16000, + .is_static = false, + .dims = .{.{ .len = 16000, .stride_bytes = 1 }}, + .fields = .{.{ + .name = ".", + .offset_bits = 0, + .bit_width = 8, + .dims = .{}, + .is_padding = false, + .domain = .{ .values = .{"\x00"} }, + }}, +}} diff --git a/tests/big_pool/target.c.zon b/tests/big_pool/target.c.zon new file mode 100644 index 0000000..7f46e54 --- /dev/null +++ b/tests/big_pool/target.c.zon @@ -0,0 +1,29 @@ +.{ .{ + .name = "big_pool", + .source_file = "tests/big_pool/target.c", + .size_bytes = 16000, + .is_static = false, + .dims = .{.{ .len = 16000, .stride_bytes = 1 }}, + .fields = .{.{ + .name = ".", + .offset_bits = 0, + .bit_width = 8, + .dims = .{}, + .is_padding = false, + .domain = .{ .values = .{"\x00"} }, + }}, +}, .{ + .name = "counter", + .source_file = "tests/big_pool/target.c", + .size_bytes = 4, + .is_static = false, + .dims = .{}, + .fields = .{.{ + .name = ".", + .offset_bits = 0, + .bit_width = 32, + .dims = .{}, + .is_padding = false, + .domain = .top, + }}, +} }