From ee6de69bf02df77aaf29df8b135aba5dcebad5a7 Mon Sep 17 00:00:00 2001 From: Jakub Doka <jakub.doka2@gmail.com> Date: Sat, 15 Mar 2025 12:28:36 +0100 Subject: [PATCH] fixed some bugs Signed-off-by: Jakub Doka <jakub.doka2@gmail.com> --- README.md | 23 ++++++++++++ src/backend/Builder.zig | 2 +- src/backend/Mach.zig | 3 ++ src/backend/graph.zig | 10 +++--- src/backend/static_anal.zig | 4 +-- src/hbc.zig | 5 +++ src/hbvm/HbvmGen.zig | 4 +++ src/test_util.zig | 8 ----- src/tests.zig | 3 +- tests/slices 4.txt | 72 +++++++++++++++++++++++++++++++++++++ vendored-tests/lily | 2 +- 11 files changed, 118 insertions(+), 18 deletions(-) create mode 100644 tests/slices 4.txt diff --git a/README.md b/README.md index aa30957..ba4c023 100644 --- a/README.md +++ b/README.md @@ -1640,6 +1640,29 @@ main := fn(): uint { } ``` +#### slices 4 +```hb +equals := fn(lhs: []u8, rhs: []u8): bool { + if lhs.len != rhs.len return false + if lhs.ptr == rhs.ptr return true + i := 0 + loop if i == lhs.len break else { + if lhs[i] != rhs[i] return false + i += 1 + } + return true +} + +main := fn(): uint { + abc := "abc" + a_b_c := u8.['a', 'b', 'c'][..] + if !equals(abc, abc) return 1 + if !equals(a_b_c, abc) return 1 + + return 0 +} +``` + #### nullable types 1 ```hb expectations := .{ diff --git a/src/backend/Builder.zig b/src/backend/Builder.zig index 25bbc47..e5fa3b6 100644 --- a/src/backend/Builder.zig +++ b/src/backend/Builder.zig @@ -57,7 +57,7 @@ pub fn addParam(self: *Builder, idx: usize) SpecificNode(.Arg) { } pub fn end(self: *Builder, _: BuildToken) void { - if (self.func.end.inputs()[0] == null and !self.isUnreachable()) self.addReturn(&.{}); + if (!self.isUnreachable()) self.addReturn(&.{}); } // #MEM ======================================================================== diff --git a/src/backend/Mach.zig b/src/backend/Mach.zig index cf2b31e..36507ec 100644 --- a/src/backend/Mach.zig +++ b/src/backend/Mach.zig @@ -86,6 +86,7 @@ pub const EmitOptions = struct { name: []const u8 = &.{}, entry: bool = false, optimizations: struct { + verbose: bool = false, dead_code_fuel: usize = 1000, mem2reg: bool = true, peephole_fuel: usize = 1000, @@ -120,6 +121,8 @@ pub const EmitOptions = struct { func.gcm.buildCfg(); } + if (self.verbose) func.fmtScheduled(std.io.getStdErr().writer().any(), .escape_codes); + if (self.error_buf) |eb| { func.static_anal.analize(self.arena.?, eb); } diff --git a/src/backend/graph.zig b/src/backend/graph.zig index 8346abf..9f33590 100644 --- a/src/backend/graph.zig +++ b/src/backend/graph.zig @@ -1207,13 +1207,13 @@ pub fn Func(comptime MachNode: type) type { if (base.kind == .Local) eliminate_stack: { for (base.outputs()) |o| { - _ = knownStore(o) orelse { + _ = knownStore(o, base) orelse { break :eliminate_stack; }; } - for (base.outputs()) |o| if (knownStore(o).? != node) { - worklist.add(knownStore(o).?); + for (base.outputs()) |o| if (knownStore(o, base).? != node) { + worklist.add(knownStore(o, base).?); }; return node.mem(); @@ -1287,8 +1287,8 @@ pub fn Func(comptime MachNode: type) type { return if (comptime optApi("idealize", @TypeOf(idealize))) MachNode.idealize(self, node, worklist) else null; } - pub fn knownStore(base: *Node) ?*Node { - if (base.isStore() and !base.isSub(MemCpy)) return base; + pub fn knownStore(base: *Node, root: *Node) ?*Node { + if (base.isStore() and !base.isSub(MemCpy) and base.base() == root) return base; if (base.kind == .BinOp and base.outputs().len == 1 and base.outputs()[0].isStore() and !base.isSub(MemCpy) and base.outputs()[0].base() == base) { return base.outputs()[0]; } diff --git a/src/backend/static_anal.zig b/src/backend/static_anal.zig index fb9d759..b2b0482 100644 --- a/src/backend/static_anal.zig +++ b/src/backend/static_anal.zig @@ -95,7 +95,7 @@ pub fn StaticAnalMixin(comptime Mach: type) type { for (arg.outputs()) |ao| { // TODO: we skip MemCpy, this will miss a class of problesm, // but memcpy elimination might help and effort here would be redundant - const store = Func.knownStore(ao) orelse continue; + const store = Func.knownStore(ao, arg) orelse continue; if (store.value().kind == .Local) { local_stores.append(tmp.arena.allocator(), store) catch unreachable; @@ -106,7 +106,7 @@ pub fn StaticAnalMixin(comptime Mach: type) type { // filter out the stores that are overriden for (arg.outputs()) |unmarked| { - const store = Func.knownStore(unmarked) orelse continue; + const store = Func.knownStore(unmarked, arg) orelse continue; if (store.value().kind == .Local) continue; diff --git a/src/hbc.zig b/src/hbc.zig index b885540..540846e 100644 --- a/src/hbc.zig +++ b/src/hbc.zig @@ -184,6 +184,11 @@ pub fn compile(opts: CompileOptions) anyerror!struct { var tmp = Arena.scrath(null); defer tmp.deinit(); + //var out_fmt = std.ArrayList(u8).init(tmp.arena.allocator()); + //defer out_fmt.deinit(); + //try asts[@intFromEnum(func.key.file)].fmtExpr(&out_fmt, func.key.ast); + //try std.io.getStdErr().writeAll(out_fmt.items); + var errors = std.ArrayListUnmanaged(static_anal.Error){}; backend.emitFunc(&codegen.bl.func, .{ diff --git a/src/hbvm/HbvmGen.zig b/src/hbvm/HbvmGen.zig index f35ba74..07cb259 100644 --- a/src/hbvm/HbvmGen.zig +++ b/src/hbvm/HbvmGen.zig @@ -285,9 +285,11 @@ pub fn finalize(self: *HbvmGen) std.ArrayListUnmanaged(u8) { pub fn makeSymMap(self: *HbvmGen, offset: u32, arena: std.mem.Allocator) std.AutoHashMapUnmanaged(u32, []const u8) { var map = std.AutoHashMap(u32, []const u8).init(arena); for (self.funcs.items) |gf| { + if (gf.offset < offset) continue; map.put(gf.offset - offset, gf.name) catch unreachable; } for (self.globals.items) |gf| { + if (gf.offset < offset) continue; map.put(gf.offset - offset, gf.name) catch unreachable; } return map.unmanaged; @@ -797,6 +799,8 @@ pub fn idealizeMach(func: *Func, node: *Func.Node, work: *Func.WorkList) ?*Func. } if (node.kind == .If) { + //if (node.outputs().len != 2) utils.panic("{} {} {}\n", .{ node, node.outputs()[0], node.data_type }); + if (inps[1].?.kind == .BinOp) b: { work.add(inps[1].?); const op = inps[1].?.extra(.BinOp).*; diff --git a/src/test_util.zig b/src/test_util.zig index 7ba4f59..16ba88b 100644 --- a/src/test_util.zig +++ b/src/test_util.zig @@ -139,14 +139,6 @@ pub fn testBuilder( cg.bl.func.reset(); } - if (verbose) { - if (verbose) try header("SOURCE", output, colors); - var out_fmt = std.ArrayList(u8).init(gpa); - defer out_fmt.deinit(); - try asts[@intFromEnum(func.key.file)].fmtExpr(&out_fmt, func.key.ast); - try output.writeAll(out_fmt.items); - } - if (verbose) try header("UNSCHEDULED SON", output, colors); cg.build(func) catch { errored = true; diff --git a/src/tests.zig b/src/tests.zig index c1e77b3..87b1932 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -54,7 +54,8 @@ pub fn runFuzzFindingTest(name: []const u8, code: []const u8) !void { } pub fn runVendoredTest(path: []const u8) !void { - if (std.mem.count(u8, path, "lily") == 2) return; + if (std.mem.endsWith(u8, path, "arena-crash.hb")) return; + if (std.mem.endsWith(u8, path, "fmt.hb")) return; utils.Arena.initScratch(1024 * 1024); defer utils.Arena.deinitScratch(); try test_util.runVendoredTest(std.testing.allocator, path); diff --git a/tests/slices 4.txt b/tests/slices 4.txt new file mode 100644 index 0000000..e014e05 --- /dev/null +++ b/tests/slices 4.txt @@ -0,0 +1,72 @@ +main: + st $31, $254, -56, 56 + addi64 $254, $254, -91 + addi64 $32, $254, 0 + lra $33, $0, :main.abc + st $33, $254, 0, 8 + li64 $34, 3 + st $34, $254, 8, 8 + addi64 $35, $254, 16 + addi64 $36, $254, 32 + li8 $37, 97 + st $37, $254, 32, 1 + li8 $37, 98 + st $37, $254, 33, 1 + li8 $37, 99 + st $37, $254, 34, 1 + st $36, $254, 16, 8 + st $34, $254, 24, 8 + cp $1, $33 + cp $2, $34 + cp $3, $33 + cp $4, $34 + jal $31, $0, :equals + cp $33, $1 + andi $33, $33, 255 + not $33, $33 + andi $33, $33, 255 + ld $34, $254, 8, 8 + ld $36, $254, 16, 8 + ld $35, $254, 24, 8 + ld $32, $254, 0, 8 + jeq $33, $0, :2 + jmp :3 +2: cp $1, $36 + cp $2, $35 + cp $3, $32 + cp $4, $34 + jal $31, $0, :equals + andi $1, $1, 255 + not $1, $1 + andi $1, $1, 255 + jeq $1, $0, :4 +3: li64 $1, 1 + jmp :5 +4: li64 $1, 0 +5: addi64 $254, $254, 91 + ld $31, $254, -56, 56 + tx +equals: + li64 $5, 0 + jeq $2, $4, :6 + cp $1, $5 + jmp :7 +6: li64 $4, 1 + jne $1, $3, :8 + cp $1, $4 +7: jmp :9 +8: cp $6, $5 +c: jne $6, $2, :a + cp $1, $4 + jmp :9 +a: add64 $7, $1, $6 + add64 $8, $3, $6 + ld $7, $7, 0, 1 + ld $8, $8, 0, 1 + andi $7, $7, 255 + andi $8, $8, 255 + jeq $7, $8, :b + cp $1, $5 +9: jala $0, $31, 0 +b: addi64 $6, $6, 1 + jmp :c \ No newline at end of file diff --git a/vendored-tests/lily b/vendored-tests/lily index 8465a14..cbc2872 160000 --- a/vendored-tests/lily +++ b/vendored-tests/lily @@ -1 +1 @@ -Subproject commit 8465a141b79aec2f5ca07ff899613f85833ae592 +Subproject commit cbc28723a29da52ffe5fa89c4b022f8f0d8c5637