about summary refs log tree commit diff
path: root/synth.zig
blob: 453cb46819c5fa9cab8bff3e89818e58ba9e87bc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! Patch's predicate synthesizer
// Copyright (C) 2025  Nguyễn Gia Phong
//
// This file is part of taosc.
//
// Taosc is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Taosc is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with taosc.  If not, see <https://www.gnu.org/licenses/>.

const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;
const Dir = std.fs.Dir;
const File = std.fs.File;
const Reader = std.Io.Reader;
const argsAlloc = std.process.argsAlloc;
const argsFree = std.process.argsFree;
const assert = std.debug.assert;
const cwd = std.fs.cwd;
const exit = std.process.exit;
const page_allocator = std.heap.page_allocator;
const parseUnsigned = std.fmt.parseUnsigned;
const print = std.debug.print;
const std = @import("std");

const State = extern struct {
    flags: u16,
    r15: i64,
    r14: i64,
    r13: i64,
    r12: i64,
    r11: i64,
    r10: i64,
    r9: i64,
    r8: i64,
    rdi: i64,
    rsi: i64,
    rbp: i64,
    rbx: i64,
    rdx: i64,
    rcx: i64,
    rax: i64,
    rsp: u64, // internal use only
    rip: i64,
};

fn countFiles(dir: Dir) Dir.Iterator.Error!usize {
    var count: usize = 0;
    var entries = dir.iterate();
    while (try entries.next()) |entry| {
        assert(entry.kind == .file);
        count += 1;
    }
    return count;
}

const ReadError = Dir.Iterator.Error || File.OpenError || Reader.Error;

const Data = struct {
    states: []const State,
    memory: []const u8,

    fn init(allocator: Allocator, dir: Dir,
            stack_len: u64) (Allocator.Error || ReadError)!Data {
        const count = try countFiles(dir);
        const states = try allocator.alloc(State, count);
        const memory = try allocator.alloc(u8, stack_len * count);
        var entries = dir.iterate();
        var sp: u64 = 0;
        for (states) |*state| {
            const entry = try entries.next();
            const file = try dir.openFile(entry.?.name, .{});
            defer file.close();
            var buffer: [4096]u8 = undefined;
            var reader = file.reader(&buffer);
            assert(try reader.read(@ptrCast(state)) == @sizeOf(State));
            state.rsp = sp;
            assert(try reader.read(memory[sp..][0..stack_len]) == stack_len);
            sp += stack_len;
            print("{}\n", .{ state });
        }
        return .{ .states = states, .memory = memory };
    }

    fn deinit(data: Data, allocator: Allocator) void {
        allocator.free(data.states);
        allocator.free(data.memory);
    }
};

pub fn main() !void {
    var arena = ArenaAllocator.init(page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();
    const args = try argsAlloc(allocator);
    defer argsFree(allocator, args);
    if (args.len != 4) {
        print("Usage: taosc-synth OFF-DIR ON-DIR STACK-SIZE", .{});
        exit(1);
    }
    var off_dir = try cwd().openDir(args[1], .{ .iterate = true });
    defer off_dir.close();
    var on_dir = try cwd().openDir(args[2], .{ .iterate = true });
    defer on_dir.close();
    const stack_len = try parseUnsigned(u64, args[3], 0);

    const off_data = try Data.init(allocator, off_dir, stack_len);
    defer off_data.deinit(allocator);
    const on_data = try Data.init(allocator, on_dir, stack_len);
    defer on_data.deinit(allocator);
}