148 lines
3.7 KiB
Zig
148 lines
3.7 KiB
Zig
const std = @import("std");
|
|
const device = @import("../device.zig");
|
|
const ids = @import("id.zig");
|
|
const operand = @import("operand.zig");
|
|
const pseudo = @import("pseudo.zig");
|
|
|
|
pub const LoadGlobalInvocationId = struct {
|
|
destination: operand.Destination,
|
|
component: u8,
|
|
};
|
|
|
|
pub const LoadBuffer = struct {
|
|
destination: operand.Destination,
|
|
buffer: ids.StorageBufferId,
|
|
byte_offset: operand.Source,
|
|
immediate_offset: u32 = 0,
|
|
};
|
|
|
|
pub const StoreBuffer = struct {
|
|
buffer: ids.StorageBufferId,
|
|
byte_offset: operand.Source,
|
|
immediate_offset: u32 = 0,
|
|
source: operand.Source,
|
|
};
|
|
|
|
pub const Move = struct {
|
|
destination: operand.Destination,
|
|
source: operand.Source,
|
|
};
|
|
|
|
pub const BinaryOpcode = enum {
|
|
add,
|
|
multiply,
|
|
bitwise_and,
|
|
bitwise_or,
|
|
bitwise_xor,
|
|
shift_left,
|
|
shift_right,
|
|
};
|
|
|
|
pub const Binary = struct {
|
|
opcode: BinaryOpcode,
|
|
destination: operand.Destination,
|
|
lhs: operand.Source,
|
|
rhs: operand.Source,
|
|
};
|
|
|
|
pub const CompareOpcode = enum {
|
|
equal,
|
|
not_equal,
|
|
less_than,
|
|
less_or_equal,
|
|
greater_than,
|
|
greater_or_equal,
|
|
};
|
|
|
|
pub const Compare = struct {
|
|
opcode: CompareOpcode,
|
|
destination: operand.FlagRef,
|
|
lhs: operand.Source,
|
|
rhs: operand.Source,
|
|
};
|
|
|
|
pub const Operation = union(enum) {
|
|
load_global_invocation_id: LoadGlobalInvocationId,
|
|
load_buffer: LoadBuffer,
|
|
store_buffer: StoreBuffer,
|
|
move: Move,
|
|
binary: Binary,
|
|
compare: Compare,
|
|
parallel_copy: pseudo.ParallelCopy,
|
|
};
|
|
|
|
pub fn cloneOperation(allocator: std.mem.Allocator, operation: Operation) std.mem.Allocator.Error!Operation {
|
|
return switch (operation) {
|
|
.parallel_copy => |copy| .{
|
|
.parallel_copy = .{
|
|
.register_copies = try allocator.dupe(pseudo.RegisterCopy, copy.register_copies),
|
|
.flag_copies = try allocator.dupe(pseudo.FlagCopy, copy.flag_copies),
|
|
},
|
|
},
|
|
else => operation,
|
|
};
|
|
}
|
|
|
|
pub const Instruction = struct {
|
|
parent_block: ids.BlockId,
|
|
execution_size: device.ExecutionSize,
|
|
predicate: ?operand.Predicate = null,
|
|
operation: Operation,
|
|
};
|
|
|
|
pub const Edge = struct {
|
|
target: ids.BlockId,
|
|
arguments: []const pseudo.EdgeArgument,
|
|
};
|
|
|
|
pub const Terminator = union(enum) {
|
|
jump: Edge,
|
|
conditional_branch: struct {
|
|
predicate: operand.Predicate,
|
|
true_edge: Edge,
|
|
false_edge: Edge,
|
|
},
|
|
end_thread,
|
|
@"unreachable",
|
|
};
|
|
|
|
pub fn cloneEdge(allocator: std.mem.Allocator, edge: Edge) std.mem.Allocator.Error!Edge {
|
|
return .{
|
|
.target = edge.target,
|
|
.arguments = try allocator.dupe(pseudo.EdgeArgument, edge.arguments),
|
|
};
|
|
}
|
|
|
|
pub fn cloneTerminator(allocator: std.mem.Allocator, terminator: Terminator) std.mem.Allocator.Error!Terminator {
|
|
return switch (terminator) {
|
|
.jump => |edge| .{ .jump = try cloneEdge(allocator, edge) },
|
|
.conditional_branch => |branch| .{
|
|
.conditional_branch = .{
|
|
.predicate = branch.predicate,
|
|
.true_edge = try cloneEdge(allocator, branch.true_edge),
|
|
.false_edge = try cloneEdge(allocator, branch.false_edge),
|
|
},
|
|
},
|
|
else => terminator,
|
|
};
|
|
}
|
|
|
|
pub const StructuredControl = union(enum) {
|
|
none,
|
|
selection: struct {
|
|
merge_block: ids.BlockId,
|
|
},
|
|
loop: struct {
|
|
merge_block: ids.BlockId,
|
|
continue_block: ids.BlockId,
|
|
},
|
|
};
|
|
|
|
pub const Block = struct {
|
|
parameters: std.ArrayList(pseudo.BlockParameter) = .empty,
|
|
instructions: std.ArrayList(ids.InstructionId) = .empty,
|
|
terminator: ?Terminator = null,
|
|
structured_control: StructuredControl = .none,
|
|
name: ?[]const u8 = null,
|
|
};
|